I dug around Obsidian Vimrc Support Plugin source code to figure this out plus messed around a lot in Obsidian’s developer console. I’m probably doing some things inefficiently in this code, but it works.
It doesn’t require Obsidian Vimrc Support Plugin. And yes, I know you can show the operating mode with that plugin in Obsidian’s status bar thingy, but that’s not available on mobile without forcing it with CSS[1].
What this script does is change the color of the lil’ “More options” kebab menu icon on the top right of Obsidian’s header based on what your Vim operating mode is. Normal is green, insert is orange, visual is yellow, visual block is light yellow, and replace is red.
Point CodeScript Toolkit to it as your “Startup script path.”
exports.invoke = async (app) => {
function colorvimmode(mode) {
document
.querySelectorAll('.clickable-icon.view-action')
.forEach(el => {
const label = el.getAttribute('aria-label') || '';
if (label.startsWith("More options")) {
const vimStatusPromptMap = {
'normal': 'green',
'insert': 'orange',
'visual': 'yellow',
'visual block': 'lightyellow',
'replace': 'red',
}
const color = vimStatusPromptMap[mode];
if (color) {
el.style.setProperty('color', color);
} else {
el.style.removeProperty('color');
}
}
});
}
let vimmodechangewatcher;
let cminstance;
function vimlistner() {
const cm = app.workspace?.activeLeaf?.view?.currentMode?.cm?.cm;
if (!cm) {
colorvimmode();
const mode = app.workspace.activeLeaf.view.currentMode?.type;
if (mode !== 'preview' && app.workspace.activeLeaf.view?.file?.extension == 'md') colorvimmode('normal');
return;
} else {
colorvimmode(cm.state.vim.mode ?? "normal");
}
if (cm._vimModeListenerBound) return;
if (vimmodechangewatcher && cminstance) {
cminstance.off('vim-mode-change', vimmodechangewatcher);
cminstance._vimModeListenerBound = false;
}
cm.on('vim-mode-change', vimmodechangewatcher = (e) => {
colorvimmode(cm.state.vim.mode)
});
cm._vimModeListenerBound = true;
cminstance = cm;
}
vimlistner()
app.workspace.on('active-leaf-change', () => {
vimlistner()
});
app.workspace.on('layout-change', () => {
vimlistner()
});
}
Which I guess works, but I didn’t want to do that. ↩︎