v0.28.0 3cb3770

defaults.go RawHistoryFolder

1package config
2
3// Default configuration constants
4const (
5	// History defaults
6	defaultMaxHistoryEntries = 10000 // entries
7	defaultRetentionDays     = 365   // 1 year
8
9	// Dmenu defaults
10	defaultMaxHistoryDays = 30 // days
11
12	// Logging defaults
13	defaultMaxLogAgeDays = 7 // days
14
15	// Appearance defaults
16	defaultFontSize = 16 // points
17
18	// Workspace defaults
19	defaultNewPaneURL = "about:blank"
20
21	// Omnibox defaults
22	defaultOmniboxInitialBehavior   = "recent"
23	defaultOmniboxAutoOpenOnNewPane = false
24
25	// Workspace defaults
26	defaultPaneActivationShortcut    = "ctrl+p"
27	defaultPaneTimeoutMilliseconds   = 3000
28	defaultTabActivationShortcut     = "ctrl+t"
29	defaultTabTimeoutMilliseconds    = 3000
30	defaultResizeActivationShortcut  = "ctrl+n"
31	defaultResizeTimeoutMilliseconds = 3000
32	defaultResizeStepPercent         = 5.0
33	defaultResizeMinPanePercent      = 10.0
34	defaultTabBarPosition            = "bottom"
35	defaultPopupPlacement            = "right"
36	defaultFloatingPaneWidthPct      = 0.82
37	defaultFloatingPaneHeightPct     = 0.72
38
39	// Session defaults
40	defaultSessionActivationShortcut  = "ctrl+o"
41	defaultSessionTimeoutMilliseconds = 3000
42	defaultSnapshotIntervalMs         = 5000
43	defaultMaxExitedSessions          = 50
44	defaultMaxExitedSessionAgeDays    = 7
45
46	// Workspace styling defaults
47	// Active pane border (overlay)
48	defaultBorderWidth = 1
49	defaultBorderColor = "@theme_selected_bg_color"
50
51	// Mode border width (consolidated for all modes)
52	defaultModeBorderWidth = 4
53
54	// Mode colors (used for both borders and toaster)
55	defaultPaneModeColor    = "#4A90E2" // Blue for pane mode
56	defaultTabModeColor     = "#FFA500" // Orange for tab mode
57	defaultSessionModeColor = "#9B59B6" // Purple for session mode
58	defaultResizeModeColor  = "#00D4AA" // Cyan/teal for resize mode
59
60	// Mode indicator toaster
61	defaultModeIndicatorToasterEnabled = true
62
63	// Other styling
64	defaultTransitionDuration = 120
65	defaultUIScale            = 1.0 // UI scale multiplier (1.0 = 100%, 1.2 = 120%)
66
67	// Performance defaults
68	defaultZoomCacheSize           = 256 // domains to cache (~20KB memory)
69	defaultWebViewPoolPrewarmCount = 4   // WebViews to pre-create at startup
70
71	// Skia threading defaults (0 = unset, -1 = unset for GPU threads)
72	defaultSkiaCPUPaintingThreads = 0
73	defaultSkiaGPUPaintingThreads = -1 // -1 means unset; 0 would disable GPU tile painting
74)
75
76// getDefaultLogDir returns the default log directory, falls back to empty string on error
77func getDefaultLogDir() string {
78	logDir, err := GetLogDir()
79	if err != nil {
80		return ""
81	}
82	return logDir
83}
84
85// DefaultConfig returns the default configuration values for dumber.
86func DefaultConfig() *Config {
87	return &Config{
88		Database: DatabaseConfig{
89			// Path is set dynamically in config.Load()
90		},
91		History: HistoryConfig{
92			MaxEntries:          defaultMaxHistoryEntries,
93			RetentionPeriodDays: defaultRetentionDays, // 1 year
94			CleanupIntervalDays: 1,                    // daily cleanup
95		},
96		SearchShortcuts:     GetDefaultSearchShortcuts(),
97		DefaultSearchEngine: "https://duckduckgo.com/?q=%s",
98		Dmenu: DmenuConfig{
99			MaxHistoryDays:   defaultMaxHistoryDays,
100			ShowVisitCount:   true,
101			ShowLastVisited:  true,
102			HistoryPrefix:    "🕒",
103			ShortcutPrefix:   "🔍",
104			URLPrefix:        "🌐",
105			DateFormat:       "2006-01-02 15:04",
106			SortByVisitCount: true,
107		},
108		Logging: LoggingConfig{
109			Level:          "info",
110			Format:         "text", // text or json
111			MaxAge:         defaultMaxLogAgeDays,
112			LogDir:         getDefaultLogDir(),
113			EnableFileLog:  true,
114			CaptureConsole: false, // Disabled by default
115			CaptureGTKLogs: false, // Disabled by default
116		},
117		Appearance: AppearanceConfig{
118			SansFont:        "Fira Sans",
119			SerifFont:       "Fira Sans",
120			MonospaceFont:   "Fira Code",
121			DefaultFontSize: defaultFontSize,
122			LightPalette: ColorPalette{
123				Background:     "#fafafa",
124				Surface:        "#f4f4f5",
125				SurfaceVariant: "#e4e4e7",
126				Text:           "#18181b",
127				Muted:          "#71717a",
128				Accent:         "#22c55e", // Green-500 - vibrant primary
129				Border:         "#d4d4d8",
130			},
131			DarkPalette: ColorPalette{
132				Background:     "#0a0a0b",
133				Surface:        "#18181b",
134				SurfaceVariant: "#27272a",
135				Text:           "#fafafa",
136				Muted:          "#a1a1aa",
137				Accent:         "#4ade80", // Green-400 - vibrant primary
138				Border:         "#3f3f46",
139			},
140			ColorScheme: "default", // default follows system theme
141		},
142		Debug: DebugConfig{
143			EnableDevTools: true,
144		},
145		Engine: EngineConfig{
146			Type:             "webkit",
147			Profile:          ProfileDefault,
148			PoolPrewarmCount: defaultWebViewPoolPrewarmCount,
149			ZoomCacheSize:    defaultZoomCacheSize,
150			// With ITP enabled, WebKit ignores ACCEPT_NO_THIRD_PARTY — ITP handles
151			// third-party cookie isolation more intelligently. Using Always + ITP
152			// matches Epiphany's model and avoids a misleading setting.
153			CookiePolicy: CookiePolicyAlways,
154			WebKit: WebKitEngineConfig{
155				ITPEnabled:             true,
156				SkiaCPUPaintingThreads: defaultSkiaCPUPaintingThreads,
157				SkiaGPUPaintingThreads: defaultSkiaGPUPaintingThreads,
158				GSKRenderer:            GSKRendererAuto,
159				GLRenderingMode:        GLRenderingModeAuto,
160			},
161		},
162		DefaultWebpageZoom: 1.2,            // 120% default zoom for better readability
163		DefaultUIScale:     defaultUIScale, // 1.0 = 100%, 2.0 = 200%
164		Workspace: WorkspaceConfig{
165			NewPaneURL:        defaultNewPaneURL,
166			SwitchToTabOnMove: true,
167			PaneMode: PaneModeConfig{
168				ActivationShortcut:  defaultPaneActivationShortcut,
169				TimeoutMilliseconds: defaultPaneTimeoutMilliseconds,
170				Actions: map[string]ActionBinding{
171					"split-right":           {Keys: []string{"arrowright", "r"}, Desc: "Split pane to the right"},
172					"split-left":            {Keys: []string{"arrowleft", "l"}, Desc: "Split pane to the left"},
173					"split-up":              {Keys: []string{"arrowup", "u"}, Desc: "Split pane upward"},
174					"split-down":            {Keys: []string{"arrowdown", "d"}, Desc: "Split pane downward"},
175					"stack-pane":            {Keys: []string{"s"}, Desc: "Stack pane with sibling"},
176					"close-pane":            {Keys: []string{"x"}, Desc: "Close current pane"},
177					"move-pane-to-tab":      {Keys: []string{"m"}, Desc: "Move pane to different tab"},
178					"move-pane-to-next-tab": {Keys: []string{"M", "shift+m"}, Desc: "Move pane to next tab"},
179
180					"consume-or-expel-left":  {Keys: []string{"["}, Desc: "Consume/expel pane left"},
181					"consume-or-expel-right": {Keys: []string{"]"}, Desc: "Consume/expel pane right"},
182					"consume-or-expel-up":    {Keys: []string{"{"}, Desc: "Consume/expel pane up"},
183					"consume-or-expel-down":  {Keys: []string{"}"}, Desc: "Consume/expel pane down"},
184
185					"focus-right": {Keys: []string{"shift+arrowright", "shift+l"}, Desc: "Focus pane to the right"},
186					"focus-left":  {Keys: []string{"shift+arrowleft", "shift+h"}, Desc: "Focus pane to the left"},
187					"focus-up":    {Keys: []string{"shift+arrowup", "shift+k"}, Desc: "Focus pane above"},
188					"focus-down":  {Keys: []string{"shift+arrowdown", "shift+j"}, Desc: "Focus pane below"},
189					"confirm":     {Keys: []string{"enter"}, Desc: "Confirm action"},
190					"cancel":      {Keys: []string{"escape"}, Desc: "Cancel/exit mode"},
191				},
192			},
193			TabMode: TabModeConfig{
194				ActivationShortcut:  defaultTabActivationShortcut,
195				TimeoutMilliseconds: defaultTabTimeoutMilliseconds,
196				Actions: map[string]ActionBinding{
197					"new-tab":      {Keys: []string{"n", "c"}, Desc: "Create new tab"},
198					"close-tab":    {Keys: []string{"x"}, Desc: "Close current tab"},
199					"next-tab":     {Keys: []string{"l", "tab"}, Desc: "Switch to next tab"},
200					"previous-tab": {Keys: []string{"h", "shift+tab"}, Desc: "Switch to previous tab"},
201					"rename-tab":   {Keys: []string{"r"}, Desc: "Rename current tab"},
202					"confirm":      {Keys: []string{"enter"}, Desc: "Confirm action"},
203					"cancel":       {Keys: []string{"escape"}, Desc: "Cancel/exit mode"},
204				},
205			},
206			ResizeMode: ResizeModeConfig{
207				ActivationShortcut:  defaultResizeActivationShortcut,
208				TimeoutMilliseconds: defaultResizeTimeoutMilliseconds,
209				StepPercent:         defaultResizeStepPercent,
210				MinPanePercent:      defaultResizeMinPanePercent,
211				Actions: map[string]ActionBinding{
212					"resize-increase-left":  {Keys: []string{"h", "arrowleft"}, Desc: "Increase size leftward"},
213					"resize-increase-down":  {Keys: []string{"j", "arrowdown"}, Desc: "Increase size downward"},
214					"resize-increase-up":    {Keys: []string{"k", "arrowup"}, Desc: "Increase size upward"},
215					"resize-increase-right": {Keys: []string{"l", "arrowright"}, Desc: "Increase size rightward"},
216					"resize-decrease-left":  {Keys: []string{"H"}, Desc: "Decrease size leftward"},
217					"resize-decrease-down":  {Keys: []string{"J"}, Desc: "Decrease size downward"},
218					"resize-decrease-up":    {Keys: []string{"K"}, Desc: "Decrease size upward"},
219					"resize-decrease-right": {Keys: []string{"L"}, Desc: "Decrease size rightward"},
220					"resize-increase":       {Keys: []string{"+", "="}, Desc: "Increase pane size"},
221					"resize-decrease":       {Keys: []string{"-"}, Desc: "Decrease pane size"},
222					"confirm":               {Keys: []string{"enter"}, Desc: "Confirm action"},
223					"cancel":                {Keys: []string{"escape"}, Desc: "Cancel/exit mode"},
224				},
225			},
226			Shortcuts: GlobalShortcutsConfig{
227				Actions: map[string]ActionBinding{
228					"toggle_floating_pane":   {Keys: []string{"alt+f"}, Desc: "Toggle floating pane"},
229					"close_pane":             {Keys: []string{"ctrl+w"}, Desc: "Close active pane"},
230					"next_tab":               {Keys: []string{"ctrl+tab"}, Desc: "Switch to next tab"},
231					"previous_tab":           {Keys: []string{"ctrl+shift+tab"}, Desc: "Switch to previous tab"},
232					"consume_or_expel_left":  {Keys: []string{"alt+["}, Desc: "Consume/expel pane left"},
233					"consume_or_expel_right": {Keys: []string{"alt+]"}, Desc: "Consume/expel pane right"},
234					"consume_or_expel_up":    {Keys: []string{"alt+{"}, Desc: "Consume/expel pane up"},
235					"consume_or_expel_down":  {Keys: []string{"alt+}"}, Desc: "Consume/expel pane down"},
236				},
237			},
238			FloatingPane: FloatingPaneConfig{
239				WidthPct:  defaultFloatingPaneWidthPct,
240				HeightPct: defaultFloatingPaneHeightPct,
241				Profiles:  map[string]FloatingPaneProfile{},
242			},
243			TabBarPosition:          defaultTabBarPosition,
244			HideTabBarWhenSingleTab: true,
245			Popups: PopupBehaviorConfig{
246				Behavior:             PopupBehaviorSplit, // Default: open JavaScript popups in split panes
247				Placement:            defaultPopupPlacement,
248				OpenInNewPane:        true,
249				FollowPaneContext:    true,
250				BlankTargetBehavior:  "stacked", // Default: open _blank links in stacked mode
251				EnableSmartDetection: true,      // Use WindowProperties to detect popup vs tab
252				OAuthAutoClose:       true,      // Auto-close OAuth popups on success
253			},
254			Styling: WorkspaceStylingConfig{
255				BorderWidth:                 defaultBorderWidth,
256				BorderColor:                 defaultBorderColor,
257				ModeBorderWidth:             defaultModeBorderWidth,
258				PaneModeColor:               defaultPaneModeColor,
259				TabModeColor:                defaultTabModeColor,
260				SessionModeColor:            defaultSessionModeColor,
261				ResizeModeColor:             defaultResizeModeColor,
262				ModeIndicatorToasterEnabled: defaultModeIndicatorToasterEnabled,
263				TransitionDuration:          defaultTransitionDuration,
264			},
265		},
266		ContentFiltering: ContentFilteringConfig{
267			Enabled:    true, // Ad blocking enabled by default
268			AutoUpdate: true, // Auto-update filters from GitHub releases
269		},
270		Clipboard: ClipboardConfig{
271			AutoCopyOnSelection: true, // Enabled by default (zellij-style)
272		},
273		Omnibox: OmniboxConfig{
274			InitialBehavior:   defaultOmniboxInitialBehavior,
275			AutoOpenOnNewPane: defaultOmniboxAutoOpenOnNewPane,
276		},
277		Session: SessionConfig{
278			AutoRestore:             false,
279			SnapshotIntervalMs:      defaultSnapshotIntervalMs,
280			MaxExitedSessions:       defaultMaxExitedSessions,
281			MaxExitedSessionAgeDays: defaultMaxExitedSessionAgeDays,
282			SessionMode: SessionModeConfig{
283				ActivationShortcut:  defaultSessionActivationShortcut,
284				TimeoutMilliseconds: defaultSessionTimeoutMilliseconds,
285				Actions: map[string]ActionBinding{
286					"session-manager": {Keys: []string{"s", "w"}, Desc: "Open session manager"},
287					"confirm":         {Keys: []string{"enter"}, Desc: "Confirm action"},
288					"cancel":          {Keys: []string{"escape"}, Desc: "Cancel/exit mode"},
289				},
290			},
291		},
292		Media: MediaConfig{
293			HardwareDecodingMode:     HardwareDecodingAuto, // auto allows sw fallback
294			PreferAV1:                false,                // Don't force codec preference, let site choose
295			ShowDiagnosticsOnStartup: false,                // Disabled - diagnostics can be noisy
296			// GStreamer fields (ForceVSync, GLRenderingMode, GStreamerDebugLevel)
297			// moved to [engine.webkit] — zero values here prevent them from being
298			// written back when marshaling the Config struct.
299		},
300		Update: UpdateConfig{
301			EnableOnStartup:     true,  // Check for updates on startup by default
302			AutoDownload:        false, // Conservative: don't auto-download by default
303			NotifyOnNewSettings: true,  // Show toast when new config settings available
304		},
305		Downloads: DownloadsConfig{
306			Path: "", // Empty = use XDG_DOWNLOAD_DIR or ~/Downloads
307		},
308	}
309}
310
311// GetDefaultSearchShortcuts returns the default search shortcuts.
312func GetDefaultSearchShortcuts() map[string]SearchShortcut {
313	return map[string]SearchShortcut{
314		"ddg": {
315			URL:         "https://duckduckgo.com/?q=%s",
316			Description: "DuckDuckGo search",
317		},
318		"g": {
319			URL:         "https://www.google.com/search?q=%s",
320			Description: "Google search",
321		},
322		"gi": {
323			URL:         "https://www.google.com/search?tbm=isch&q=%s",
324			Description: "Google Images search",
325		},
326		"gh": {
327			URL:         "https://github.com/search?q=%s",
328			Description: "GitHub search",
329		},
330		"go": {
331			URL:         "https://pkg.go.dev/search?q=%s",
332			Description: "Go package search",
333		},
334		"mdn": {
335			URL:         "https://developer.mozilla.org/en-US/search?q=%s",
336			Description: "MDN Web Docs search",
337		},
338		"npm": {
339			URL:         "https://www.npmjs.com/search?q=%s",
340			Description: "npm package search",
341		},
342		"r": {
343			URL:         "https://www.reddit.com/search?q=%s",
344			Description: "Reddit search",
345		},
346		"so": {
347			URL:         "https://stackoverflow.com/search?q=%s",
348			Description: "Stack Overflow search",
349		},
350		"w": {
351			URL:         "https://en.wikipedia.org/wiki/%s",
352			Description: "Wikipedia search",
353		},
354		"yt": {
355			URL:         "https://www.youtube.com/results?search_query=%s",
356			Description: "YouTube search",
357		},
358	}
359}

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