Open-Source Wikis

/

fzf

/

Systems

/

Options and the action language

junegunn/fzf

Options and the action language

Purpose

src/options.go parses the command line, validates options, and exposes a populated Options struct that the rest of the program consumes. It also defines the action-language enum and the parsing rules for --bind. It's the largest single file in the codebase after src/terminal.go (~3,950 lines), and almost every user-visible feature touches it at some point.

Directory layout

src/
├── options.go               # The big one: ParseOptions, all flags, action types.
├── options_test.go
├── options_pprof.go         # Build tag: pprof. Adds --profile-* flags.
├── options_no_pprof.go      # Default build. Stub.
├── options_pprof_test.go
├── actiontype_string.go     # Generated by stringer.
└── constants.go             # ExitCodes, sizes, intervals.

Key abstractions

Symbol Description
Options Holds every parsed setting. Fields cover search, IO, display, key bindings, preview, popup, listen, walker, scoring scheme, etc.
ParseOptions(...) Top-level entry. Builds an Options from os.Args (or any []string).
Usage Multi-line const containing the help text printed by --help.
actionType An iota enum with 200+ values (actAccept, actAbort, actReload, actBecome, actChangePreview, ...). The string form is in the generated actiontype_string.go.
action A single instance of an action with optional argument (e.g. actExecute("rg {}")).
actionList An ordered list of actions chained via +.
Keymap map[tui.Event]actionList — the parsed --bind values.
parseKeyChords, parseKeymap Parse user-supplied bind strings.
parseAction, parseActionList Tokenize the action expression in a bind.
parsePlaceholder (in terminal.go) Pairs with the parsing here for placeholders inside action arguments.
BorderShape (re-used from tui) Validated by parseBorder.
walkerOpts Built-in file system walker config (file, dir, hidden, follow).
Tmux (struct) Position, size, and border for the --tmux popup.
Color / ColorTheme (re-used from tui) Validated by parseTheme.
Delimiter, Range (in tokenizer.go) Parsed for --nth, --with-nth, --accept-nth.

How it works

Parsing approach

Rather than using flag or a third-party library, ParseOptions is a hand-written iterator over the argument slice. It supports:

  • Long and short forms (--exact / -e, --ignore-case / -i).
  • --key=value and --key value.
  • Boolean inversion (--bold vs --no-bold, --mouse vs --no-mouse).
  • Composite flags whose value is a small DSL, parsed by dedicated helpers (--bind, --color, --style, --preview-window, --header-border, --info, --tmux, --listen, etc.).
  • Reading defaults from FZF_DEFAULT_OPTS and a file pointed at by FZF_DEFAULT_OPTS_FILE, before overlaying CLI args.

The parser is forgiving about ordering: FZF_DEFAULT_OPTS=--reverse fzf --no-reverse works as expected because the second pass overwrites.

The action language

A --bind value is a comma-separated list of event:action[+action]* pairs. For example:

--bind 'ctrl-r:reload(rg --files)+clear-query,enter:become(vim {}),change:first'

Events are either:

  • A key chord: ctrl-a, alt-up, f5, tab, shift-tab, enter, space, mouse events (click, right-click, double-click, scroll-up, scroll-down, etc.).
  • A named event: start, load, change, result, focus, one, zero, jump, jump-cancel, multi, backward-eof.
  • Bracketed paste boundaries.

Actions take optional arguments:

  • execute(...), execute-silent(...), become(...), reload(...), reload-sync(...), transform-query(...), transform-prompt(...), transform-header(...), transform-search(...), change-preview(...), change-prompt(...), change-query(...), put(...), pos(...), unbind(...), rebind(...), toggle-bind(...), etc.
  • The argument can use any delimiter that consistently brackets the value: reload(...) and reload:... both work.
  • + chains actions. They run in order; if one of them is accept or abort, the rest still execute up to the terminating action.

parseAction walks the value byte-by-byte to honor escapes, balanced parentheses, and shell-style quoting. The result is a []action.

The named action arguments interact with the placeholder language defined in src/terminal.go (see Terminal UI).

Lazy / transform-* options

A subset of options can be either:

  1. A literal value, e.g. --prompt='> ', --query='foo', --nth=2,3.
  2. A shell command whose stdout is read at runtime and treated as the value, via the matching transform-* action.

For example, --bind 'change:transform-prompt(echo "{q}> ")' recomputes the prompt every time the query changes. The mechanism is implemented inside terminal.go's action engine, but the wiring lives in options.go where the action token is parsed.

Build-tagged option families

When built without the pprof tag, options_no_pprof.go is compiled and the profile flags are no-ops. With -tags pprof, options_pprof.go provides real implementations using runtime/pprof. The user-visible flag list in Usage does not mention these unless the binary supports them — the Usage constant is shared and the implementation gates the actual behavior.

Validation

postProcessOptions (called from core.go) finalizes the Options: cross-flag consistency (e.g. --filter requires --no-sync?), defaults that depend on the terminal (--height only meaningful interactively), and --listen initialization (parses the address, generates an API key).

Integration points

  • From main.go: fzf.ParseOptions(true, os.Args[1:]) is called once.
  • To core.go: the populated *Options is passed to Run. Almost every field is used somewhere downstream.
  • To terminal.go: the action engine consumes Options.Keymap and the various per-action argument fields.
  • To server.go: the listen-mode body strings are parsed back into actions by re-using the same parseAction machinery.

Entry points for modification

  • New flag:
    1. Add a field to Options.
    2. Extend the parsing switch in ParseOptions.
    3. Document it in the Usage constant.
    4. Update man/man1/fzf.1 and CHANGELOG.md.
    5. Add tests in src/options_test.go (parsing) and test/*.rb (behavior).
  • New action:
    1. Add a constant to the actionType enum.
    2. make generate to refresh src/actiontype_string.go.
    3. Wire it in parseAction (so --bind 'enter:my-action(arg)' parses).
    4. Implement the behavior in src/terminal.go.
    5. Document and test as above.
  • New placeholder: see Terminal UI. Most placeholder work is in terminal.go; options.go only needs changes if the placeholder is recognized at parse time (rare).
  • Tweak default: changing a default has knock-on effects across Usage, the integration tests (which often pin the default in their expected output), and CHANGELOG.md.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Options and the action language – fzf wiki | Factory