Add proper support for double width characters to legacy mode and few related formatting functions
This commit is contained in:
parent
412d0e7be9
commit
16f62bbcfe
|
@ -33,6 +33,8 @@
|
|||
#
|
||||
#
|
||||
|
||||
from deluge.ui.console.modes import format_utils
|
||||
|
||||
try:
|
||||
import curses
|
||||
except ImportError:
|
||||
|
@ -150,6 +152,24 @@ def get_line_length(line, encoding="UTF-8"):
|
|||
line = replace_tabs(line)
|
||||
return len(line)
|
||||
|
||||
def get_line_width(line, encoding="UTF-8"):
|
||||
"""
|
||||
Get width of string considering double width characters
|
||||
|
||||
"""
|
||||
if line.count("{!") != line.count("!}"):
|
||||
raise BadColorString("Number of {! is not equal to number of !}")
|
||||
|
||||
if isinstance(line, unicode):
|
||||
line = line.encode(encoding, "replace")
|
||||
|
||||
# Remove all the color tags
|
||||
line = strip_colors(line)
|
||||
|
||||
# Replace tabs with the appropriate amount of spaces
|
||||
line = replace_tabs(line)
|
||||
return format_utils.strwidth(line)
|
||||
|
||||
def parse_color_string(s, encoding="UTF-8"):
|
||||
"""
|
||||
Parses a string and returns a list of 2-tuples (color, string).
|
||||
|
|
|
@ -201,3 +201,33 @@ def wrap_string(string,width,min_lines=0,strip_colors=True):
|
|||
ret.append(" ")
|
||||
|
||||
return ret
|
||||
|
||||
from unicodedata import east_asian_width
|
||||
|
||||
def strwidth(string):
|
||||
"""
|
||||
Measure width of a string considering asian double width characters
|
||||
"""
|
||||
if not isinstance(string, unicode):
|
||||
string = unicode(string, 'utf-8')
|
||||
eaw = east_asian_width
|
||||
length = sum( [1 + (eaw(c) in ['W','F']) for c in string] )
|
||||
#Using list comprehenstion for improved performance
|
||||
#The code above is equal to:
|
||||
#length = 0
|
||||
#for char in string:
|
||||
#length += 1
|
||||
#if east_asian_width(char) in ['W','F']:
|
||||
#length += 1
|
||||
return length
|
||||
|
||||
def pad_string(string, length, character=" ", side="right"):
|
||||
"""
|
||||
Pad string with specified character to desired length, considering double width characters.
|
||||
"""
|
||||
w = strwidth(string)
|
||||
diff = length - w
|
||||
if side == "left":
|
||||
return "%s%s" % (character * diff, string)
|
||||
elif side == "right":
|
||||
return "%s%s" % (string, character * diff)
|
|
@ -47,6 +47,7 @@ from deluge.ui.client import client
|
|||
import deluge.component as component
|
||||
|
||||
from deluge.ui.console.modes import format_utils
|
||||
strwidth = format_utils.strwidth
|
||||
|
||||
import logging,os
|
||||
log = logging.getLogger(__name__)
|
||||
|
@ -353,7 +354,7 @@ class Legacy(BaseMode):
|
|||
for line in text.splitlines():
|
||||
# We need to check for line lengths here and split as necessary
|
||||
try:
|
||||
line_length = colors.get_line_length(line)
|
||||
line_length = colors.get_line_width(line)
|
||||
except colors.BadColorString:
|
||||
log.error("Passed a bad colored line: %s", line)
|
||||
continue
|
||||
|
@ -364,11 +365,11 @@ class Legacy(BaseMode):
|
|||
s_len = 0
|
||||
# We need to split this over multiple lines
|
||||
for chunk in get_line_chunks(line):
|
||||
if (len(chunk[1]) + s_len) < (self.cols - 1):
|
||||
if (strwidth(chunk[1]) + s_len) < (self.cols - 1):
|
||||
# This chunk plus the current string in 's' isn't over
|
||||
# the maximum width, so just append the color tag and text
|
||||
s += chunk[0] + chunk[1]
|
||||
s_len += len(chunk[1])
|
||||
s_len += strwidth(chunk[1])
|
||||
else:
|
||||
# The chunk plus the current string in 's' is too long.
|
||||
# We need to take as much of the chunk and put it into 's'
|
||||
|
@ -379,7 +380,7 @@ class Legacy(BaseMode):
|
|||
self.lines.append(s)
|
||||
# Start a new 's' with the remainder chunk
|
||||
s = chunk[0] + chunk[1][remain:]
|
||||
s_len = len(chunk[1][remain:])
|
||||
s_len = strwidth(chunk[1][remain:])
|
||||
# Append the final string which may or may not be the full width
|
||||
if s:
|
||||
self.lines.append(s)
|
||||
|
@ -411,13 +412,13 @@ class Legacy(BaseMode):
|
|||
for index, (color, s) in enumerate(parsed):
|
||||
if index + 1 == len(parsed):
|
||||
# This is the last string so lets append some " " to it
|
||||
s += " " * (self.cols - (col + len(s)) - 1)
|
||||
s += " " * (self.cols - (col + strwidth(s)) - 1)
|
||||
try:
|
||||
self.stdscr.addstr(row, col, s, color)
|
||||
except curses.error:
|
||||
pass
|
||||
|
||||
col += len(s)
|
||||
col += strwidth(s)
|
||||
|
||||
|
||||
def do_command(self, cmd):
|
||||
|
|
Loading…
Reference in New Issue