* feat: define and expose obsidian-specific vim commands jumpToNextHeading: g] jumpToPreviousHeading: g[ * Implement jumpToPreviousLink motion * Refactoring and implementing jumpToNextLink * refactor: new jumpToPattern function that can be used for motions * refactor: renamed file and removed unneeded exports * fix: return last found index even if fewer than n instances found, instead of undefined * feat: implement moveUpSkipFold and moveDownSkipFold * refactor: extract out helper functions for defining obsidian vim actions * refactor: split vimApi.ts into two files * refactor: add comment * refactor: update names, types, etc * feat: followLinkUnderCursor action * feat: jumpToLink now jumps to both markdown and wiki links * refactor: rename fns * refactor: add docstrings / change var names * feat: implement looping around * refactor: cleaner implementation of jumpToPattern * Change mappings for next/prev heading to [[ and ]] * Tiny fixes * docs: update docs now that some more motions are provided by default --------- Co-authored-by: Erez Shermer <erezshermer@gmail.com>
4.1 KiB
Useful JS Snippets for jscommand and jsfile
In this document I will collect some of my and user-contributed ideas for how to utilize JS commands in the Vimrc plugin.
If you have interesting snippets, please contribute by opening a pull request!
Note that these examples are included for demonstration purposes, and many of them are now provided by default in this plugin. Their actual implementations can be found under motions/, which you can also use as reference (either for your own custom motions, or if you wish to submit a PR for a new motion to be provided by this plugin).
Jump to Next/Previous Markdown Heading
In a file you can call mdHelpers.js, put this:
// Taken from https://stackoverflow.com/questions/273789/is-there-a-version-of-javascripts-string-indexof-that-allows-for-regular-expr
function regexIndexOf(string, regex, startpos) {
var indexOf = string.substring(startpos || 0).search(regex);
return (indexOf >= 0) ? (indexOf + (startpos || 0)) : indexOf;
}
function regexLastIndexOf(string, regex, startpos) {
regex = (regex.global) ? regex : new RegExp(regex.source, "g" + (regex.ignoreCase ? "i" : "") + (regex.multiLine ? "m" : ""));
if(typeof (startpos) == "undefined") {
startpos = string.length;
} else if(startpos < 0) {
startpos = 0;
}
var stringToWorkWith = string.substring(0, startpos + 1);
var lastIndexOf = -1;
var nextStop = 0;
while((result = regex.exec(stringToWorkWith)) != null) {
lastIndexOf = result.index;
regex.lastIndex = ++nextStop;
}
return lastIndexOf;
}
function jumpHeading(isForward) {
const editor = view.editor;
let posToSearchFrom = editor.getCursor();
posToSearchFrom.line += isForward ? 1 : -1;
const cursorOffset = editor.posToOffset(posToSearchFrom);
const lookupToUse = isForward ? regexIndexOf : regexLastIndexOf;
let headingOffset = lookupToUse(editor.getValue(), /^#(#*) /gm, cursorOffset);
// If not found from the cursor position, try again from the document beginning (or reverse beginning)
if (headingOffset === -1)
headingOffset = lookupToUse(editor.getValue(), /^#(#*) /gm);
const newPos = editor.offsetToPos(headingOffset);
editor.setCursor(newPos);
}
Then in your .obsidian.vimrc file add the following:
exmap nextHeading jsfile mdHelpers.js {jumpHeading(true)}
exmap prevHeading jsfile mdHelpers.js {jumpHeading(false)}
nmap ]] :nextHeading
nmap [[ :prevHeading
Avoid unfolding folded sections
function moveUpSkipFold() {
view.editor.exec('goUp');
}
function moveDownSkipFold() {
view.editor.exec('goDown');
}
Then in your .obsidian.vimrc file add the following:
exmap upSkipFold jsfile mdHelpers.js {moveUpSkipFold()}
exmap downSkipFold jsfile mdHelpers.js {moveDownSkipFold()}
nmap k :upSkipFold
nmap j :downSkipFold
Vimwiki-like link navigation
This snippet allows to navigate next/previous links with Tab/Shift+Tab.
It mimicks the behaviour of vimwiki keybindings where you would press Tab several times to get to the link you want.
Append this function to the file mentioned above (after jumpHeading).
function jumpNextLink(isForward) {
const editor = view.editor;
let posToSearchFrom = editor.getCursor();
posToSearchFrom.line += isForward ? 0 : -1;
const cursorOffset = editor.posToOffset(posToSearchFrom);
const lookupToUse = isForward ? regexIndexOf : regexLastIndexOf;
let headingOffset = lookupToUse(editor.getValue(), /\[\[/g, cursorOffset);
// If not found from the cursor position, try again from the document beginning (or reverse beginning)
if (headingOffset === -1)
headingOffset = lookupToUse(editor.getValue(), /\[\[/g);
const newPos = editor.offsetToPos(headingOffset+2);
editor.setCursor(newPos);
}
Then put these lines in vimrc file to set the keybindings. Optionally (as in vimwiki) you can have ENTER bound to follow the link.
exmap nextLink jsfile mdHelpers.js {jumpNextLink(true)}
exmap prevLink jsfile mdHelpers.js {jumpNextLink(false)}
nmap <Tab> :nextLink
nmap <S-Tab> :prevLink
exmap followlink obcommand editor:follow-link
nmap <CR> :followlink