aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2015-03-28 19:50:46 +0100
committerMattias Andrée <maandree@operamail.com>2015-03-28 19:50:46 +0100
commit6ea0a7d635408c87a1dd46ab7c4a92f3d8e8419a (patch)
tree7fa95f1103e1f14d29a834cbeb0f00d685c821dc /src
parentupdate todo (diff)
downloadxpybar-6ea0a7d635408c87a1dd46ab7c4a92f3d8e8419a.tar.gz
xpybar-6ea0a7d635408c87a1dd46ab7c4a92f3d8e8419a.tar.bz2
xpybar-6ea0a7d635408c87a1dd46ab7c4a92f3d8e8419a.tar.xz
add sprintf and colour_aware_len
Signed-off-by: Mattias Andrée <maandree@operamail.com>
Diffstat (limited to 'src')
-rw-r--r--src/util.py63
1 files changed, 63 insertions, 0 deletions
diff --git a/src/util.py b/src/util.py
index e7f3862..a966bfd 100644
--- a/src/util.py
+++ b/src/util.py
@@ -105,6 +105,69 @@ def reduce(f, items):
return rc
+def colour_aware_len(string, original_len = len):
+ '''
+ Colour-aware object length measurement function
+
+ It is suggested to redefine `len` with this
+ function in the following way.
+
+ len_ = len
+ len = lambda string : colour_aware_len(string, len_)
+
+ @param string:object The object to measure
+ @param original_len:(object)→int The original implementation of `len`
+ @return :int The length of `string`
+ '''
+ if not isinstance(string, str):
+ return original_len(string)
+ rc, esc = 0, False
+ for c in string:
+ if esc:
+ if c == 'm':
+ esc = False
+ elif c == '\033':
+ esc = True
+ else:
+ rc += 1
+ return rc
+
+
+def sprintf(format, *args):
+ '''
+ Alternative to the %-operator for strings, with support for '%n'
+
+ @param format:str The format string
+ @param args:*object The arguments to include in place of
+ the placeholders in the format string
+ @return :(text:str, stops:list<int>) The text after formatting, and locations of all '%n':s.
+ Locations of '%n':s are measured using `len`, meaning that
+ this function is aware of redefinitions of `len`.
+ '''
+ rc, measurements, curlen, esc, buf, args, argc = '', [], 0, False, '', tuple(args), 0
+ for c in format:
+ if esc:
+ esc = False
+ if c == 'n':
+ buf %= args[:argc]
+ curlen += len(buf)
+ rc += buf
+ buf = ''
+ args = args[argc:]
+ argc = 0
+ measurements.append(curlen)
+ else:
+ buf += '%'
+ buf += c
+ argc += 1
+ elif c == '%':
+ esc = True
+ else:
+ buf += c
+ rc += buf % args
+ return (rc, measurements)
+
+
class Sometimes:
'''
Function wrapper for only actually invoking