detached 9631504

feat(config): add resize mode configuration

commit
9631504faadf0064d5283f8e4e17f2a91c43cd5e
author
brice · · 2025-12-26 07:03 UTC
parent
35136f8
signature
unsigned
3 files · +72 -6
M internal/infrastructure/config/defaults.go +36 -6
@@ -19,12 +19,16 @@ const (
1919 defaultOmniboxInitialBehavior = "recent"
2020
2121 // Workspace defaults
22- defaultPaneActivationShortcut = "ctrl+p"
23- defaultPaneTimeoutMilliseconds = 3000
24- defaultTabActivationShortcut = "ctrl+t"
25- defaultTabTimeoutMilliseconds = 3000
26- defaultTabBarPosition = "bottom"
27- defaultPopupPlacement = "right"
22+ defaultPaneActivationShortcut = "ctrl+p"
23+ defaultPaneTimeoutMilliseconds = 3000
24+ defaultTabActivationShortcut = "ctrl+t"
25+ defaultTabTimeoutMilliseconds = 3000
26+ defaultResizeActivationShortcut = "ctrl+n"
27+ defaultResizeTimeoutMilliseconds = 3000
28+ defaultResizeStepPercent = 5.0
29+ defaultResizeMinPanePercent = 10.0
30+ defaultTabBarPosition = "bottom"
31+ defaultPopupPlacement = "right"
2832
2933 // Session defaults
3034 defaultSessionActivationShortcut = "ctrl+o"
@@ -50,6 +54,10 @@ const (
5054 defaultSessionModeBorderWidth = 4
5155 defaultSessionModeBorderColor = "#9B59B6" // Purple for session mode indicator
5256
57+ // Resize mode border (Ctrl+N - overlay)
58+ defaultResizeModeBorderWidth = 4
59+ defaultResizeModeBorderColor = "#00D4AA" // Cyan/teal for resize mode indicator
60+
5361 // Other styling
5462 defaultTransitionDuration = 120
5563 defaultUIScale = 1.0 // UI scale multiplier (1.0 = 100%, 1.2 = 120%)
@@ -174,6 +182,26 @@ func DefaultConfig() *Config {
174182 "cancel": {"escape"},
175183 },
176184 },
185+ ResizeMode: ResizeModeConfig{
186+ ActivationShortcut: defaultResizeActivationShortcut,
187+ TimeoutMilliseconds: defaultResizeTimeoutMilliseconds,
188+ StepPercent: defaultResizeStepPercent,
189+ MinPanePercent: defaultResizeMinPanePercent,
190+ Actions: map[string][]string{
191+ "resize-increase-left": {"h", "arrowleft"},
192+ "resize-increase-down": {"j", "arrowdown"},
193+ "resize-increase-up": {"k", "arrowup"},
194+ "resize-increase-right": {"l", "arrowright"},
195+ "resize-decrease-left": {"H"},
196+ "resize-decrease-down": {"J"},
197+ "resize-decrease-up": {"K"},
198+ "resize-decrease-right": {"L"},
199+ "resize-increase": {"+", "="},
200+ "resize-decrease": {"-"},
201+ "confirm": {"enter"},
202+ "cancel": {"escape"},
203+ },
204+ },
177205 Shortcuts: GlobalShortcutsConfig{
178206 ClosePane: "ctrl+w",
179207 NextTab: "ctrl+tab",
@@ -199,6 +227,8 @@ func DefaultConfig() *Config {
199227 TabModeBorderColor: defaultTabModeBorderColor,
200228 SessionModeBorderWidth: defaultSessionModeBorderWidth,
201229 SessionModeBorderColor: defaultSessionModeBorderColor,
230+ ResizeModeBorderWidth: defaultResizeModeBorderWidth,
231+ ResizeModeBorderColor: defaultResizeModeBorderColor,
202232 TransitionDuration: defaultTransitionDuration,
203233 },
204234 },
@@ -19,12 +19,16 @@ const (
19 defaultOmniboxInitialBehavior = "recent"19 defaultOmniboxInitialBehavior = "recent"
20 20
21 // Workspace defaults21 // Workspace defaults
22- defaultPaneActivationShortcut = "ctrl+p"22+ defaultPaneActivationShortcut = "ctrl+p"
23- defaultPaneTimeoutMilliseconds = 300023+ defaultPaneTimeoutMilliseconds = 3000
24- defaultTabActivationShortcut = "ctrl+t"24+ defaultTabActivationShortcut = "ctrl+t"
25- defaultTabTimeoutMilliseconds = 300025+ defaultTabTimeoutMilliseconds = 3000
26- defaultTabBarPosition = "bottom"26+ defaultResizeActivationShortcut = "ctrl+n"
27- defaultPopupPlacement = "right"27+ defaultResizeTimeoutMilliseconds = 3000
28+ defaultResizeStepPercent = 5.0
29+ defaultResizeMinPanePercent = 10.0
30+ defaultTabBarPosition = "bottom"
31+ defaultPopupPlacement = "right"
28 32
29 // Session defaults33 // Session defaults
30 defaultSessionActivationShortcut = "ctrl+o"34 defaultSessionActivationShortcut = "ctrl+o"
@@ -50,6 +54,10 @@ const (
50 defaultSessionModeBorderWidth = 454 defaultSessionModeBorderWidth = 4
51 defaultSessionModeBorderColor = "#9B59B6" // Purple for session mode indicator55 defaultSessionModeBorderColor = "#9B59B6" // Purple for session mode indicator
52 56
57+ // Resize mode border (Ctrl+N - overlay)
58+ defaultResizeModeBorderWidth = 4
59+ defaultResizeModeBorderColor = "#00D4AA" // Cyan/teal for resize mode indicator
60+
53 // Other styling61 // Other styling
54 defaultTransitionDuration = 12062 defaultTransitionDuration = 120
55 defaultUIScale = 1.0 // UI scale multiplier (1.0 = 100%, 1.2 = 120%)63 defaultUIScale = 1.0 // UI scale multiplier (1.0 = 100%, 1.2 = 120%)
@@ -174,6 +182,26 @@ func DefaultConfig() *Config {
174 "cancel": {"escape"},182 "cancel": {"escape"},
175 },183 },
176 },184 },
185+ ResizeMode: ResizeModeConfig{
186+ ActivationShortcut: defaultResizeActivationShortcut,
187+ TimeoutMilliseconds: defaultResizeTimeoutMilliseconds,
188+ StepPercent: defaultResizeStepPercent,
189+ MinPanePercent: defaultResizeMinPanePercent,
190+ Actions: map[string][]string{
191+ "resize-increase-left": {"h", "arrowleft"},
192+ "resize-increase-down": {"j", "arrowdown"},
193+ "resize-increase-up": {"k", "arrowup"},
194+ "resize-increase-right": {"l", "arrowright"},
195+ "resize-decrease-left": {"H"},
196+ "resize-decrease-down": {"J"},
197+ "resize-decrease-up": {"K"},
198+ "resize-decrease-right": {"L"},
199+ "resize-increase": {"+", "="},
200+ "resize-decrease": {"-"},
201+ "confirm": {"enter"},
202+ "cancel": {"escape"},
203+ },
204+ },
177 Shortcuts: GlobalShortcutsConfig{205 Shortcuts: GlobalShortcutsConfig{
178 ClosePane: "ctrl+w",206 ClosePane: "ctrl+w",
179 NextTab: "ctrl+tab",207 NextTab: "ctrl+tab",
@@ -199,6 +227,8 @@ func DefaultConfig() *Config {
199 TabModeBorderColor: defaultTabModeBorderColor,227 TabModeBorderColor: defaultTabModeBorderColor,
200 SessionModeBorderWidth: defaultSessionModeBorderWidth,228 SessionModeBorderWidth: defaultSessionModeBorderWidth,
201 SessionModeBorderColor: defaultSessionModeBorderColor,229 SessionModeBorderColor: defaultSessionModeBorderColor,
230+ ResizeModeBorderWidth: defaultResizeModeBorderWidth,
231+ ResizeModeBorderColor: defaultResizeModeBorderColor,
202 TransitionDuration: defaultTransitionDuration,232 TransitionDuration: defaultTransitionDuration,
203 },233 },
204 },234 },
M internal/infrastructure/config/loader.go +7 -0
@@ -386,6 +386,11 @@ func (m *Manager) setWorkspaceDefaults(defaults *Config) {
386386 m.viper.SetDefault("workspace.tab_mode.activation_shortcut", defaults.Workspace.TabMode.ActivationShortcut)
387387 m.viper.SetDefault("workspace.tab_mode.timeout_ms", defaults.Workspace.TabMode.TimeoutMilliseconds)
388388 m.viper.SetDefault("workspace.tab_mode.actions", defaults.Workspace.TabMode.Actions)
389+ m.viper.SetDefault("workspace.resize_mode.activation_shortcut", defaults.Workspace.ResizeMode.ActivationShortcut)
390+ m.viper.SetDefault("workspace.resize_mode.timeout_ms", defaults.Workspace.ResizeMode.TimeoutMilliseconds)
391+ m.viper.SetDefault("workspace.resize_mode.step_percent", defaults.Workspace.ResizeMode.StepPercent)
392+ m.viper.SetDefault("workspace.resize_mode.min_pane_percent", defaults.Workspace.ResizeMode.MinPanePercent)
393+ m.viper.SetDefault("workspace.resize_mode.actions", defaults.Workspace.ResizeMode.Actions)
389394 m.viper.SetDefault("workspace.shortcuts.close_pane", defaults.Workspace.Shortcuts.ClosePane)
390395 m.viper.SetDefault("workspace.shortcuts.next_tab", defaults.Workspace.Shortcuts.NextTab)
391396 m.viper.SetDefault("workspace.shortcuts.previous_tab", defaults.Workspace.Shortcuts.PreviousTab)
@@ -406,6 +411,8 @@ func (m *Manager) setWorkspaceDefaults(defaults *Config) {
406411 m.viper.SetDefault("workspace.styling.tab_mode_border_color", defaults.Workspace.Styling.TabModeBorderColor)
407412 m.viper.SetDefault("workspace.styling.session_mode_border_width", defaults.Workspace.Styling.SessionModeBorderWidth)
408413 m.viper.SetDefault("workspace.styling.session_mode_border_color", defaults.Workspace.Styling.SessionModeBorderColor)
414+ m.viper.SetDefault("workspace.styling.resize_mode_border_width", defaults.Workspace.Styling.ResizeModeBorderWidth)
415+ m.viper.SetDefault("workspace.styling.resize_mode_border_color", defaults.Workspace.Styling.ResizeModeBorderColor)
409416 m.viper.SetDefault("workspace.styling.transition_duration", defaults.Workspace.Styling.TransitionDuration)
410417 }
411418
@@ -386,6 +386,11 @@ func (m *Manager) setWorkspaceDefaults(defaults *Config) {
386 m.viper.SetDefault("workspace.tab_mode.activation_shortcut", defaults.Workspace.TabMode.ActivationShortcut)386 m.viper.SetDefault("workspace.tab_mode.activation_shortcut", defaults.Workspace.TabMode.ActivationShortcut)
387 m.viper.SetDefault("workspace.tab_mode.timeout_ms", defaults.Workspace.TabMode.TimeoutMilliseconds)387 m.viper.SetDefault("workspace.tab_mode.timeout_ms", defaults.Workspace.TabMode.TimeoutMilliseconds)
388 m.viper.SetDefault("workspace.tab_mode.actions", defaults.Workspace.TabMode.Actions)388 m.viper.SetDefault("workspace.tab_mode.actions", defaults.Workspace.TabMode.Actions)
389+ m.viper.SetDefault("workspace.resize_mode.activation_shortcut", defaults.Workspace.ResizeMode.ActivationShortcut)
390+ m.viper.SetDefault("workspace.resize_mode.timeout_ms", defaults.Workspace.ResizeMode.TimeoutMilliseconds)
391+ m.viper.SetDefault("workspace.resize_mode.step_percent", defaults.Workspace.ResizeMode.StepPercent)
392+ m.viper.SetDefault("workspace.resize_mode.min_pane_percent", defaults.Workspace.ResizeMode.MinPanePercent)
393+ m.viper.SetDefault("workspace.resize_mode.actions", defaults.Workspace.ResizeMode.Actions)
389 m.viper.SetDefault("workspace.shortcuts.close_pane", defaults.Workspace.Shortcuts.ClosePane)394 m.viper.SetDefault("workspace.shortcuts.close_pane", defaults.Workspace.Shortcuts.ClosePane)
390 m.viper.SetDefault("workspace.shortcuts.next_tab", defaults.Workspace.Shortcuts.NextTab)395 m.viper.SetDefault("workspace.shortcuts.next_tab", defaults.Workspace.Shortcuts.NextTab)
391 m.viper.SetDefault("workspace.shortcuts.previous_tab", defaults.Workspace.Shortcuts.PreviousTab)396 m.viper.SetDefault("workspace.shortcuts.previous_tab", defaults.Workspace.Shortcuts.PreviousTab)
@@ -406,6 +411,8 @@ func (m *Manager) setWorkspaceDefaults(defaults *Config) {
406 m.viper.SetDefault("workspace.styling.tab_mode_border_color", defaults.Workspace.Styling.TabModeBorderColor)411 m.viper.SetDefault("workspace.styling.tab_mode_border_color", defaults.Workspace.Styling.TabModeBorderColor)
407 m.viper.SetDefault("workspace.styling.session_mode_border_width", defaults.Workspace.Styling.SessionModeBorderWidth)412 m.viper.SetDefault("workspace.styling.session_mode_border_width", defaults.Workspace.Styling.SessionModeBorderWidth)
408 m.viper.SetDefault("workspace.styling.session_mode_border_color", defaults.Workspace.Styling.SessionModeBorderColor)413 m.viper.SetDefault("workspace.styling.session_mode_border_color", defaults.Workspace.Styling.SessionModeBorderColor)
414+ m.viper.SetDefault("workspace.styling.resize_mode_border_width", defaults.Workspace.Styling.ResizeModeBorderWidth)
415+ m.viper.SetDefault("workspace.styling.resize_mode_border_color", defaults.Workspace.Styling.ResizeModeBorderColor)
409 m.viper.SetDefault("workspace.styling.transition_duration", defaults.Workspace.Styling.TransitionDuration)416 m.viper.SetDefault("workspace.styling.transition_duration", defaults.Workspace.Styling.TransitionDuration)
410 }417 }
411 418
M internal/infrastructure/config/schema.go +29 -0
@@ -299,6 +299,8 @@ type WorkspaceConfig struct {
299299 PaneMode PaneModeConfig `mapstructure:"pane_mode" yaml:"pane_mode" toml:"pane_mode" json:"pane_mode"`
300300 // TabMode defines modal tab behavior and bindings (Alt+T).
301301 TabMode TabModeConfig `mapstructure:"tab_mode" yaml:"tab_mode" toml:"tab_mode" json:"tab_mode"`
302+ // ResizeMode defines modal pane resizing behavior and bindings (Ctrl+N).
303+ ResizeMode ResizeModeConfig `mapstructure:"resize_mode" yaml:"resize_mode" toml:"resize_mode" json:"resize_mode"`
302304 // Shortcuts holds global (non-modal) keyboard shortcuts.
303305 Shortcuts GlobalShortcutsConfig `mapstructure:"shortcuts" yaml:"shortcuts" toml:"shortcuts" json:"shortcuts"`
304306 // TabBarPosition determines tab bar placement: "top" or "bottom".
@@ -349,6 +351,27 @@ func (t *TabModeConfig) GetKeyBindings() map[string]string {
349351 return keyToAction
350352 }
351353
354+// ResizeModeConfig defines modal behavior for resizing panes (Zellij-style).
355+type ResizeModeConfig struct {
356+ ActivationShortcut string `mapstructure:"activation_shortcut" yaml:"activation_shortcut" toml:"activation_shortcut" json:"activation_shortcut"` //nolint:lll // struct tags must stay on one line
357+ TimeoutMilliseconds int `mapstructure:"timeout_ms" yaml:"timeout_ms" toml:"timeout_ms" json:"timeout_ms"`
358+ StepPercent float64 `mapstructure:"step_percent" yaml:"step_percent" toml:"step_percent" json:"step_percent"`
359+ MinPanePercent float64 `mapstructure:"min_pane_percent" yaml:"min_pane_percent" toml:"min_pane_percent" json:"min_pane_percent"` //nolint:lll // struct tags must stay on one line
360+ Actions map[string][]string `mapstructure:"actions" yaml:"actions" toml:"actions" json:"actions"`
361+}
362+
363+// GetKeyBindings returns an inverted map for O(1) key→action lookup.
364+// This is built from the action→keys structure in the config.
365+func (r *ResizeModeConfig) GetKeyBindings() map[string]string {
366+ keyToAction := make(map[string]string)
367+ for action, keys := range r.Actions {
368+ for _, key := range keys {
369+ keyToAction[key] = action
370+ }
371+ }
372+ return keyToAction
373+}
374+
352375 // GlobalShortcutsConfig defines global shortcuts (always active, not modal).
353376 type GlobalShortcutsConfig struct {
354377 ClosePane string `mapstructure:"close_pane" yaml:"close_pane" toml:"close_pane" json:"close_pane"`
@@ -422,6 +445,12 @@ type WorkspaceStylingConfig struct {
422445 // Defaults to "#9B59B6" (purple) if not set - MUST be different from other mode colors
423446 SessionModeBorderColor string `mapstructure:"session_mode_border_color" yaml:"session_mode_border_color" toml:"session_mode_border_color" json:"session_mode_border_color"` //nolint:lll // struct tags must stay on one line
424447
448+ // ResizeModeBorderWidth in pixels for resize mode indicator border (Ctrl+N overlay)
449+ ResizeModeBorderWidth int `mapstructure:"resize_mode_border_width" yaml:"resize_mode_border_width" toml:"resize_mode_border_width" json:"resize_mode_border_width"` //nolint:lll // struct tags must stay on one line
450+ // ResizeModeBorderColor for the resize mode indicator border (CSS color value or theme variable)
451+ // Defaults to "#00D4AA" (cyan/teal) if not set - MUST be different from other mode colors
452+ ResizeModeBorderColor string `mapstructure:"resize_mode_border_color" yaml:"resize_mode_border_color" toml:"resize_mode_border_color" json:"resize_mode_border_color"` //nolint:lll // struct tags must stay on one line
453+
425454 // TransitionDuration in milliseconds for border animations
426455 TransitionDuration int `mapstructure:"transition_duration" yaml:"transition_duration" toml:"transition_duration" json:"transition_duration"` //nolint:lll // struct tags must stay on one line
427456 }
@@ -299,6 +299,8 @@ type WorkspaceConfig struct {
299 PaneMode PaneModeConfig `mapstructure:"pane_mode" yaml:"pane_mode" toml:"pane_mode" json:"pane_mode"`299 PaneMode PaneModeConfig `mapstructure:"pane_mode" yaml:"pane_mode" toml:"pane_mode" json:"pane_mode"`
300 // TabMode defines modal tab behavior and bindings (Alt+T).300 // TabMode defines modal tab behavior and bindings (Alt+T).
301 TabMode TabModeConfig `mapstructure:"tab_mode" yaml:"tab_mode" toml:"tab_mode" json:"tab_mode"`301 TabMode TabModeConfig `mapstructure:"tab_mode" yaml:"tab_mode" toml:"tab_mode" json:"tab_mode"`
302+ // ResizeMode defines modal pane resizing behavior and bindings (Ctrl+N).
303+ ResizeMode ResizeModeConfig `mapstructure:"resize_mode" yaml:"resize_mode" toml:"resize_mode" json:"resize_mode"`
302 // Shortcuts holds global (non-modal) keyboard shortcuts.304 // Shortcuts holds global (non-modal) keyboard shortcuts.
303 Shortcuts GlobalShortcutsConfig `mapstructure:"shortcuts" yaml:"shortcuts" toml:"shortcuts" json:"shortcuts"`305 Shortcuts GlobalShortcutsConfig `mapstructure:"shortcuts" yaml:"shortcuts" toml:"shortcuts" json:"shortcuts"`
304 // TabBarPosition determines tab bar placement: "top" or "bottom".306 // TabBarPosition determines tab bar placement: "top" or "bottom".
@@ -349,6 +351,27 @@ func (t *TabModeConfig) GetKeyBindings() map[string]string {
349 return keyToAction351 return keyToAction
350 }352 }
351 353
354+// ResizeModeConfig defines modal behavior for resizing panes (Zellij-style).
355+type ResizeModeConfig struct {
356+ ActivationShortcut string `mapstructure:"activation_shortcut" yaml:"activation_shortcut" toml:"activation_shortcut" json:"activation_shortcut"` //nolint:lll // struct tags must stay on one line
357+ TimeoutMilliseconds int `mapstructure:"timeout_ms" yaml:"timeout_ms" toml:"timeout_ms" json:"timeout_ms"`
358+ StepPercent float64 `mapstructure:"step_percent" yaml:"step_percent" toml:"step_percent" json:"step_percent"`
359+ MinPanePercent float64 `mapstructure:"min_pane_percent" yaml:"min_pane_percent" toml:"min_pane_percent" json:"min_pane_percent"` //nolint:lll // struct tags must stay on one line
360+ Actions map[string][]string `mapstructure:"actions" yaml:"actions" toml:"actions" json:"actions"`
361+}
362+
363+// GetKeyBindings returns an inverted map for O(1) key→action lookup.
364+// This is built from the action→keys structure in the config.
365+func (r *ResizeModeConfig) GetKeyBindings() map[string]string {
366+ keyToAction := make(map[string]string)
367+ for action, keys := range r.Actions {
368+ for _, key := range keys {
369+ keyToAction[key] = action
370+ }
371+ }
372+ return keyToAction
373+}
374+
352 // GlobalShortcutsConfig defines global shortcuts (always active, not modal).375 // GlobalShortcutsConfig defines global shortcuts (always active, not modal).
353 type GlobalShortcutsConfig struct {376 type GlobalShortcutsConfig struct {
354 ClosePane string `mapstructure:"close_pane" yaml:"close_pane" toml:"close_pane" json:"close_pane"`377 ClosePane string `mapstructure:"close_pane" yaml:"close_pane" toml:"close_pane" json:"close_pane"`
@@ -422,6 +445,12 @@ type WorkspaceStylingConfig struct {
422 // Defaults to "#9B59B6" (purple) if not set - MUST be different from other mode colors445 // Defaults to "#9B59B6" (purple) if not set - MUST be different from other mode colors
423 SessionModeBorderColor string `mapstructure:"session_mode_border_color" yaml:"session_mode_border_color" toml:"session_mode_border_color" json:"session_mode_border_color"` //nolint:lll // struct tags must stay on one line446 SessionModeBorderColor string `mapstructure:"session_mode_border_color" yaml:"session_mode_border_color" toml:"session_mode_border_color" json:"session_mode_border_color"` //nolint:lll // struct tags must stay on one line
424 447
448+ // ResizeModeBorderWidth in pixels for resize mode indicator border (Ctrl+N overlay)
449+ ResizeModeBorderWidth int `mapstructure:"resize_mode_border_width" yaml:"resize_mode_border_width" toml:"resize_mode_border_width" json:"resize_mode_border_width"` //nolint:lll // struct tags must stay on one line
450+ // ResizeModeBorderColor for the resize mode indicator border (CSS color value or theme variable)
451+ // Defaults to "#00D4AA" (cyan/teal) if not set - MUST be different from other mode colors
452+ ResizeModeBorderColor string `mapstructure:"resize_mode_border_color" yaml:"resize_mode_border_color" toml:"resize_mode_border_color" json:"resize_mode_border_color"` //nolint:lll // struct tags must stay on one line
453+
425 // TransitionDuration in milliseconds for border animations454 // TransitionDuration in milliseconds for border animations
426 TransitionDuration int `mapstructure:"transition_duration" yaml:"transition_duration" toml:"transition_duration" json:"transition_duration"` //nolint:lll // struct tags must stay on one line455 TransitionDuration int `mapstructure:"transition_duration" yaml:"transition_duration" toml:"transition_duration" json:"transition_duration"` //nolint:lll // struct tags must stay on one line
427 }456 }

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