v0.15.0 9006957

locale.go RawHistoryFolder

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

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