2

I am migrating from a well tested and used for years init.vim to a new init.lua. The last two lines do not show errors but they do not work. The idea is to show an underline when I enter insert mode and remove it when in normal mode.

In init.lua

vim.cmd('highlight Cursorline cterm=NONE gui=NONE guibg=NONE')
vim.cmd('autocmd InsertEnter * highlight Cursorline cterm=underline gui=underline') -- Does not work
vim.cmd('autocmd InsertLeave * highlight Cursorline cterm=NONE gui=NONE')           -- Does not work

Full init.lua

-- General setting
vim.api.nvim_set_option('mouse', 'a')
vim.api.nvim_set_option('laststatus', 2)
vim.api.nvim_set_option('title', true)
vim.api.nvim_set_option('cursorline', true)
vim.api.nvim_set_option('clipboard', 'unnamedplus') -- Register * as clipboard
vim.api.nvim_set_option('ignorecase', true)         -- Search ignore case
vim.api.nvim_set_option('splitright', true)
vim.api.nvim_set_option('splitbelow', true)

-- Search
vim.api.nvim_set_option('hlsearch', true)           -- Highlight search
vim.api.nvim_set_option('incsearch', true)          -- set incremental search

-- UTF-8
vim.api.nvim_set_option('encoding', 'utf-8')
vim.api.nvim_set_option('fileencoding', 'utf-8')
--vim.api.nvim_set_option('termencoding', 'utf-8')

-- Tabs
vim.api.nvim_set_option('expandtab', false)
vim.api.nvim_set_option('tabstop', 4)
vim.api.nvim_set_option('shiftwidth', 4)
vim.api.nvim_set_option('textwidth', 100)
--vim.api.nvim_set_option('', )

-- Colors
vim.api.nvim_set_option('termguicolors', true)
vim.api.nvim_set_option('syntax', 'on')
vim.api.nvim_command('colorscheme oceanicnext')

-- SHORTCUTS --------------------------------------------------
-- General shortcuts
vim.api.nvim_set_keymap('n', 'cc', ':!make', {})
vim.api.nvim_set_keymap('n', '<S-s><S-s>', ':w<cr>', {})
vim.api.nvim_set_keymap('n', 'ls', ':buffers<cr>', {})
vim.api.nvim_set_keymap('n', 'gb', ':w<cr>:buffers<cr>:b<space>', {})
vim.api.nvim_set_keymap('n', '<space>', '/', {})

