slop-review

Keys

Everything the window can be asked for has a key, and the bar along the bottom always shows what applies right now — generated from the keymap itself, so it cannot describe a key that does something else. It names the panel the keys act on, and lists only the ones that would actually fire there.

There are more actions than a bar can list, so the rarer ones sit behind a leader key and the bar shows one layer at a time. Both layers are the same whichever style you use:

Leader Layer Keys
C comment on f this file · c the commits
X check off f this file · c the commits
g go g first line · e last line · c C commit
w window w wrap · s side by side · c commits panel · r review panel

The two capitals are the lower-case keys asked to name a scope: x and c act on whatever the panel is on, and X and C ask which — the file or the commits — from wherever you happen to be reading.

The base layer is what a reviewer does over and over, and key_style picks the one your fingers already know:

Action vim emacs arrows
next, previous panel Ctrl+Tab Ctrl+Shift+Tab Ctrl+Tab Ctrl+Shift+Tab Ctrl+Tab Ctrl+Shift+Tab
down, up one j k Ctrl+N Ctrl+P Down Up
down, up a page J K Ctrl+V Ctrl+Shift+V Ctrl+Down Ctrl+Up
next, previous file ] [ ] [ ] [
next, previous hunk n p Ctrl+S Ctrl+R PageDown PageUp
next, previous unread N P Ctrl+Shift+S Ctrl+Shift+R Shift+PageDown Shift+PageUp
pick a run of lines v Ctrl+Space v
step into what the cursor is on Enter Enter Enter
more context above the hunk Shift+Enter Shift+Enter Shift+Enter
tick off a hunk, a file, a commit x x Space
remark on what the panel is on c c c
take back the remark under the cursor d d d
approve, request changes, comment D D D
file the remark, or send the review Ctrl+Enter Ctrl+Enter Ctrl+Enter
put down whatever is open Esc Ctrl+G Esc

A key on the bar that would do nothing where the cursor is — taking back a remark that is not there, asking for more of a gap that has run out — is drawn dimmed rather than dropped, with the reason in its hover text. A bar whose entries come and go as the cursor moves has no shape to learn.

Ctrl+Tab cycles the keyboard's attention between the commit list, the file list, the diff and the review panel — whichever of them are open — and is marked on the panel it lands on, and named at the left of the bottom bar. It is modified because an unmodified Tab belongs to the GUI toolkit, which walks a focus ring of its own with it.

Moving follows the panel: down one is the next commit in the commit list, the next file in the file list, and the next line in the diff. So does ticking off, so do first and last, and so does remarking — c in the commit list writes about the selected commits, in the file list about the file, and in the diff about the line or the run the cursor is on.

Opening steps inwards: Enter on a commit shows its files, on a file its diff, and in the diff it shows the lines folded away below the hunk being read — or above it, once nothing is left below. The keyboard follows, so Enter walks a review from the commit list to the code without a detour through the panel keys.

A collapsed gap opens from either end, and each end remembers how far. The strip has an arrow for each — the lines come out under the hunk above or over the hunk below — as well as show all, and the keyboard asks for the same two things about the hunk being read: Enter for more of what comes after it, Shift+Enter for more of what comes before. The declaration a changed call sits under is usually the last line of the gap above it, not the first.

The review panel is the list of what you have written, so the keyboard walks that: down one is the next remark, Enter opens the one under the cursor where it stands, d takes it back, c writes the summary and D cycles the decision. A review can be read through, pruned, summarised and sent without the mouse.

The cursor is a bar down the left edge of one line. Every line on the page is one it can stand on: unified, a line changed on both sides is drawn twice, and stopping on the removal writes a remark about the old file the way stopping on the addition writes one about the new. The bar is solid on the half the cursor is on and a shadow of itself on the other half of the same row, so a pair drawn apart still reads as a pair. Clicking a line number moves the cursor there, so the mouse and the keyboard point at the same place — and there is only ever one place, since walking away with the keyboard drops whatever the mouse left picked. To remark on several lines, press the select key, move to the far end, then c; with the mouse, drag down the line numbers or shift-click the far end.

A file opens with the cursor already on its first hunk, so ticking off the first change or writing about it is one keystroke rather than a hunt for where the changes start. Walking back to a file you have already been in puts the cursor where you left it, for as long as the window is open — a row number means nothing once the diff behind it has been rendered again, so this is the one thing about your place that is not written down. While a remark is being typed the text box has the keyboard, and only two things reach past it: filing what is open and putting it down again.

Inside a box — a remark, the summary, the file in the settings window — the usual editing keys are the toolkit's: Ctrl+Left and Ctrl+Right move by word, Home and End reach the ends of a line and Ctrl+Home and Ctrl+End the ends of the text, Shift with any of those selects instead of moving, and Ctrl+A, Ctrl+C, Ctrl+X and Ctrl+V do what they do everywhere. Four more are the window's own, because a GUI text box has no answer for them:

Key What it does
Ctrl+Backspace Ctrl+Delete take back the word behind or ahead of the caret
Ctrl+K Ctrl+U kill to the end or the start of the line

The two kills leave what they took on the clipboard, so Ctrl+V puts it back; the two word erasures do not, because deleting a word is not a reason to lose what you were about to paste.

edit_style lays a second set over that, for fingers that already know one. It is a separate setting from key_style because they are separate questions: those keys read a diff, and these ones write a remark, and there is no reason reading with j and k should mean writing without Ctrl+A.

Action plain emacs
left, right one Left Right Ctrl+B Ctrl+F
up, down one Up Down Ctrl+P Ctrl+N
left, right one word Ctrl+Left Ctrl+Right Alt+B Alt+F
start, end of the line Home End Ctrl+A Ctrl+E
start, end of the text Ctrl+Home Ctrl+End Alt+< Alt+>
up, down a page PageUp PageDown Alt+V Ctrl+V
take back a character Backspace Delete Ctrl+H Ctrl+D
take back a word Ctrl+Backspace Ctrl+Delete Alt+Backspace Alt+D
cut, copy, paste Ctrl+X Ctrl+C Ctrl+V Ctrl+W Alt+W Ctrl+Y

plain is the column every text box on the desktop already answers to, and emacs is laid over it rather than replacing it: Ctrl+Left still moves by word there, and the four keys in the table above it still do what they do. What does change is Ctrl+A, which stops selecting everything and becomes the start of the line — which is the point of asking for this.

Pick a style, and disagree with as much of it as you like, in any configuration file. The [keys] table is laid over the style rather than replacing it, so rebinding one action leaves the rest alone:

key_style = "emacs"

[keys]
row_down = "n"
row_up = "e"
top = "Home"

A chord is a key name (j, ], Esc, Enter, Tab, Down); a single capital letter means that key with shift; a named key with no case of its own takes an explicit Shift+ instead, as in Shift+Tab; Ctrl+ and Alt+ in front mean hold control and hold alt, in that order. A leader is written in front with a space, as in g e. Which layer an action lives on is a fact about the action rather than about the key it is on: binding one of a layer's actions to a bare key, as with top above, moves it into the base bar, and putting a leader in front of a base one leaves it there with both keys on its hint. The action names are panel_next, panel_prev, row_down, row_up, page_down, page_up, hunk_next, hunk_prev, unread_next, unread_prev, select, open, toggle_read, top, bottom, file_next, file_prev, commit_next, commit_prev, toggle_read_file, toggle_read_commit, comment, comment_file, comment_commit, comment_delete, decide, toggle_wrap, toggle_split, toggle_compare, toggle_nav, toggle_review, submit and cancel.