From Helix
Select, then act
As in Helix, you select the text first and then act on the selection.
w, b and e select by words, and x selects the lines of each selection.
Then d deletes the selection, c deletes it and enters Insert mode, and y yanks it.
dk has multiple selections too. Each selection is a Range, and every key acts on all of them:
,keeps only the primary selection.Cadds a selection on the line below each one, at the same display column.Kkeeps the selections whose text matches, andA-Kremoves them.sopens theselect:prompt, and each regex match inside each selection becomes a selection.Ssplits each selection at the matches.venters Select mode, whereh,j,k,l,w,b,e,W,BandEextend every selection instead of moving it. Esc orvtakes you back to Normal mode.
The same keys start a sequence: [, ], C-w, g, m, space and z.
After you press one, a box at the bottom right shows the keys that can come next.
Keys are spelled the same way too: A-x for Alt, C-x for Control, S-tab for Shift, and names such as space, esc and minus.
What differs
dk has a Block mode.
C-v enters it and puts a Range on each line of a rectangle.
Command names in the [keys] table of config.toml are kebab-case, with whole words.
Helix’s move_char_left is move-character-left in dk, and goto_prev_function is goto-previous-function.
The Manual lists every name.
Where a key in the table below does something different in dk, the note on its row says what dk does.
Keys
The table lists the Helix keys that have a close match in dk. The dk column has only default keys.
| Task | Helix | dk | Note |
|---|---|---|---|
| move left one grapheme | h or left | h or left | |
| move down one line | j or down | j or down | |
| move up one line | k or up | k or up | |
| move right one grapheme | l or right | l or right | |
| select to before the next match of the next key | t | t | |
| select to the next match of the next key | f | f | |
| select back to after the match of the next key | T | T | |
| select back to the match of the next key | F | F | |
| replace each character of the selection with the next key | r | r | |
| put the register in place of each selection | R | R | |
| run the last motion again | A-. | A-. | |
| switch the case of each selection | ~ | ~ | |
| make each selection lower case | ` | ` | |
| make each selection upper case | A-` | A-` | |
| go to the start of the line | home | home | |
| go to the last grapheme of the line | end | end | |
| select to the start of the next word | w | w | |
| select to the start of the previous word | b | b | |
| select to the end of the next word | e | e | |
| select to the start of the next long word | W | W | |
| select back to the start of a long word | B | B | |
| select to the end of the next long word | E | E | |
| enter Select mode | v | v | |
| go to line N with a count, or to the last line | G | G | With no count, dk goes to the last line. |
| go to the first line, or to line N with a count | g g | g g | |
| go to grapheme N of the line | g | | g | | |
| go to the last line | g e | g e | |
| open the file named at the cursor or by each selection | g f | g f | |
| go to the start of the line | g h | g h | |
| go to the last grapheme of the line | g l | g l | |
| go to the first character of the line that is not whitespace | g s | g s | |
| go to the definition of the symbol | g d | g d | |
| go to the declaration of the symbol | g D | g D | |
| go to the type definition of the symbol | g y | g y | |
| go to the references of the symbol | g r | g r | |
| go to the implementation of the symbol | g i | g i | |
| go to the top of the view | g t | H | dk puts the cursor on the first character of the line that is not whitespace. |
| go to the middle of the view | g c | M | dk puts the cursor on the first character of the line that is not whitespace. |
| go to the bottom of the view | g b | L | dk puts the cursor on the first character of the line that is not whitespace. |
| show the document that the view showed last | g a | g a | |
| show the document that the view left last with a change | g m | g m | |
| show the next open document | g n | g n | |
| show the previous open document | g p | g p | |
| move up one text line | g k | g k | |
| move down one text line | g j | g j | |
| go to the revision position of the current revision | g . | g . | |
| go to a two-character label | g w | g w | |
| open the prompt | : | : | |
| enter Insert mode | i | i | |
| insert at the first character of the line | I | I | |
| insert after the selection | a | a | |
| insert at the end of the line | A | A | |
| add a line below each range, then insert | o | o | |
| add a line above each range, then insert | O | O | |
| delete the selection | d | d | |
| delete the selection with no yank | A-d | A-d | |
| delete the selection, then insert | c | c | |
| delete the selection with no yank, then insert | A-c | A-c | |
| add a range on the line below each range | C | C | |
| add a range on the line above each range | A-C | A-C | |
| select each regex match inside the selections | s | s | |
| split the selections into their lines | A-s | A-s | |
| merge the selections into one | A-minus | A-minus | |
| merge the selections that touch | A-_ | A-_ | |
| split the selections at each regex match | S | S | |
| make each selection a cursor | ; | ; | |
| swap the anchor and the cursor of each selection | A-; | A-; | |
| select the parent syntax node of each selection | A-o or A-up | A-o or A-up | |
| go back to the selection before A-o, or select the first child node | A-i or A-down | A-i or A-down | |
| select each named child node of each selection | A-I or A-S-down | A-I or A-S-down | |
| select the previous named sibling node | A-p or A-left | A-p or A-left | |
| select the next named sibling node | A-n or A-right | A-n or A-right | |
| select each named sibling node of each selection | A-a | A-a | |
| select the whole text | % | % | |
| select the line, or add the line below | x | x | |
| select the whole lines of each selection | X | X | |
| shrink each selection to the whole lines in it | A-x | A-x | |
| go to the bracket that matches the one at the cursor | m m | m m | |
| surround each selection with the pair of the next key | m s | m s | |
| replace the pair of the next key around each selection | m r | m r | |
| delete the pair of the next key around each selection | m d | m d | |
| select around the object of the next key | m a | m a | |
| select inside the object of the next key | m i | m i | |
| go to the previous change | [ g | [ g | |
| go to the first change | [ G | [ G | |
| go to the previous function | [ f | [ f | |
| go to the previous type definition | [ t | [ t | |
| go to the previous parameter | [ a | [ a | |
| go to the previous comment | [ c | [ c | |
| go to the previous pairing | [ e | [ e | |
| go to the previous test | [ T | [ T | |
| go to the previous paragraph | [ p | [ p | |
| go to the previous (X)HTML element | [ x | [ x | |
| go to the next change | ] g | ] g | |
| go to the last change | ] G | ] G | |
| go to the next function | ] f | ] f | |
| go to the next type definition | ] t | ] t | |
| go to the next parameter | ] a | ] a | |
| go to the next comment | ] c | ] c | |
| go to the next pairing | ] e | ] e | |
| go to the next test | ] T | ] T | |
| go to the next paragraph | ] p | ] p | |
| go to the next (X)HTML element | ] x | ] x | |
| search for a regex | / | / | |
| search back for a regex | ? | ? | |
| select the next search match | n | n | |
| select the previous search match | N | N | |
| use the selection as the search pattern, with word boundaries | * | * | |
| use the selection as the search pattern | A-* | A-* | |
| undo the last change | u | u | |
| redo the last undone change | U | U | |
| move back to the change made before | A-u | A-u | |
| move on to the change made after | A-U | A-U | |
| yank the selection to the register | y | y | |
| paste the register after each selection | p | p | |
| paste the register before each selection | P | P | |
| indent the lines of each selection | > | > | |
| unindent the lines of each selection | < | < | |
| format the selection with a language server | = | = | |
| join the lines of each selection | J | J | |
| join the lines of each selection and select the spaces | A-J | A-J | |
| keep the selections that match a regex | K | K | |
| remove the selections that match a regex | A-K | A-K | |
| keep only the primary range | , | , | |
| remove the primary selection | A-, | A-, | |
| align the selections of each line in columns | & | & | |
| trim the whitespace of each selection | _ | _ | |
| make the previous selection primary | ( | ( | |
| make the next selection primary | ) | ) | |
| move the text of each selection to the previous one | A-( | A-( | |
| move the text of each selection to the next one | A-) | A-) | |
| scroll up one page | C-b or pageup | C-b or pageup | |
| scroll down one page | C-f or pagedown | C-f or pagedown | |
| scroll and move every range up half a page | C-u | C-u | |
| scroll and move every range down half a page | C-d | C-d | |
| focus the next view | C-w C-w or C-w w | C-w C-w or C-w w | |
| split the view: the new view goes below | C-w C-s or C-w s | C-w C-s or C-w s | |
| split the view: the new view goes to the right | C-w C-v or C-w v | C-w C-v or C-w v | |
| close the view | C-w C-q or C-w q | C-w C-q or C-w q | |
| close every other view | C-w C-o or C-w o | C-w C-o or C-w o | |
| focus the view to the left | C-w h or C-w left | C-w h or C-w left | |
| focus the view below | C-w j or C-w down | C-w j or C-w down | |
| focus the view above | C-w k or C-w up | C-w k or C-w up | |
| focus the view to the right | C-w l or C-w right | C-w l or C-w right | |
| swap the view with the view to the right | C-w L | C-w L | dk moves the view to the far right, with the full height. |
| swap the view with the view above | C-w K | C-w K | dk moves the view to the top, with the full width. |
| swap the view with the view to the left | C-w H | C-w H | dk moves the view to the far left, with the full height. |
| swap the view with the view below | C-w J | C-w J | dk moves the view to the bottom, with the full width. |
| comment or uncomment the lines of each selection | C-c | C-c | |
| go to the next jump on the jumplist | C-i or tab | C-i or tab | |
| go back to the jump before on the jumplist | C-o | C-o | |
| save the selection to the jumplist | C-s | C-s | |
| pick a file of the workspace | space f | space f | |
| pick a file under the directory of the document | space F | space F | |
| pick an open document | space b | space b | |
| pick a jump of the jumplists | space j | space j | |
| pick a symbol of the document | space s | space s | |
| pick a symbol of the workspace | space S | space S | |
| pick a diagnostic of the document | space d | space d | |
| pick a diagnostic of an open document | space D | space D | |
| pick a file that the working copy changes | space g | space g | dk lists the files that the jj working copy changes. |
| pick a code action of the language servers | space a | space a | |
| open the picker that closed last | space ' | space ' | |
| yank the selection to the system clipboard | space y | space y | |
| yank the primary selection to the system clipboard | space Y | space Y | |
| paste the system clipboard after each selection | space p | space p | |
| paste the system clipboard before each selection | space P | space P | |
| put the system clipboard in place of each selection | space R | space R | |
| search the working directory for a regex | space / | space / | |
| show docs for the item under the cursor | space k | space k | |
| rename the symbol under the cursor with a language server | space r | space r | |
| select each use of the symbol under the cursor | space h | space h | |
| comment or uncomment the lines of each selection | space c | space c | |
| pick a command and run it | space ? | space ? | |
| show the change of the cursor line | space B | space B | |
| put the cursor line on the middle row of the view | z z or z c | z z or z c | |
| put the cursor line on the first row of the view | z t | z t | |
| put the cursor line on the last row of the view | z b | z b | |
| put the cursor column in the middle of the view | z m | z m | |
| scroll the view up a count of lines | z k or z up | z k or z up | |
| scroll the view down a count of lines | z j or z down | z j or z down | |
| scroll up one page | z C-b or z pageup | z C-b or z pageup | |
| scroll down one page | z C-f or z pagedown | z C-f or z pagedown | |
| scroll and move every range up half a page | z C-u or z backspace | z C-u or z backspace | |
| scroll and move every range down half a page | z C-d or z space | z C-d or z space | |
| search for a regex | z / | z / | |
| search back for a regex | z ? | z ? | |
| select the next search match | z n | z n | |
| select the previous search match | z N | z N | |
| put the cursor line on the middle row of the view | Z z or Z c | Z z or Z c | |
| put the cursor line on the first row of the view | Z t | Z t | |
| put the cursor line on the last row of the view | Z b | Z b | |
| put the cursor column in the middle of the view | Z m | Z m | |
| scroll the view up a count of lines | Z k or Z up | Z k or Z up | |
| scroll the view down a count of lines | Z j or Z down | Z j or Z down | |
| scroll up one page | Z C-b or Z pageup | Z C-b or Z pageup | |
| scroll down one page | Z C-f or Z pagedown | Z C-f or Z pagedown | |
| scroll and move every range up half a page | Z C-u or Z backspace | Z C-u or Z backspace | |
| scroll and move every range down half a page | Z C-d or Z space | Z C-d or Z space | |
| search for a regex | Z / | Z / | |
| search back for a regex | Z ? | Z ? | |
| select the next search match | Z n | Z n | |
| select the previous search match | Z N | Z N | |
| pick the register of the next command | " | " | |
| run the command for each selection, with its text as stdin, and put the output in its place | | | | | |
| run the command for each selection, with its text as stdin, and drop the output | A-| | A-| | |
| run the command once, and put its output before each selection | ! | ! | |
| run the command once, and put its output after each selection | A-! | A-! | |
| stop dk and go back to the shell; fg brings it back | C-z | C-z | |
| increment item under cursor | C-a | C-a | |
| decrement item under cursor | C-x | C-x | |
| extend left one grapheme | v h or v left | v h or v left | |
| extend down one line | v j or v down | v j or v down | |
| extend up one line | v k or v up | v k or v up | |
| extend right one grapheme | v l or v right | v l or v right | |
| extend to the start of the next word | v w | v w | |
| extend to the start of the previous word | v b | v b | |
| extend to the end of the next word | v e | v e | |
| extend to the start of the next long word | v W | v W | |
| extend back to the start of a long word | v B | v B | |
| extend to the end of the next long word | v E | v E | |
| add the next search match as a selection | v n | v n | |
| add the previous search match as a selection | v N | v N | |
| extend to before the next match of the next key | v t | v t | |
| extend to the next match of the next key | v f | v f | |
| extend back to after the match of the next key | v T | v T | |
| extend back to the match of the next key | v F | v F | |
| extend to the start of the line | v home | v home | |
| extend to the end of the line | v end | v end | |
| return to Normal mode | v esc | v esc | |
| return to Normal mode | v v | v v | |
| extend to the first line, or to line N with a count | v g g | v g g | |
| extend to grapheme N of the line | v g | | v g | | |
| extend to the last line | v g e | v g e | |
| extend up one text line | v g k | v g k | |
| extend down one text line | v g j | v g j | |
| extend to a two-character label | v g w | v g w | |
| return to Normal mode | i esc | i esc | |
| make an undo step of the text typed so far | i C-s | i C-s | |
| ask the language servers for completions | i C-x | i C-x | |
| paste a register at each cursor | i C-r | i C-r | |
| delete back to the start of the word | i C-w or i A-backspace | i C-w or i A-backspace | |
| delete to the end of the word | i A-d or i A-del | i A-d or i A-del | |
| delete back to the indent, then to the line start | i C-u | i C-u | |
| delete to the end of the line | i C-k | i C-k | |
| delete the grapheme before the cursor | i C-h or i backspace or i S-backspace | i C-h or i backspace or i S-backspace | |
| delete the grapheme at the cursor | i C-d or i del | i C-d or i del | |
| add a line break | i C-j or i ret | i C-j or i ret | |
| select the next tab stop of the snippet | i tab | i tab | |
| insert a tab, or spaces to the next indent column | i S-tab | i S-tab | |
| move up one line | i up | i up | |
| move down one line | i down | i down | |
| move left one grapheme | i left | i left | |
| move right one grapheme | i right | i right | |
| scroll up one page | i pageup | i pageup | |
| scroll down one page | i pagedown | i pagedown | |
| go to the start of the line | i home | i home | |
| go to the line ending | i end | i end |
Keys without a counterpart
dk has no match for these Helix keys:
$, which filters the selections with a shell command.[ d,[ D,] dand] D, which go to a diagnostic. Usespace dto pick one of the diagnostics in the document.[ spaceand] space, which add a newline above and below.A-:, which makes each selection face forward. dk has the commandensure-ranges-forwardfor this. It has no default key, so bind it in[keys]if you want it.A-bandA-e, which move to the start and the end of the parent syntax node.C-w C-h,C-w C-j,C-w C-kandC-w C-l. UseC-w h,C-w j,C-w kandC-w lto move the focus between views.C-w f,C-w F,C-w nandC-w t.escin Normal mode.Qandq, which record and replay a macro.space .andspace e, which open the file explorer.space A-candspace C, which comment and uncomment lines and blocks. In dk,C-candspace ctoggle comments.space G, which starts the debugger keys.space w, which repeats theC-wkeys.
Config
dk reads config.toml from ~/.config/ductus/.
It has the same theme, keys and editor as a Helix config.
A key that dk does not read gets a note on the last row, and the rest of the file still loads.
Helix’s bufferline has no counterpart.
dk’s tabline is for tab pages, not buffers.
dk shows a language server’s diagnostics after the text of their line, and [editor] has no option to change that.
Options with a counterpart
These options have the same name and the same place in dk, under [editor].
Where the default differs, the note says how.
| Option | Note |
|---|---|
auto-completion | |
auto-format | |
auto-info | |
auto-pairs | |
clipboard-provider | |
color-modes | Off in Helix, on in dk. |
completion-replace | |
completion-timeout | |
completion-trigger-len | |
default-yank-register | |
file-picker.deduplicate-links | |
file-picker.follow-symlinks | |
file-picker.git-exclude | |
file-picker.git-global | |
file-picker.git-ignore | |
file-picker.hidden | |
file-picker.ignore | |
file-picker.max-depth | |
file-picker.parents | |
gutters.layout | |
gutters.line-numbers.min-width | |
indent-heuristic | |
inline-blame.auto-fetch | |
inline-blame.format | {author} and {commit} in Helix, {author-short} and {change} in dk. |
inline-blame.show | |
jump-label-alphabet | |
line-number | |
lsp.auto-document-highlight | Off in Helix, on in dk. |
lsp.auto-signature-help | |
lsp.display-signature-help-docs | |
lsp.goto-reference-include-declaration | |
lsp.snippets | |
middle-click-paste | |
mouse | |
mouse-yank-register | |
popup-border | none in Helix, popup in dk. |
preview-completion-insert | |
rainbow-brackets | Off in Helix, on in dk. |
rulers | |
scrolloff | |
search.smart-case | |
search.wrap-around | |
shell | |
smart-tab.enable | |
smart-tab.supersede-menu | |
soft-wrap.enable | |
soft-wrap.max-indent-retain | |
soft-wrap.max-wrap | |
soft-wrap.wrap-at-text-width | |
soft-wrap.wrap-indicator | |
statusline.center | |
statusline.left | dk’s default adds spacer and version-control. |
statusline.mode.insert | |
statusline.mode.normal | |
statusline.mode.select | |
statusline.right | dk’s default adds total-line-numbers and file-type. |
statusline.separator | |
text-width |
Options without a counterpart
dk does not read these Helix [editor] options:
atomic-saveauto-save.*buffer-picker.start-positionbufferlinecontinue-commentscursor-shapecursorcolumncursorlinedefault-line-endingeditor-configend-of-line-diagnosticsfile-explorer.*idle-timeoutindent-guides.*inline-diagnostics.*insert-final-newlinekitty-keyboard-protocollsp.display-color-swatcheslsp.display-inlay-hintslsp.display-messageslsp.display-progress-messageslsp.enablelsp.inlay-hints-length-limitpath-completionscroll-linesstatusline.diagnosticsstatusline.workspace-diagnosticsterminal.*trim-final-newlinestrim-trailing-whitespacetrue-colorundercurlwhitespace.*word-completion.*workspace-lsp-rootsworkspace-trust.*
languages.toml
dk reads languages.toml from the same directory.
Your languages and grammars join the shipped ones, and a [[language]] with a shipped name changes only the keys it sets.
The tables are the same as in Helix: [[language]], [language-server.<name>], [[grammar]] and use-grammars.
In a [[language]], dk reads these keys:
auto-format, auto-pairs, block-comment-tokens, comment-token, comment-tokens, file-types,
formatter, grammar, hoist-locals, indent, injection-regex, language-id, language-servers,
name, rainbow-brackets, roots, rulers and shebangs.
In a [language-server.<name>] it reads args, command, config, environment and timeout,
and in a [[grammar]] the name and the source.
Helix has no hoist-locals key; that one is dk’s own.
Keys of languages.toml without a counterpart
dk does not read these Helix keys:
code-actions-on-save,debugger,diagnostic-severity,path-completion,persistent-diagnostic-sources,scope,soft-wrap,text-width,word-completionandworkspace-lsp-rootsof a[[language]].language-server.required-root-patternsof a[language-server.<name>].only-featuresandexcept-featuresof an entry oflanguage-servers.