v0.14.1 0da30ba

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	var locale string
16
17	// 0) Explicit override
18	locale = os.Getenv("DUMBER_KEYBOARD_LOCALE")
19	if locale == "" {
20		locale = os.Getenv("DUMB_BROWSER_KEYBOARD_LOCALE") // legacy prefix
21	}
22
23	// 1) XKB env override (actual keyboard layout)
24	if locale == "" {
25		locale = os.Getenv("XKB_DEFAULT_LAYOUT")
26	}
27
28	// 2) Best-effort probe of localectl/setxkbmap (actual keyboard layout)
29	// Check these BEFORE LANG since LANG is system language, not keyboard layout
30	if locale == "" {
31		if out, err := exec.Command("localectl", "status").Output(); err == nil {
32			s := string(out)
33			for _, line := range strings.Split(s, "\n") {
34				line = strings.TrimSpace(line)
35				if strings.HasPrefix(strings.ToLower(line), "x11 layout:") || strings.HasPrefix(strings.ToLower(line), "keyboard layout:") {
36					parts := strings.SplitN(line, ":", colonSplitParts)
37					if len(parts) == colonSplitParts {
38						cand := strings.TrimSpace(parts[1])
39						if cand != "" {
40							locale = cand
41							log.Printf("[locale] keyboard layout from localectl: %s", locale)
42						}
43					}
44					break
45				}
46			}
47		}
48	}
49	if locale == "" {
50		if out, err := exec.Command("setxkbmap", "-query").Output(); err == nil {
51			s := string(out)
52			for _, line := range strings.Split(s, "\n") {
53				line = strings.TrimSpace(line)
54				if strings.HasPrefix(strings.ToLower(line), "layout:") {
55					parts := strings.SplitN(line, ":", colonSplitParts)
56					if len(parts) == colonSplitParts {
57						cand := strings.TrimSpace(parts[1])
58						if cand != "" {
59							locale = cand
60							log.Printf("[locale] keyboard layout from setxkbmap: %s", locale)
61						}
62					}
63					break
64				}
65			}
66		}
67	}
68
69	// 3) Fallback to system locale (language, not keyboard layout)
70	if locale == "" {
71		locale = os.Getenv("LC_ALL")
72	}
73	if locale == "" {
74		locale = os.Getenv("LANG")
75	}
76	if locale == "" {
77		locale = os.Getenv("LC_CTYPE")
78	}
79	// Trim variants from locale
80	if locale != "" {
81		if i := strings.IndexByte(locale, '.'); i > 0 {
82			locale = locale[:i]
83		}
84		if i := strings.IndexByte(locale, '@'); i > 0 {
85			locale = locale[:i]
86		}
87		if i := strings.IndexByte(locale, '_'); i > 0 {
88			locale = locale[:i]
89		}
90		log.Printf("[locale] keyboard layout from system locale: %s", locale)
91	}
92
93	if locale == "" {
94		locale = "en"
95		log.Printf("[locale] keyboard layout defaulted to: %s", locale)
96	}
97
98	log.Printf("[locale] keyboard locale detected: %s", locale)
99}

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