trail-fm 1.11.2

A terminal-first workspace for navigating, inspecting and acting on the filesystem
Documentation
# Trail default configuration.

[general]
editor = "nvim"
# Shell that runs `!<command>` and `:git`: a program, then the flags that make
# it read a command string as one argument.  Empty keeps the platform default
# -- `cmd.exe /C` on Windows, `sh -c` elsewhere -- which is what Trail has
# always used, so leaving this alone changes nothing.
#
# Set it to pick a different interpreter, e.g. `pwsh -NoProfile -Command` on
# Windows so that `./program` and other POSIX-ish spellings resolve (cmd.exe
# reads a leading `/` as a switch and fails on `./program`), or `bash -c` to
# get bash syntax instead of whatever `sh` is on this system.  The trade-off is
# startup cost per command -- pwsh is markedly slower to launch than cmd.exe,
# and `-NoProfile` is what keeps that from getting worse -- and that shell
# builtins stop matching the ones your muscle memory expects.
#
# Whitespace separates tokens; double-quote a program path containing spaces.
# Windows paths need a TOML literal string, e.g.
# shell = '"C:\Program Files\PowerShell\7\pwsh.exe" -NoProfile -Command'
shell = ""
# Whether to wait for Enter after a `!<command>` or `:git` finishes, before
# Trail takes the screen back: always | on_error | never.
#
# A command's output is printed on the normal screen, which Trail covers again
# the moment the command exits -- so without a pause, `!ls` paints its output and
# erases it in the same breath.  The trade-off is a keystroke per command: set
# `on_error` to be held up only when something failed, or `never` if you run
# commands for their effect rather than their output and would rather read them
# in the log.  Opening a file in the editor never pauses whatever this says --
# an editor owns the screen while it runs and leaves nothing behind to read.
shell_pause = "always"
# How much of a file the preview reads, in KiB.  Together with
# `[preview] max_lines` this bounds one preview: max_lines stops an ordinary
# file, this stops one whose lines are enormous -- minified JavaScript, a
# one-line JSON blob -- which would otherwise be loaded whole however few lines
# it has.  Either ceiling marks the pane's footer with a `+`.  Raising it lets
# you scroll further into such a file, at proportionally more worker time and
# memory per preview.  The name is historical: it once chose which files were
# highlighted on the UI thread, which none are now.
text_sync_threshold_kb = 256
# Where `dd` sends an entry: trash | permanent.
#
# `trash` hands it to the platform's recycle bin, so a mistake is recoverable by
# the user without Trail's help -- and `dd` on a directory takes everything under
# it, which is exactly the mistake worth being able to undo.  The trade-offs are
# that deleting no longer frees the space until the bin is emptied, and that a
# path the recycle bin refuses (a network share, a removable volume without one)
# is reported as an error rather than silently deleted anyway.  Use `permanent`
# for the old behaviour, and read the confirmation prompt: it says which one is
# about to happen.
delete_mode = "trash"
# Show Trail's version on the preview pane's top border.
#
# A diagnostic, not decoration: `trail --version` cannot be asked of a session
# that is already running, and on Windows an upgrade leaves older sessions alive
# on the previous binary -- they cannot be overwritten, only renamed aside -- so
# several windows can be running different builds and look identical.  Turn this
# on when that matters; it costs the right-hand end of a border that is drawn
# either way, and it is hidden when a long file name needs the room.
# A dev build reads `v1.10.1-dev.3+f7863b6` (3 commits past v1.10.1, at that
# commit, `.dirty` if built with uncommitted changes) in the git_dirty colour,
# so a build under test is never mistaken for a release.
show_version = false
git_status_enabled = true
fs_watch_debounce_ms = 200

