This function merges lines segment when they are vertically aligned
    :param lines: list of lines coordinates (top, left, bottom, right)
    :return: list of merged lines coordinates
502184
def merge_vertical_lines(lines, tol=TOLERANCE):
    
    if len(lines) == 0:
        return []
    merged_lines = [lines[0]]
    for line in lines[1:]:
        last_line = merged_lines[-1]
        if line[1] == last_line[1]:  # lines are vertically aligned
            if line[0] <= last_line[2] + tol:  # lines intersect
                y0, x0, y1, x1 = merged_lines[-1]
                merged_lines[-1] = (y0, x0, line[2], x1)
            else:
                merged_lines.append(
                    line
                )  # lines are vertically aligned but do not intersect
        else:
            merged_lines.append(line)
    return merged_lines
173045
def parse(self, lines):
    

    if isinstance(lines, str):
      lines = lines.split('\n')
    sub = _re.sub
    for line in lines:
      if line.endswith('\n'):
        line = line[:-1]
      line = line.lstrip()
      if not line.startswith('#'):
        invert = False
        if line.startswith('!'):
          line = line[1:]
          invert = True
        while line.endswith(' ') and line[-2:] != '\ ':
          line = line[:-1]
        line = sub(r'\\([!# ])', r'\1', line)
        if '/' in line and not line.startswith('/'):
          # Patterns with a slash can only be matched absolute.
          line = '/' + line
        self.patterns.append(Pattern(line, invert))
1088732
def dashed_line(self, x1,y1,x2,y2, dash_length=1, space_length=1):
        """"""
        self._set_dash(dash_length, space_length)
        self.line(x1, y1, x2, y2)
        self._set_dash()
903329
public static String join(String start, String linePrefix, Collection<?> lines) {
        if (lines.isEmpty()) {
            return "";
        }
        StringBuilder out = new StringBuilder(start);
        for (Object line : lines) {
            out.append(linePrefix).append(line).append("\n");
        }
        return out.substring(0, out.length() - 1); //lose last EOL
    }
17815
def __moveLineOrCol(self, line, d):
        
        nl = [c for c in line if c != 0]
        if d == Board.UP or d == Board.LEFT:
            return nl + [0] * (self.__size - len(nl))
        return [0] * (self.__size - len(nl)) + nl
748772
def find_shape(bottom_lines, max_len):
    
    shape = [1] * max_len
    for i in range(max_len):
        for line in bottom_lines:
            if line[0] <= i + 1 < line[2]:
                shape[i] = line[1]
                break
    return shape
155765
def make_ranges(cls, lines):
        
        start_line = last_line = lines.pop(0)
        ranges = []
        for line in lines:
            if line == (last_line + 1):
                last_line = line
            else:
                ranges.append((start_line, last_line))
                start_line = line
                last_line = line
        ranges.append((start_line, last_line))
        return ranges
1041134
def tail(self, lines=10):
        
        self.seek_end()
        end_pos = self.file.tell()

        for i in range(lines):
            if not self.seek_line():
                break

        data = self.file.read(end_pos - self.file.tell() - 1)
        if data:
            return self.splitlines(data)
        else:
            return []
