nvim-hlslens

repository·main·Indexed 21 days ago

https://github.com/kevinhwang91/nvim-hlslens

A Neovim plugin that provides enhanced visual feedback for search matches by displaying match counts and relative positions via virtual text or floating windows. It includes support for custom lens rendering via override_lens, integration with nvim-ufo for peeking at folded lines, and the ability to export search ranges to the Quickfix or Location list. Requires Neovim 0.7.2 or later.

Tokens
2.5K
Snippets
9
Records
11
Agent score
25%

What's inside nvim-hlslens

  1. How to use nvim-hlslens

    main

    Once configured, nvim-hlslens displays search results as virtual text at the end of the line or in a floating window if space is limited.

    Start hlslens

    • Use / or ? to search (supports /s and /e offsets).
    • Or call the API: require('hlslens').start().

    Stop hlslens

    • Run the :nohlsearch command.
    • Or call the API: require('hlslens').stop().
    • Use <C-g> and <C-t> to move to the next and previous matches.
  2. Minimal configuration for nvim-hlslens

    main

    To use nvim-hlslens with standard search and jump behavior, call .setup() and map the following keys. This configuration ensures that pressing n, N, *, #, g*, or g# triggers the lens display.

    require('hlslens').setup()
    
    local kopts = {noremap = true, silent = true}
    
    vim.api.nvim_set_keymap('n', 'n', 
        [[<Cmd>execute('normal! ' . v:count1 . 'n')<CR><Cmd>lua require('hlslens').start()<CR>]], 
        kopts)
    vim.api.nvim_set_keymap('n', 'N', 
        [[<Cmd>execute('normal! ' . v:count1 . 'N')<CR><Cmd>lua require('hlslens').start()<CR>]], 
        kopts)
    vim.api.nvim_set_keymap('n', '*', [[*<Cmd>lua require('hlslens').start()<CR>]], kopts)
    vim.api.nvim_set_keymap('n', '#', [[#<Cmd>lua require('hlslens').start()<CR>]], kopts)
    vim.api.nvim_set_keymap('n', 'g*', [[g*<Cmd>lua require('hlslens').start()<CR>]], kopts)
    vim.api.nvim_set_keymap('n', 'g#', [[g#<Cmd>lua require('hlslens').start()<CR>]], kopts)
    
    vim.api.nvim_set_keymap('n', '<Leader>l', '<Cmd>noh<CR>', kopts)
  3. Integrate nvim-hlslens with nvim-ufo

    main

    To peek at folded lines using nvim-ufo, you must remap n and N to use hlslens.nNPeekWithUFO. Note that ufo might restore buffer-local keymaps, so you may need to re-apply a mapping for <CR> to switch to the preview window.

    -- packer
    use {'kevinhwang91/nvim-ufo', requires = 'kevinhwang91/promise-async'}
    
    local function nN(char)
        local ok, winid = hlslens.nNPeekWithUFO(char)
        if ok and winid then
            vim.keymap.set('n', '<CR>', function()
                return '<Tab><CR>'
            end, {buffer = true, remap = true, expr = true})
        end
    end
    
    vim.keymap.set({'n', 'x'}, 'n', function() nN('n') end)
    vim.keymap.set({'n', 'x'}, 'N', function() nN('N') end)
  4. Configure nvim-hlslens options

    main

    Pass an options table to require('hlslens').setup() to customize behavior.

    OptionDefaultDescription
    auto_enabletrueEnable nvim-hlslens automatically
    enable_incsearchtrueAdd lens for the current matched instance when incsearch is on
    calm_downfalseClear lens/highlighting when cursor leaves range or text changes
    nearest_onlyfalseOnly add lens for the nearest matched instance
    nearest_float_when'auto''auto': float if no room; 'always': always float; 'never': never float for nearest
    float_shadow_blend50Winblend for the nearest floating window
    virt_priority100Priority of virtual text (lower values overlay others)
    override_lensnilFunction for customizing the lens rendering
    require('hlslens').setup({
        calm_down = true,
        nearest_only = true,
        nearest_float_when = 'always'
    })
  5. Customize virtual text with override_lens

    main

    The override_lens option allows you to completely redefine how the lens is rendered using the render.setVirt method.

    Callback Signature: function(render, posList, nearest, idx, relIdx)

    • render: Table containing setVirt to set virtual text.
    • posList: Table of (row, col) positions.
    • nearest: Boolean indicating if this is the nearest match.
    • idx: Index of the match in posList.
    • relIdx: Relative index (negative if before current position, positive if after).
    require('hlslens').setup({
        override_lens = function(render, posList, nearest, idx, relIdx)
            local sfw = vim.v.searchforward == 1
            local indicator, text, chunks
            local absRelIdx = math.abs(relIdx)
            if absRelIdx > 1 then
                indicator = ('%d%s'):format(absRelIdx, sfw ~= (relIdx > 1) and '▲' or '▼')
            elseif absRelIdx == 1 then
                indicator = sfw ~= (relIdx == 1) and '▲' or '▼'
            else
                indicator = ''
            end
    
            local lnum, col = unpack(posList[idx])
            if nearest then
                local cnt = #posList
                if indicator ~= '' then
                    text = ('[%s %d/%d]'):format(indicator, idx, cnt)
                else
                    text = ('[%d/%d]'):format(idx, cnt)
                end
                chunks = {{' '}, {text, 'HlSearchLensNear'}}
            else
                text = ('[%s %d]'):format(indicator, idx)
                chunks = {{' '}, {text, 'HlSearchLens'}}
            end
            render.setVirt(0, lnum - 1, col - 1, chunks, nearest)
        end
    })
  6. Set highlight groups for hlslens

    main

    Use the following highlight groups to customize the appearance of the lens and matches:

    • HlSearchLensNear: Highlight the nearest virtual text for the floating window.
    • HlSearchLens: Highlight virtual text except for the nearest one.
    • HlSearchNear: Highlight the nearest matched instance.
    hi default link HlSearchNear CurSearch
    hi default link HlSearchLens WildMenu
    hi default link HlSearchLensNear CurSearch
  7. Manage hlslens state with enable, disable, and toggle

    main

    The hlslens module provides functions to control the plugin's lifecycle.

    • enable(): Activates the plugin, initializes namespaces, sets up autocommands for command-line events (/, ?, :), and starts the rendering engine if hlsearch is active.
    • disable(): Deactivates the plugin and cleans up all resources (disposables) created during initialization.
    • isEnabled(): Returns a boolean indicating whether the plugin is currently active.
    • start(): If the plugin is enabled, starts the rendering process.
    • stop(): If the plugin is enabled, stops the rendering process.
    local hlslens = require('hlslens')
    
    -- Enable the plugin
    hlslens.enable()
    
    -- Check status
    if hlslens.isEnabled() then
        hlslens.start()
    end
    
    -- Disable the plugin
    hlslens.disable()
  8. Export search ranges to Quickfix or Location list

    main

    The exportToQuickfix(isLocation) function allows you to take the current search ranges managed by hlslens and populate Neovim's Quickfix or Location list.

    • isLocation: A boolean. Set to true to use the Location list; set to false to use the Quickfix list.
    local hlslens = require('hlslens')
    
    -- Export to Quickfix list
    hlslens.exportToQuickfix(false)
    
    -- Export to Location list
    hlslens.exportToQuickfix(true)
  9. Use HlSearchLens commands

    main

    When hlslens.enable() is called, the following user commands are registered in Neovim:

    • :HlSearchLensToggle: Toggles the plugin state.
    • :HlSearchLensEnable: Enables the plugin.
    • :HlSearchLensDisable: Disables the plugin.
    :HlSearchLensToggle
    :HlSearchLensEnable
    :HlSearchLensDisable