rubyterm 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/bitmapwindow.rb +9 -5
- data/lib/charwidth.rb +37 -7
- data/lib/rubyterm/version.rb +1 -1
- data/lib/term.rb +5 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dad934f37ee68f63661c2d7bbd2e8c7af64a8811fb8fd27b9d5bd63787a8f021
|
|
4
|
+
data.tar.gz: 124c7b36ea94bef960b7bbc78f9143149cce43cf443b4e7d9ed99207e40d1f01
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ea7bf3f07aa5088ca07bc79058aa836d20af2c95d5d6887d7fe5e7fd8f44283170c4fa2df7078d5f10a271582b5d339143473e8fc3d1af51d74c42f562e3e0a5
|
|
7
|
+
data.tar.gz: 491468d6aab9c96754001425718102aaa1c677c994ca1f82c47a3fa07196327bb3ed132ef72c547d77904216f6ed9f700373fdd3c6b08cae3769904f36f562a9
|
data/lib/bitmapwindow.rb
CHANGED
|
@@ -83,10 +83,14 @@ class BitmapWindow
|
|
|
83
83
|
# for now - it does not affect correctness of the text, only its scale.
|
|
84
84
|
def draw(x, y, str, fg, bg, _lineattrs = nil)
|
|
85
85
|
fillrect(x, y, str.length * @char_w, @char_h, bg)
|
|
86
|
-
str.each_char.
|
|
87
|
-
|
|
86
|
+
cps = str.each_char.map(&:ord)
|
|
87
|
+
cps.each_with_index do |cp, i|
|
|
88
88
|
next if cp == 32 || cp == CharWidth::WIDE_SPACER # space / wide-glyph tail
|
|
89
|
-
|
|
89
|
+
# A WIDE_SPACER in the next cell means this is a double-width glyph; render
|
|
90
|
+
# it two cells wide so it overflows into the (skipped) spacer cell instead
|
|
91
|
+
# of being shrunk into one.
|
|
92
|
+
cells = cps[i + 1] == CharWidth::WIDE_SPACER ? 2 : 1
|
|
93
|
+
blit_glyph(cp, x + i * @char_w, y, fg, cells)
|
|
90
94
|
end
|
|
91
95
|
end
|
|
92
96
|
|
|
@@ -146,8 +150,8 @@ class BitmapWindow
|
|
|
146
150
|
end
|
|
147
151
|
end
|
|
148
152
|
|
|
149
|
-
def blit_glyph(codepoint, cx, cy, fg)
|
|
150
|
-
g = @cache.glyph(codepoint)
|
|
153
|
+
def blit_glyph(codepoint, cx, cy, fg, cells = 1)
|
|
154
|
+
g = @cache.glyph(codepoint, cells)
|
|
151
155
|
return unless g
|
|
152
156
|
if g.color?
|
|
153
157
|
blit_rgba(g, codepoint, cx, cy)
|
data/lib/charwidth.rb
CHANGED
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
# * width(cp) -> 1 or 2 cells (wide = CJK/Hangul/Kana/fullwidth + emoji)
|
|
12
12
|
# * emoji?(cp) -> whether to render in colour (the non-CJK wide blocks)
|
|
13
13
|
#
|
|
14
|
-
# Combining marks (width 0) are deliberately not handled yet (treated as 1).
|
|
15
14
|
module CharWidth
|
|
16
15
|
# Codepoint stored in the second cell of a double-width glyph: a blank,
|
|
17
16
|
# advancing placeholder. The terminal writes it after a wide char so the
|
|
@@ -19,6 +18,26 @@ module CharWidth
|
|
|
19
18
|
# advancing glyph and the bitmap/virtual backends skip it.
|
|
20
19
|
WIDE_SPACER = 0
|
|
21
20
|
|
|
21
|
+
# Zero-width (combining) codepoints. These modify the preceding base glyph
|
|
22
|
+
# rather than advancing the cursor, so they occupy no column — matching tmux
|
|
23
|
+
# (a lone U+FE0F reports cursor_x=0; a base+U+FE0F sequence stays the base's
|
|
24
|
+
# width). Notably this includes the variation selectors: U+FE0F (VS16, emoji
|
|
25
|
+
# presentation) and U+FE0E (VS15, text presentation) request a presentation
|
|
26
|
+
# for the preceding char but are themselves invisible and zero-width. Treating
|
|
27
|
+
# them as width 1 gave each its own cell, drawing a stray glyph over the next
|
|
28
|
+
# column. Per-script combining marks beyond these blocks are a deferred
|
|
29
|
+
# non-goal (still treated as width 1).
|
|
30
|
+
ZERO = [
|
|
31
|
+
0x0300..0x036F, # combining diacritical marks
|
|
32
|
+
0x1AB0..0x1AFF, # combining diacritical marks extended
|
|
33
|
+
0x1DC0..0x1DFF, # combining diacritical marks supplement
|
|
34
|
+
0x200B..0x200F, # ZWSP, ZWNJ, ZWJ, LRM, RLM (zero-width format)
|
|
35
|
+
0x20D0..0x20FF, # combining diacritical marks for symbols
|
|
36
|
+
0xFE00..0xFE0F, # variation selectors (incl. VS15/VS16)
|
|
37
|
+
0xFE20..0xFE2F, # combining half marks
|
|
38
|
+
0xE0100..0xE01EF # variation selectors supplement
|
|
39
|
+
].freeze
|
|
40
|
+
|
|
22
41
|
# Wide (two-cell) blocks: CJK, Hangul, Kana, fullwidth forms, and emoji.
|
|
23
42
|
#
|
|
24
43
|
# In the BMP symbol zone (Misc Symbols, Dingbats, Misc Symbols & Arrows)
|
|
@@ -45,9 +64,16 @@ module CharWidth
|
|
|
45
64
|
0x1FA70..0x1FAD6, 0x20000..0x2EBE0, 0x2F800..0x2FA1D, 0x30000..0x3134A
|
|
46
65
|
].freeze
|
|
47
66
|
|
|
48
|
-
#
|
|
49
|
-
# in colour
|
|
50
|
-
#
|
|
67
|
+
# Emoji code blocks (excludes CJK/Hangul/Kana/fullwidth): a codepoint renders
|
|
68
|
+
# in colour only if it is BOTH in one of these blocks AND wide (width 2) —
|
|
69
|
+
# see emoji?. The width-2 gate is what distinguishes emoji-presentation
|
|
70
|
+
# codepoints (⚡ U+26A1, ✨ U+2728 — colour, width 2) from text-presentation
|
|
71
|
+
# dingbats that merely share a block (❤ U+2764, ✔ U+2714, ⚠ U+26A0 — width 1).
|
|
72
|
+
# Both properties derive from the same Unicode Emoji_Presentation flag, so
|
|
73
|
+
# this is not "width deciding colour": rather, colour is the subset of these
|
|
74
|
+
# blocks that is wide enough to render a square colour glyph without spilling
|
|
75
|
+
# into the next cell. Digits, '#', '*' are absent, so they stay ordinary text
|
|
76
|
+
# even though Noto maps colour keycaps.
|
|
51
77
|
EMOJI = [
|
|
52
78
|
0x231A..0x232A, 0x23E9..0x23F3, 0x25FD..0x27BF, 0x2B1B..0x2B55,
|
|
53
79
|
0x1F18E..0x1F19A, 0x1F200..0x1F265, 0x1F300..0x1F5A4, 0x1F5FB..0x1F6FC,
|
|
@@ -56,18 +82,22 @@ module CharWidth
|
|
|
56
82
|
|
|
57
83
|
module_function
|
|
58
84
|
|
|
59
|
-
# Number of terminal cells a codepoint occupies (1 or 2).
|
|
85
|
+
# Number of terminal cells a codepoint occupies (0, 1 or 2).
|
|
60
86
|
def width(cp)
|
|
61
|
-
return 1 if cp <
|
|
87
|
+
return 1 if cp < 0x0300 # fast path: ASCII/Latin-1 (no combining below)
|
|
88
|
+
return 0 if in_ranges?(ZERO, cp)
|
|
89
|
+
return 1 if cp < 0x1100 # fast path: most other text
|
|
62
90
|
in_ranges?(WIDE, cp) ? 2 : 1
|
|
63
91
|
end
|
|
64
92
|
|
|
65
93
|
def wide?(cp) = width(cp) == 2
|
|
66
94
|
|
|
67
95
|
# Whether a codepoint should render as a colour emoji (when the font has it).
|
|
96
|
+
# Gated to width-2 emoji: a colour glyph is rasterised square (~2 cells wide),
|
|
97
|
+
# so colouring a width-1 cell would overflow and corrupt the next column.
|
|
68
98
|
def emoji?(cp)
|
|
69
99
|
return false if cp < 0x231A
|
|
70
|
-
in_ranges?(EMOJI, cp)
|
|
100
|
+
in_ranges?(EMOJI, cp) && width(cp) == 2
|
|
71
101
|
end
|
|
72
102
|
|
|
73
103
|
# Binary search over a sorted array of non-overlapping ranges.
|
data/lib/rubyterm/version.rb
CHANGED
data/lib/term.rb
CHANGED
|
@@ -565,6 +565,11 @@ class Term
|
|
|
565
565
|
return if ch == 127 # DEL is ignored in the data stream
|
|
566
566
|
|
|
567
567
|
cw = CharWidth.width(ch)
|
|
568
|
+
# Zero-width codepoints (variation selectors like U+FE0F, combining marks,
|
|
569
|
+
# zero-width joiners) modify the preceding glyph. This buffer stores one
|
|
570
|
+
# codepoint per cell and can't compose, so drop them rather than letting
|
|
571
|
+
# them claim a cell of their own — which would paint over the next column.
|
|
572
|
+
return if cw == 0
|
|
568
573
|
# A double-width glyph can't straddle the right margin: if only one
|
|
569
574
|
# column is left, blank it and wrap so the glyph starts the next line.
|
|
570
575
|
if cw == 2 && @wraparound && @x == line_width - 1
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubyterm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vidar Hokstad
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-06-
|
|
11
|
+
date: 2026-06-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: pure-x11
|