code: def add_string(self, data):
          
          lines = []
          while data:
              match = self._line_end_re.search(data)
              if match is None:
                  chunk = data
              else:
                  chunk = data[:match.end()]
  
              data = data[len(chunk):]
  
              if self._buf and self._buf[-1].endswith(b('\r')) and not chunk.startswith(b('\n')):
                  # if we get a carriage return followed by something other than
                  # a newline then we assume that we're overwriting the current
                  # line (ie. a progress bar)
                  #
                  # We don't terminate lines that end with a carriage return until
                  # we see what's coming next so we can distinguish between a
                  # progress bar situation and a Windows line terminator.
                  #
                  # TODO(adrian): some day these hacks should be replaced with
                  # real terminal emulation
                  lines.append(self._finish_line())
  
              self._buf.append(chunk)
              if chunk.endswith(b('\n')):
                  lines.append(self._finish_line())
  
          return lines
docs: Process some data splitting it into complete lines and buffering the rest
  
          Args:
              data: A `str` in Python 2 or `bytes` in Python 3
          Returns:
              list of complete lines ending with a carriage return (eg. a progress
              bar) or a newline.