Persist settings using Greasemonkey

143 views
Skip to first unread message

Emiliano Heyns

unread,
Dec 14, 2018, 9:46:54 AM12/14/18
to Ajax.org Cloud9 Editor (Ace)
I use a LaTeX-editing service (Overleaf) which uses Ace for the editor component. I can do some simple keymappings in their editor in VI-mode (like ":nmap j gj"), but they don't persist. They previously used CodeMirror and there you could persist settings using a Greasemonkey script (https://www.overleaf.com/learn/how-to/How_can_I_define_custom_Vim_macros_in_a_vimrc_file_on_Overleaf%3F#Adding_Custom_Vim_Macros_in_FireFox_with_Greasemonkey). Is something similar possible for Ace? If so, how would I do it?

Harutyun Amirjanyan

unread,
Dec 14, 2018, 9:53:34 AM12/14/18
to ace-d...@googlegroups.com
Ace uses vim mode from CodeMirror, so the script will be very similar:

ace.require("ace/keyboard/vim").Vim.map('jj', '<Esc>', 'insert')

Linfeng Li

unread,
Apr 10, 2020, 3:09:16 PM4/10/20
to Ajax.org Cloud9 Editor (Ace)
How may I replicate the normal-mode mapping for <localleader>lv? As specified in the doc-page for vimtex, it performs a "forward jump" from code to PDF? On Overleaf, visually, this is done by clicking the following button. I wonder if it is possible to:
  1. Map <localleader> in ACE, and
  2. In particular, to actually call some "element" on the webpage?


I have set up a demo project, editable through this link:
https://www.overleaf.com/8672143158mhwnggyrkdnt

The button of interest may be hard to find: it is at the upper part of the vertical split in the middle.

I know very little about HTML/JavaScript, nor Tampermonkey. Please advise if I need to post questions to other forums.

Harutyun Amirjanyan

unread,
Apr 10, 2020, 4:59:19 PM4/10/20
to ace-d...@googlegroups.com
ace doen't support localleader, but it is possible to use the key for localleader directly in the mapping
you could use the following code snippet, but it's probably something common enough that oveleaf should support directly

ace.config.loadModule("ace/keyboard/vim", function(m) {
    m.Vim.mapCommand("\\lv", "action", "aceCommand", {
        name: "jumpToPdf"
    }, {
        context: "normal"
    })
})
document.querySelector(".ace_editor").env.editor.commands.addCommand({
    name: "jumpToPdf",
    exec: function() {
        document.querySelector(".synctex-control-goto-pdf").click()
    }
})

Linfeng Li

unread,
Apr 10, 2020, 9:45:24 PM4/10/20
to Ajax.org Cloud9 Editor (Ace)
Thanks a lot for your timely reply! I have updated this Github Gist with the full script that works for me. 

One more quick thing: can I assign the same jumpToPdf to ;lv in normal mode?  I should have mentioned that I use (semi-colon) as the localleader. ;lv has been muscle memory :)

Also, what is special about the syntax ".synctex-control-goto-pdf"? I found a string without the dot-prefix. Can I call other "clickable-element" on the page using the same syntax? How about:


  1. This button to hide file-tree ==> Can I map it to ,v in Normal mode? Ideally, this is the :VimtexTocToggle command from vimtex.Hide_FileTree.png

  2. Another button to hide PDF panel ==> Can we map it to some Commandline argument, callable as :ClosePDF? Its counterpart will be :ShowPDF
    OpenPDF.png vs Hide_PDF.png

All the best,

-Linfeng

Harutyun Amirjanyan

unread,
Apr 11, 2020, 5:16:03 AM4/11/20
to ace-d...@googlegroups.com
to use  ;lv  change the string  "\\lv" in mapCommand call  to ";lv", but because ";" is already used for something else you would need to  call vimKeyboard.Vim.unmap(";") first

