main 5041353

vimkeys_bridge.go RawHistoryFolder

1package input
2
3import (
4	"strings"
5
6	"github.com/bnema/dumber/internal/domain/vimkeys"
7	"github.com/bnema/puregotk/v4/gdk"
8)
9
10// namedKeyvalSym maps a GDK named keyval onto a canonical vimkeys symbol.
11// Immutable switch mirrors Phase 1 parser quality (no mutable package map).
12func namedKeyvalSym(keyval uint) (string, bool) {
13	switch keyval {
14	case uint(gdk.KEY_Escape):
15		return "Esc", true
16	case uint(gdk.KEY_Return), uint(gdk.KEY_KP_Enter):
17		return "CR", true
18	case uint(gdk.KEY_Tab), uint(gdk.KEY_ISO_Left_Tab):
19		return "Tab", true
20	case uint(gdk.KEY_BackSpace):
21		return "BackSpace", true
22	case uint(gdk.KEY_space):
23		return "Space", true
24	case uint(gdk.KEY_Left):
25		return "Left", true
26	case uint(gdk.KEY_Right):
27		return "Right", true
28	case uint(gdk.KEY_Up):
29		return "Up", true
30	case uint(gdk.KEY_Down):
31		return "Down", true
32	case uint(gdk.KEY_Home):
33		return "Home", true
34	case uint(gdk.KEY_End):
35		return "End", true
36	case uint(gdk.KEY_Page_Up):
37		return "PageUp", true
38	case uint(gdk.KEY_Page_Down):
39		return "PageDown", true
40	case uint(gdk.KEY_Delete):
41		return "Delete", true
42	default:
43		return "", false
44	}
45}
46
47// KeyvalToVimKey converts a GDK key event into a vimkeys.Key.
48// Named keys keep modifiers. Printable non-letter glyphs drop Shift because the
49// glyph already encodes it; Ctrl and Alt are preserved.
50func KeyvalToVimKey(keyval uint, state gdk.ModifierType) (vimkeys.Key, bool) {
51	mods := vimModsFromState(state)
52	if sym, ok := namedKeyvalSym(keyval); ok {
53		return vimkeys.Key{Sym: sym, Mods: mods}, true
54	}
55
56	r := rune(keyvalToUnicode(keyval))
57	if r == 0 || r < 0x20 {
58		return vimkeys.Key{}, false
59	}
60	if r >= 'A' && r <= 'Z' {
61		return vimkeys.Key{Sym: strings.ToLower(string(r)), Mods: mods}, true
62	}
63	if r >= 'a' && r <= 'z' {
64		return vimkeys.Key{Sym: string(r), Mods: mods}, true
65	}
66	return vimkeys.Key{Sym: string(r), Mods: mods &^ vimkeys.ModShift}, true
67}
68
69func vimModsFromState(state gdk.ModifierType) vimkeys.Mods {
70	var mods vimkeys.Mods
71	if state&gdk.ControlMaskValue != 0 {
72		mods |= vimkeys.ModCtrl
73	}
74	if state&gdk.ShiftMaskValue != 0 {
75		mods |= vimkeys.ModShift
76	}
77	if state&gdk.AltMaskValue != 0 {
78		mods |= vimkeys.ModAlt
79	}
80	return mods
81}
82
83// keyvalToUnicode mirrors gdk_keyval_to_unicode for Latin-1 graphic keysyms
84// (identity mapping) and falls back to GDK for the remaining keyvals.
85func keyvalToUnicode(keyval uint) uint32 {
86	// ASCII graphic and Latin-1 supplement keysyms share Unicode code points.
87	if keyval >= 0x20 && keyval <= 0x7e {
88		return uint32(keyval)
89	}
90	if keyval >= 0xa0 && keyval <= 0xff {
91		return uint32(keyval)
92	}
93	return gdk.KeyvalToUnicode(keyval)
94}

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 8

Tags 42

↑↓ moveenter openesc close