[navigation]
# How the listing is ordered: name | size | modified | extension.
#
# `size` puts the largest first and `modified` the most recent first, the way
# `ls -S` and `ls -t` do -- the end of the range you went looking for.  `name`
# and `extension` run A-Z.  `sort_reverse` flips whichever of those is active.
#
# This seeds the first tab only.  Each tab then owns its order, so `ss` in a
# downloads tab does not re-sort the source tree in the next one, and a new tab
# inherits the order of the tab it was opened from.
sort_by = "name"
sort_reverse = false
# Group directories ahead of files whatever `sort_by` says.  This is an axis of
# its own: `sort_reverse` does not flip it, because reversing a listing is
# asking for the files in the other order, not for the directories to move to
# the bottom.  Set false to rank directories among the files -- though note that
# a directory has no meaningful size, so a size sort keeps them in name order
# either way.
dirs_first = true
# What each row shows beside the name: none | size | modified | both.
#
# The navigation panel is 40% of the screen -- 28 columns on an 80-column
# terminal -- and `both` wants 26 of them, so the column stands down rather than
# crushing names when there is not room for a readable name beside it.  On a
# narrow panel `both` first drops the clock time and keeps the date.  Default is
# `none`: the name is what you navigate by, and the preview pane already shows
# size and modification time for whatever is selected.
entry_details = "none"
# Rows kept between the selection and the top or bottom of the panel while
# scrolling -- vim's `scrolloff`.  The margin gives up at the true ends of the
# listing, so the first entry still reaches the top row and the last entry the
# bottom one.  0 lets the selection ride the edge, which shows the least context
# and scrolls the most.  A value larger than half the panel keeps the selection
# centred.
scroll_margin = 3

[preview]
# Inline-image protocol: auto | kitty | iterm2 | sixel | halfblocks | none
image_protocol = "auto"
# Terminal character cell size in pixels.  0 detects it where the platform will
# say (never on Windows) and otherwise assumes a deliberately small default, so
# that an image errs towards leaving a margin rather than overflowing the pane
# and being dropped by the terminal.  Set a real measurement to fill the pane
# exactly: lower these if images overflow, raise them if images look too small.
image_cell_width = 0
image_cell_height = 0
# How many lines of a text file the preview loads.  The preview scrolls within
# this window (J/K, Shift-arrows, Ctrl-f/Ctrl-b) and its footer marks a file
# that continues past it with a "+".  Raising this lets you scroll further into
# long files, at proportionally more worker time and memory per preview; the
# accepted range is 1 to 100000.
max_lines = 2000

[terminal]
# The terminal panel: real, interactive shells under the file list.  Ctrl-.
# shows and hides it, F12 moves the keyboard between the file list and the
# shell; `:term new [profile]`, `:term close`, `:term <n>` and `:term max` do
# the rest.  Nothing starts until the panel is first opened.
#
# Which profile a new shell runs.  Blank means the first [[terminal.profile]],
# or -- with none configured -- PowerShell 7 if installed, else Windows
# PowerShell (on Linux/macOS: $SHELL).
default_profile = ""
# The panel's height as a percentage of the screen above the status bar, 10-90.
# A screen too short for both the file list and the panel gives the panel all
# of it.  `:term max` fills the screen and restores it.
height = 35
# Whether quitting Trail, and `:term close`, ask before ending shells:
#   when_busy -- only if a shell is running a command (default).  Trail tells by
#                whether the shell has child processes; when it cannot tell, it
#                asks, rather than risk ending a build.
#   always    -- every time there is a shell to end.
#   never     -- end them at once, whatever they are doing.
confirm_quit = "when_busy"
confirm_close = "when_busy"
# Named shells.  `command` is the program and its arguments, run directly (no
# shell parses it, so nothing in it is expanded).  For example:
#
#   [[terminal.profile]]
#   name = "pwsh"
#   command = ["pwsh.exe", "-NoLogo"]
#
#   [[terminal.profile]]
#   name = "gitbash"
#   command = ['C:\Program Files\Git\bin\bash.exe', "--login", "-i"]
#
# Listing profiles in your own config replaces this empty list.
profile = []

[theme]
foreground = "white"
background = "black"
border = "dark_gray"
selection_fg = "black"
selection_bg = "dark_gray"
directory = "blue"
symlink = "cyan"
hidden = "dark_gray"
status_fg = "dark_gray"
error = "red"
search = "yellow"
command = "cyan"
git_clean = "green"
git_dirty = "yellow"

