├── .github ├── FUNDING.yml └── workflows │ ├── commitlint.yml │ ├── luacheck.yml │ └── stylua.yml ├── .luacheckrc ├── .stylua.toml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── doc └── nvim_context_vt.txt ├── lua └── nvim_context_vt │ ├── config.lua │ ├── init.lua │ └── utils.lua └── plugin └── nvim_context_vt.vim /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: andersevenrud 2 | patreon: andersevenrud 3 | custom: https://paypal.me/andersevenrud 4 | -------------------------------------------------------------------------------- /.github/workflows/commitlint.yml: -------------------------------------------------------------------------------- 1 | name: Commitlint 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | jobs: 8 | commitlint: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | with: 13 | fetch-depth: 0 14 | - uses: wagoid/commitlint-github-action@v4 15 | 16 | -------------------------------------------------------------------------------- /.github/workflows/luacheck.yml: -------------------------------------------------------------------------------- 1 | name: Luacheck 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | jobs: 8 | lint: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | with: 13 | fetch-depth: 0 14 | - uses: Jayrgo/luacheck-action@v1 15 | with: 16 | files: '.' 17 | -------------------------------------------------------------------------------- /.github/workflows/stylua.yml: -------------------------------------------------------------------------------- 1 | name: Stylua 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | jobs: 8 | stylua: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | with: 13 | fetch-depth: 0 14 | - uses: JohnnyMorganz/stylua-action@v3 15 | with: 16 | version: v0.17.1 17 | token: ${{ secrets.GITHUB_TOKEN }} 18 | args: --check . 19 | -------------------------------------------------------------------------------- /.luacheckrc: -------------------------------------------------------------------------------- 1 | ignore = { 2 | "212", 3 | } 4 | 5 | read_globals = { 6 | "vim", 7 | } 8 | 9 | new_globals = { 10 | vim = { 11 | fields = { 12 | g = { 13 | other_fields = true, 14 | }, 15 | }, 16 | }, 17 | } 18 | -------------------------------------------------------------------------------- /.stylua.toml: -------------------------------------------------------------------------------- 1 | quote_style = "AutoPreferSingle" 2 | indent_type = "Spaces" 3 | indent_width = 4 4 | column_width = 120 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guide 2 | 3 | Pull requests are very welcome and this guide will walk through some of the basics 4 | on how to contribute. 5 | 6 | ## Code style 7 | 8 | This project uses [stylua](https://github.com/JohnnyMorganz/StyLua) and [luacheck](https://github.com/mpeterv/luacheck) 9 | to check the code for potential errors and styling issues. 10 | 11 | It is adviced to install these utilities and check your code before submission. Most modern IDEs and editors have some 12 | way of alerting you with diagnostics using the provided configurations. 13 | 14 | ## Commit messages 15 | 16 | This project uses the [conventional commits](https://conventionalcommits.org/) specification for git commit messages. 17 | 18 | ## Modifying context virtual text 19 | 20 | The file `lua/nvim_context_vt/config.lua` contains the tables required for resolving virtual text. 21 | 22 | Use the command `:NvimContextVtDebug` to show the context for the current line to inspect the tree of nodes. 23 | 24 | * `targets`: valid node targets 25 | * `ignore_root_targets`: invalid root node targets 26 | * `line_targets`: valid node targets used for line targets and not inline 27 | * `line_ft`: filetypes that should use `line_targets` 28 | 29 | Commit the changes with the message `feat: support X` or `feat: improve Y`, etc. into your fork and open a pull-request. 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Harings Rob 4 | Copyright (c) Anders Evenrud 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nvim_context_vt 2 | 3 | Shows virtual text of the current context after functions, methods, statements, etc. 4 | 5 | ![nvim_context_vt](https://user-images.githubusercontent.com/866743/128077347-051430c4-2c89-4161-aa48-5a5793ec8499.gif) 6 | 7 | ## How to install 8 | 9 | Use your favourite package manager and install [treesitter](https://github.com/nvim-treesitter/nvim-treesitter) 10 | alongside this plugin. No configuration is required out of the box. 11 | 12 | ## Advanced usage 13 | 14 | To customize the behavior use the setup function: 15 | 16 | ```lua 17 | require('nvim_context_vt').setup({ 18 | -- Enable by default. You can disable and use :NvimContextVtToggle to maually enable. 19 | -- Default: true 20 | enabled = true, 21 | 22 | -- Override default virtual text prefix 23 | -- Default: '-->' 24 | prefix = '', 25 | 26 | -- Override the internal highlight group name 27 | -- Default: 'ContextVt' 28 | highlight = 'CustomContextVt', 29 | 30 | -- Disable virtual text for given filetypes 31 | -- Default: { 'markdown' } 32 | disable_ft = { 'markdown' }, 33 | 34 | -- Disable display of virtual text below blocks for indentation based languages like Python 35 | -- Default: false 36 | disable_virtual_lines = false, 37 | 38 | -- Same as above but only for spesific filetypes 39 | -- Default: {} 40 | disable_virtual_lines_ft = { 'yaml' }, 41 | 42 | -- How many lines required after starting position to show virtual text 43 | -- Default: 1 (equals two lines total) 44 | min_rows = 1, 45 | 46 | -- Same as above but only for spesific filetypes 47 | -- Default: {} 48 | min_rows_ft = {}, 49 | 50 | -- Custom virtual text node parser callback 51 | -- Default: nil 52 | custom_parser = function(node, ft, opts) 53 | local utils = require('nvim_context_vt.utils') 54 | 55 | -- If you return `nil`, no virtual text will be displayed. 56 | if node:type() == 'function' then 57 | return nil 58 | end 59 | 60 | -- This is the standard text 61 | return opts.prefix .. ' ' .. utils.get_node_text(node)[1] 62 | end, 63 | 64 | -- Custom node validator callback 65 | -- Default: nil 66 | custom_validator = function(node, ft, opts) 67 | -- Internally a node is matched against min_rows and configured targets 68 | local default_validator = require('nvim_context_vt.utils').default_validator 69 | if default_validator(node, ft) then 70 | -- Custom behaviour after using the internal validator 71 | if node:type() == 'function' then 72 | return false 73 | end 74 | end 75 | 76 | return true 77 | end, 78 | 79 | -- Custom node virtual text resolver callback 80 | -- Default: nil 81 | custom_resolver = function(nodes, ft, opts) 82 | -- By default the last node is used 83 | return nodes[#nodes] 84 | end, 85 | }) 86 | ``` 87 | 88 | ## Commands 89 | 90 | * `:NvimContextVtToggle` - Enable/disable context virtual text 91 | 92 | ## Debug 93 | 94 | If you don't see the expected context vitual text, run `:NvimContextVtDebug` to print out the 95 | context tree. Use this information to open a pull-request or an issue to add support. 96 | 97 | ## License 98 | 99 | MIT 100 | -------------------------------------------------------------------------------- /doc/nvim_context_vt.txt: -------------------------------------------------------------------------------- 1 | *nvim_context_vt* 2 | 3 | Shows virtual text of the current context after functions, methods, statements, etc. 4 | 5 | ================================================================================ 6 | CONTENTS *nvim_context_vt-contents* 7 | 8 | 1. nvim_context_vt...............................................|nvim_context_vt| 9 | 1.1. How to install..................................|nvim_context_vt-install| 10 | 1.2. Advanced usage.................................|nvim_context_vt-advanced| 11 | 1.3. Commands.......................................|nvim_context_vt-commands| 12 | 1.4. Debug.............................................|nvim_context_vt-debug| 13 | 1.5. License.........................................|nvim_context_vt-license| 14 | 15 | -------------------------------------------------------------------------------- 16 | HOW TO INSTALL *nvim_context_vt-install* 17 | 18 | Use your favourite package manager and install treesitter (https://github.com/nvim-treesitter/nvim-treesitter) 19 | alongside this plugin. No configuration is required out of the box. 20 | 21 | -------------------------------------------------------------------------------- 22 | ADVANCED USAGE *nvim_context_vt-advanced* 23 | 24 | To customize the behavior use the setup function: 25 | > 26 | require('nvim_context_vt').setup({ 27 | -- Enable by default. You can disable and use :NvimContextVtToggle to maually enable. 28 | -- Default: true 29 | enabled = true, 30 | 31 | -- Override default virtual text prefix 32 | -- Default: '-->' 33 | prefix = '', 34 | 35 | -- Override the internal highlight group name 36 | -- Default: 'ContextVt' 37 | highlight = 'CustomContextVt', 38 | 39 | -- Disable virtual text for given filetypes 40 | -- Default: { 'markdown' } 41 | disable_ft = { 'markdown' }, 42 | 43 | -- Disable display of virtual text below blocks for indentation based languages like Python 44 | -- Default: false 45 | disable_virtual_lines = false, 46 | 47 | -- Same as above but only for spesific filetypes 48 | -- Default: {} 49 | disable_virtual_lines_ft = { 'yaml' }, 50 | 51 | -- How many lines required after starting position to show virtual text 52 | -- Default: 1 (equals two lines total) 53 | min_rows = 1, 54 | 55 | -- Same as above but only for spesific filetypes 56 | -- Default: {} 57 | min_rows_ft = {}, 58 | 59 | -- Custom virtual text node parser callback 60 | -- Default: nil 61 | custom_parser = function(node, ft, opts) 62 | local utils = require('nvim_context_vt.utils') 63 | 64 | -- If you return `nil`, no virtual text will be displayed. 65 | if node:type() == 'function' then 66 | return nil 67 | end 68 | -- This is the standard text 69 | return opts.prefix .. ' ' .. utils.get_node_text(node)[1] 70 | end, 71 | 72 | -- Custom node validator callback 73 | -- Default: nil 74 | custom_validator = function(node, ft, opts) 75 | -- Internally a node is matched against min_rows and configured targets 76 | local default_validator = require('nvim_context_vt.utils').default_validator 77 | if default_validator(node, ft) then 78 | -- Custom behaviour after using the internal validator 79 | if node:type() == 'function' then 80 | return false 81 | end 82 | end 83 | return false 84 | end, 85 | 86 | -- Custom node virtual text resolver callback 87 | -- Default: nil 88 | custom_resolver = function(nodes, ft, opts) 89 | -- By default the last node is used 90 | return nodes[#nodes] 91 | end, 92 | }) 93 | < 94 | 95 | -------------------------------------------------------------------------------- 96 | COMMANDS *nvim_context_vt-commands* 97 | 98 | * `:NvimContextVtToggle` - Enable/disable context virtual text 99 | 100 | -------------------------------------------------------------------------------- 101 | DEBUG *nvim_context_vt-debug* 102 | 103 | If you don't see the expected context vitual text, run `:NvimContextVtDebug` to print out the 104 | context tree. Use this information to open a pull-request or an issue to add support. 105 | 106 | -------------------------------------------------------------------------------- 107 | LICENSE *nvim_context_vt-license* 108 | 109 | MIT 110 | 111 | vim:tw=78:ts=4:et:ft=help:norl: 112 | -------------------------------------------------------------------------------- /lua/nvim_context_vt/config.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | M.default_opts = { 4 | enabled = true, 5 | min_rows = 1, 6 | min_rows_ft = {}, 7 | custom_parser = nil, 8 | custom_validator = nil, 9 | custom_resolver = nil, 10 | highlight = 'ContextVt', 11 | disable_ft = { 'markdown' }, 12 | disable_virtual_lines = false, 13 | disable_virtual_lines_ft = {}, 14 | prefix = '-->', 15 | } 16 | 17 | M.targets = { 18 | 'function', 19 | 'arguments', 20 | 'case', 21 | 22 | 'local_function', 23 | 'arrow_function', 24 | 25 | 'class_definition', 26 | 'method_definition', 27 | 'function_definition', 28 | 29 | 'method_declaration', 30 | 'function_declaration', 31 | 'lexical_declaration', 32 | 'class_declaration', 33 | 'interface_declaration', 34 | 'enum_declaration', 35 | 'type_declaration', 36 | 'field_declaration', 37 | 38 | 'catch_clause', 39 | 'finally_clause', 40 | 41 | 'if_expression', 42 | 'switch_expression', 43 | 'call_expression', 44 | 'struct_expression', 45 | 'test_expression', 46 | 'while_expression', 47 | 'for_expression', 48 | 49 | 'try_statement', 50 | 'if_statement', 51 | 'while_statement', 52 | 'foreach_statement', 53 | 'for_statement', 54 | 'for_in_statement', 55 | 'with_statement', 56 | 'case_statement', 57 | 'switch_statement', 58 | 59 | -- rust 60 | 'match_expression', 61 | 'if_let_expression', 62 | 'tuple_struct_pattern', 63 | 'while_let_expression', 64 | 'loop_expression', 65 | 'function_item', 66 | 'struct_item', 67 | 'unsafe_block', 68 | 69 | -- ruby 70 | 'class', 71 | 'module', 72 | 'method', 73 | 'call', 74 | 'if', 75 | 'while', 76 | 'for', 77 | 78 | -- typescript/javascript 79 | 'export_statement', 80 | 'property_signature', 81 | 'switch_case', 82 | 83 | -- lua, 84 | 'local_variable_declaration', 85 | 'variable_declaration', 86 | 'assignment_statement', 87 | 'function_call', 88 | 'expression_list', 89 | 'field', 90 | 91 | -- go 92 | 'type_spec', 93 | 'short_var_declaration', 94 | 'defer_statement', 95 | 'expression_switch_statement', 96 | 'composite_literal', 97 | 'func_literal', 98 | 'go_statement', 99 | 'select_statement', 100 | 'communication_case', 101 | 'default_case', 102 | 'struct_type', 103 | 104 | -- cpp 105 | 'for_range_loop', 106 | 107 | -- python 108 | 'list', 109 | 'pair', 110 | 'assignment', 111 | 'decorated_definition', 112 | 113 | -- yaml 114 | 'block_mapping_pair', 115 | 116 | -- css / sass 117 | 'rule_set', 118 | 'mixin_statement', 119 | 120 | -- vala 121 | 'class_constructor_definition', 122 | 'class_destructor', 123 | 124 | -- bash 125 | 'case_item', 126 | 'elif_clause', 127 | 128 | -- html / vue / jsx 129 | 'element', 130 | 'template_element', 131 | 'style_element', 132 | 'script_element', 133 | 'jsx_element', 134 | 'jsx_expression', 135 | 'jsx_fragment', 136 | 137 | -- commonlisp 138 | 'list_lit', 139 | 'defun', 140 | 141 | -- elixir 142 | 'anonymous_function', 143 | 'do_block', 144 | 'tuple', 145 | 'map', 146 | } 147 | 148 | M.ignore_root_targets = { 149 | 'program', 150 | 'document', 151 | } 152 | 153 | M.line_targets = { 154 | 'function_definition', 155 | 'class_definition', 156 | 'if_statement', 157 | 'try_statement', 158 | 'with_statement', 159 | 'for_statement', 160 | 161 | -- haskell 162 | 'function', 163 | 164 | -- python 165 | 'decorated_definition', 166 | 167 | -- yaml 168 | 'block_mapping_pair', 169 | } 170 | 171 | M.line_ft = { 172 | 'haskell', 173 | 'python', 174 | 'yaml', 175 | } 176 | 177 | return M 178 | -------------------------------------------------------------------------------- /lua/nvim_context_vt/init.lua: -------------------------------------------------------------------------------- 1 | local config = require('nvim_context_vt.config') 2 | local utils = require('nvim_context_vt.utils') 3 | 4 | local M = {} 5 | local ns = vim.api.nvim_create_namespace('context_vt') 6 | local opts = config.default_opts 7 | 8 | function M.setup(user_opts) 9 | opts = vim.tbl_extend('force', config.default_opts, user_opts or {}) 10 | end 11 | 12 | function M.ft_to_lang(ft) 13 | local result = vim.treesitter.language.get_lang(ft) 14 | if result then 15 | return result 16 | else 17 | ft = vim.split(ft, '.', { plain = true })[1] 18 | return vim.treesitter.language.get_lang(ft) or ft 19 | end 20 | end 21 | 22 | --- Gets the language of a given buffer 23 | ---@param bufnr number? or current buffer 24 | ---@return string 25 | function M.get_buf_lang(bufnr) 26 | bufnr = bufnr or vim.api.nvim_get_current_buf() 27 | return M.ft_to_lang(vim.api.nvim_buf_get_option(bufnr, 'ft')) 28 | end 29 | 30 | function M.show_debug() 31 | local ft = M.get_buf_lang() 32 | local result = utils.find_virtual_text_nodes(function() 33 | return true 34 | end, ft, opts) 35 | 36 | ---@type TSNode[][] 37 | local values = vim.tbl_values(result) 38 | ---@type number[] 39 | local lines = vim.tbl_keys(result) 40 | 41 | for index, nodes in ipairs(values) do 42 | local prefix = string.rep(' ', #values - index) 43 | local line = lines[index] 44 | 45 | for _, node in ipairs(nodes) do 46 | print(prefix .. line .. ':' .. node:type() .. ' ' .. utils.default_parser(node, ft, opts)) 47 | end 48 | end 49 | end 50 | 51 | function M.toggle_context() 52 | if opts.enabled then 53 | opts.enabled = false 54 | M.hide_context() 55 | else 56 | opts.enabled = true 57 | M.show_context() 58 | end 59 | end 60 | 61 | function M.show_context() 62 | local ft = M.get_buf_lang() 63 | if not opts.enabled or vim.tbl_contains(opts.disable_ft, ft) then 64 | return 65 | end 66 | 67 | local validate = opts.custom_validator or utils.default_validator 68 | local resolve = opts.custom_resolver or utils.default_resolver 69 | local parse = opts.custom_parser or utils.default_parser 70 | 71 | vim.api.nvim_buf_clear_namespace(0, ns, 0, -1) 72 | 73 | local result = utils.find_virtual_text_nodes(validate, ft, opts) 74 | local create_vt = utils.create_virtual_text_factory(parse, ft, opts) 75 | 76 | for line, nodes in pairs(result) do 77 | local node = resolve(nodes, ft, opts) 78 | local vt = create_vt(node, nodes) 79 | 80 | if vt then 81 | vim.api.nvim_buf_set_extmark(0, ns, line, 0, vt) 82 | end 83 | end 84 | end 85 | 86 | function M.hide_context() 87 | vim.api.nvim_buf_clear_namespace(0, ns, 0, -1) 88 | end 89 | 90 | return M 91 | -------------------------------------------------------------------------------- /lua/nvim_context_vt/utils.lua: -------------------------------------------------------------------------------- 1 | local config = require('nvim_context_vt.config') 2 | local M = {} 3 | 4 | -- This is from nvim-treesitter 5 | function M.get_node_text(node, bufnr) 6 | bufnr = bufnr or vim.api.nvim_get_current_buf() 7 | if not node then 8 | return {} 9 | end 10 | 11 | local start_row, start_col, end_row, end_col = vim.treesitter.get_node_range(node) 12 | if start_row ~= end_row then 13 | local lines = vim.api.nvim_buf_get_lines(bufnr, start_row, end_row + 1, false) 14 | lines[1] = string.sub(lines[1], start_col + 1) 15 | if #lines == end_row - start_row + 1 then 16 | lines[#lines] = string.sub(lines[#lines], 1, end_col) 17 | end 18 | return lines 19 | else 20 | local line = vim.api.nvim_buf_get_lines(bufnr, start_row, start_row + 1, false)[1] 21 | return line and { string.sub(line, start_col + 1, end_col) } or {} 22 | end 23 | end 24 | 25 | M.default_parser = function(node, _, opts) 26 | return opts.prefix .. ' ' .. M.get_node_text(node, 0)[1] 27 | end 28 | 29 | ---@param node TSNode 30 | ---@param ft string 31 | ---@param opts table 32 | ---@return boolean 33 | M.default_validator = function(node, ft, opts) 34 | ---@type integer 35 | local min_rows = opts.min_rows_ft[ft] or opts.min_rows 36 | if vim.tbl_contains(config.targets, node:type()) then 37 | return node:end_() > node:start() + min_rows 38 | end 39 | return false 40 | end 41 | 42 | ---@param nodes TSNode[] 43 | ---@return TSNode 44 | M.default_resolver = function(nodes) 45 | return nodes[#nodes] 46 | end 47 | 48 | ---@param validator fun(node: TSNode, ft: string, opts: table): boolean 49 | ---@param ft string 50 | ---@param opts table 51 | ---@return table> 52 | M.find_virtual_text_nodes = function(validator, ft, opts) 53 | local result = {} ---@type table> 54 | local ok, node = pcall(vim.treesitter.get_node) 55 | if not ok then 56 | return result 57 | end 58 | 59 | while node ~= nil and not vim.tbl_contains(config.ignore_root_targets, node:type()) do 60 | if validator(node, ft, opts) then 61 | local target_line = node:end_() 62 | if not result[target_line] then 63 | result[target_line] = {} 64 | end 65 | table.insert(result[target_line], node) 66 | end 67 | 68 | local pnode = node:parent() 69 | if pnode == node then 70 | -- in case of dead loop 71 | break 72 | else 73 | node = pnode 74 | end 75 | end 76 | 77 | return result 78 | end 79 | 80 | ---@param parser fun(node: TSNode, ft: string, opts: table): string 81 | ---@param ft string 82 | ---@param opts table 83 | ---@return fun(node: TSNode, nodes: TSNode[]): table? 84 | M.create_virtual_text_factory = function(parser, ft, opts) 85 | local is_line_ft = vim.tbl_contains(config.line_ft, ft) 86 | local skip_line_ft = opts.disable_virtual_lines or vim.tbl_contains(opts.disable_virtual_lines_ft, ft) 87 | 88 | ---@param nodes TSNode[] 89 | ---@return table 90 | local function lines_from_nodes(nodes) 91 | local lines = {} 92 | for _, n in ipairs(nodes) do 93 | local vt = parser(n, ft, opts) 94 | if vt then 95 | local _, col = n:start() 96 | local prefix = string.rep(' ', col) 97 | table.insert(lines, { { prefix .. vt, opts.highlight } }) 98 | end 99 | end 100 | return lines 101 | end 102 | 103 | ---@param node TSNode 104 | ---@return table? 105 | local function text_from_node(node) 106 | local vt = parser(node, ft, opts) 107 | if vt then 108 | return { virt_text = { { vt, opts.highlight } }, hl_mode = 'combine' } 109 | end 110 | return nil 111 | end 112 | 113 | return function(node, nodes) 114 | if is_line_ft and vim.tbl_contains(config.line_targets, node:type()) then 115 | if skip_line_ft then 116 | return nil 117 | end 118 | 119 | local lines = lines_from_nodes(nodes) 120 | if #lines > 0 then 121 | return { virt_lines = lines, hl_mode = 'combine' } 122 | end 123 | end 124 | 125 | return text_from_node(node) 126 | end 127 | end 128 | 129 | return M 130 | -------------------------------------------------------------------------------- /plugin/nvim_context_vt.vim: -------------------------------------------------------------------------------- 1 | highlight default link ContextVt Comment 2 | 3 | command NvimContextVtDebug lua require'nvim_context_vt'.show_debug() 4 | command NvimContextVtToggle lua require'nvim_context_vt'.toggle_context() 5 | 6 | autocmd CursorMoved * lua require 'nvim_context_vt'.show_context() 7 | autocmd CursorMovedI * lua require 'nvim_context_vt'.show_context() 8 | --------------------------------------------------------------------------------