Skip to content

Commit 8e69abc

Browse files
committed
add matrix enter shortcut to vim
give the option to redefine the `insert new line below` to also append a \\ at end of the current line in a matrix environment. The enter is handled by simulating a enter press call. The cursor is moved to the current line and collum = line.length + 1. This may have unwanted consequences, other option would be to handle the key with vim but that relies on the vim keymap.
1 parent f938e27 commit 8e69abc

File tree

4 files changed

+90
-5
lines changed

4 files changed

+90
-5
lines changed

DOCS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,3 +301,6 @@ The shortcut should be a vim keybinding with no spaces. Some keybindings are not
301301
Keep in mind that the shortcut from visual -> select mode only works in visual mode, and the shortcut from select -> visual mode only works when something is selected and you are in insert mode.
302302

303303
Macros are not yet supported for visual snippets.
304+
305+
### Vim matrix shortcut \\\\
306+
Same key mapping rules apply. You can define or redefine `open a new line below` action, which also inserts \\\\ at the end of the current line if it's in a matrix environment.

src/features/editor_commands.ts

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import LatexSuitePlugin from "src/main";
55
import { Context } from "src/utils/context";
66
import { CodeMirrorEditor, Vim } from "src/utils/vim_types";
77
import { LatexSuitePluginSettings } from "src/settings/settings";
8+
import { runMatrixShortcuts } from "./matrix_shortcuts";
9+
import { insertNewlineAndIndent } from "@codemirror/commands";
10+
import { Transaction, Annotation, TransactionSpec } from "@codemirror/state";
811

912

