Skip to content

Instantly share code, notes, and snippets.

@digitalmaster
Created November 29, 2024 03:57
Show Gist options
  • Select an option

  • Save digitalmaster/b6f5e9251eaa392e52001091d02ac18a to your computer and use it in GitHub Desktop.

Select an option

Save digitalmaster/b6f5e9251eaa392e52001091d02ac18a to your computer and use it in GitHub Desktop.
Modal Edit Config
// add count argument
function repeatable(command) {
return {
command,
count: "_ctx.count"
};
}
// record command to a register
function record(command, reg) {
return {
command,
record: reg
};
}
// reset previous selections but keep all cursors
function reselect(command) {
return [
"modalEditor.clearSelections",
command
];
}
// Select all text (inner/around) pairs
function selectPair(till, left, right) {
right = typeof right !== "undefined" ? right : left;
return [
findText(till, false, true, false, left),
findText(till, true, false, false, right)
];
}
// Call findText with computer or un-computed args
function findText(till, select, backward, regex, text) {
let computedArgs = text.includes("_ctx");
let args = computedArgs
? `{ text: ${text}, till: ${till}, select: ${select}, backward: ${backward}, regex: ${regex} }`
: { text: text, till: till, select: select, backward: backward, regex: regex };
return {
command: "modalEditor.findText",
computedArgs: computedArgs,
args: args
};
}
// All jumps (find/till/sneak) have the same basic formation
function jumpMotion(till, select, backward, numKeys, extraCommands) {
let commandList = [];
const left = select ? "cursorLeftSelect" : "cursorLeft";
const right = select ? "cursorRightSelect" : "cursorRight";
// Skip current character when moving backward
if (till && backward) commandList.push(left);
// Adjust cursor when moving forward
else if (till && !backward) commandList.push(right);
// Find text based on the previously typed keys
commandList.push(findText(till, select, backward, false, `_ctx.keys.slice(-${numKeys})`));
// // Move cursor left when motion is forward
// if (!backward) commandList.push(left);
// Add extra commands
if (extraCommands) commandList.push(extraCommands);
// Return the wildcard command
return { "": recordMotion(repeatable([commandList])) };
}
// Use find widget with arguments
function findWidget(caseSensitive, regex, wholeWord) {
return {
command: "editor.actions.findWithArgs",
args: {
// findInSelection: false,
isCaseSensitive: caseSensitive,
isRegex: regex,
matchWholeWord: wholeWord
}
};
}
// record change
const recordChange = command => record(command, "change");
// record motion
const recordMotion = command => record(command, "motion");
const cursorMove = (direction, select = false, by = 1) => {
return repeatable({
command: "cursorMove",
args: {
to: direction,
by: 'wrappedLine',
select: select,
value: by
}
});
};
const SelectActions = {
entireWord: ['modalEditor.setSelectMode', 'cursorWordStartLeft', 'cursorWordEndRightSelect'],
restWord: repeatable('cursorWordEndRightSelect'),
backWord: repeatable(['cursorWordStartLeftSelect']),
expand: ['modalEditor.setSelectMode', 'editor.action.smartSelect.expand'],
reduce: ['modalEditor.setSelectMode', 'editor.action.smartSelect.shrink'],
};
SelectActions.inside = {
word: SelectActions.entireWord,
}
SelectActions.around = {
word: SelectActions.entireWord,
}
const withMotions = (command = [], select = false) => {
return {
"h": [
cursorMove('left', select),
command,
],
"j": [
cursorMove('down', select),
command,
],
"k": [
cursorMove('up', select),
command,
],
"l": [
cursorMove('right', select),
command,
],
"J": [
cursorMove('down', select, 10),
command,
],
"K": [
cursorMove('up', select, 10),
command,
],
"w": [SelectActions.restWord, command],
"b": [SelectActions.backWord, command],
"^": [cursorMove('wrappedLineFirstNonWhitespaceCharacter', select), command],
"$": [cursorMove('wrappedLineEnd', select), command],
"i": {
"w": [SelectActions.inside.word, command],
'"': [selectPair(true, '"'), command],
" ": [selectPair(true, " "), command],
"'": [selectPair(true, "'"), command],
"`": [selectPair(true, "`"), command],
"*": [selectPair(true, "*"), command],
"_": [selectPair(true, "_"), command],
"~": [selectPair(true, "~"), command],
"<": [selectPair(true, "<", ">"), command],
">": [selectPair(true, ">", "<"), command],
"(": ["extension.selectParenthesis", command],
")": ["extension.selectParenthesis", command],
"{": ["extension.selectCurlyBrackets", command],
"}": ["extension.selectCurlyBrackets", command],
"[": ["extension.selectSquareBrackets", command],
"]": ["extension.selectSquareBrackets", command],
},
"a": {
"w": [SelectActions.inside.word, command],
'"': [selectPair(false, '"'), command],
" ": [selectPair(false, " "), command],
"'": [selectPair(false, "'"), command],
"`": [selectPair(false, "`"), command],
"*": [selectPair(false, "*"), command],
"_": [selectPair(false, "_"), command],
"~": [selectPair(false, "~"), command],
"<": [selectPair(false, "<", ">"), command],
">": [selectPair(false, ">", "<"), command],
"(": ["extension.selectParenthesisOuter", command],
")": ["extension.selectParenthesisOuter", command],
"{": ["extension.selectCurlyBracketsOuter", command],
"}": ["extension.selectCurlyBracketsOuter", command],
"[": ["extension.selectSquareBracketsOuter", command],
"]": ["extension.selectSquareBracketsOuter", command],
},
// Jump till next typed character
"t": jumpMotion(true, true, false, 1, command),
"T": jumpMotion(true, true, true, 1, command),
// Jump past next typed character
"f": jumpMotion(false, true, false, 1, command),
"F": jumpMotion(false, true, true, 1, command),
}
}
const Mode = {
Insert: { command: "modalEditor.setMode", args: "insert" }
};
const EditorActions = {
change: recordChange([
{ command: ['deleteRight', 'modalEditor.setInsertMode'], when: "!_ctx.selection.isEmpty" },
{ command: 'modalEditor.setInsertMode', when: "_ctx.selection.isEmpty" }
]),
copy: [
"highlightOnCopy.run",
"editor.action.clipboardCopyAction",
"modalEditor.setNormalMode"
],
cut: recordChange([
"editor.action.clipboardCutAction",
"modalEditor.setNormalMode"
]),
paste: recordChange(repeatable(["editor.action.clipboardPasteAction", "modalEditor.setNormalMode"])),
paseLineBelow: recordChange(repeatable([
"editor.action.insertLineAfter",
"editor.action.clipboardPasteAction",
])),
delete: recordChange(repeatable([
{ command: 'editor.action.deleteLines', when: "_ctx.selection.isEmpty" },
{ command: 'deleteRight', when: "!_ctx.selection.isEmpty" },
"modalEditor.setNormalMode"
])),
duplicate: recordChange(repeatable(["geeebe.duplicateText", "modalEditor.setNormalMode"])),
search: {
find: findWidget(false, false, false),
repeatForward: [
// Move right to find the next instead of current
{ command: "cursorRight", when: "!_ctx.selection.isEmpty" },
// Find next
"editor.action.nextMatchFindAction",
"closeFindWidget"
],
repeatBackward: [
// Find previous
"editor.action.previousMatchFindAction",
"closeFindWidget"
]
}
}
let map = {
// Common keybindings (except for insert mode)
"": {
// Unmound mappings
"r": "",
"+": "",
"u": repeatable("undo"),
"U": repeatable("redo"),
// Change Mode
":": "modalEditor.setCommandMode",
"S": [
{
"command": "cursorMove",
"args": {
"to": "wrappedLineStart"
}
},
"modalEditor.setSelectMode",
"cursorDownSelect"
],
"<": repeatable("editor.action.outdentLines"),
">": repeatable("editor.action.indentLines"),
"y": EditorActions.copy,
"x": EditorActions.cut,
"D": EditorActions.duplicate,
"p": EditorActions.paste,
"P": EditorActions.paseLineBelow,
// replay last change
".": {
command: "modalEditor.replayRecord",
args: "change"
},
// Search
"/": EditorActions.search.find,
"'": "leap.find",
"&": "editor.action.startFindReplaceAction",
"*": "editor.action.nextSelectionMatchFindAction",
// Repeat search forward
"n": EditorActions.search.repeatForward,
";": EditorActions.search.repeatForward,
// Repeat search backward
"N": EditorActions.search.repeatBackward,
"e": [SelectActions.expand],
"r": [SelectActions.reduce],
"m": "editor.action.wordHighlight.next",
"M": "editor.action.wordHighlight.prev",
"g": {
"g": "cursorTop",
"G": "cursorBottom",
// Relative go-to-line
"d": "go-to-relative.goToLine",
"u": "go-to-relative.goToLineNegative",
// Go to to matching bracket
"m": "editor.action.jumpToBracket",
"M": {
"command": "editor.action.jumpToBracket",
"count": "2"
},
// Go to last change
"c": "workbench.action.navigateToLastEditLocation",
},
"G": "cursorBottom",
// UI Toggles
"z": {
"h": "workbench.action.toggleAuxiliaryBar",
"l": "workbench.action.toggleSidebarVisibility",
"j": "workbench.action.togglePanel",
"k": "workbench.action.toggleZenMode",
"z": "workbench.action.toggleZenMode",
"m": "workbench.action.toggleMaximizeEditorGroup",
// // Center Cursor on Screen
// "z": {
// "command": "revealLine",
// "args": "{ lineNumber: __line, at: 'center' }"
// }
},
"-": "vsnetrw.open",
"!": "extension.toggleBool",
",": "workbench.action.showCommands",
// Hitting enter creates a new line
"\n": recordChange([
"editor.action.insertLineAfter",
Mode.Insert
]),
// Changes
"i": recordChange(Mode.Insert),
"I": recordChange([
"cursorHome",
Mode.Insert
]),
"a": recordChange([
Mode.Insert,
"cursorRight"
]),
"A": recordChange([
"cursorLineEnd",
Mode.Insert
]),
"o": recordChange([
"editor.action.insertLineAfter",
Mode.Insert
]),
"O": recordChange([
"editor.action.insertLineBefore",
Mode.Insert
]),
"h": cursorMove('left'),
"j": cursorMove('down'),
"k": cursorMove('up'),
"l": cursorMove('right'),
// Page Up/Down
"J": cursorMove('down', false, 10),
"K": cursorMove('up', false, 10),
// Jump till next typed character
"t": jumpMotion(true, false, false, 1),
"T": jumpMotion(true, false, true, 1),
// Jump past next typed character
"f": jumpMotion(false, false, false, 1),
"F": jumpMotion(false, false, true, 1),
"s": withMotions("modalEditor.setSelectMode", true),
"d": {
...withMotions([EditorActions.delete, "modalEditor.setNormalMode"]),
"d": EditorActions.delete,
"s": {
"(": "bracketeer.removeBrackets",
")": "bracketeer.removeBrackets",
"[": "bracketeer.removeBrackets",
"]": "bracketeer.removeBrackets",
"{": "bracketeer.removeBrackets",
"}": "bracketeer.removeBrackets",
'"': "bracketeer.removeQuotes",
"'": "bracketeer.removeQuotes",
}
},
"c": {
...withMotions(EditorActions.change),
"c": EditorActions.change,
"s": {
"(": "bracketeer.changeBracketsTo",
")": "bracketeer.changeBracketsTo",
"[": "bracketeer.changeBracketsTo",
"]": "bracketeer.changeBracketsTo",
"{": "bracketeer.changeBracketsTo",
"}": "bracketeer.changeBracketsTo",
'"': "bracketeer.changeQuotesTo",
"'": "bracketeer.changeQuotesTo",
}
},
"y": {
...withMotions([EditorActions.copy, "modalEditor.setNormalMode"]),
"y": EditorActions.copy
},
"x": {
...withMotions([EditorActions.cut, "modalEditor.setNormalMode"]),
"x": EditorActions.cut
},
// Leader Namespace commands
" ": {
"-": "",
"w": "",
// Show hover
" ": "editor.action.showHover",
// Go to definition
"d": "editor.action.revealDefinition",
"D": "editor.action.revealDefinitionAside",
"p": "editor.action.peekDefinition",
"c": "",
// References
"r": "editor.action.referenceSearch.trigger",
"R": "references-plus.getAllReferences",
// Suggestions
".": "editor.action.triggerSuggest",
// Rename symbol
",": "editor.action.rename",
">": "editor.action.quickFix",
// Toggle Fold / Unfold
"f": "editor.toggleFold",
// Navigate breadcrumbs
// "b": "breadcrumbs.focusAndSelect",
// Bookmarks
"b": {
"b": "bookmarks.toggle",
"l": "bookmarks.listFromAllFiles",
"c": "bookmarks.clearFromAllFiles",
"n": "bookmarks.jumpToNext",
";": "bookmarks.jumpToNext",
"N": "bookmarks.jumpToPrevious",
},
"B": "bookmarks.toggleLabeled",
// Diagnostics
"e": "multiCommand.gotoNextProblem",
"E": "multiCommand.gotoPreviousProblem",
// Symbol navigation
"m": "editor.action.wordHighlight.next",
"M": "editor.action.wordHighlight.prev",
// Console log
"x": "turboConsoleLog.displayLogMessage",
"-": "",
"/": "editor.action.commentLine",
// Open terminal here
"t": "terminalHere.create",
// Save File
"s": "workbench.action.files.save",
// Close window
"q": "workbench.action.closeActiveEditor",
// Create/Join Window Splits
"v": "workbench.action.splitEditorRight",
"V": "workbench.action.splitEditorDown",
"U": "workbench.action.joinTwoGroups",
// Move Windows
"H": "workbench.action.moveEditorToLeftGroup",
"L": "workbench.action.moveEditorToRightGroup",
"J": "workbench.action.moveEditorToBelowGroup",
"K": "workbench.action.moveEditorToAboveGroup",
// Move Focus
"h": "workbench.action.focusLeftGroup",
"l": "workbench.action.focusRightGroup",
"j": "workbench.action.focusBelowGroup",
"k": "workbench.action.focusAboveGroup",
// Copilot
"i": "inlineChat.start",
"I": "workbench.panel.chat.view.copilot.focus",
},
},
"normal": {
"w": repeatable(reselect('cursorWordEndRight')),
"b": repeatable(reselect("cursorWordStartLeft")),
"^": cursorMove('wrappedLineFirstNonWhitespaceCharacter'),
"$": cursorMove('wrappedLineEnd'),
// set to select mode
"v": "modalEditor.setSelectMode"
},
"select": {
"w": repeatable([
findText(false, true, false, true, "\\w"),
"cursorWordStartRightSelect",
]),
"b": repeatable("cursorWordStartLeftSelect"),
"a": {
"w": repeatable(reselect("editor.action.addSelectionToNextFindMatch"))
},
"d": EditorActions.delete,
"y": EditorActions.copy,
"x": EditorActions.cut,
"D": EditorActions.duplicate,
// Move Selected Lines Up/Down
"J": [
"editor.action.moveLinesDownAction"
],
"K": [
"editor.action.moveLinesUpAction"
],
"/": "editor.action.commentLine",
"h": cursorMove('left', true),
"j": cursorMove('down', true),
"k": cursorMove('up', true),
"l": cursorMove('right', true),
"f": {
"": repeatable({
command: "modalEditor.findText",
computedArgs: true,
args: `{
text: _ctx.keys.charAt(_ctx.keys.length-1),
select: true,
}`
})
},
"F": {
"": repeatable({
command: "modalEditor.findText",
computedArgs: true,
args: `{
text: _ctx.keys.charAt(_ctx.keys.length-1),
backward: true,
select: true
}`
})
},
"t": {
"": repeatable({
command: "modalEditor.findText",
computedArgs: true,
args: `{
text: _ctx.keys.charAt(_ctx.keys.length-1),
till: false,
select: true
}`
})
},
"T": {
"": repeatable({
command: "modalEditor.findText",
computedArgs: true,
args: `{
text: _ctx.keys.charAt(_ctx.keys.length-1),
till: true,
backward: true,
select: true
}`
})
},
},
// Command mode
"command": {
"w": "workbench.action.files.save",
"q": "workbench.action.closeActiveEditor",
"d": "workbench.action.debug.start",
"r": "modalEditor.importPreset",
"theme": "workbench.action.selectTheme",
"reload": "workbench.action.reloadWindow",
"wrap": "surround.with",
"x": "workbench.extensions.action.installExtensions",
"git": "openInGithub.openInGitHubFile",
"config": "workbench.action.openSettingsJson",
"keys": "workbench.action.openGlobalKeybindings",
"p": "projectManager.listProjectsNewWindow"
}
};
module.exports = map;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment