diff options
Diffstat (limited to 'src/utils/strwidth.nim')
-rw-r--r-- | src/utils/strwidth.nim | 82 |
1 files changed, 28 insertions, 54 deletions
diff --git a/src/utils/strwidth.nim b/src/utils/strwidth.nim index 8c367991..4ce9aa12 100644 --- a/src/utils/strwidth.nim +++ b/src/utils/strwidth.nim @@ -1,7 +1,6 @@ -import std/unicode - -import utils/proptable import utils/map +import utils/proptable +import utils/twtuni include res/map/charwidth_gen @@ -9,8 +8,7 @@ include res/map/charwidth_gen var isCJKAmbiguous* = false # Warning: this shouldn't be called without normalization. -func width*(r: Rune): int = - let u = uint32(r) +func width*(u: uint32): int = if u <= 0xFFFF: # fast path for BMP if u in CombiningTable: return 0 @@ -31,80 +29,56 @@ func width*(r: Rune): int = # Width, but also works with tabs. # Needs the column width of the text so far. -func twidth*(r: Rune; w: int): int = - if r != Rune('\t'): - return r.width() +func twidth*(u: uint32; w: int): int = + if u != uint32('\t'): + return u.width() return ((w div 8) + 1) * 8 - w -func width*(s: string): int = - result = 0 - for r in s.runes: - result += r.twidth(result) +func width*(s: openArray[char]): int = + var w = 0 + for u in s.points: + w += u.twidth(w) + return w func width*(s: string; start, len: int): int = - result = 0 + var w = 0 var i = start var m = len if m > s.len: m = s.len while i < m: - var r: Rune - fastRuneAt(s, i, r) - result += r.twidth(result) - -when NimMajor < 2: - template ones(n: untyped): untyped = ((1 shl n)-1) - template fastRuneAt(s: openArray[char]; i: int; result: untyped) = - result = Rune(0xFFFD) - if uint32(s[i]) <= 127: - result = Rune(uint32(s[i])) - elif uint32(s[i]) shr 5 == 0b110: - if i <= s.len - 2: - result = Rune((uint32(s[i]) and (ones(5))) shl 6 or - (uint32(s[i+1]) and ones(6))) - i += 1 - elif uint32(s[i]) shr 4 == 0b1110: - if i <= s.len - 3: - result = Rune((uint32(s[i]) and ones(4)) shl 12 or - (uint32(s[i+1]) and ones(6)) shl 6 or (uint32(s[i+2]) and ones(6))) - i += 2 - elif uint32(s[i]) shr 3 == 0b11110: - if i <= s.len - 4: - result = Rune((uint32(s[i]) and ones(3)) shl 18 or - (uint32(s[i+1]) and ones(6)) shl 12 or - (uint32(s[i+2]) and ones(6)) shl 6 or - (uint32(s[i+3]) and ones(6))) - i += 3 - inc i + let u = s.nextUTF8(i) + w += u.twidth(w) + return w func notwidth*(s: openArray[char]): int = - result = 0 - var i = 0 - while i < s.len: - var r: Rune - fastRuneAt(s, i, r) - result += r.width() + var w = 0 + for u in s.points: + w += u.width() + return w func twidth*(s: string; w: int): int = var i = w - for r in s.runes: - i += r.twidth(w) + for u in s.points: + i += u.twidth(w) return i - w func padToWidth*(s: string; size: int; schar = '$'): string = result = newStringOfCap(s.len) var w = 0 - var r: Rune var i = 0 + var pi = 0 while i < s.len: - fastRuneAt(s, i, r) - w += r.width() + pi = i + w += s.nextUTF8(i).width() if w > size - 1: break - result &= r + for j in pi ..< i: + result &= s[j] if w > size - 1: if w == size and i == s.len: - result &= r + for j in pi ..< i: + result &= s[j] else: result &= schar while w < size: |