1013
function boxCurrentEquation(view: EditorView) {
@@ -130,19 +133,20 @@ export const getEditorCommands = (plugin: LatexSuitePlugin) => {
130133

131134
export interface vimCommand {
132135
id: string;
133-
defineType: "defineMotion"| "defineOperator" | "defineAction";
136+
defineType: "defineMotion" | "defineOperator" | "defineAction";
134137
type: "action" | "operator" | "motion";
135138
action: (cm: CodeMirrorEditor) => void;
136139
key: string;
137140
context?: "normal" | "visual" | "replace" | "insert";
138141
}
142+
139143
export function getVimSelectModeCommand(settings: LatexSuitePluginSettings): vimCommand {
140144
return {
141145
id: "latex-suite-vim-select-mode",
142146
defineType: "defineAction",
143147
type: "action",
144148
// copies current selection and selects it again since changing vim modes deletes the selection
145-
action: (cm: CodeMirrorEditor) => {
149+
action: (cm: CodeMirrorEditor) => {
146150
//@ts-ignore undocumented object
147151
const vimObject: Vim | null = window?.CodeMirrorAdapter?.Vim;
148152
if (!vimObject) return;
@@ -154,6 +158,7 @@ export function getVimSelectModeCommand(settings: LatexSuitePluginSettings): vim
154158
context: "visual",
155159
}
156160
}
161+
157162
export function getVimVisualModeCommand(settings: LatexSuitePluginSettings): vimCommand {
158163
return {
159164
id: "latex-suite-vim-visual-mode",
@@ -173,9 +178,62 @@ export function getVimVisualModeCommand(settings: LatexSuitePluginSettings): vim
173178
context: "insert",
174179
}
175180
}
181+
182+
export function getVimRunMatrixEnterCommand(settings: LatexSuitePluginSettings): vimCommand {
183+
return {
184+
id: "latex-suite-vim-special-enter",
185+
defineType: "defineAction",
186+
type: "action",
187+
action: (cm: CodeMirrorEditor) => {
188+
//@ts-ignore
189+
const vimObj: Vim | null = window?.CodeMirrorAdapter?.Vim;
190+
if (!vimObj) return;
191+
const cursorLine: number = cm.getCursor().line;
192+
const line: string = cm.getLine(cursorLine);
193+
cm.setCursor({line: cursorLine, ch: line.length + 1})
194+
const view = EditorView.findFromDOM(cm.getWrapperElement());
195+
const ctx = Context.fromView(view);
196+
if (runMatrixShortcuts(view, ctx, "Enter", false)) {
197+
vimObj.enterInsertMode(cm);
198+
return;
199+
}
200+
// code taken from vim plugin, documentation is not clear on what this does
201+
const succes: boolean = insertNewlineAndIndent({
202+
state: cm.cm6.state,
203+
dispatch: (transaction: Transaction & TransactionSpec) => {
204+
const view: EditorView = cm.cm6;
205+
// should not fire by the design of insertNewlineAndIndent but its in the vim plugin so it is included
206+
if (view.state.readOnly) return;
207+
let type: string = "input.type.compose";
208+
if (cm.curOp && !cm.curOp.lastChange) type = "input.type.compose.start";
209+
if (Array.isArray(transaction.annotations)) {
210+
try {
211+
transaction.annotations.forEach((note: Annotation<string|number|boolean>) => {
212+
//@ts-ignore its "supposed" to be readonly but it is not
213+
if (note.value === "input") note.value = type;
214+
});
215+
} catch (e) {
216+
console.error(e);
217+
}
218+
} else {
219+
transaction.userEvent = type;
220+
}
221+
view.dispatch(transaction);
222+
}
223+
});
224+
if (!succes) console.error(`Failed to insert newline and indent latex-suite-insert-newline-and-indent`);
225+
// go into insert mode after the newline is inserted, otherwise macros rerun for some reason
226+
vimObj.enterInsertMode(cm);
227+
},
228+
key: settings.vimMatrixEnter,
229+
context: "normal",
230+
}
231+
}
232+
176233
export function getVimEditorCommands(settings: LatexSuitePluginSettings): vimCommand[] {
177234
return [
178235
getVimSelectModeCommand(settings),
179236
getVimVisualModeCommand(settings),
237+
getVimRunMatrixEnterCommand(settings),
180238
]
181239
}

src/settings/settings.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ interface LatexSuiteBasicSettings {
2929
vimEnabled: boolean;
3030
vimSelectMode: string;
3131
vimVisualMode: string;
32+
vimMatrixEnter: string;
3233

3334
}
3435

@@ -92,6 +93,7 @@ export const DEFAULT_SETTINGS: LatexSuitePluginSettings = {
9293
vimEnabled: false,
9394
vimSelectMode: "<C-g>",
9495
vimVisualMode: "<C-g>",
96+
vimMatrixEnter: "o",
9597
}
9698

9799
export function processLatexSuiteSettings(snippets: Snippet[], settings: LatexSuitePluginSettings):LatexSuiteCMSettings {

src/settings/settings_tab.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import LatexSuitePlugin from "../main";
77
import { DEFAULT_SETTINGS } from "./settings";
88
import { FileSuggest } from "./ui/file_suggest";
99
import { basicSetup } from "./ui/snippets_editor/extensions";
10-
import { getVimSelectModeCommand, vimCommand, getVimVisualModeCommand, getVimEditorCommands } from "src/features/editor_commands";
10+
import { getVimSelectModeCommand, vimCommand, getVimVisualModeCommand, getVimEditorCommands, getVimRunMatrixEnterCommand } from "src/features/editor_commands";
1111
import { Vim } from "src/utils/vim_types";
1212

1313

@@ -503,7 +503,7 @@ export class LatexSuiteSettingTab extends PluginSettingTab {
503503
const selectMode: Setting = new Setting(containerEl)
504504
.setName("Vim: Switch from visual mode to select mode")
505505
.setDesc(`maps the key to switch from visual mode to select mode.
506-
Keymap must be a vim keymap and can't contain any spaces.
506+
Keymap must be a vim keymap and can't contain any spaces. Use empty string to disable this feature.
507507
(select mode=insert keybindings)`)
508508
.addText((text) =>
509509
text.setPlaceholder(DEFAULT_SETTINGS.vimSelectMode)
@@ -527,7 +527,7 @@ export class LatexSuiteSettingTab extends PluginSettingTab {
527527
.setName("Vim: Switch from select mode to visual mode")
528528
.setDesc(`maps the key to switch from select mode to visual mode.
529529
must be a vim keymap and can't contain any spaces. Example <C-g><C-A-i> = Ctrl-g + Ctrl-Alt-i.
530-
Please check the vim keybinding first on another command like w before reporting it. Some keybindings like shift don't work due to the original vim plugin.
530+
Please check the vim keybinding first on another command like w before reporting it. Some keybindings like shift don't work due to the original vim plugin. Use empty string to disable this feature.
531531
(select mode=insert keybindings)`)
532532
.addText((text) =>{
533533
text.setPlaceholder(DEFAULT_SETTINGS.vimVisualMode)
@@ -547,6 +547,28 @@ export class LatexSuiteSettingTab extends PluginSettingTab {
547547
})
548548
});
549549
vimSettings.push(visualMode);
550+
const matrixEnter: Setting = new Setting(containerEl)
551+
.setName("Vim: run matrix enter")
552+
.setDesc(`maps the key to the action of inserting a new line below while appending \\\\ to the current line in a matrix environment.
553+
Use empty string to disable this feature.`)
554+
.addText((text) => {
555+
text.setPlaceholder(DEFAULT_SETTINGS.vimMatrixEnter)
556+
.setValue(this.plugin.settings.vimMatrixEnter)
557+
.onChange(async (value) => {
558+
const oldValue: string = this.plugin.settings.vimMatrixEnter;
559+
this.plugin.settings.vimMatrixEnter = value;
560+
await this.plugin.saveSettings();
561+
//@ts-ignore
562+
const vimObj: Vim | null = window?.CodeMirrorAdapter?.Vim;
563+
if (!vimObj) return;
564+
vimObj.unmap(oldValue, "normal");
565+
const command: vimCommand = getVimRunMatrixEnterCommand(this.plugin.settings);
566+
vimObj[command.defineType](command.id, command.action);
567+
vimObj.mapCommand(command.key, command.type, command.id, {}, { context: command.context });
568+
vimObj.unmap(oldValue, command.context)
569+
})
570+
});
571+
vimSettings.push(matrixEnter);
550572
// shows/hides the vim settings, since these settings are not needed if vim is not enabled.
551573
vimEnabled.addToggle((toggle) => {
552574
//@ts-ignore

0 commit comments

Comments
 (0)