preen # auto: diffs in a git repo, else markdown
preen md [DIR] # browse markdown files under DIR (default .)
preen diff [REV] # browse files changed vs REV (default: working tree)
preen FILE.md # render one file, paged, and quit
... | preen # render piped input and quit
preen - < FILE # the same, said out loud
preen with no argument asks git one question — am I inside a work tree? —
and picks diff if the answer is yes and md if it is no.
preen md — browse markdownpreen md # every .md under the current directory
preen md docs/ # under docs/ instead
It finds every .md and .markdown file below the directory you name,
skipping .git/ and node_modules/, and sorts them. The file list is on the
left; glow renders the file under the cursor on the right.
preen diff — browse changespreen diff # everything not committed yet
preen diff main # everything that differs from main
preen diff HEAD~3 # ...or from three commits ago
With no revision, the list is what git diff --name-only HEAD reports plus
your untracked files, sorted and de-duplicated. That means staged and
unstaged changes appear together — you see the file as it will land, not one
half of it.
An untracked file has nothing to diff against, so preen shows the whole file as one large addition rather than skipping it.
In a repository with no commit yet there is no HEAD to compare with, so it
falls back to the index.
With a revision, the list is exactly git diff --name-only REV.
preen FILE.md — render one filepreen README.md
No picker and no fzf. On a terminal the render is paged through less -R, so
it stays on screen until you press q. That matters in a split pane opened
only to read a file: without a pager the command ends the moment the last line
is written, and the pane closes with it.
Into a pipe there is no pager, so preen NOTES.md | head behaves. The output
keeps its color codes, which a terminal shows as color and a paste does not —
see the last bullet below.
The wheel scrolls the page, because preen adds --mouse when your less
knows it (551 and up). While less holds the mouse, though, it is less
receiving the clicks rather than the terminal — so a plain drag no longer
selects text.
Three ways around it:
prefix + [. This is the one to reach for. Copy mode moves and
selects from the keyboard, the wheel scrolls the buffer, and — the part that
matters in a split — it selects within the pane.less and from tmux,
so the terminal makes the selection, and a terminal knows nothing about
panes. In a split you get a rectangle across the whole screen, with the
neighboring pane's text spliced into every line. Fine in a single pane,
usually wrong in a split.pbcopy < NOTES.md puts the markdown on the clipboard. Piping
the render instead does not work. Out of a terminal preen still writes the
color codes, so preen NOTES.md | pbcopy pastes them as [38;2;…m noise,
not as color, and preen NOTES.md > out.txt keeps them in the file, which
only less -R out.txt shows the way it looked.less keeps its own keys throughout: / to search, g and G for the ends,
q to quit.
Any file is treated as markdown here, whatever its extension. There is no
check: preen foo.py hands the file to glow and you get mangled markdown
rather than an error. To render a single diff, pipe it in instead — see
Pipes.
Diffs start side-by-side. Press ctrl-s to flip to inline, and ctrl-s
again to flip back. The preview repaints immediately; the toggle is live, so
you can switch mid-review on a file that is too wide for two columns.
To start in inline instead:
PREEN_LAYOUT=inline preen diff
The toggle works in diff, pr and worktrees modes. Markdown has one
layout, so ctrl-s does nothing in md mode.
How the toggle is wired — two named delta features — is explained in Theming. It matters if you edit your own delta config, because one common mistake silently breaks it.
| key | action |
|---|---|
ctrl-s | toggle side-by-side / inline (diff, pr and worktrees modes) |
enter | open the full render in a pager |
ctrl-e | open in $EDITOR |
ctrl-d / ctrl-u | scroll the preview 8 lines |
pgdn / pgup | scroll the preview half a page |
shift-down / shift-up | scroll the preview one line |
home / end | jump the preview to the top or bottom |
ctrl-/ | hide or show the preview |
esc | quit, or in worktrees mode go back one level |
ctrl-c | quit |
Typing filters the list, as in any fzf picker. The arrow keys move the cursor and the list cycles at both ends.
enter versus the previewThe preview pane is a preview: it is 65% of the window. enter renders the same file at full terminal width into
less -R, which is where to read anything longer than a screen. q comes back
to the picker.
ctrl-d moves eight lines in one step rather than sliding. fzf has no timer or
delay action, so a chain of preview-down binds still paints a single frame.
Smooth scrolling would need something that redraws on its own tick, which a
--bind chain cannot do.
mdcat was tried and dropped for this reason.ctrl-e hands the file to $EDITOR and that is as far as it
goes.Next: Pipes, or Pull requests.