87235
def _process(self, segments):
        """"""
        # sort_f= lambda r: max_line_width*(r[1]/max_line_height)+r[0]
        # segments= sorted(segments, key=sort_f)
        # segments= segments_to_numpy( segments )
        # return segments
        mlh, mlw = self.max_line_height, self.max_line_width
        s = segments.astype(numpy.uint32)  # prevent overflows
        order = mlw * (s[:, 1] // mlh) + s[:, 0]
        sort_order = numpy.argsort(order)
        return segments[sort_order]
1202821
def __remove_leading_empty_lines(lines):
        
        tmp = list()
        empty = True
        for i in range(0, len(lines)):
            empty = empty and lines[i] == ''
            if not empty:
                tmp.append(lines[i])

        return tmp
585468
def join_lines(line1, line2):
    
    if line1 == u"":
        pass
    elif line1[-1] == u'-':
        # hyphenated word at the end of the
        # line - don't add in a space and remove hyphen
        line1 = line1[:-1]
    elif line1[-1] != u' ':
        # no space at the end of this
        # line, add in a space
        line1 = line1 + u' '
    return line1 + line2
1306473
def get_curr_lines(self):
        
        start = max(0, self._coord.line - 5)
        end = min(len(self._template_lines), self._coord.line + 4)

        lines = [(x, self._template_lines[x]) for x in six.moves.range(start, end, 1)]
        return self._coord.line, lines
934409
private void connectInSameElement(List<LineSegment2D_F32> lines ) {
		for( int i = 0; i < lines.size(); i++ ) {
			LineSegment2D_F32 a = lines.get(i);

			int index = findBestCompatible(a,lines,i+1);
			if( index == -1 )
				continue;

			// remove the line from the index which it is being connected to
			LineSegment2D_F32 b = lines.remove(index);

			// join the two lines by connecting the farthest points from each other
			Point2D_F32 pt0 = farthestIndex < 2 ? a.a : a.b;
			Point2D_F32 pt1 = (farthestIndex %2) == 0 ? b.a : b.b;

			a.a.set(pt0);
			a.b.set(pt1);
		}
	}
835445
def get_line_segments(line):
    
    line = line.strip()

    tokens = tk.generate_tokens(io.StringIO(line).readline)

    equality_signs = [-1]
    comment_tuple = None, ""
    for i, t in enumerate(tokens):
        if t.type == tk.COMMENT:
            # store string_index and comment string
            comment_tuple = t.start[1], t.string
        if t.type == tk.OP and t.string == "=":
            equality_signs.append(t.start[1])

    if len(equality_signs) > 1:
        # we have at least one assignment
        lhs = line[equality_signs[-2]+1:equality_signs[-1]].strip()
        equality_signs.pop(0)
    else:
        lhs = None

    rhs_start_idx = equality_signs[-1] + 1

    # from the last `=` until the beginning of the comment
    rhs = line[rhs_start_idx:comment_tuple[0]].strip()
    if rhs == "":
        rhs = None
    comment = comment_tuple[1].strip()

    return lhs, rhs, comment
834975
def _lines(self):
        

        chunkIndices = self._listChunks()
        for chunkIndex in chunkIndices:
            with self._openChunk(chunkIndex) as chunk:
                yield from chunk._lines()
511883
def set_lines( lines, target_level, indent_string="    ", indent_empty_lines=False ):
    

    first_non_empty_line_index = _get_first_non_empty_line_index( lines )
    first_line_original_level =  get_line_level( lines[first_non_empty_line_index], indent_string )

    for i in range(first_non_empty_line_index, len(lines)):
        if not indent_empty_lines and lines[i] == "":
            continue

        line_i_unindented = get_line_unindented( lines[i], indent_string )
        line_i_level =      get_line_level( lines[i], indent_string )

        on_second_line_or_later = i > first_non_empty_line_index
        if on_second_line_or_later:
            first_line_final_level = get_line_level( lines[first_non_empty_line_index], indent_string )
            relative_indent_move =   first_line_final_level - first_line_original_level
            target_level =           line_i_level + relative_indent_move

        if line_i_level == target_level:
            continue

        lines[i] = indent_string * target_level + line_i_unindented
105280
protected boolean mergeSegments() {
		// can't merge a single line
		if( splits.size <= 2 )
			return false;

		boolean change = false;
		work.reset();

		// first point is always at the start
		work.add(splits.data[0]);

		for( int i = 0; i < splits.size-2; i++ ) {
			if( selectSplitBetween(splits.data[i],splits.data[i+2]) < 0 ) {
				// merge the two lines by not adding it
				change = true;
			} else {
				work.add(splits.data[i + 1]);
			}
		}

		// and end
		work.add(splits.data[splits.size-1]);

		// swap the two lists
		GrowQueue_I32 tmp = work;
		work = splits;
		splits = tmp;

		return change;
	}