v0.11.0 dc50343

locale.go RawHistoryFolder

1package environment
2
3import (
4	"log"
5	"os"
6	"os/exec"
7	"strings"
8)
9
10// DetectAndSetKeyboardLocale attempts to determine the current keyboard layout
11// and hints it to the webkit input layer for accelerator compatibility.
12func DetectAndSetKeyboardLocale() {
13	const colonSplitParts = 2 // Number of parts when splitting on colon
14
15	// 0) Explicit override
16	locale := os.Getenv("DUMBER_KEYBOARD_LOCALE")
17	if locale == "" {
18		locale = os.Getenv("DUMB_BROWSER_KEYBOARD_LOCALE") // legacy prefix
19	}
20	// 1) Environment
21	if locale == "" {
22		locale = os.Getenv("LC_ALL")
23	}
24	if locale == "" {
25		locale = os.Getenv("LANG")
26	}
27	if locale == "" {
28		locale = os.Getenv("LC_CTYPE")
29	}
30	// Trim variants
31	if i := strings.IndexByte(locale, '.'); i > 0 {
32		locale = locale[:i]
33	}
34	if i := strings.IndexByte(locale, '@'); i > 0 {
35		locale = locale[:i]
36	}
37	if i := strings.IndexByte(locale, '_'); i > 0 {
38		locale = locale[:i]
39	}
40
41	// 2) Try XKB env override
42	if locale == "" {
43		locale = os.Getenv("XKB_DEFAULT_LAYOUT")
44	}
45
46	// 3) Best-effort probe of setxkbmap/localectl (non-fatal)
47	if locale == "" {
48		if out, err := exec.Command("localectl", "status").Output(); err == nil {
49			s := string(out)
50			for _, line := range strings.Split(s, "\n") {
51				line = strings.TrimSpace(line)
52				if strings.HasPrefix(strings.ToLower(line), "x11 layout:") || strings.HasPrefix(strings.ToLower(line), "keyboard layout:") {
53					parts := strings.SplitN(line, ":", colonSplitParts)
54					if len(parts) == colonSplitParts {
55						cand := strings.TrimSpace(parts[1])
56						if cand != "" {
57							locale = cand
58						}
59					}
60					break
61				}
62			}
63		}
64	}
65	if locale == "" {
66		if out, err := exec.Command("setxkbmap", "-query").Output(); err == nil {
67			s := string(out)
68			for _, line := range strings.Split(s, "\n") {
69				line = strings.TrimSpace(line)
70				if strings.HasPrefix(strings.ToLower(line), "layout:") {
71					parts := strings.SplitN(line, ":", colonSplitParts)
72					if len(parts) == colonSplitParts {
73						cand := strings.TrimSpace(parts[1])
74						if cand != "" {
75							locale = cand
76						}
77					}
78					break
79				}
80			}
81		}
82	}
83
84	if locale == "" {
85		locale = "en"
86	}
87	// No layout-specific remaps; log for diagnostics only
88	log.Printf("[locale] keyboard locale detected: %s", locale)
89}

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