styles

package
v1.20.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 30, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const (
	AppPaddingLeft = 1 // Keep in sync with AppStyle padding

	// DoubleClickThreshold is the maximum time between clicks to register as a double-click
	DoubleClickThreshold = 400 * time.Millisecond
)

Base Styles

View Source
const DefaultThemeRef = "default"

DefaultThemeRef is the reference for the built-in default theme.

View Source
const UserThemePrefix = "user:"

UserThemePrefix is used to distinguish user themes from built-in themes when they have the same base name. A ref like "user:nord" refers to the user's custom nord theme, while "nord" refers to the built-in.

Variables

View Source
var (
	// Background colors
	Background    color.Color
	BackgroundAlt color.Color

	// Primary accent colors
	White    color.Color
	MobyBlue color.Color
	Accent   color.Color

	// Status colors
	Success   color.Color
	Error     color.Color
	Warning   color.Color
	Info      color.Color
	Highlight color.Color

	// Text hierarchy
	TextPrimary   color.Color
	TextSecondary color.Color
	TextMuted     color.Color
	TextMutedGray color.Color

	// Border colors
	BorderPrimary   color.Color
	BorderSecondary color.Color
	BorderMuted     color.Color
	BorderWarning   color.Color

	// Diff colors
	DiffAddBg    color.Color
	DiffRemoveBg color.Color
	DiffAddFg    color.Color
	DiffRemoveFg color.Color

	// UI element colors
	LineNumber color.Color
	Separator  color.Color

	// Interactive element colors
	Selected         color.Color
	SelectedFg       color.Color
	PlaceholderColor color.Color

	// Badge colors
	AgentBadgeFg color.Color
	AgentBadgeBg color.Color
	BadgePurple  color.Color
	BadgeCyan    color.Color
	BadgeGreen   color.Color

	// Error colors (extended)
	ErrorStrong color.Color
	ErrorDark   color.Color

	// Additional muted colors
	FadedGray color.Color

	// Tabs
	TabBg        color.Color
	TabPrimaryFg color.Color
	TabAccentFg  color.Color
)

Color variables - initialized by ApplyTheme() before TUI starts. These are set from the theme's YAML values (see themes/default.yaml for defaults).

View Source
var (
	NoStyle   = lipgloss.NewStyle()
	BaseStyle = NoStyle.Foreground(TextPrimary)
	AppStyle  = BaseStyle.Padding(0, 1, 0, AppPaddingLeft)
)
View Source
var (
	HighlightWhiteStyle = BaseStyle.Foreground(White).Bold(true)
	MutedStyle          = BaseStyle.Foreground(TextMutedGray)
	SecondaryStyle      = BaseStyle.Foreground(TextSecondary)
	BoldStyle           = BaseStyle.Bold(true)
	FadingStyle         = NoStyle.Foreground(FadedGray) // Very dim for fade-out animations (rebuilt by ApplyTheme)
)

Text Styles

View Source
var (
	SuccessStyle    = BaseStyle.Foreground(Success)
	ErrorStyle      = BaseStyle.Foreground(Error)
	WarningStyle    = BaseStyle.Foreground(Warning)
	InfoStyle       = BaseStyle.Foreground(Info)
	ActiveStyle     = BaseStyle.Foreground(Success)
	ToBeDoneStyle   = BaseStyle.Foreground(TextPrimary)
	InProgressStyle = BaseStyle.Foreground(Highlight)
	CompletedStyle  = BaseStyle.Foreground(TextMutedGray)
)

Status Styles

View Source
var (
	BaseMessageStyle = BaseStyle.
						Padding(1, 1).
						BorderLeft(true).
						BorderStyle(lipgloss.HiddenBorder()).
						BorderForeground(BorderPrimary)

	UserMessageStyle = BaseMessageStyle.
						BorderStyle(lipgloss.ThickBorder()).
						BorderForeground(BorderPrimary).
						Foreground(TextPrimary).
						Background(BackgroundAlt).
						Bold(true)

	AssistantMessageStyle = BaseMessageStyle.
							Padding(0, 1)

	WelcomeMessageStyle = BaseMessageStyle.
						BorderStyle(lipgloss.DoubleBorder()).
						Bold(true)

	ErrorMessageStyle = BaseMessageStyle.
						BorderStyle(lipgloss.ThickBorder()).
						Foreground(Error)

	SelectedMessageStyle = AssistantMessageStyle.
							BorderStyle(lipgloss.NormalBorder()).
							BorderForeground(Success)
)

