Drill 03: Neovim API
The vim global object: options, keymaps, autocommands, and buffer operations.
Run these code blocks inside Neovim with :lua
|
Run This Drill
bash ~/atelier/_bibliotheca/domus-captures/docs/modules/ROOT/examples/lua-drills/03-neovim-api.sh
Drill Script
#!/bin/bash
# LUA DRILL 03: NEOVIM API
# Run these commands in Neovim with :lua or in init.lua
# Topics: vim.api, vim.fn, vim.opt, vim.keymap
echo "=================================================================="
echo " LUA DRILL 03: NEOVIM API "
echo "=================================================================="
echo ""
echo "These drills are meant to be run INSIDE Neovim."
echo "Copy each block and run with :lua or add to your init.lua"
echo ""
# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 3.1: vim GLOBAL OBJECT"
echo "The gateway to all Neovim functionality"
echo "------------------------------------------------------------------"
echo ""
cat << 'NVIMEOF'
-- Run in Neovim: :lua <command>
-- vim.inspect - pretty print tables
:lua print(vim.inspect(vim.opt.number:get()))
-- vim.api - Neovim API functions
:lua print(vim.api.nvim_get_current_buf())
:lua print(vim.api.nvim_buf_get_name(0))
-- vim.fn - Vimscript functions
:lua print(vim.fn.expand('%')) -- current filename
:lua print(vim.fn.getcwd()) -- current working dir
:lua print(vim.fn.has('nvim')) -- 1 if Neovim
-- vim.cmd - Execute Vimscript
:lua vim.cmd('echo "Hello from Lua!"')
:lua vim.cmd('set number')
-- vim.v - Vim variables (v:count, v:register, etc)
:lua print(vim.v.count)
NVIMEOF
echo ""
# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 3.2: OPTIONS (vim.opt)"
echo "Set Neovim options"
echo "------------------------------------------------------------------"
echo ""
cat << 'NVIMEOF'
-- Get option value
:lua print(vim.opt.number:get())
:lua print(vim.opt.tabstop:get())
:lua print(vim.inspect(vim.opt.completeopt:get()))
-- Set options
:lua vim.opt.number = true
:lua vim.opt.relativenumber = true
:lua vim.opt.tabstop = 4
:lua vim.opt.shiftwidth = 4
-- List/set options
:lua vim.opt.completeopt = {'menu', 'menuone', 'noselect'}
-- Append/prepend/remove from list options
:lua vim.opt.wildignore:append('*.pyc')
:lua vim.opt.wildignore:prepend('node_modules')
:lua vim.opt.wildignore:remove('*.pyc')
-- In init.lua, typical pattern:
local opt = vim.opt
opt.number = true
opt.relativenumber = true
opt.tabstop = 4
opt.shiftwidth = 4
opt.expandtab = true
opt.smartindent = true
opt.wrap = false
opt.cursorline = true
opt.termguicolors = true
opt.signcolumn = "yes"
opt.clipboard = "unnamedplus"
NVIMEOF
echo ""
# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 3.3: KEYMAPS (vim.keymap)"
echo "Define keybindings"
echo "------------------------------------------------------------------"
echo ""
cat << 'NVIMEOF'
-- Basic keymap
:lua vim.keymap.set('n', '<leader>w', ':w<CR>')
-- With options
:lua vim.keymap.set('n', '<leader>q', ':q<CR>', {silent = true})
-- With description (for which-key)
:lua vim.keymap.set('n', '<leader>h', ':nohlsearch<CR>', {desc = 'Clear highlights'})
-- Multiple modes
:lua vim.keymap.set({'n', 'v'}, '<leader>y', '"+y', {desc = 'Yank to clipboard'})
-- Lua function as callback
:lua vim.keymap.set('n', '<leader>p', function() print('Hello!') end)
-- In init.lua, typical pattern:
local keymap = vim.keymap.set
-- Better navigation
keymap('n', '<C-h>', '<C-w>h', {desc = 'Move to left window'})
keymap('n', '<C-j>', '<C-w>j', {desc = 'Move to lower window'})
keymap('n', '<C-k>', '<C-w>k', {desc = 'Move to upper window'})
keymap('n', '<C-l>', '<C-w>l', {desc = 'Move to right window'})
-- Buffer navigation
keymap('n', '<S-l>', ':bnext<CR>', {desc = 'Next buffer'})
keymap('n', '<S-h>', ':bprev<CR>', {desc = 'Previous buffer'})
-- Stay in visual mode when indenting
keymap('v', '<', '<gv', {desc = 'Indent left'})
keymap('v', '>', '>gv', {desc = 'Indent right'})
-- Move lines up/down
keymap('v', 'J', ":m '>+1<CR>gv=gv", {desc = 'Move selection down'})
keymap('v', 'K', ":m '<-2<CR>gv=gv", {desc = 'Move selection up'})
NVIMEOF
echo ""
# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 3.4: AUTOCOMMANDS (vim.api.nvim_create_autocmd)"
echo "React to events"
echo "------------------------------------------------------------------"
echo ""
cat << 'NVIMEOF'
-- Create autocommand group
:lua vim.api.nvim_create_augroup('MyGroup', {clear = true})
-- Single autocommand
:lua vim.api.nvim_create_autocmd('BufWritePre', {
pattern = '*.lua',
callback = function()
print('About to save Lua file!')
end
})
-- Typical init.lua patterns:
local augroup = vim.api.nvim_create_augroup
local autocmd = vim.api.nvim_create_autocmd
-- Highlight yanked text
augroup('YankHighlight', {clear = true})
autocmd('TextYankPost', {
group = 'YankHighlight',
callback = function()
vim.highlight.on_yank({higroup = 'IncSearch', timeout = 200})
end
})
-- Remove trailing whitespace on save
augroup('TrimWhitespace', {clear = true})
autocmd('BufWritePre', {
group = 'TrimWhitespace',
pattern = '*',
command = [[%s/\s\+$//e]]
})
-- Set options for specific filetypes
augroup('FileTypeSettings', {clear = true})
autocmd('FileType', {
group = 'FileTypeSettings',
pattern = {'lua', 'python'},
callback = function()
vim.opt_local.tabstop = 4
vim.opt_local.shiftwidth = 4
end
})
NVIMEOF
echo ""
# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 3.5: BUFFERS AND WINDOWS"
echo "Work with buffers, windows, tabs"
echo "------------------------------------------------------------------"
echo ""
cat << 'NVIMEOF'
-- Get current buffer/window
:lua print(vim.api.nvim_get_current_buf())
:lua print(vim.api.nvim_get_current_win())
-- Get buffer info
:lua print(vim.api.nvim_buf_get_name(0)) -- 0 = current buffer
:lua print(vim.api.nvim_buf_line_count(0))
-- Get buffer lines
:lua print(vim.inspect(vim.api.nvim_buf_get_lines(0, 0, 5, false)))
-- Set buffer lines
:lua vim.api.nvim_buf_set_lines(0, 0, 0, false, {'-- Header added by Lua'})
-- List all buffers
:lua for _, buf in ipairs(vim.api.nvim_list_bufs()) do print(buf, vim.api.nvim_buf_get_name(buf)) end
-- Create new buffer
:lua local buf = vim.api.nvim_create_buf(false, true) -- not listed, scratch
:lua vim.api.nvim_buf_set_lines(buf, 0, -1, false, {'Line 1', 'Line 2'})
-- Window operations
:lua print(vim.api.nvim_win_get_cursor(0)) -- {line, col}
:lua vim.api.nvim_win_set_cursor(0, {1, 0}) -- go to line 1, col 0
NVIMEOF
echo ""
# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 3.6: USER COMMANDS"
echo "Create custom :Commands"
echo "------------------------------------------------------------------"
echo ""
cat << 'NVIMEOF'
-- Simple command
:lua vim.api.nvim_create_user_command('Hello', function() print('Hello World!') end, {})
-- Command with arguments
:lua vim.api.nvim_create_user_command('Greet', function(opts)
print('Hello, ' .. opts.args .. '!')
end, {nargs = 1})
-- Usage: :Greet Admin
-- In init.lua, typical patterns:
local cmd = vim.api.nvim_create_user_command
-- Toggle line numbers
cmd('ToggleNumbers', function()
vim.opt.number = not vim.opt.number:get()
vim.opt.relativenumber = not vim.opt.relativenumber:get()
end, {})
-- Copy current file path
cmd('CopyPath', function()
local path = vim.fn.expand('%:p')
vim.fn.setreg('+', path)
print('Copied: ' .. path)
end, {})
-- Format JSON in buffer
cmd('FormatJSON', function()
vim.cmd('%!jq .')
end, {})
NVIMEOF
echo ""
# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "YOUR TURN - RUN IN NEOVIM:"
echo "------------------------------------------------------------------"
echo ""
echo "1. Check if file is modified:"
echo " :lua print(vim.bo.modified)"
echo ""
echo "2. Get filetype:"
echo " :lua print(vim.bo.filetype)"
echo ""
echo "3. Simple keymap:"
echo " :lua vim.keymap.set('n', '<leader>t', ':echo \"test\"<CR>')"
echo ""
echo "------------------------------------------------------------------"
echo "KEY TAKEAWAYS:"
echo "1. vim.opt for options, vim.keymap.set for maps"
echo "2. vim.api.nvim_* for Neovim API"
echo "3. vim.fn.* for Vimscript functions"
echo "4. vim.cmd for Vimscript commands"
echo "5. 0 means current buffer/window in API calls"
echo "------------------------------------------------------------------"