Skip to content

Commit

Permalink
Added ability to add custom descriptions for keybindings bound to a b…
Browse files Browse the repository at this point in the history
…lock and command to browse keybindings
  • Loading branch information
Nimaoth committed Jun 24, 2024
1 parent a7f8a72 commit fc6b3a1
Show file tree
Hide file tree
Showing 7 changed files with 315 additions and 22 deletions.
2 changes: 2 additions & 0 deletions config/default_config.nim
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ proc loadDefaultKeybindings*(clearExisting: bool = false) {.expose("load-default
addCommand "editor", "r", "move-current-view-to-top"
addCommand "editor", "h", "open-previous-editor"
addCommand "editor", "f", "open-next-editor"
addCommand "editor", "s", "split-view"

if getBackend() != Terminal:
addCommand "editor", "<CA-v>", "create-view"
Expand Down Expand Up @@ -107,6 +108,7 @@ proc loadDefaultKeybindings*(clearExisting: bool = false) {.expose("load-default
addCommand "editor", "<LEADER>gu", "explore-user-config-dir"
addCommand "editor", "<LEADER>ga", "explore-app-config-dir"
addCommand "editor", "<LEADER>gs", "search-global-interactive"
addCommand "editor", "<LEADER>gk", "browse-keybinds"
addCommandBlock "editor", "<LEADER>log":
runAction "logs"
if getActiveEditor().isTextEditor(ed):
Expand Down
205 changes: 204 additions & 1 deletion config/keybindings_normal.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import absytree_runtime
import misc/[event, id, timer]

{.used.}

proc setModeChangedHandler*(handler: proc(editor: TextDocumentEditor, oldMode: string, newMode: string)) =
let modeChangedHandler = getOption("editor.text.mode-changed-handler", "")
if modeChangedHandler != "":
Expand All @@ -11,6 +13,67 @@ proc setModeChangedHandler*(handler: proc(editor: TextDocumentEditor, oldMode: s
handler(editor, arg.oldMode, arg.newMode)
setOption("editor.text.mode-changed-handler", $id)


proc loadStandardKeybindings() =
addCommand "editor", "<C-s>", "write-file"

addTextCommand "", "<LEFT>", "move-cursor-column", -1
addTextCommand "", "<RIGHT>", "move-cursor-column", 1
addTextCommand "", "<C-LEFT>", "move-last", "word-line-back"
addTextCommand "", "<C-RIGHT>", "move-last", "word-line"
addTextCommand "", "<HOME>", "move-first", "line"
addTextCommand "", "<END>", "move-last", "line"
addTextCommand "", "<C-UP>", "scroll-text", 20
addTextCommand "", "<C-DOWN>", "scroll-text", -20
addTextCommand "", "<CS-LEFT>", "move-last", "word-line-back", "last"
addTextCommand "", "<CS-RIGHT>", "move-last", "word-line", "last"
addTextCommand "", "<UP>", "move-cursor-line", -1
addTextCommand "", "<DOWN>", "move-cursor-line", 1
addTextCommand "", "<C-HOME>", "move-first", "file"
addTextCommand "", "<C-END>", "move-last", "file"
addTextCommand "", "<CS-HOME>", "move-first", "file", "last"
addTextCommand "", "<CS-END>", "move-last", "file", "last"
addTextCommand "", "<S-LEFT>", "move-cursor-column", -1, "last"
addTextCommand "", "<S-RIGHT>", "move-cursor-column", 1, "last"
addTextCommand "", "<S-UP>", "move-cursor-line", -1, "last"
addTextCommand "", "<S-DOWN>", "move-cursor-line", 1, "last"
addTextCommand "", "<S-HOME>", "move-first", "line", "last"
addTextCommand "", "<S-END>", "move-last", "line", "last"
addTextCommand "", "<C-z>", "undo"
addTextCommand "", "<C-y>", "redo"
addTextCommand "", "<C-c>", "copy"
addTextCommand "", "<C-v>", "paste"
addTextCommand "", "<BACKSPACE>", "delete-left"
addTextCommand "", "<C-BACKSPACE>", "delete-move", "word-line-back"
addTextCommand "", "<DELETE>", "delete-right"
addTextCommand "", "<C-DELETE>", "delete-move", "word-line"
addTextCommand "", "<ENTER>", "insert-text", "\n"
addTextCommand "", "<SPACE>", "insert-text", " "
addTextCommand "", "<TAB>", "insert-indent"

proc loadStandardSelectorPopupKeybindings() =
addCommand "popup.selector", "<ENTER>", "accept"
addCommand "popup.selector", "<C-y>", "accept"
addCommand "popup.selector", "<ESCAPE>", "cancel"
addCommand "popup.selector", "<UP>", "prev"
addCommand "popup.selector", "<C-p>", "prev"
addCommand "popup.selector", "<DOWN>", "next"
addCommand "popup.selector", "<C-n>", "next"
addCommand "popup.selector", "<C-u>", "prev", 5
addCommand "popup.selector", "<C-d>", "next", 5
addCommand "popup.selector", "<TAB>", "toggle-focus-preview"
addCommand "popup.selector.preview", "<TAB>", "toggle-focus-preview"
addCommandBlock "popup.selector", "<C-l>":
setLocationListFromCurrentPopup()

addCommand "popup.selector.open", "<C-x>", "close-selected"

addCommand "popup.selector.git", "<C-a>", "stage-selected"
addCommand "popup.selector.git", "<C-u>", "unstage-selected"
addCommand "popup.selector.git", "<C-r>", "revert-selected"
addCommand "popup.selector.file-explorer", "<C-UP>", "go-up"
addCommand "popup.selector.file-explorer", "<C-r>", "go-up"

proc loadNormalKeybindings*() {.scriptActionWasmNims("load-normal-keybindings").} =
let t = startTimer()
defer:
Expand Down Expand Up @@ -215,4 +278,144 @@ proc loadModelKeybindings*() {.scriptActionWasmNims("load-model-keybindings").}
addCommand "editor.model.completion", "<TAB>", "apply-selected-completion"
addCommand "editor.model.completion", "<ENTER>", "apply-selected-completion"

addCommand "editor.model.goto", "<END>", "end"
addCommand "editor.model.goto", "<END>", "end"

proc vscodeSelectLines(editor: TextDocumentEditor, selections: Selections): Selections =
result = selections.mapIt (if it.isBackwards:
((it.first.line, editor.lineLength(it.first.line)), (it.last.line, 0))
else:
((it.first.line, 0), (it.last.line, editor.lineLength(it.last.line))))

proc vscodeExtendForLineDeletion(editor: TextDocumentEditor, selections: Selections): Selections =
result = selections.mapIt (
if it.isBackwards:
if it.last.line > 0:
(it.first, editor.doMoveCursorColumn(it.last, -1))
elif it.first.line + 1 < editor.lineCount:
(editor.doMoveCursorColumn(it.first, 1), it.last)
else:
it
else:
if it.first.line > 0:
(editor.doMoveCursorColumn(it.first, -1), it.last)
elif it.last.line + 1 < editor.lineCount:
(it.first, editor.doMoveCursorColumn(it.last, 1))
else:
it
)

proc vscodeDeleteLine(editor: TextDocumentEditor) {.expose("vscode-delete-line").} =
editor.addNextCheckpoint("word")
let lineSelections = editor.vscodeExtendForLineDeletion(editor.vscodeSelectLines(editor.selections))
editor.selections = editor.delete(lineSelections, inclusiveEnd=true).mapIt(
editor.doMoveCursorLine(it.normalized.first, 1).toSelection
)

proc vscodeTodo(editor: TextDocumentEditor, command: string) {.expose("vscode-todo").} =
infof"command not implemented: '{command}'. Open an issue."

proc loadVSCodeKeybindings*() {.scriptActionWasmNims("load-vscode-keybindings").} =
let t = startTimer()
defer:
infof"loadVSCodeKeybindings: {t.elapsed.ms} ms"

info "Applying vscode keybindings"

clearCommands("editor.text")
for id in getAllEditors():
if id.isTextEditor(editor):
editor.setMode("")

setHandleInputs "editor.text", true
setOption "editor.text.cursor.movement.", "both"
setOption "editor.text.cursor.wide.", false

loadStandardKeybindings()
loadStandardSelectorPopupKeybindings()

addCommand "editor", "<A-F4>", "quit"

addCommand "editor", "<LEADER><LEADER>", "command-line"
addCommand "editor", "<C-g>t", "choose-theme"
addCommand "editor", "<C-g>f", "choose-file", "new"
addCommand "editor", "<C-p>", "choose-file", "new"
addCommand "editor", "<C-g>o", "choose-open", "new"
addCommand "editor", "<C-g>d", "choose-open-document"
addCommand "editor", "<C-g>l", "choose-location", "new"
addCommand "editor", "<C-g>g", "choose-git-active-files", false
addCommand "editor", "<C-g>e", "explore-files"
addCommand "editor", "<C-g>w", "explore-workspace-primary"
addCommand "editor", "<C-g>u", "explore-user-config-dir"
addCommand "editor", "<C-g>a", "explore-app-config-dir"
addCommand "editor", "<C-g>s", "search-global-interactive"

addTextCommand "", "<C-x>", "vscode-delete-line"

addTextCommand "", "<A-UP>", "vscode-todo", "move-line-up"
addTextCommand "", "<A-DOWN>", "vscode-todo", "move-line-down"
addTextCommand "", "<SA-UP>", "vscode-todo", "copy-line-up"
addTextCommand "", "<SA-DOWN>", "vscode-todo", "copy-line-down"
addTextCommand "", "<CS-K>", "vscode-todo", "delete-line"

addTextCommand "", "<C-ENTER>", "vscode-todo", "insert-line-below"
addTextCommand "", "<CS-ENTER>", "vscode-todo", "insert-line-above"
addTextCommand "", r"<CS-\\>", "vscode-todo", "jump-to-matching-bracket"
addTextCommand "", "<CS-]", "indent"
addTextCommand "", "<CS-[", "unindent"
addTextCommand "", "<C-UP>", "scroll-lines", -1
addTextCommand "", "<C-DOWN>", "scroll-lines", 1
addTextCommand "", "<A-PAGE_UP>", "vscode-todo", "scroll-page-up"
addTextCommand "", "<A-PAGE_DOWN>", "vscode-todo", "scroll-page-down"
addTextCommand "", "<C-k><C-c>", "toggle-line-comment"

addTextCommand "", "<C-t>", "goto-workspace-symbol"
addTextCommand "", "<CS-o>", "goto-symbol"
addTextCommand "", "<CS-k>", "vscode-todo", "delete-line"

addTextCommandBlock "", "<F8>":
editor.selection = editor.getNextDiagnostic(editor.selection.last, 1).first.toSelection
editor.scrollToCursor Last
editor.updateTargetColumn()
addTextCommandBlock "", "<S-F8>":
editor.selection = editor.getPrevDiagnostic(editor.selection.last, 1).first.toSelection
editor.scrollToCursor Last
editor.updateTargetColumn()

addTextCommand "", "<A-LEFT>", "open-previous-editor" # todo: jump list
addTextCommand "", "<A-RIGHT>", "select-next" # todo: jump list
addTextCommand "", "<C-u>", "select-prev" # todo: jump list

addTextCommand "", "<C-l>", "select-line-current"

addTextCommandBlock "", "<C-f>":
commandLine(".set-search-query \\")
if getActiveEditor().isTextEditor(editor):
var arr = newJArray()
arr.add newJString("file")
discard editor.runAction("move-last", arr)
editor.setMode("insert")

addTextCommandBlock "", "<F3>":
editor.selection = editor.getNextFindResult(editor.selection.last).first.toSelection
editor.scrollToCursor Last
editor.updateTargetColumn()

addTextCommandBlock "", "<S-F3>":
editor.selection = editor.getPrevFindResult(editor.selection.last).first.toSelection
editor.scrollToCursor Last
editor.updateTargetColumn()

addTextCommand "", "<A-ENTER>", "set-all-find-result-to-selection"
addTextCommand "", "<C-d>", "add-next-find-result-to-selection"
addTextCommand "", "<C-k><C-d>", "vscode-todo", "move-selection-to-last-find-match"

addTextCommand "", "<CA-UP>", "add-cursor-above"
addTextCommand "", "<CA-DOWN>", "add-cursor-below"

addCommand "editor.text.completion", "<ESCAPE>", "hide-completions"
addCommand "editor.text.completion", "<UP>", "select-prev-completion"
addCommand "editor.text.completion", "<DOWN>", "select-next-completion"
addCommand "editor.text.completion", "<TAB>", "apply-selected-completion"

# lsp
addTextCommand "", "<C-SPACE>", "get-completions"
32 changes: 16 additions & 16 deletions config/keybindings_vim.nim
Original file line number Diff line number Diff line change
Expand Up @@ -840,16 +840,16 @@ proc loadVimKeybindings*() {.expose("load-vim-keybindings").} =
# Normal mode
addCommand "editor", ":", "command-line"

addTextCommandBlock "", "<C-e>":
addTextCommandBlockDesc "", "<C-e>", "exit to normal mode":
editor.selection = editor.selection
editor.setMode("normal")
addTextCommandBlock "", "<ESCAPE>":
addTextCommandBlockDesc "", "<ESCAPE>", "exit to normal mode and clear things":
if editor.mode == "normal":
editor.selection = editor.selection
editor.clearTabStops()
editor.setMode("normal")

addTextCommandBlock "", ".": replayCommands(".")
addTextCommandBlockDesc "", ".", "replay commands": replayCommands(".")
addCommand "editor.text.normal", "@<CHAR>", "<CHAR>", proc(editor: TextDocumentEditor, c: string) =
let register = if c == "@":
getOption("editor.current-macro-register", "")
Expand All @@ -865,7 +865,7 @@ proc loadVimKeybindings*() {.expose("load-vim-keybindings").} =
setRegisterText("", c)
startRecordingCommands(c)

addTextCommandBlock "", "Q":
addTextCommandBlockDesc "", "Q", "stop recording macro":
if isReplayingCommands() or not isRecordingCommands(getCurrentMacroRegister()):
return
stopRecordingCommands(getCurrentMacroRegister())
Expand Down Expand Up @@ -991,22 +991,22 @@ proc loadVimKeybindings*() {.expose("load-vim-keybindings").} =
addSubCommandWithCount "", "move", "j", "vim-move-cursor-line", 1

# search
addTextCommandBlock "", "*":
addTextCommandBlockDesc "", "*", "set search query to word":
editor.selection = editor.setSearchQueryFromMove("word", prefix=r"\b", suffix=r"\b").first.toSelection
addTextCommandBlock "visual", "*":
addTextCommandBlockDesc "visual", "*", "set search query to selection":
editor.setSearchQuery(editor.getText(editor.selection, inclusiveEnd=true), escapeRegex=true)
editor.selection = editor.selection.first.toSelection
editor.setMode("normal")
addTextCommandBlock "", "n":
addTextCommandBlockDesc "", "n", "go to next search result":
editor.selection = editor.getNextFindResult(editor.selection.last).first.toSelection
editor.scrollToCursor Last
editor.updateTargetColumn()
addTextCommandBlock "", "N":
addTextCommandBlockDesc "", "N", "go to previous search result":
editor.selection = editor.getPrevFindResult(editor.selection.last).first.toSelection
editor.scrollToCursor Last
editor.updateTargetColumn()

addTextCommandBlock "", "/":
addTextCommandBlockDesc "", "/", "open search bar":
commandLine(r".set-search-query \")
if getActiveEditor().isTextEditor(editor):
var arr = newJArray()
Expand All @@ -1015,7 +1015,7 @@ proc loadVimKeybindings*() {.expose("load-vim-keybindings").} =
editor.setMode("insert")
editor.updateTargetColumn()

addTextCommandBlock "", r"\\":
addTextCommandBlockDesc "", r"\\", "open global search bar":
commandLine(r"search-global \")
if getActiveEditor().isTextEditor(editor):
var arr = newJArray()
Expand All @@ -1033,40 +1033,40 @@ proc loadVimKeybindings*() {.expose("load-vim-keybindings").} =
addSubCommandWithCountBlock "", "move", "<C-u>": editor.vimMoveCursorLine(-editor.screenLineCount div 2, count, center=true)
addSubCommandWithCountBlock "", "move", "<PAGE_UP>": editor.vimMoveCursorLine(-editor.screenLineCount, count, center=true)

addTextCommandBlock "", "z<ENTER>":
addTextCommandBlockDesc "", "z<ENTER>", "scroll line to top":
if editor.getCommandCount != 0:
editor.selection = (editor.getCommandCount, 0).toSelection
editor.moveFirst "line-no-indent"
editor.vimFinishMotion()
editor.setCursorScrollOffset getVimLineMargin() * platformTotalLineHeight()

addTextCommandBlock "", "zt":
addTextCommandBlockDesc "", "zt", "scroll line to top":
if editor.getCommandCount != 0:
editor.selection = (editor.getCommandCount, editor.selection.last.column).toSelection
editor.vimFinishMotion()
editor.setCursorScrollOffset getVimLineMargin() * platformTotalLineHeight()

addTextCommandBlock "", "z.":
addTextCommandBlockDesc "", "z.", "center line":
if editor.getCommandCount != 0:
editor.selection = (editor.getCommandCount, 0).toSelection
editor.moveFirst "line-no-indent"
editor.vimFinishMotion()
editor.centerCursor()

addTextCommandBlock "", "zz":
addTextCommandBlockDesc "", "zz", "center line":
if editor.getCommandCount != 0:
editor.selection = (editor.getCommandCount, editor.selection.last.column).toSelection
editor.vimFinishMotion()
editor.centerCursor()

addTextCommandBlock "", "z-":
addTextCommandBlockDesc "", "z-", "scroll line to bottom":
if editor.getCommandCount != 0:
editor.selection = (editor.getCommandCount, 0).toSelection
editor.moveFirst "line-no-indent"
editor.vimFinishMotion()
editor.setCursorScrollOffset (editor.screenLineCount.float - getVimLineMargin()) * platformTotalLineHeight()

addTextCommandBlock "", "zb":
addTextCommandBlockDesc "", "zb", "scroll line to bottom":
if editor.getCommandCount != 0:
editor.selection = (editor.getCommandCount, editor.selection.last.column).toSelection
editor.vimFinishMotion()
Expand Down
Binary file modified config/wasm/keybindings_plugin.wasm
Binary file not shown.
25 changes: 25 additions & 0 deletions scripting/absytree_runtime.nim
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,28 @@ proc addCommand*(context: string, keys: string, action: proc(): void) =
# addCommandScript(context, "", keysPrefix & keys, "lambda-action", key.toJsonString)
addCommandScript(context, "", keysPrefix & keys, key, "")

proc addCommandDesc*(context: string, keys: string, desc: string, action: proc(): void) =
let key = "$" & context & keys
scriptActions[key] = proc(args: JsonNode): JsonNode =
action()
return newJNull()

addCommandScript(context, "", keysPrefix & keys, key, "", desc)

proc addCommand*[T: proc](context: string, keys: string, args: string, action: T) =
let key = "$" & context & keys
scriptActions[key] = proc(args: JsonNode): JsonNode =
return callJson(action, args)

addCommandScript(context, "", keysPrefix & keys, key, args)

proc addCommandDesc*[T: proc](context: string, keys: string, args: string, desc: string, action: T) =
let key = "$" & context & keys
scriptActions[key] = proc(args: JsonNode): JsonNode =
return callJson(action, args)

addCommandScript(context, "", keysPrefix & keys, key, args, desc)

template addCommandBlock*(context: string, keys: string, body: untyped): untyped =
addCommand context, keys, proc() =
body
Expand Down Expand Up @@ -277,6 +292,16 @@ template addTextCommandBlock*(mode: string, keys: string, body: untyped): untype
let k {.inject.} = keys
infof"TextCommandBlock {m} {k}: {getCurrentExceptionMsg()}"

template addTextCommandBlockDesc*(mode: string, keys: string, desc: string, body: untyped): untyped =
addCommandDesc getContextWithMode("editor.text", mode), keys, desc, proc() =
try:
let editor {.inject, used.} = TextDocumentEditor(id: getActiveEditor())
body
except:
let m {.inject.} = mode
let k {.inject.} = keys
infof"TextCommandBlock {m} {k}: {getCurrentExceptionMsg()}"

proc addTextCommand*(mode: string, keys: string, action: proc(editor: TextDocumentEditor): void) =
let context = getContextWithMode("editor.text", mode)
addCommand context, keys, proc() =
Expand Down
Loading

0 comments on commit fc6b3a1

Please sign in to comment.