Border Styles

View Source
var (
	DialogStyle = BaseStyle.
				Border(lipgloss.RoundedBorder()).
				BorderForeground(BorderSecondary).
				Foreground(TextPrimary).
				Padding(1, 2).
				Align(lipgloss.Left)

	DialogWarningStyle = BaseStyle.
						Border(lipgloss.RoundedBorder()).
						BorderForeground(BorderWarning).
						Foreground(TextPrimary).
						Padding(1, 2).
						Align(lipgloss.Left)

	DialogTitleStyle = BaseStyle.
						Bold(true).
						Foreground(TextSecondary).
						Align(lipgloss.Center)

	DialogTitleWarningStyle = BaseStyle.
							Bold(true).
							Foreground(Warning).
							Align(lipgloss.Center)

	DialogTitleInfoStyle = BaseStyle.
							Bold(true).
							Foreground(Info).
							Align(lipgloss.Center)

	DialogContentStyle = BaseStyle.
						Foreground(TextPrimary)

	DialogSeparatorStyle = BaseStyle.
							Foreground(BorderMuted)

	DialogQuestionStyle = BaseStyle.
						Bold(true).
						Foreground(TextPrimary).
						Align(lipgloss.Center)

	DialogOptionsStyle = BaseStyle.
						Foreground(TextMuted).
						Align(lipgloss.Center)

	DialogHelpStyle = BaseStyle.
					Foreground(TextMuted).
					Italic(true)

	TabTitleStyle = BaseStyle.
					Foreground(TabPrimaryFg)

	TabPrimaryStyle = BaseStyle.
					Foreground(TextPrimary)

	TabStyle = TabPrimaryStyle.
				Padding(1, 0)

	TabAccentStyle = BaseStyle.
					Foreground(TabAccentFg)
)

Dialog Styles

View Source
var (
	PaletteCategoryStyle = BaseStyle.
							Bold(true).
							Foreground(White).
							MarginTop(1)

	PaletteUnselectedActionStyle = BaseStyle.
									Foreground(TextPrimary).
									Bold(true)

	PaletteSelectedActionStyle = PaletteUnselectedActionStyle.
								Background(MobyBlue).
								Foreground(White)

	PaletteUnselectedDescStyle = BaseStyle.
								Foreground(TextSecondary)

	PaletteSelectedDescStyle = PaletteUnselectedDescStyle.
								Background(MobyBlue).
								Foreground(White)

	// Badge styles for model picker - use color vars set by ApplyTheme()
	BadgeAlloyStyle = BaseStyle.
					Foreground(BadgePurple)

	BadgeDefaultStyle = BaseStyle.
						Foreground(BadgeCyan)

	BadgeCurrentStyle = BaseStyle.
						Foreground(BadgeGreen)
)

Command Palette Styles - rebuilt by ApplyTheme()

View Source
var (
	StarredStyle   = BaseStyle.Foreground(Success)
	UnstarredStyle = BaseStyle.Foreground(TextMuted)
)

Star Styles for session browser and sidebar

View Source
var (
	DiffAddStyle = BaseStyle.
					Background(DiffAddBg).
					Foreground(DiffAddFg)

	DiffRemoveStyle = BaseStyle.
					Background(DiffRemoveBg).
					Foreground(DiffRemoveFg)

	DiffUnchangedStyle = BaseStyle.Background(BackgroundAlt)
)

Diff Styles (matching glamour markdown theme)

View Source
var (
	LineNumberStyle = BaseStyle.Foreground(LineNumber).Background(BackgroundAlt)
	SeparatorStyle  = BaseStyle.Foreground(Separator).Background(BackgroundAlt)
)

Syntax highlighting UI element styles

