v0.5.0 31affde

rune_width.go RawHistoryFolder

1package core
2
3import "unicode"
4
5// RuneWidth returns the terminal cell width of a rune.
6//
7// Returns 0 for combining marks, zero-width characters, and control codes.
8// Returns 2 for CJK, fullwidth, and wide emoji characters.
9// Returns 1 for all other printable characters.
10//
11// Wide runes (width 2) occupy two grid cells: a left cell holding the rune and
12// a right continuation cell. Combining marks (Mn/Me) and zero-width joiner
13// sequences are out of scope: combining marks report width 0 (current
14// behavior), ZWJ sequences are not coalesced (each rune is measured on its own).
15func RuneWidth(r rune) int {
16	switch {
17	case r < 0x20 || r == 0x7F || (r >= 0x80 && r <= 0x9F):
18		return 0
19	// Soft hyphen, combining grapheme joiner, Arabic sign, etc.
20	case r == 0x00AD || r == 0x034F || r == 0x061C:
21		return 0
22	// Hangul Jungseong O/E, Hangul Jungseong Yu
23	case r == 0x115F || r == 0x1160:
24		return 0
25	// Balinese musical symbols
26	case r == 0x17B4 || r == 0x17B5:
27		return 0
28	// Mongolian variation selectors, free variation selector
29	case r == 0x180B || r == 0x180E || r == 0x200B || r == 0x200C || r == 0x200D || r == 0x200E || r == 0x200F:
30		return 0
31	// Line/paragraph separator, bidirectional overrides
32	case r >= 0x2028 && r <= 0x202E:
33		return 0
34	// Word joiner, invisible operators, Arabic/Syriac number marks, etc.
35	case r >= 0x2060 && r <= 0x206F:
36		return 0
37	case r == 0xFEFF || r == 0xFFF9 || r == 0xFFFA || r == 0xFFFB:
38		return 0
39	// Tags
40	case r >= 0xE0001 && r <= 0xE007F:
41		return 0
42	// Combining diacritical marks (Unicode categories Mn, Me)
43	case unicode.Is(unicode.Mn, r) || unicode.Is(unicode.Me, r):
44		return 0
45	// --- Wide characters (width 2) ---
46	// Hangul Jamo
47	case r >= 0x1100 && r <= 0x115F:
48		return 2
49	// Left/right-pointing angle bracket (for compatibility)
50	case r == 0x2329 || r == 0x232A:
51		return 2
52	// CJK Radicals Supplement, Kangxi Radicals, Ideographic Description
53	// CJK Symbols, Hiragana, Katakana, Bopomofo, Hangul Compatibility Jamo
54	// Kanbun, CJK Strokes, Enclosed CJK Letters
55	case r >= 0x2E80 && r <= 0x303E:
56		return 2
57	// Hiragana, Katakana, Bopomofo, Hangul Compatibility Jamo, Kanbun
58	case r >= 0x3040 && r <= 0x33FF:
59		return 2
60	// CJK Unified Ideographs Extension A
61	case r >= 0x3400 && r <= 0x4DBF:
62		return 2
63	// CJK Unified Ideographs, Yi Syllables, Yi Radicals
64	case r >= 0x4E00 && r <= 0xA4CF:
65		return 2
66	// Hangul Jamo Extended-A
67	case r >= 0xA960 && r <= 0xA97C:
68		return 2
69	// Hangul Syllables
70	case r >= 0xAC00 && r <= 0xD7AF:
71		return 2
72	// Hangul Jamo Extended-B
73	case r >= 0xD7B0 && r <= 0xD7FF:
74		return 2
75	// CJK Compatibility Ideographs
76	case r >= 0xF900 && r <= 0xFAFF:
77		return 2
78	// Vertical Forms
79	case r >= 0xFE10 && r <= 0xFE19:
80		return 2
81	// CJK Compatibility Forms
82	case r >= 0xFE30 && r <= 0xFE6F:
83		return 2
84	// Fullwidth Forms (variation selectors, fullwidth punctuation, etc.)
85	case r >= 0xFF01 && r <= 0xFF60:
86		return 2
87	// Fullwidth Signs (cent, pound, yen, won, etc.)
88	case r >= 0xFFE0 && r <= 0xFFE6:
89		return 2
90	// Kana Supplement
91	case r >= 0x1B000 && r <= 0x1B0FF:
92		return 2
93	// Kana Extended-A
94	case r >= 0x1B100 && r <= 0x1B12F:
95		return 2
96	// Mahjong Tiles, Domino Tiles, Playing Cards
97	case r >= 0x1F000 && r <= 0x1F09F:
98		return 2
99	// Miscellaneous Symbols and Pictographs, Emoticons, Ornamental Dingbats
100	case r >= 0x1F0A0 && r <= 0x1F64F:
101		return 2
102	// Transport and Map Symbols
103	case r >= 0x1F680 && r <= 0x1F6FF:
104		return 2
105	// Supplemental Symbols and Pictographs
106	case r >= 0x1F900 && r <= 0x1F9FF:
107		return 2
108	// Symbols and Pictographs Extended-A (emoji added in recent Unicode)
109	case r >= 0x1FA70 && r <= 0x1FAFF:
110		return 2
111	// CJK Unified Ideographs Extension B and beyond
112	case r >= 0x20000 && r <= 0x2FFFF:
113		return 2
114	// CJK Unified Ideographs Extension G and beyond
115	case r >= 0x30000 && r <= 0x3FFFF:
116		return 2
117	default:
118		return 1
119	}
120}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 2

Tags 13

↑↓ moveenter openesc close