[keymap.navigation]
move_down = "j"
move_up = "k"
jump_bottom = "G"
jump_top = "gg"
enter_or_open = "l"
go_parent = "h"
history_back = "u"
history_forward = "ctrl-r"
# Return from a jump: back to where the last :jump was made from, however far
# you wandered after it landed.  u steps back one directory at a time; U skips
# everything since the jump.
return_from_jump = "U"
refresh = "R"
toggle_hidden = "."
# Listing order, per tab.  `s` is a prefix rather than a binding of its own, so
# the second key picks the field: name, size, time, extension.  `sr` flips the
# order and `sd` toggles directory grouping.
sort_name = "sn"
sort_size = "ss"
sort_time = "st"
sort_extension = "se"
sort_reverse = "sr"
sort_dirs_first = "sd"
# Step the details column through none -> size -> modified -> both -> none.
toggle_details = "m"
copy_absolute_path = "ya"
copy_relative_path = "yr"
copy_filename = "yn"
copy_content = "yc"
delete = "dd"
# Marks survive navigation: mark here, paste somewhere else.  Space marks the
# selection and moves down; Esc clears every mark (it does nothing else in
# Navigation Mode, so nothing is lost by giving it this job).
toggle_mark = "space"
clear_marks = "esc"
# Paste the marked entries into the directory you are looking at.  `p` is a
# prefix: pp copies (the marks stay, so the same set can be pasted again), pm
# moves (the moved entries leave the mark set).  A name already taken here is
# skipped and reported, never overwritten.
paste_copy = "pp"
paste_move = "pm"
# Visual mode: v anchors a range at the selection, and moving extends it.
# Space or v adds the range to the marks, h/l add it and then navigate, dd
# deletes it, Esc abandons it.
enter_visual = "v"
# Repeat the last file operation: a : or ! command, or dd, pp or pm, whichever
# came last (a repeated dd still asks).  Moving and marking never replace it.  @ works
# however your layout types it: Shift+2 on US English, AltGr+Q on Spanish and
# Latin American, AltGr+Q on German.
repeat_command = "@"
enter_search = "/"
enter_command = ":"
quit = "q"
open_with_os = "o"
new_tab = "ctrl-t"
close_tab = "ctrl-w"
switch_tab_next = "tab"
switch_tab_prev = "shift-tab"
# Preview pane scrolling.  Shift-down and Shift-up are built-in aliases for the
# first two, the same way the plain arrows alias move_down/move_up.
preview_scroll_down = "J"
preview_scroll_up = "K"
preview_page_down = "ctrl-f"
preview_page_up = "ctrl-b"
preview_scroll_top = "shift-home"
preview_scroll_bottom = "shift-end"

[keymap.search]
# Search Mode is a typing mode: unmodified characters go into the query, so
# these must be named or modified keys.  Binding a bare letter here is a
# config error -- it would make that letter impossible to search for.
# Ctrl-n / Ctrl-p / Ctrl-h also work as built-in aliases.
exit = "esc"
confirm = "enter"
move_down = "down"
move_up = "up"
delete_char = "backspace"

[keymap.terminal]
# The terminal panel's keys.  Each is one chord -- ctrl-, alt-, shift- plus a
# character or a key name (f1-f12, pageup, pagedown, home, end, insert, delete,
# enter, esc, tab, space, arrows).
#
# toggle and focus work from anywhere.  The other four are taken only while the
# shell has the keyboard, and every key here is one no program in the shell can
# receive -- which is why they avoid everything shells, vim and Windows Terminal
# already use.  F12 in particular is used by none of them.  The four PageUp /
# PageDown keys carry Alt because terminals keep Ctrl- and Shift-PageUp for
# themselves (WezTerm switches tabs and scrolls its own window with them), so
# Trail would never see them.
toggle = "ctrl-."
focus = "f12"
next_shell = "alt-shift-pagedown"
prev_shell = "alt-shift-pageup"
scroll_up = "alt-pageup"
scroll_down = "alt-pagedown"

[plugins]
enabled = []