View Source
var (
	ToolMessageStyle = BaseStyle.
						Foreground(TextMutedGray)

	ToolErrorMessageStyle = BaseStyle.
							Foreground(ErrorStrong)

	ToolName = ToolMessageStyle.
				Foreground(TextMutedGray).
				Padding(0, 1)

	ToolNameError = ToolName.
					Foreground(ErrorStrong).
					Background(ErrorDark)

	ToolNameDim = ToolMessageStyle.
				Foreground(TextMutedGray).
				Italic(true)

	ToolDescription = ToolMessageStyle.
					Foreground(TextPrimary)

	ToolCompletedIcon = BaseStyle.
						MarginLeft(2).
						Foreground(TextMutedGray)

	ToolErrorIcon = ToolCompletedIcon.
					Background(ErrorStrong)

	ToolPendingIcon = ToolCompletedIcon.
					Background(Warning)

	ToolCallArgs = ToolMessageStyle.
					Padding(0, 0, 0, 2)

	ToolCallResult = ToolMessageStyle.
					Padding(0, 0, 0, 2)
)

Tool Call Styles

View Source
var (
	InputStyle = textarea.Styles{
		Focused: textarea.StyleState{
			Base:        BaseStyle,
			Placeholder: BaseStyle.Foreground(PlaceholderColor),
		},
		Blurred: textarea.StyleState{
			Base:        BaseStyle,
			Placeholder: BaseStyle.Foreground(PlaceholderColor),
		},
		Cursor: textarea.CursorStyle{
			Color: Accent,
		},
	}

	// DialogInputStyle is the style for textinput fields in dialogs,
	// matching the main editor's look (cursor color, text color).
	DialogInputStyle = textinput.Styles{
		Focused: textinput.StyleState{
			Text:        BaseStyle,
			Placeholder: BaseStyle.Foreground(PlaceholderColor),
		},
		Blurred: textinput.StyleState{
			Text:        BaseStyle,
			Placeholder: BaseStyle.Foreground(PlaceholderColor),
		},
		Cursor: textinput.CursorStyle{
			Color: Accent,
		},
	}
	EditorStyle = BaseStyle.Padding(1, 0, 0, 0)
	// SuggestionGhostStyle renders inline auto-complete hints in a muted tone.
	// Use a distinct grey so suggestion text is visually separate from the user's input.
	// NOTE: Rebuilt by ApplyTheme() using theme's suggestion_ghost color.
	SuggestionGhostStyle = BaseStyle.Foreground(TextMutedGray)
	// SuggestionCursorStyle renders the first character of a suggestion inside the cursor.
	// Uses the same blue accent background as the normal cursor, with ghost-colored foreground text.
	// NOTE: Rebuilt by ApplyTheme().
	SuggestionCursorStyle = BaseStyle.Background(Accent).Foreground(TextMutedGray)

	// Attachment banner styles - polished look with subtle border
	AttachmentBannerStyle = BaseStyle.
							Foreground(TextSecondary)

	AttachmentBadgeStyle = BaseStyle.
							Foreground(Info).
							Bold(true)

	AttachmentSizeStyle = BaseStyle.
						Foreground(TextMuted).
						Italic(true)

	AttachmentIconStyle = BaseStyle.
						Foreground(Info)
)

Input Styles

View Source
var (
	TrackStyle       = lipgloss.NewStyle().Foreground(BorderSecondary)
	ThumbStyle       = lipgloss.NewStyle().Foreground(Info).Background(BackgroundAlt).Bold(true)
	ThumbActiveStyle = lipgloss.NewStyle().Foreground(White).Background(BackgroundAlt).Bold(true)
)

Scrollbar

View Source
var (
	ResizeHandleStyle = BaseStyle.
						Foreground(BorderSecondary)

	ResizeHandleHoverStyle = BaseStyle.
							Foreground(Info).
							Bold(true)

	ResizeHandleActiveStyle = BaseStyle.
							Foreground(White).
							Bold(true)
)

Resize Handle Style

View Source
var (
	NotificationStyle = BaseStyle.
						Border(lipgloss.RoundedBorder()).
						BorderForeground(Success).
						Padding(0, 1)

	NotificationInfoStyle = BaseStyle.
							Border(lipgloss.RoundedBorder()).
							BorderForeground(Info).
							Padding(0, 1)

	NotificationWarningStyle = BaseStyle.
								Border(lipgloss.RoundedBorder()).
								BorderForeground(Warning).
								Padding(0, 1)

	NotificationErrorStyle = BaseStyle.
							Border(lipgloss.RoundedBorder()).
							BorderForeground(Error).
							Padding(0, 1)
)

