Exemplo n.º 1
0
def do_get_col_num_rfc_lines(view, cur_line, cnum, start_line, end_line, delim,
                             expected_num_fields):
    cursor_line_offset = cur_line - start_line
    lines = []
    for l in range(start_line, end_line + 1):
        lines.append(get_line_text(view, l))
    record_str = '\n'.join(lines)
    fields, has_warning = csv_utils.smart_split(
        record_str, delim, 'quoted_rfc', preserve_quotes_and_whitespaces=True)
    if has_warning or len(fields) != expected_num_fields:
        return None
    current_line_offset = 0
    col_num = 0
    while col_num < len(fields):
        current_line_offset += fields[col_num].count('\n')
        if current_line_offset >= cursor_line_offset:
            break
        col_num += 1
    if current_line_offset > cursor_line_offset:
        # The cursor line is inside the multiline col_num field
        return col_num
    if current_line_offset < cursor_line_offset:
        # Should never happend
        return None
    length_of_previous_field_segment_on_cursor_line = 0
    if current_line_offset > 0:
        length_of_previous_field_segment_on_cursor_line = len(
            fields[col_num].split('\n')[-1]) + len(delim)
        if cnum <= length_of_previous_field_segment_on_cursor_line:
            return col_num
        col_num += 1
    col_num = col_num + get_col_num_single_line(
        fields[col_num:], len(delim), cnum,
        length_of_previous_field_segment_on_cursor_line)
    return col_num
Exemplo n.º 2
0
def csv_lint(view, delim, policy):
    if policy == 'quoted_rfc':
        # FIXME support csv_lint for rfc policy
        sublime.error_message(
            'CSVLint is currently not supported for RFC4180-compatible dialects'
        )
        return False
    num_fields = None
    line_regions = view.lines(sublime.Region(0, view.size()))
    for ln, lr in enumerate(line_regions):
        line = view.substr(lr)
        fields, warning = csv_utils.smart_split(line, delim, policy, True)
        if warning:
            sublime.error_message(
                'CSVLint: line {} has formatting error: double quote chars are not consistent'
                .format(ln + 1))
            return False
        if num_fields is None:
            num_fields = len(fields)
        if num_fields != len(fields):
            sublime.error_message(
                'Number of fields is not consistent: e.g. line 1 has {} fields, and line {} has {} fields'
                .format(num_fields, ln + 1, len(fields)))
            return False
    return True
Exemplo n.º 3
0
 def run(self, edit):
     dialect = get_dialect(self.view.settings())
     if dialect[1] == 'monocolumn':
         sublime.error_message(
             'Error. You need to select a separator first')
         return
     delim, policy = dialect
     adjusted_lines = []
     has_edit = False
     line_regions = self.view.lines(sublime.Region(0, self.view.size()))
     for ln, lr in enumerate(line_regions):
         line = self.view.substr(lr)
         fields, warning = csv_utils.smart_split(line, delim, policy, True)
         if warning:
             sublime.error_message(
                 'Unable to Shrink: line {} has formatting error: double quote chars are not consistent'
                 .format(ln + 1))
             return
         for i in range(len(fields)):
             adjusted = fields[i].strip()
             if len(adjusted) != len(fields[i]):
                 fields[i] = adjusted
                 has_edit = True
         adjusted_lines.append(delim.join(fields))
     if not has_edit:
         sublime.message_dialog('Table is already shrinked, skipping')
         return
     adjusted_content = '\n'.join(adjusted_lines)
     self.view.replace(edit, sublime.Region(0, self.view.size()),
                       adjusted_content)
Exemplo n.º 4
0
def show_names_for_line(view, delim, policy, line_region):
    point = line_region.a
    line_text = view.substr(line_region)
    fields = csv_utils.smart_split(line_text, delim, policy, True)[0]
    tab_stop = view.settings().get('tab_size', 4) if delim == '\t' else 1
    layout_width_dip = view.layout_extent()[0]
    font_char_width_dip = view.em_width()
    dip_reserve = 10
    char_reserve = 2
    max_status_width = layout_width_dip - dip_reserve
    max_available_chars = max_status_width // font_char_width_dip - char_reserve

    status_labels = generate_tab_statusline(tab_stop, len(delim), fields,
                                            max_available_chars)
    if not len(status_labels):
        return
    num_fields = len(status_labels) // 2
    html_text = ''
    for i in range(num_fields):
        hex_color = get_column_color(view, i)
        column_name = status_labels[i * 2]
        space_filling = status_labels[i * 2 + 1].replace(' ', '&nbsp;')
        html_text += '<span style="color:{}">{}{}</span>'.format(
            hex_color, html_escape(column_name), space_filling)
    view.show_popup(html_text,
                    location=point,
                    max_width=max_status_width,
                    max_height=100)
Exemplo n.º 5
0
 def on_hover(self, point, hover_zone):
     if hover_zone == sublime.HOVER_TEXT:
         dialect = get_dialect(self.view.settings())
         if not dialect:
             return
         delim, policy = dialect
         # lnum and cnum are 0-based
         cnum = self.view.rowcol(point)[1]
         line_text = self.view.substr(self.view.line(point))
         hover_record, warning = csv_utils.smart_split(
             line_text, delim, policy, True)
         field_num = get_field_by_line_position(hover_record, cnum)
         header = get_document_header(self.view, delim, policy)
         ui_text = 'Col #{}'.format(field_num + 1)
         if field_num < len(header):
             column_name = header[field_num]
             max_header_len = 30
             if len(column_name) > max_header_len:
                 column_name = column_name[:max_header_len] + '...'
             ui_text += ', Header: "{}"'.format(column_name)
         if len(header) != len(hover_record):
             ui_text += '; WARN: num of fields in Header and this line differs'
         if warning:
             ui_text += '; This line has quoting error'
         ui_hex_color = get_column_color(self.view, field_num)
         self.view.show_popup('<span style="color:{}">{}</span>'.format(
             ui_hex_color, ui_text),
                              sublime.HIDE_ON_MOUSE_MOVE_AWAY,
                              point,
                              on_hide=hover_hide_cb,
                              max_width=1000)
Exemplo n.º 6
0
 def on_hover(self, point, hover_zone):
     if hover_zone == sublime.HOVER_TEXT:
         dialect = get_dialect(self.view.settings())
         if dialect[1] == 'monocolumn':
             return
         delim, policy = dialect
         header = get_document_header(self.view, delim, policy)
         # lnum and cnum are 0-based
         cnum = self.view.rowcol(point)[1]
         quoting_warning = False
         inconsistent_num_fields_warning = False
         if policy == 'quoted_rfc':
             try:
                 field_num = get_col_num_rfc_lines(self.view, delim, point,
                                                   len(header))
                 if field_num is None:
                     self.view.show_popup(
                         '<span>Unable to infer column id</span>',
                         sublime.HIDE_ON_MOUSE_MOVE_AWAY,
                         point,
                         on_hide=hover_hide_cb,
                         max_width=1000)
                     return
             except Exception as e:
                 print(
                     'Rainbow CSV: Unexpected Exception while showing column info: {}'
                     .format(e))
                 return
         else:
             line_text = self.view.substr(self.view.line(point))
             hover_record, quoting_warning = csv_utils.smart_split(
                 line_text, delim, policy, True)
             field_num = get_col_num_single_line(hover_record, len(delim),
                                                 cnum)
             if len(header) != len(hover_record):
                 inconsistent_num_fields_warning = True
         use_zero_based_column_indices = get_setting(
             self.view, 'use_zero_based_column_indices', False)
         ui_text = 'Col {}'.format(
             field_num if use_zero_based_column_indices else field_num + 1)
         if field_num < len(header):
             column_name = header[field_num]
             max_header_len = 30
             if len(column_name) > max_header_len:
                 column_name = column_name[:max_header_len] + '...'
             ui_text += ', {}'.format(column_name)
         if inconsistent_num_fields_warning:
             ui_text += '; WARN: num of fields in Header and this line differs'
         if quoting_warning:
             ui_text += '; This line has quoting error'
         ui_hex_color = get_column_color(self.view, field_num)
         self.view.show_popup('<span style="color:{}">{}</span>'.format(
             ui_hex_color, html_escape(ui_text)),
                              sublime.HIDE_ON_MOUSE_MOVE_AWAY,
                              point,
                              on_hide=hover_hide_cb,
                              max_width=1000)