-- LaTeX shortcuts
vim.api.nvim_command('augroup filetype_tex')
    -- Begin End block
    vim.api.nvim_command('autocmd filetype tex inoremap <C-B> <ESC>YpkI\\begin{<ESC>A}<ESC>jI\\end{<ESC>A}<esc>kA')

    -- Greek letters
    vim.api.nvim_set_keymap('i','<C-g>a','\\alpha',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-g>b','\\beta',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-g>e','\\epsilon',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-g>g','\\gamma',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-g>l','\\lambda',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-g>m','\\mu',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-g>o','\\omega',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-g>s','\\sigma',{noremap=true})

    -- Pretty letter for sets
    vim.api.nvim_set_keymap('i','<C-b>c','\\mathbb{C}',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-b>k','\\mathbb{K}',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-b>n','\\mathbb{N}',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-b>r','\\mathbb{R}',{noremap=true})

    -- Vectors
    vim.api.nvim_set_keymap('i','<C-e>0','\\vec{0}',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-e>e','\\vec{e}',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-e>u','\\vec{u}',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-e>v','\\vec{v}',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-e>w','\\vec{w}',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-e>x','\\vec{x}',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-e>y','\\vec{y}',{noremap=true})
    vim.api.nvim_set_keymap('i','<C-e>z','\\vec{z}',{noremap=true})
vim.api.nvim_command('augroup end')


-- Relative line numbers
vim.api.nvim_set_option('number', true)
vim.api.nvim_set_option('relativenumber', true)
vim.cmd('augroup numbertoggle')
vim.cmd('autocmd!')
vim.cmd('autocmd BufEnter,FocusGained,InsertLeave * :set relativenumber')
vim.cmd('autocmd BufLeave,FocusLost,InsertEnter   * :set norelativenumber')
vim.cmd('autocmd BufLeave,FocusLost,InsertEnter   * :set number')
vim.cmd('augroup end')

-- Change aspect if in insert mode or not
vim.cmd('highlight Cursorline cterm=NONE gui=NONE guibg=NONE')
vim.cmd('autocmd InsertEnter * highlight Cursorline cterm=underline gui=underline')
vim.cmd('autocmd InsertLeave * highlight Cursorline cterm=NONE gui=NONE')
Samuel Gómez
  • 877
  • 1
  • 6
  • 7

2 Answers2

2

There is a bug, but it isn't the autocmd. You can tell if you :set cursorline in Vim that your highlights do work.

At this point you might be confused, because you already have:

vim.api.nvim_set_option('cursorline', true)

in your init.nvim. Should work, right?

Well, turns out not. Take a look at this:

:echo &cursorline
:lua vim.api.nvim_set_option('cursorline', true)
:echo &cursorline

In nvim 0.5.0-beta (built a couple weeks ago, nvim doesn't explicitly say when exactly), the output of this is two zeroes - not 0 and 1. As in, nvim_set_option('cursorline', true) has no effect. Real sus.

Let's look at :h 'cursorline' for a minute:

                        'cursorline' 'cul' 'nocursorline' 'nocul'
'cursorline' 'cul'      boolean (default off)
                        local to window
                        {not available when compiled without the +syntax
                        feature}
        Highlight the text line of the cursor with CursorLine hl-CursorLine.
        Useful to easily spot the cursor.  Will make screen redrawing slower.
        When Visual mode is active the highlighting isn't used to make it
        easier to see the selected text.

Look closely at local to window - this is why your code doesn't work. I'm not gonna pretend to understand why (because I don't use nvim that much and I personally find the lua api to be a mess), but nvim_set_options doesn't work for window variables. Interestingly enough, if you try passing an int instead of a bool to cursorline, the method will throw an error, but it'll still fail to set it like you'd expect. I'll get back to this bit at the end of the post.

Let's look at another example of that with an arbitrary variable; 'foldmarker'

:echo &foldmarker
> {{{,}}}
:lua vim.api.nvim_set_option('foldmarker', 'literally,anythingelse')
> (completes, no error)
:echo &foldmarker
> {{{,}}}
:lua vim.api.nvim_win_set_option(0, 'foldmarker', 'literally,anythingelse')
> (completes, no error)
:echo &foldmarker
> literally,anythingelse

As an exercise to the reader, the first step can be done with 'paste' as well. 'paste' is a global variable, and presumably as a consequence, nvim_win_set_option(0, 'paste', true) will throw

Interestingly enough, this works fine with just a normal :set:

:set foldmarker&
:echo &foldmarker
> {{{,}}}
:set foldmarker=literally,anythingelse
:echo &foldmarker
> literally,anythingelse

This means, all you need to do to fix your code is:

vim.api.nvim_win_set_option(0, 'cursorline', true)

Or alternatively:

vim.api.nvim_command('set cursorline')

TL;DR: the reason this works is because you're now actually setting cursorline. Window options can't be set with vim.api.nvim_set_option(name, value) (and I don't know why). Your autocmds are fine, but they don't work because cursorline is off. This is also unrelated to the highlights themselves; clearing the highlight just hides the cursorline, and doesn't disable the cursorline option. This also means your autocmds and highlights are fine in this case, but that it's your use of the wrong API function for a window variable that caused this problem.

And a final bit of advice: check the documentation of the variables you're setting. If it says window, you'll have to use nvim_win_set_option, and if it's a buffer, you need nvim_buf_set_option. These are also covered in nanotee's nvim lua guide - which also covers the meaning of the extra variable.


I'm not entirely sure if this behavior constitutes a bug or if it just is unintuitive API design, but I found a bug related to 'number' when researching bug reports after finishing the rest of the answer that may indicate that this is intended behavior. I'm not gonna be reporting it as a bug, or opening an issue to ask if this is intended, though, so this is mild speculation on my side. However, the evidence at hand still makes it look like it's intended.

This also means you have to make sure you know what type of variable you're setting if you're using the *_set_option() APIs. If it really is intended for nvim_set_option() to silently fail window options, you'll have to manually check to make sure you're using the right functions on the right variables, because the API functions aren't gonna tell you when you're doing it wrong. Or alternatively just use vim.api.nvim_command() - Vim's :set does set window variables properly.

Zoe
  • 27,060
  • 21
  • 118
  • 148
0

You can use: vim.o or vim.opt

  • Note: to reproduce :set option_name need use vim.o.option_name = true or vim.opt.option_name = true. For example: vim.opt.number = true
AlexElizard
  • 785
  • 4
  • 17