Notification Styles

View Source
var (
	CompletionBoxStyle = BaseStyle.
						Border(lipgloss.RoundedBorder()).
						BorderForeground(BorderSecondary).
						Padding(0, 1)

	CompletionNormalStyle = BaseStyle.
							Foreground(TextPrimary).
							Bold(true)

	CompletionSelectedStyle = CompletionNormalStyle.
							Foreground(White).
							Background(MobyBlue)

	CompletionDescStyle = BaseStyle.
						Foreground(TextSecondary)

	CompletionSelectedDescStyle = CompletionDescStyle.
								Foreground(White).
								Background(MobyBlue)

	CompletionNoResultsStyle = BaseStyle.
								Foreground(TextMuted).
								Italic(true).
								Align(lipgloss.Center)
)

Completion Styles

View Source
var (
	AgentBadgeStyle = BaseStyle.
					Foreground(AgentBadgeFg).
					Background(AgentBadgeBg).
					Padding(0, 1)

	ThinkingBadgeStyle = BaseStyle.
						Foreground(TextMuted).
						Bold(true).
						Italic(true)
)

Agent and transfer badge styles

View Source
var (
	SpinnerDotsAccentStyle    = BaseStyle.Foreground(Accent)
	SpinnerDotsHighlightStyle = BaseStyle.Foreground(TabAccentFg)
	SpinnerTextBrightestStyle = BaseStyle.Foreground(Accent)
	SpinnerTextBrightStyle    = BaseStyle.Foreground(Accent)
	SpinnerTextDimStyle       = BaseStyle.Foreground(Accent)
	SpinnerTextDimmestStyle   = BaseStyle.Foreground(Accent)
)

Spinner Styles - rebuilt by ApplyTheme() with actual spinner colors from theme

View Source
var (
	CenterStyle = BaseStyle.Align(lipgloss.Center, lipgloss.Center)
)

Layout Styles

View Source
var (
	ChatStyle = BaseStyle
)

Deprecated styles (kept for backward compatibility)

View Source
var (
	SelectionStyle = BaseStyle.
		Background(Selected).
		Foreground(SelectedFg)
)

Selection Styles

Functions

func ApplyTheme added in v1.20.0

func ApplyTheme(theme *Theme)

ApplyTheme applies the given theme to all style variables. This updates all exported color and style variables in the styles package. After calling this, send ThemeChangedMsg to invalidate all TUI caches.

func ChromaStyle added in v1.8.2

func ChromaStyle() *chroma.Style

func GetPersistedThemeRef added in v1.20.0

func GetPersistedThemeRef() string

GetPersistedThemeRef returns the theme reference persisted in user config. Returns DefaultThemeRef if no theme is set or if loading fails.

func InvalidateThemeCache added in v1.20.0

func InvalidateThemeCache(ref string)

InvalidateThemeCache clears the theme cache for a specific ref, or all if ref is empty. This is primarily for testing; the cache is mtime-aware so it auto-invalidates on file changes.

func IsBuiltinTheme added in v1.20.0

func IsBuiltinTheme(ref string) bool

IsBuiltinTheme returns true if the given theme reference is a built-in theme. Refs prefixed with "user:" are always considered user themes, not built-in.

func ListThemeRefs added in v1.20.0

func ListThemeRefs() ([]string, error)

ListThemeRefs returns the list of available theme references. It includes all built-in themes (including "default") and user themes from ~/.cagent/themes/. User themes with names matching built-in themes are prefixed with "user:" to distinguish them. The "default" theme is always listed first for UX purposes.

func MarkdownStyle added in v1.8.2

func MarkdownStyle() ansi.StyleConfig

MarkdownStyle returns the markdown style configuration, deriving colors from the current theme.

func RenderComposite added in v1.8.2

func RenderComposite(style lipgloss.Style, content string) string

RenderComposite renders the content with the given style, but ensures that any ANSI reset codes in the content are replaced with the style's active sequences, preventing the style's background/foreground from being interrupted.

func SaveThemeToUserConfig added in v1.20.0

func SaveThemeToUserConfig(themeRef string) error

SaveThemeToUserConfig persists the theme reference to the user config file. If themeRef equals DefaultThemeRef, the setting is cleared (empty string).

func StarIndicator added in v1.18.4