Exemplo n.º 7
0
def is_delimited_table(sampled_lines, delim, policy, min_num_lines):
    if len(sampled_lines) < min_num_lines:
        return False
    num_fields = None
    for sl in sampled_lines:
        fields, warning = csv_utils.smart_split(sl, delim, policy, True)
        if warning or len(fields) < 2:
            return False
        if num_fields is None:
            num_fields = len(fields)
        if num_fields != len(fields):
            return False
    return True
Exemplo n.º 8
0
def calc_column_sizes(view, delim, policy):
    result = []
    line_regions = view.lines(sublime.Region(0, view.size()))
    for ln, lr in enumerate(line_regions):
        line = view.substr(lr)
        fields, warning = csv_utils.smart_split(line, delim, policy, True)
        if warning:
            return (None, ln)
        for i in range(len(fields)):
            if len(result) <= i:
                result.append(0)
            result[i] = max(result[i], len(fields[i].strip()))
    return (result, None)
Exemplo n.º 9
0
def csv_lint(view, delim, policy):
    num_fields = None
    line_regions = view.lines(sublime.Region(0, view.size()))
    for ln, lr in enumerate(line_regions):
        line = view.substr(lr)
        fields, warning = csv_utils.smart_split(line, delim, policy, True)
        if warning:
            sublime.error_message(
                'CSVLint: line {} has formatting error: double quote chars are not consistent'
                .format(ln + 1))
            return False
        if num_fields is None:
            num_fields = len(fields)
        if num_fields != len(fields):
            sublime.error_message(
                'Number of fields is not consistent: e.g. line 1 has {} fields, and line {} has {} fields'
                .format(num_fields, ln + 1, len(fields)))
            return False
    return True
Exemplo n.º 10
0
    def run(self, edit):
        dialect = get_dialect(self.view.settings())
        if dialect[1] == 'monocolumn':
            sublime.error_message(
                'Error. You need to select a separator first')
            return
        delim, policy = dialect
        column_sizes, failed_line_num = calc_column_sizes(
            self.view, delim, policy)
        if failed_line_num is not None:
            sublime.error_message(
                'Unable to Align: line {} has formatting error: double quote chars are not consistent'
                .format(failed_line_num + 1))
            return

        adjusted_lines = []
        has_edit = False
        line_regions = self.view.lines(sublime.Region(0, self.view.size()))
        for lr in line_regions:
            line = self.view.substr(lr)
            fields = csv_utils.smart_split(line, delim, policy, True)[0]
            for i in range(0, len(fields) - 1):
                if i >= len(column_sizes):
                    break
                adjusted = fields[i].strip()
                delta_len = column_sizes[i] - len(adjusted)
                if delta_len >= 0:  # Safeguard against async doc edit
                    adjusted += ' ' * (delta_len + 1)
                if fields[i] != adjusted:
                    fields[i] = adjusted
                    has_edit = True
            adjusted_lines.append(delim.join(fields))
        if not has_edit:
            sublime.message_dialog('Table is already aligned, skipping')
            return
        adjusted_content = '\n'.join(adjusted_lines)
        self.view.replace(edit, sublime.Region(0, self.view.size()),
                          adjusted_content)
Exemplo n.º 11
0
def get_document_header(view, delim, policy):
    header_line = get_line_text(view, 0)
    return csv_utils.smart_split(header_line, delim, policy, False)[0]
Exemplo n.º 12
0
def get_col_num_rfc_basic_even_case(line, cnum, delim, expected_num_fields):
    fields, warning = csv_utils.smart_split(
        line, delim, 'quoted_rfc', preserve_quotes_and_whitespaces=True)
    if warning or len(fields) != expected_num_fields:
        return None
    return get_col_num_single_line(fields, len(delim), cnum)