Interested in using/teaching VIM editor keybindings?

As a VIM user I really wanted to be able to use VIM keybindings when testing out levels in Code Combat. I noticed the text editor being used was Ace which supports VIM keybindings, but I could’t find a way to enable them in the options. Fortunately I was able to make it work using the following javascript and a browser extension that allows you to inject arbitrary javascript:

function runVimLoader() {
  if (!window.vimLoader) {
    window.runCount = 0;
    window.vimLoader = window.setInterval(
      () => {
        let aceElement = document.getElementsByClassName('ace')[0];
        if (aceElement) {
          let editor = aceElement.env && aceElement.env.editor;
          if (editor) {
            let bindings = editor.getKeyboardHandler();
            if (bindings.$id !== 'ace/keyboard/vim') {
              editor.setKeyboardHandler('ace/keyboard/vim');
              console.log('Vim keybindings enabled.');
            }
          } else {
            console.log('No editor found.');
          }
        } else {
          console.log('No editor element found.');
        }
      },
      1000
    );
  }
}

const runInPageContext = (method, ...args) => {
  // The stringified method which will be parsed as a function object.
  const stringifiedMethod = method instanceof Function
    ? method.toString()
    : `() => { ${method} }`;

  // The stringified arguments for the method as JS code that will reconstruct the array.
  const stringifiedArgs = JSON.stringify(args);

  // The full content of the script tag.
  const scriptContent = `
    // Parse and run the method with its arguments.
    (${stringifiedMethod})(...${stringifiedArgs});

    // Remove the script element to cover our tracks.
    document.currentScript.parentElement
      .removeChild(document.currentScript);
  `;

  // Create a script tag and inject it into the document.
  const scriptElement = document.createElement('script');
  scriptElement.innerHTML = scriptContent;
  document.documentElement.prepend(scriptElement);
};

runInPageContext(runVimLoader);
1 Like