func StarIndicator(starred bool) string

StarIndicator returns the styled star indicator for a given starred status

func ThemesDir added in v1.20.0

func ThemesDir() string

ThemesDir returns the directory where user themes are stored.

func UserThemeExists added in v1.20.0

func UserThemeExists(ref string) bool

UserThemeExists returns true if a user theme file exists for the given ref in the user themes directory (typically ~/.cagent/themes/).

This handles the "user:" prefix - "user:nord" checks for ~/.cagent/themes/nord.yaml.

Types

type ChromaColors added in v1.20.0

type ChromaColors struct {
	ErrorFg             string `yaml:"error_fg,omitempty"`
	ErrorBg             string `yaml:"error_bg,omitempty"`
	Success             string `yaml:"success,omitempty"`
	Comment             string `yaml:"comment,omitempty"`
	CommentPreproc      string `yaml:"comment_preproc,omitempty"`
	Keyword             string `yaml:"keyword,omitempty"`
	KeywordReserved     string `yaml:"keyword_reserved,omitempty"`
	KeywordNamespace    string `yaml:"keyword_namespace,omitempty"`
	KeywordType         string `yaml:"keyword_type,omitempty"`
	Operator            string `yaml:"operator,omitempty"`
	Punctuation         string `yaml:"punctuation,omitempty"`
	NameBuiltin         string `yaml:"name_builtin,omitempty"`
	NameTag             string `yaml:"name_tag,omitempty"`
	NameAttribute       string `yaml:"name_attribute,omitempty"`
	NameDecorator       string `yaml:"name_decorator,omitempty"`
	LiteralNumber       string `yaml:"literal_number,omitempty"`
	LiteralString       string `yaml:"literal_string,omitempty"`
	LiteralStringEscape string `yaml:"literal_string_escape,omitempty"`
	GenericDeleted      string `yaml:"generic_deleted,omitempty"`
	GenericSubheading   string `yaml:"generic_subheading,omitempty"`
	Background          string `yaml:"background,omitempty"`
}

ChromaColors contains syntax highlighting colors (for code blocks).

type MarkdownTheme added in v1.20.0

type MarkdownTheme struct {
	Heading    string `yaml:"heading,omitempty"`
	Link       string `yaml:"link,omitempty"`
	Strong     string `yaml:"strong,omitempty"`
	Code       string `yaml:"code,omitempty"`
	CodeBg     string `yaml:"code_bg,omitempty"`
	Blockquote string `yaml:"blockquote,omitempty"`
	List       string `yaml:"list,omitempty"`
	HR         string `yaml:"hr,omitempty"`
}

MarkdownTheme contains markdown-specific color overrides.

type Theme added in v1.20.0

type Theme struct {
	Version  int           `yaml:"version,omitempty"`
	Name     string        `yaml:"name,omitempty"`
	Ref      string        `yaml:"-"` // Set by loader, not from YAML
	Colors   ThemeColors   `yaml:"colors,omitempty"`
	Chroma   ChromaColors  `yaml:"chroma,omitempty"`
	Markdown MarkdownTheme `yaml:"markdown,omitempty"`
}

Theme represents a complete color theme for the TUI. All fields are optional; unset fields use the built-in defaults.

func CurrentTheme added in v1.20.0

func CurrentTheme() *Theme

CurrentTheme returns the currently applied theme, or the default if none applied.

func DefaultTheme added in v1.20.0

func DefaultTheme() *Theme

DefaultTheme returns the built-in default theme loaded from embedded default.yaml. The result is cached internally, but a copy is returned to prevent callers from accidentally modifying the cached theme.

func LoadTheme added in v1.20.0

func LoadTheme(ref string) (*Theme, error)

LoadTheme loads a theme by reference with mtime-aware caching. If ref is "" (empty), this is an error - caller should resolve to DefaultThemeRef first.

Refs starting with "user:" (e.g., "user:nord") explicitly load from user themes directory. Other refs load built-in themes first, falling back to user themes if no built-in exists.

The cache is mtime-aware: user themes are re-parsed only when the file's modTime changes. If a user theme file exists but fails to parse, an error is returned (no silent fallback).

type ThemeColors added in v1.20.0