".synctex-control-goto-pdf" is the classname of the button, you can use names of other buttons in a similar way

        // get current editor instance
        var editor = window._debug_editors[window._debug_editors.length -1]
        // vim keyboard plugin
        var vimKeyboard = window.ace.require("ace/keyboard/vim")
        ////////////////////////////////////////////////////////////
        // add custom keybindings - insert mode applies on insert
        vimKeyboard.Vim.map("jj", "<Esc>", "insert")
        // Equilivantly, from https://groups.google.com/d/msg/ace-discuss/gwXMzUM17I4/9B_acHBSCQAJ
        // window.ace.require("ace/keyboard/vim").Vim.map('jj', '<Esc>', 'insert')
        vimKeyboard.Vim.map("jk", "<Esc>", "insert")
        ////////////////////////////////////////////////////////////
        // Remapping one key to another is doable, in Normal mode
        // `nmap h j` can be defined as the following:
        vimKeyboard.Vim.map("h", "j", "normal")
        // Jump to PDF (forward search)
        editor.commands.addCommands([{

            name: "jumpToPdf",
            exec: function() {
                document.querySelector(".synctex-control-goto-pdf").click()
            }
        }, {
            name: "VimtexTocToggle",
            exec: function() {
                document.querySelector('a[tooltip*="the file-tree"]').click()
            }
        }, {
            name: "ClosePDF",
            exec: function() {
                document.querySelector('a[tooltip*="the PDF"]').click()
            }
        }, {
            name: "ShowPDF",
            exec: function() {
                document.querySelector('a[tooltip*="the PDF"]').click()
            }
        }])
        // add keybindings for jump to pdf
        vimKeyboard.Vim.mapCommand("\\v", "action", "aceCommand",
            { name: "VimtexTocToggle" }, { context: "normal" });
        vimKeyboard.Vim.mapCommand("\\lv", "action", "aceCommand",
            { name: "jumpToPdf" }, { context: "normal" });

        // bind to ;lv
        vimKeyboard.Vim.unmap(";")
        vimKeyboard.Vim.unmap(",")
        vimKeyboard.Vim.map(";lv", "\\lv", "normal")
        vimKeyboard.Vim.map(",v", "\\v", "normal")

        vimKeyboard.Vim.defineEx("ShowPDF", "", ()=>editor.commands.exec("ShowPDF"))
        vimKeyboard.Vim.defineEx("ClosePDF", "", ()=>editor.commands.exec("ClosePDF"))

        // set the modified keyboard handler for editor
        editor.setKeyboardHandler(vimKeyboard.handler)
        console.log("Custom key bindings applied")

Linfeng Li

unread,
Apr 11, 2020, 11:28:07 PM4/11/20
to Ajax.org Cloud9 Editor (Ace)
Amazing! You made my week!! 

Linfeng Li

unread,
Apr 12, 2020, 8:42:15 PM4/12/20
to Ajax.org Cloud9 Editor (Ace)
One intricate thing: how to let Ctrl+W do its job properly in Insert mode? For now, to delete word1 word2 [cursor-location] while placing the cursor at the [cursor-location], it takes 4 pressing of W while holding Ctrl down. In command-line, however, it takes 2 pressing of W, as intended.

I once defined the following Autohotkey sequence, but it is working imperfectly when deleting up to the start of a line. (^ stands for Ctrl; + stands for Shift).
    ^w::
        send ^+{Left}
        send ^+{Left}
        send {BS}
        send {space}
    return

I guess this would another line into the Greasemonkey script?

On Friday, December 14, 2018 at 9:53:34 AM UTC-5, Harutyun Amirjanyan wrote:

Linfeng Li

unread,
Oct 25, 2021, 11:27:08 PM10/25/21
to Ajax.org Cloud9 Editor (Ace)
To answer my own question: the simple solution is to use the Vivaldi browser, which allows the user to disable the native Ctrl+W keyboard shortcut that closes tabs. Once Ctrl+W is no longer occupied, the Ace editor gets the job done properly when one intend to delete a word with Ctrl+W under Vim bindings.
Reply all
Reply to author
Forward
0 new messages