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')
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.
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
I am currently using vim-airline in my macvim and I want to display the status of expandtab whether it is set or not in the statusline.
I can find out the status of expandtab by running the following command :set expandtab?. From the vim-airline documentation I found that I can use something like this
let g:airline_section_b = '%{getcwd()}'
I modified it to
let g:airline_section_b = '%{expandtab?}'
but I am getting the error undefined variable: expandtab.
Can someone kindly tell how I can retrieve the status of expandtab and then show it in the status line. Thanks.
:set does not access variables, so you cannot use the question mark to query variables.
You are trying to access the variable expandtab variable, which doesn't exists. You actually want to access an option setting and those are accessed using the & prefix.
Sou you should add:
let g:airline_section_b = '%{&expandtab}'
Note, the quesion mark is not necessary and has no special meaning for VimL.
See :h expr-option for the details.
Update
This will only display 1 (expandtab set) or 0 (expandtab not set). What should work however is something like this:
let g:airline_section_b = '%{&expandtab?"et":"noet"}'
Which will display 'et' when expandtab is set or 'noet' when expandtab is not set. This uses the <cond>?<true>:<false> expression to display a certain string depening on the value of the <cond> condition. This is explained in the help below :h expr1
Vim options can be accessed live variables if prefixed with &. Example:
let g:airline_section_b = '%{&expandtab}'
See :h :let-& for more
While coding, i want to select a variable and automatically add a print statement like below by using a custom shortcut:
foo = 5
bar = foo * 5
If i place my cursor on bar and use this shortcut, i want the output to change to:
foo = 5
bar = foo * 5
p "bar = #{bar}"
Can anyone help me in adding this shortcut to my vimrc based on the filetype (ruby, python, java etc)?
snippets are like the built-in :abbreviate on steroids, usually with parameter insertions, mirroring, and multiple stops inside them. One of the first, very famous (and still widely used) Vim plugins is snipMate (inspired by the TextMate editor); unfortunately, it's not maintained any more; though there is a fork. A modern alternative (that requires Python though) is UltiSnips. There are more, see this list on the Vim Tips Wiki.
There are three things to evaluate: First, the features of the snippet engine itself, second, the quality and breadth of snippets provided by the author or others; third, how easy it is to add new snippets.
function Print(p)
let tmp = a:p.' "'.expand("<cword>").' = #{'.expand("<cword>").'}"'
call append(line('.'), tmp)
endfunction
autocmd BufNewFile,BufRead *.py nmap <Leader>x :call Print("print")<CR>
I am doing a vim plugin for personal use, and it triggers from toolbar.
when I click Plugin in GVIM toolbar, it create a sub menu called 'common'.
When I click common, it start check my vim settings and create sub menu, for instance, show/hide line number. But the following code has some problem, and cannot work. What's wrong with it?
amenu &Plugin.&Common :call <SID>createSubMenu()<CR>
fun! s:createSubMenu()
let isNum = &number
if isNum == '1'
amenu &Plugin.&Common.Hide\ Line\ &Number :set nonu
else
amenu &Plugin.&Common.Show\ Line\ &Number :set nu
endif
endfunction
--------------------- Resolved -----------------------
The code above cannot be used. It's completed wrong.
Please refer to Luc Hermitte's answer.
You need to :unmenu the old entry to remove it.
BTW, I already have a fully functional toggling/cycling engine for values, than also updates menus. It's done with a function from lh-vim-lib, see the test file to have examples of use, and the documentation for more explanations.
:amenu works like map commands: you must include <CR> at the end.
:amenu &Plugin.&Common.Hide\ Line\ &Number :set nonu<CR>
Also, <SID> and s: are not the same.
You should also probably scope isNum to your script with s:
An additional remark: why don't you have a single menu entry that proposes to toggle line numbering and calls :set nu!?