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:
|
try:
|
||||||
import curses
|
import curses
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -150,6 +152,24 @@ def get_line_length(line, encoding="UTF-8"):
|
||||||
line = replace_tabs(line)
|
line = replace_tabs(line)
|
||||||
return len(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"):
|
def parse_color_string(s, encoding="UTF-8"):
|
||||||
"""
|
"""
|
||||||
Parses a string and returns a list of 2-tuples (color, string).
|
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(" ")
|
ret.append(" ")
|
||||||
|
|
||||||
return ret
|
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
|
import deluge.component as component
|
||||||
|
|
||||||
from deluge.ui.console.modes import format_utils
|
from deluge.ui.console.modes import format_utils
|
||||||
|
strwidth = format_utils.strwidth
|
||||||
|
|
||||||
import logging,os
|
import logging,os
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@ -353,7 +354,7 @@ class Legacy(BaseMode):
|
||||||
for line in text.splitlines():
|
for line in text.splitlines():
|
||||||
# We need to check for line lengths here and split as necessary
|
# We need to check for line lengths here and split as necessary
|
||||||
try:
|
try:
|
||||||
line_length = colors.get_line_length(line)
|
line_length = colors.get_line_width(line)
|
||||||
except colors.BadColorString:
|
except colors.BadColorString:
|
||||||
log.error("Passed a bad colored line: %s", line)
|
log.error("Passed a bad colored line: %s", line)
|
||||||
continue
|
continue
|
||||||
|
@ -364,11 +365,11 @@ class Legacy(BaseMode):
|
||||||
s_len = 0
|
s_len = 0
|
||||||
# We need to split this over multiple lines
|
# We need to split this over multiple lines
|
||||||
for chunk in get_line_chunks(line):
|
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
|
# This chunk plus the current string in 's' isn't over
|
||||||
# the maximum width, so just append the color tag and text
|
# the maximum width, so just append the color tag and text
|
||||||
s += chunk[0] + chunk[1]
|
s += chunk[0] + chunk[1]
|
||||||
s_len += len(chunk[1])
|
s_len += strwidth(chunk[1])
|
||||||
else:
|
else:
|
||||||
# The chunk plus the current string in 's' is too long.
|
# 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'
|
# 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)
|
self.lines.append(s)
|
||||||
# Start a new 's' with the remainder chunk
|
# Start a new 's' with the remainder chunk
|
||||||
s = chunk[0] + chunk[1][remain:]
|
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
|
# Append the final string which may or may not be the full width
|
||||||
if s:
|
if s:
|
||||||
self.lines.append(s)
|
self.lines.append(s)
|
||||||
|
@ -411,13 +412,13 @@ class Legacy(BaseMode):
|
||||||
for index, (color, s) in enumerate(parsed):
|
for index, (color, s) in enumerate(parsed):
|
||||||
if index + 1 == len(parsed):
|
if index + 1 == len(parsed):
|
||||||
# This is the last string so lets append some " " to it
|
# 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:
|
try:
|
||||||
self.stdscr.addstr(row, col, s, color)
|
self.stdscr.addstr(row, col, s, color)
|
||||||
except curses.error:
|
except curses.error:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
col += len(s)
|
col += strwidth(s)
|
||||||
|
|
||||||
|
|
||||||
def do_command(self, cmd):
|
def do_command(self, cmd):
|
||||||
|
|
Loading…
Reference in New Issue