Skip to content

Commit

Permalink
Add support for double-width characters
Browse files Browse the repository at this point in the history
  • Loading branch information
ulidtko committed Oct 23, 2015
1 parent ab114b9 commit f2e9d63
Showing 1 changed file with 25 additions and 3 deletions.
28 changes: 25 additions & 3 deletions elastic_tabstops.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@
from ElasticTabstops.edit import Edit
from itertools import zip_longest

# works the same in Py2 and Py3 (thanks jesus)
from unicodedata import east_asian_width

def unicode_char_width(c):
""" Wide chars are Chinese ideographs, Japanese kanji and alike.
They get two columns of space to render.
"""
return {
'Na': 1, 'N': 1, 'H': 1,
'W': 2, 'F': 2

This comment has been minimized.

Copy link
@adzenith

adzenith Dec 17, 2015

Do you know if this is a comprehensive list of return values? What if I have other weird unicode characters?

This comment has been minimized.

Copy link
@ulidtko

ulidtko Jan 7, 2016

Author Owner

Yes.

This comment has been minimized.

Copy link
@ulidtko

ulidtko Jan 7, 2016

Author Owner

Hah! The 'A' case is missing. Good catch, have to add this.

Per Unicode, the 'A' case is for Ambiguous-width characters. The recommendation is to treat them as narrow:

Ambiguous characters behave like wide or narrow characters depending on the context (language tag, script identification, associated font, source of data, or explicit markup; all can provide the context). If the context cannot be established reliably, they should be treated as narrow characters by default.

I.e. 'A': 1.

} [east_asian_width(c)]

def column_width(s):
""" Calculate string width in columns, accounting for wide chars """
return sum(map(unicode_char_width, s))

def lines_in_buffer(view):
row, col = view.rowcol(view.size())
#"row" is the index of the last row; need to add 1 to get number of rows
Expand Down Expand Up @@ -67,7 +83,7 @@ def cell_widths_for_row(view, row):
right_edge = tabs[i+1]
rightmost_selection = rightmost_selection_in_cell(selection_columns, right_edge)
cell = line[left_edge:right_edge]
widths[i] = max(len(cell.rstrip()), rightmost_selection - left_edge)
widths[i] = max(column_width(cell.rstrip()), rightmost_selection - left_edge)
return widths

def find_cell_widths_for_block(view, row):
Expand Down Expand Up @@ -106,13 +122,19 @@ def adjust_row(view, glued, row, widths):
location += 1 + w
it += bias
difference = location - it

This comment has been minimized.

Copy link
@adzenith

adzenith Dec 17, 2015

Looks like this line can be deleted too.

if difference == 0:
continue

end_tab_point = view.text_point(row, it)
partial_line = view.substr(view.line(end_tab_point))[0:it]

columns = column_width(partial_line)
difference = location - columns

if difference == 0:
continue

stripped_partial_line = partial_line.rstrip()
ispaces = len(partial_line) - len(stripped_partial_line)

if difference > 0:
view.run_command("maybe_mark_undo_groups_for_gluing")
glued = True
Expand Down

0 comments on commit f2e9d63

Please sign in to comment.