type ThemeColors struct {
	// Text colors
	TextBright    string `yaml:"text_bright,omitempty"`    // Bright/emphasized text
	TextPrimary   string `yaml:"text_primary,omitempty"`   // Primary text
	TextSecondary string `yaml:"text_secondary,omitempty"` // Secondary text
	TextMuted     string `yaml:"text_muted,omitempty"`     // Muted/subtle text
	TextFaint     string `yaml:"text_faint,omitempty"`     // Very faint text/decorations

	// Accent colors
	Accent      string `yaml:"accent,omitempty"`       // Primary accent color
	AccentMuted string `yaml:"accent_muted,omitempty"` // Muted accent color

	// Background colors
	Background    string `yaml:"background,omitempty"`     // Main background
	BackgroundAlt string `yaml:"background_alt,omitempty"` // Alternate background (cards, panels)

	// Border colors
	BorderSecondary string `yaml:"border_secondary,omitempty"`

	// Status colors
	Success   string `yaml:"success,omitempty"`   // Success/positive state
	Error     string `yaml:"error,omitempty"`     // Error/negative state
	Warning   string `yaml:"warning,omitempty"`   // Warning state
	Info      string `yaml:"info,omitempty"`      // Info/neutral state
	Highlight string `yaml:"highlight,omitempty"` // Highlighted elements

	// Brand colors
	Brand   string `yaml:"brand,omitempty"`    // Primary brand color
	BrandBg string `yaml:"brand_bg,omitempty"` // Brand background

	// Error-specific colors
	ErrorStrong string `yaml:"error_strong,omitempty"` // Strong error emphasis
	ErrorDark   string `yaml:"error_dark,omitempty"`   // Dark error background

	// Spinner colors
	SpinnerDim       string `yaml:"spinner_dim,omitempty"`
	SpinnerBright    string `yaml:"spinner_bright,omitempty"`
	SpinnerBrightest string `yaml:"spinner_brightest,omitempty"`

	// Diff colors
	DiffAddBg    string `yaml:"diff_add_bg,omitempty"`
	DiffRemoveBg string `yaml:"diff_remove_bg,omitempty"`

	// UI element colors
	LineNumber      string `yaml:"line_number,omitempty"`
	Separator       string `yaml:"separator,omitempty"`
	Selected        string `yaml:"selected,omitempty"`
	SelectedFg      string `yaml:"selected_fg,omitempty"` // Text on selected/brand backgrounds
	SuggestionGhost string `yaml:"suggestion_ghost,omitempty"`
	TabBg           string `yaml:"tab_bg,omitempty"`
	Placeholder     string `yaml:"placeholder,omitempty"`

	// Badge colors
	BadgeAccent  string `yaml:"badge_accent,omitempty"`  // Accent badge (e.g., purple highlights)
	BadgeInfo    string `yaml:"badge_info,omitempty"`    // Info badge (e.g., cyan)
	BadgeSuccess string `yaml:"badge_success,omitempty"` // Success badge (e.g., green)
}

ThemeColors contains all color definitions for the TUI. Use hex color strings (e.g., "#7AA2F7") or ANSI color numbers (e.g., "39").

type ThemeWatcher added in v1.20.0

type ThemeWatcher struct {
	// contains filtered or unexported fields
}

ThemeWatcher watches the current theme file for changes and signals when the file is modified. It does NOT apply the theme directly to avoid race conditions with the TUI goroutine.

func NewThemeWatcher added in v1.20.0

func NewThemeWatcher(onThemeChanged func(themeRef string)) *ThemeWatcher

NewThemeWatcher creates a new theme watcher. The onThemeChanged callback is called whenever the theme file is modified. The callback receives the theme ref so the caller can load and apply the theme on the appropriate goroutine (e.g., the TUI main loop).

func (*ThemeWatcher) Stop added in v1.20.0

func (tw *ThemeWatcher) Stop()

Stop stops watching the current theme file.

func (*ThemeWatcher) Watch added in v1.20.0

func (tw *ThemeWatcher) Watch(themeRef string) error

Watch starts watching the theme file for the given theme reference. Only watches if a user theme file exists for this ref (in ~/.cagent/themes/). Handles "user:" prefix - e.g., "user:nord" watches ~/.cagent/themes/nord.yaml. If the theme is the built-in default or no user file exists, no watching occurs.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL