Skip to content

Feature Request: Highlight Cursor Position #35

Closed

Description

@zz-f-g

Thx for this wonderful plugin!
It is useful to highlight the corresponding part in rendered markdown of the line where the cursor in vim located.

Activity

  1. jannis-baum commented on Sep 27, 2025

    @jannis-baum
    Owner

    Hello, happy you like the project! This is actually already possible with Vivify's customization options but it's not super simple right now. Here's how you could do it on the current version (and older versions) by setting up the following files.

    ~/.config/vivify/config.json:

    {
        "styles": "styles.css",
        "scripts": "client.js",
    }

    ~/.config/vivify/styles.css:

    .has-vim-cursor {
        border: 1px solid var(--bg-mark);
    }

    ~/.config/vivify/client.js:

    // websocket listener from
    // https://github.com/jannis-baum/Vivify/blob/f644c89e17ad7a320dbbf6e15146ebfde0a55344/static/client.mjs#L26-L34
    
    const ws = new WebSocket(`ws://localhost:${window.VIV_PORT}`);
    ws.addEventListener('message', async (event) => {
        const fields = event.data.toString().split(': ');
        if (fields.length < 2) return;
        const [key, ...values] = fields;
        const value = values.join(': ');
    
        switch (key) {
            // same setup as
            // https://github.com/jannis-baum/Vivify/blob/f644c89e17ad7a320dbbf6e15146ebfde0a55344/static/client.mjs#L59-L71
            // but highlight instead of scroll to element
            case 'SCROLL':
                // remove all existing highlights
                const highlightedElements = document.querySelectorAll('.has-vim-cursor');
                highlightedElements.forEach(el => el.classList.remove('has-vim-cursor'));
    
                let line = parseInt(value);
                while (line) {
                    const targets = document.querySelectorAll(`[data-source-line="${line - 1}"]`);
                    if (targets.length) {
                        // create new highlight
                        targets[0].classList.add('has-vim-cursor')
                        break;
                    }
                    line -= 1;
                }
                break;
        }
    });
    
    // communicate to server where we are so we get messages for this file
    // https://github.com/jannis-baum/Vivify/blob/f644c89e17ad7a320dbbf6e15146ebfde0a55344/static/client.mjs#L86-L88
    ws.addEventListener('open', () => {
        ws.send(`PATH: ${window.VIV_PATH}`);
    });

    and then it looks like this:

    Image


    That said, I think this is a cool idea and will discuss with the others if we may want to add it natively into Vivify. Either way, I am also currently reworking the customization options to make some things easier and enable lots of new ways to change Vivify with custom configs and will keep this in mind. So even if we don't add it natively it should hopefully soon be possible with a lot less code :) I'll try and remember to update you here with whatever comes up.

    Let me know if the setup above works for you or if you need help!

  2. jannis-baum commented on Sep 27, 2025

    @jannis-baum
    Owner

    Update: We decided to add the .has-vim-cursor class natively in jannis-baum/Vivify#264 but it will still take a while until the other things happening in that context are implemented and merged :) Thanks again for the idea!

  3. zz-f-g commented on Sep 29, 2025

    @zz-f-g
    Author

    Hello, happy you like the project! This is actually already possible with Vivify's customization options but it's not super simple right now. Here's how you could do it on the current version (and older versions) by setting up the following files.

    ~/.config/vivify/config.json:

    {
    "styles": "styles.css",
    "scripts": "client.js",
    }

    ~/.config/vivify/styles.css:

    .has-vim-cursor {
    border: 1px solid var(--bg-mark);
    }

    ~/.config/vivify/client.js:

    // websocket listener from
    // https://github.com/jannis-baum/Vivify/blob/f644c89e17ad7a320dbbf6e15146ebfde0a55344/static/client.mjs#L26-L34

    const ws = new WebSocket(ws://localhost:${window.VIV_PORT});
    ws.addEventListener('message', async (event) => {
    const fields = event.data.toString().split(': ');
    if (fields.length < 2) return;
    const [key, ...values] = fields;
    const value = values.join(': ');

    switch (key) {
        // same setup as
        // https://github.com/jannis-baum/Vivify/blob/f644c89e17ad7a320dbbf6e15146ebfde0a55344/static/client.mjs#L59-L71
        // but highlight instead of scroll to element
        case 'SCROLL':
            // remove all existing highlights
            const highlightedElements = document.querySelectorAll('.has-vim-cursor');
            highlightedElements.forEach(el => el.classList.remove('has-vim-cursor'));
    
            let line = parseInt(value);
            while (line) {
                const targets = document.querySelectorAll(`[data-source-line="${line - 1}"]`);
                if (targets.length) {
                    // create new highlight
                    targets[0].classList.add('has-vim-cursor')
                    break;
                }
                line -= 1;
            }
            break;
    }
    

    });

    // communicate to server where we are so we get messages for this file
    // https://github.com/jannis-baum/Vivify/blob/f644c89e17ad7a320dbbf6e15146ebfde0a55344/static/client.mjs#L86-L88
    ws.addEventListener('open', () => {
    ws.send(PATH: ${window.VIV_PATH});
    });

    and then it looks like this:

    Image Image

    That said, I think this is a cool idea and will discuss with the others if we may want to add it natively into Vivify. Either way, I am also currently reworking the customization options to make some things easier and enable lots of new ways to change Vivify with custom configs and will keep this in mind. So even if we don't add it natively it should hopefully soon be possible with a lot less code :) I'll try and remember to update you here with whatever comes up.

    Let me know if the setup above works for you or if you need help!

    I tried by adding the three files in ~/.config/vivify/. But it does not work like what in your video although I restart the vivify server or even restart the device.

    I use Ubuntu 24 LTS. I use neovim with the output of nvim --version:

    NVIM v0.11.4
    Build type: Release
    LuaJIT 2.1.1741730670
    

    And I use Lazyvim as plugin manager with config:

    return {
      { "jannis-baum/vivify.vim" }
    }
    

    I suspect whether there is extra config for the vim plugin other than vivify installed in the computer.

  4. tuurep commented on Sep 29, 2025

    @tuurep
    Collaborator

    I tried it and it works, but:

    {
        "styles": "styles.css",
        "scripts": "client.js",
    }
    

    This has a trailing comma which JSON doesn't allow but it fails quite silently in Viv :/

    So:

    {
        "styles": "styles.css",
        "scripts": "client.js"
    }
    

    Second, if you use light theme, the color --bg-mark is almost unnoticeable for the 1px border.

  5. zz-f-g commented on Sep 29, 2025

    @zz-f-g
    Author

    I tried it and it works, but:

    {
        "styles": "styles.css",
        "scripts": "client.js",
    }
    

    This has a trailing comma which JSON doesn't allow but it fails quite silently in Viv :/

    So:

    {
        "styles": "styles.css",
        "scripts": "client.js"
    }
    

    Second, if you use light theme, the color --bg-mark is almost unnoticeable for the 1px border.

    Thx! I'm not familiar with json grammar.

  6. tuurep commented on Sep 29, 2025

    @tuurep
    Collaborator

    Yeah I've debugged that issue before for longer than I'd like to admit because in many other languages it's even encouraged by linters/formatters to have that trailing comma 😄

  7. zz-f-g commented on Sep 29, 2025

    @zz-f-g
    Author

    I also notice that there is bug when the cursor go to multi line code blocks as is shown below:

    Image

    The box is still on the top line.

  8. jannis-baum commented on Sep 29, 2025

    @jannis-baum
    Owner

    Thanks @tuurep for replying and finding the issue! We should probably find a way to output errors for this kind of stuff. I'll add it to my rework config PR to-do

    I also notice that there is bug when the cursor go to multi line code blocks as is shown below:

    image

    The box is still on the top line.

    Good point. That seems to go back to the plugin we use to inject the line numbers not adding them for code blocks. Might be a good reason to drop that plugin and re-implement it ourselves correctly instead. I opened #256 on Vivify for that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions