Vim Mode for editor.p5js.org

Vim mode in code mirror (p5js.org)

  1. // ==UserScript==
  2. // @name Vim Mode for editor.p5js.org
  3. // @namespace https://gist.github.com/sflanker/85899dd893f60ff47f52efd56765d5ec#file-vim-mode-editor-p5js-org-js
  4. // @version 0.2
  5. // @description Vim mode in code mirror (p5js.org)
  6. // @author dragulceo, sflanker
  7. // @license unlicense
  8. // @match https://editor.p5js.org/*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. console.log('Enabling Vim Mode for p5js.org!');
  16.  
  17. let tries = 0;
  18. const MAX_TRIES = 1000;
  19. const RETRY_EVERY_MS = 1000;
  20.  
  21. let hasVimJs = false;
  22. let hasVimStylesheet = false;
  23.  
  24. function enableVimMode() {
  25. console.log('enableVim');
  26. let enabled = false;
  27. const editors = document.querySelectorAll('.CodeMirror');
  28. if(editors && editors[0] && editors[0].CodeMirror) {
  29. // p5js.org privately imports CodeMirror
  30. if (!window.CodeMirror) {
  31. console.log('Exporting CodeMirror globally');
  32. window.CodeMirror = editors[0].CodeMirror.constructor;
  33. }
  34.  
  35. if (!window.CodeMirror.Vim || !window.CodeMirror.keyMap.vim) {
  36. if (!hasVimJs) {
  37. // Install vim keymap extension
  38. console.log('Installing vim keymap JavaScript.');
  39. const vimScript = document.createElement('script');
  40. vimScript.src='https://cdn.jsdelivr.net/npm/codemirror@5.58.2/keymap/vim.js';
  41. vimScript.crossorigin = 'anonymous';
  42. document.head.appendChild(vimScript);
  43. hasVimJs = true;
  44. } else {
  45. console.log('Waiting for vim keymap installation.');
  46. }
  47. } else {
  48. const editor = editors[0].CodeMirror;
  49. if(editor) {
  50. editor.setOption('keyMap', 'vim');
  51. editor.setOption('showCursorWhenSelecting', true);
  52. enabled = true;
  53. console.log ('Vim keymap successfully enabled.');
  54. }
  55. }
  56. } else {
  57. console.log('CodeMirror editor not found.');
  58. }
  59. if (!hasVimStylesheet) {
  60. let vimStyles = document.createElement('style');
  61. document.head.appendChild(vimStyles);
  62. vimStyles.type = 'text/css';
  63. vimStyles.appendChild(document.createTextNode(
  64. '.cm-fat-cursor .CodeMirror-cursor { width: auto !important; border: none !important; }\n' +
  65. '.cm-s-neo.cm-fat-cursor .CodeMirror-cursor { background-color: rgba(0, 0, 128, 0.5) !important; }\n' +
  66. // '.cm-s-neo.cm-fat-cursor .CodeMirror-cursor { background-color: rgba(255, 255, 255, 0.5); }\n' +
  67. '#codePanel .CodeMirror-dialog-bottom { background: #333; top: unset; bottom: 0; left: 0; width: calc(100% - 15px); display: flex; transform: none; box-shadow: unset; border-radius: unset; }\n' +
  68. '#codePanel .CodeMirror-dialog span:first-child { padding-left: 0.5em; flex-grow: 1; color: white; }\n' +
  69. '#codePanel .CodeMirror-dialog input { width: calc(100% - 1em); background-color: transparent; border: none; padding-left: 4px; }'
  70. ));
  71. hasVimStylesheet = true;
  72. }
  73. tries++;
  74. if(!enabled && tries < MAX_TRIES) {
  75. setTimeout(enableVimMode, RETRY_EVERY_MS);
  76. }
  77. }
  78.  
  79. enableVimMode();
  80. })();