diff options
author | Mattias Andrée <maandree@operamail.com> | 2015-03-28 19:50:46 +0100 |
---|---|---|
committer | Mattias Andrée <maandree@operamail.com> | 2015-03-28 19:50:46 +0100 |
commit | 6ea0a7d635408c87a1dd46ab7c4a92f3d8e8419a (patch) | |
tree | 7fa95f1103e1f14d29a834cbeb0f00d685c821dc | |
parent | update todo (diff) | |
download | xpybar-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>
-rw-r--r-- | src/util.py | 63 |
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 |