Introduction
Welcome to Learn Neovim The Hard Way, a book for those who believe in the power of persistence and repetition. Inspired by Steve Losh’s excellent Learn Vimscript the Hard Way, this book follows the same philosophy: there are no shortcuts to MASTERY. Learning Neovim requires focus, patience, and a commitment to practice.
The method is straightforward:
- learn one thing
- practice until you can do it without thinking
- repeat once
- repeat twice
- repeat thrice
- still not enough?
- repeat repeat repeat
- well... you get the point
Each chapter presents a new skill, but the key is to not rush. Take at least a few days to repeat the exercises, letting the actions become automatic to the point where your finger moves without thinking about it before moving to the next skill. Mastery isn’t achieved by speeding through content, but by building strong, lasting habits through repetition, more repetition, and yes, even more repetition.
This approach emphasizes the importance of slow but steady learning. By taking your time, practicing consistently, and committing each skill to muscle memory, you'll gradually transition into using Neovim as your daily tool without even realizing it. If you’ve ever gone through tutorials that left you overwhelmed with information and didn’t change your workflow at all, this book is your friend. No more consuming endless tutorials without real progress—Learn Neovim The Hard Way forces you to slow down, focus, and truly learn.
Remember, there’s no fast track to MASTERY. Just focused effort, one small step at a time. You’ll need to repeat the same tasks over and over, and there’s no way around that. PERIOD. This may seem like a slow process, but the long-term rewards are immense. Why? Because once you master Neovim, you’ll be spending so much of your time using it. As a programmer—or someone aspiring to be one—you’ll be writing code for the rest of your career. So, why not invest a little time now to master the tool that will shape your entire workflow?
Even if it takes a year (just for argument’s sake), what is that compared to the decades you’ll spend writing code? Neovim enhances the joy of coding and keeps improving every year. It’s a small investment if you plan to code for life. Plus, let’s be honest—using Neovim puts you in the ranks of the programmer's elite. (People really do get impressed when they hear you're using Neovim 😎.)
So buckle up because this journey will take time...
Opening and Closing Neovim
First we have to be able to open Neovim before we can use it. To start Neovim, simply open a terminal and type:
nvim
You should see a welcome screen like the picture below:
To close Neovim, press ZZ. It should exit Neovim and take you back to the shell. There are many other ways to close Neovim but I think this is the simplest. Just need to know one anyway. If you are cusious Google can give you more than enough materials to read. Let's keep our lesson short and sweet.
Moving The Cursor with hjkl
In Neovim, the most basic way to move around is by using the hjkl keys.
Here’s what each key does with the finger to press:
⬅️ h: index finger
⬇️ j: index finger
⬆️ k: middle finger
➡️ l: ring finger
Make sure that your index finger is always on the letter j. So even after you move the finger to the left to press h, it should go back to the letter j immediately after.
Spend at least a few days getting used to moving around with hjkl with the exercise below. Your fingers need to build muscle memory, so repetition is essential. You’ll know you’ve mastered this when your fingers press the right keys without consciously thinking about it.
Remember: mastery is built through steady, consistent effort.
- Learn one thing
- Practice until you can do it without thinking
- Repeat Repeat Repeat
- Install Vimium Extension
- Use jk to scroll whenver you are viewing a web page
- Keep doing it
- Do not go to the next page until it becomes automatic
Cursor
General
- How do I get the current cursor position using Neovim API?
- How do I set the cursor position using Neovim API?
- How do I move the cursor to a specific line using Neovim API?
- What is the difference between row and column indexing in
vim.api.nvim_win_get_cursor
andvim.api.nvim_win_set_cursor
? - How do I move the cursor up or down?
- How do I move the cursor up or down using feedkeys?
- How do I move the cursor to the start or end of the line using the API?
- How do I ensure the cursor stays within the visible window?
- How do I move the cursor to a specific word or character in the current buffer?
- How do I jump the cursor to a specific line in the file?
- How do I implement custom cursor motions using the Neovim API?
- How do I move the cursor to the beginning or end of the file?
Cursor Highlighting and Behavior
- How do I highlight the cursor line in Neovim using the API?
- How do I customize the cursor shape (e.g., block, underline, beam) in Neovim?
- How do I ensure the cursor position is visible in the current viewport?
- How can I highlight or visually mark the current cursor position?
- How do I prevent the cursor from moving to the wrong position when switching modes?
Visual Mode and Text Objects
- How do I get the current cursor range in visual mode using the API?
- How do I determine the text object under the cursor?
- How can I programmatically adjust the visual selection based on the cursor position?
- How do I programmatically extend a visual selection using the cursor?
Multicursor
- Does Neovim support multiple cursors natively through the API?
- How can I simulate multiple cursors programmatically in Neovim?
- How do plugins like
vim-visual-multi
implement multiple cursors?
Cursor and Windows
- How do I move the cursor between windows programmatically?
- How do I ensure the cursor position is maintained when switching between splits?
- How can I scroll a window to center the cursor programmatically?
- How do I move the cursor in a floating window using the Neovim API?
Cursor and Buffers
- How do I get the cursor position in a specific buffer?
- How do I set the cursor position in a different buffer?
- How can I programmatically restore the cursor position in a buffer after reopening it?
Cursor Events
- How do I detect when the cursor moves using autocommands or the API?
- How can I execute a function every time the cursor moves?
- How do I handle
CursorHold
andCursorMoved
events programmatically? - How do I trigger custom actions based on the cursor's position?
Cursor Styling
- How do I customize the cursor style in Neovim?
- How can I make the cursor blink programmatically?
- How do I change the cursor style for different modes (e.g., insert, normal, visual)?
- How do I create a cursor trail or animation using the API?
Cursor and Searching
- How do I move the cursor to the next search match programmatically?
- How can I highlight all occurrences of a word under the cursor?
- How do I programmatically search for a word and place the cursor at the first match?
- How do I move the cursor to the previous search result?
Troubleshooting
- Why does the cursor position change unexpectedly in some cases?
- How do I handle cursor jumps caused by plugins or custom configurations?
- Why does the cursor move out of the visible viewport during execution?
- How do I reset the cursor to its previous position after executing a function?
- How can I fix issues where the cursor position is incorrect after resizing the window?
Miscellaneous
- How do I center the cursor in the viewport programmatically?
- How do I detect if the cursor is at the end of the file?
- How do I retrieve the character under the cursor using the Neovim API?
- How do I prevent the cursor from moving during a specific operation?
- How do I move the cursor relative to a specific mark or location in the buffer?
How to Get the Current Cursor Position using Neovim's Lua API
Learn how to retrieve and display the current cursor position using Neovim Api. This guide provides step-by-step instructions with a code example, making it easy to use this code in your Neovim Plugin.
What is vim.api.nvim_win_get_cursor
?
The vim.api.nvim_win_get_cursor
function in Neovim retrieves the current cursor position in a specified window.
Function Signature
vim.api.nvim_win_get_cursor(win_id) -> { line, column }
Parameters:
win_id
: The ID of the window to query. Use0
for the current window.
Returns:
{ line, column }
- The line number (1-based).
- The column number (0-based).
Example
-- Function to retrieve and display the current cursor position
local function print_cursor_position()
-- Get the current cursor position in the current window
local cursor_pos = vim.api.nvim_win_get_cursor(0)
local line = cursor_pos[1] -- 1-based line number
local col = cursor_pos[2] -- 0-based column number
-- Display the cursor position in the command line
print("Cursor Position: Line " .. line .. ", Column " .. col)
end
-- Map the function to a key
vim.keymap.set('n', ',,', print_cursor_position, { desc = "Print cursor position" })
-- Or execute it inside the function
vim.keymap.set('n', ',,', function()
print_cursor_position()
end, { desc = "Print cursor position" })
How to Set the Cursor Position Using Neovim's Lua API
Learn how to programmatically set the cursor position in a Neovim buffer using its Lua API. This guide provides step-by-step instructions with a code example, making it easy to integrate into your Neovim configuration or plugin.
What is vim.api.nvim_win_set_cursor
?
The vim.api.nvim_win_set_cursor
function in Neovim allows you to set the cursor position in a specified window.
Function Signature
vim.api.nvim_win_set_cursor(win_id, { line, column }) -> nil
Parameters:
win_id
: The ID of the window to manipulate. Use0
for the current window.{ line, column }
- The line number (1-based).
- The column number (0-based).
Returns:
nil
Example
-- Example usage: Jump to line 10, column 5
local function jump()
vim.api.nvim_win_set_cursor(0, { 10, 5 }) -- 0 is the ID of the current window
end
-- Map the function to a key
vim.keymap.set('n', ',,', jump, { desc = "Set cursor position" })
-- Or execute it inside the function
vim.keymap.set('n', ',,', function()
jump()
end, { desc = "Set cursor position" })
How to Move the Cursor to a Specific Line using Neovim's Lua API
Learn how to programmatically move the cursor to a specific line in a file using Neovim API. This guide provides detailed instructions with a code example to help you integrate it into your Neovim configuration or plugin.
What is vim.api.nvim_win_set_cursor
?
The vim.api.nvim_win_set_cursor
function allows you to set the cursor's position in a specified window programmatically.
Function Signature
vim.api.nvim_win_set_cursor(win_id, { line, column }) -> nil
Parameters:
win_id
: The ID of the window where the cursor will be moved. Use0
for the current window.{ line, column }
: A table containing:- line (1-based): The target line number.
- column (0-based): The target column number.
Returns:
nil
Example
-- Function to move the cursor to Line 10
local function move_to_line_10()
vim.api.nvim_win_set_cursor(0, { 10, 0 }) -- 0 is the ID of the current window
end
-- Map the function to a key
vim.keymap.set('n', ',,', move_to_line_10, { desc = "Move cursor to line 10" })
-- Or execute it inside the function
vim.keymap.set('n', ',,', function()
move_to_line_10()
end, { desc = "Move cursor to Line 10" })
How to Move the Cursor Up or Down Using Neovim's Lua API
There are two ways to move the cursor up or down using Neovim's Lua API:
How to Move the Cursor Up or Down Using vim.api
Learn how to programmatically move the cursor up or down using vim.api.nvim_win_get_cursor and vim.api.nvim_win_set_cursor. This guide includes a code example to make it easy to integrate into your Neovim configuration or plugin.
APIs Required:
To move the cursor, you'll need to combine the vim.api.nvim_win_get_cursor
function (to get the current cursor position) with the vim.api.nvim_win_set_cursor
function (to set the new cursor position).
1. vim.api.nvim_win_get_cursor
Retrieves the current cursor position in a specified window.
- Signature:
vim.api.nvim_win_get_cursor(win_id) -> { line, column }
- Parameters:
win_id
: Use0
for the current window.
- Returns:
{ line, column }
: the position of the cursor as a table with the line number (1-based) and column number (0-based).
2. vim.api.nvim_win_set_cursor
Sets the cursor position in a specified window.
- Signature:
vim.api.nvim_win_set_cursor(win_id, { line, column }) -> nil
- Parameters:
win_id
: Use0
for the current window.{ line, column }
: the new position of the cursor as a table with the line number (1-based) and column number (0-based).
Example: Move the Cursor Up or Down
-- Function to move the cursor by a specified number of lines
local function move_cursor(offset)
-- Get the current cursor position
local cursor_pos = vim.api.nvim_win_get_cursor(0)
local current_line = cursor_pos[1] -- 1-based line number
local current_col = cursor_pos[2] -- 0-based column number
-- Calculate the new line position
local new_line = current_line + offset
-- Update the cursor position
vim.api.nvim_win_set_cursor(0, { new_line, current_col })
end
-- Example: Move the cursor 5 lines down
vim.keymap.set('n', '<leader>j', function()
move_cursor(5)
end, { desc = "Move cursor down by 5 lines" })
-- Example: Move the cursor 5 lines up
vim.keymap.set('n', '<leader>k', function()
move_cursor(-5)
end, { desc = "Move cursor up by 5 lines" })
How to Move the Cursor Up or Down Using feedkeys
Learn how to programmatically move the cursor up and down using Neovim's feedkeys
function. This guide provides an example for invoking normal mode commands through Lua, enabling you to manipulate the cursor efficiently.
What is vim.api.nvim_feedkeys
?
The vim.api.nvim_feedkeys
function allows you to simulate key presses in Neovim, making it a versatile tool for programmatically invoking commands.
Function Signature
vim.api.nvim_feedkeys(keys, mode, escape_ks)
Parameters:
keys
: A string representing the key sequence to simulate.mode
: A string indicating the mode to execute the keys (e.g., "n" for normal mode).escape_ks
: A boolean or string determining whether thekey
sequences should escape special characters.
Example: Moving the Cursor Up or Down
-- Function to move the cursor up by a specified number of lines
local function move_cursor_up(lines)
vim.api.nvim_feedkeys(tostring(lines) .. "k", "n", false)
end
-- Function to move the cursor down by a specified number of lines
local function move_cursor_down(lines)
vim.api.nvim_feedkeys(tostring(lines) .. "j", "n", false)
end
-- Example usage: Move the cursor up by 5 lines
vim.keymap.set('n', '<leader>k', function()
move_cursor_up(5)
end, { desc = "Move cursor up by 5 lines" })
-- Example usage: Move the cursor down by 5 lines
vim.keymap.set('n', '<leader>j', function()
move_cursor_down(5)
end, { desc = "Move cursor down by 5 lines" })
Keymap
How to Map a Key to a Lua Function in Neovim
Learn how to set a keymap to invoke a Lua function in Neovim. This guide provides step-by-step instructions with a code example, making it easy to integrate Lua functions into your Neovim Plugin.
What is vim.keymap.set
?
The vim.keymap.set
function in Neovim is a modern and flexible way to create key mappings. It allows you to map a key directly to a Lua function, providing seamless integration with Lua scripting.
Function Signature
vim.keymap.set(mode, lhs, rhs, opts) -> nil
Parameters:
mode
: The mode(s) in which the key mapping applies (e.g.,'n'
for normal mode,'i'
for insert mode).lhs
: The key sequence to trigger the mapping (left-hand side).rhs
: The Lua function to execute or a string representing a command (right-hand side).opts
(optional): A table of options to customize the mapping.
Common Options
desc
: A description of the mapping (useful for documentation in:map
output).silent
: Suppress command echo (defaultfalse
).noremap
: Prevent remapping (defaulttrue
).
Example
-- Define a Lua function
local function greet_user()
print("Hello, welcome to Neovim!")
end
-- Map the function to the key
vim.keymap.set('n', ',,', greet_user, { desc = "Greet the user" })
-- Or execute it inside the function
vim.keymap.set('n', ',,', function()
greet_user()
end, { desc = "Greet the user" })
Text
How to Get the Current Line Content using Neovim's Lua API
Learn how to retrieve the content of the current line in a Neovim buffer using its Lua API. This guide provides a simple code example for seamless integration into your Neovim configurations or plugins.
What is vim.api.nvim_get_current_line
?
The vim.api.nvim_get_current_line
function retrieves the content of the current line where the cursor is positioned.
Function Signature
vim.api.nvim_get_current_line() -> string
Returns:
string
- The content of the current line as a string.
Example
-- Function to retrieve and display the current line content
local function print_current_line_content()
-- Get the content of the current line
local line_content = vim.api.nvim_get_current_line()
-- Display the current line content in the command line
print("Current Line Content: " .. line_content)
end
-- Map the function to a key
vim.keymap.set('n', ',,', print_current_line_content, { desc = "Print current line content" })
-- Or execute it inside the function
vim.keymap.set('n', ',,', function()
print_current_line_content()
end, { desc = "Print current line content" })
Lua
Meta Methods
How to Handle Missing Keys in Lua Tables Using __index
Learn how to define custom behavior for missing keys in Lua tables using the __index
metamethod. This guide provides step-by-step instructions with a code example, making it easy to implement in your Lua scripts.
What is the __index
Metamethod?
The __index
metamethod in Lua allows you to customize what happens when a missing key is accessed in a table. By setting it to a function, you can define dynamic or default behavior.
Function Signature
function(tbl, key) -> value
Parameters:
tbl
: The table being accessed.key
: The key that is missing in the table.
Returns:
value
- The result that Lua returns when the missing key is accessed.
Example
-- Table representing a basic inventory
inventory = {
apple = 5,
banana = 10,
}
-- Define a metatable with an __index function
setmetatable(inventory, {
-- when the key does not exist in inventory table, invoke this function
-- tbl is the inventory table
-- key is the missing key eg. mango or orange
__index = function(tbl, key)
print("Item '" .. key .. "' is not in the inventory.")
-- return a default value
return 0
end
})
-- Example usage
print(inventory.apple) -- Exists, prints 5
print(inventory.banana) -- Exists, prints 10
print(inventory.mango) -- Missing, calls __index
print(inventory.orange) -- Missing, calls __index
Lazy Loading in Lua with Plenary.nvim
Plenary.nvim, a popular Lua library for Neovim, uses the __index
metamethod to implement lazy loading. Lazy loading allows you to defer loading a module or resource until it is accessed, optimizing performance and reducing initial load times.
How Does Plenary Use __index
for Lazy Loading?
Plenary utilizes the __index
metamethod to dynamically load modules when they are accessed for the first time. The loaded modules are cached to avoid repeated lookups.
Function Signature for __index
function(tbl, key) -> value
Parameters:
tbl
: The table being accessed.key
: The key that is missing in the table.
Returns:
value
- The dynamically loaded module or resource.
Simplified Example: Lazy Loading with __index
For this example, we create a dummy plenary
plugin.
-- plenary/lua/plenary/init.lua
local M = {}
return M
It also has an empty submodule.
-- plenary/lua/plenary/a.lua
local M = {}
return M
This is init.lua
calling the dummy plenary plugin.
local plenary = require("plenary") -- assuming plenary is an empty table
setmetatable(plenary, {
__index = function(tbl, key)
-- load the submodule
local module = require("plenary." .. key)
-- store the submodule in the plenary table
rawset(tbl, key, module)
return module
end
})
-- plenary table starts with just a metatable
vim.print(plenary)
-- {
-- <metatable> = {
-- __index = <function>,
-- }
-- }
-- Triggers __index, require "plenary.a" and insert it into plenary table
vim.print(plenary.a) -- {}
-- now plenary table has "a" with the loaded submodule
vim.print(plenary)
-- {
-- <metatable> = {
-- __index = <function>,
-- }
-- a = <submodule returned by require "plenary.a">
-- }
-- From the second time onwards, it does not trigger __index
-- because the submodule is already in the table
vim.print(plenary.a) -- {}
Providing Default User Config with __index
Using Lua's __index
metamethod, you can provide default values for user configurations in your Neovim plugins or scripts. This pattern is particularly useful for maintaining flexibility while ensuring that critical configurations are always available.
Why Use __index
for Default Configs?
When creating a plugin or script, you often need to handle user-defined configurations. However, not every user will define all the options you expect. With __index
, you can set default values for missing configurations while allowing users to override them.
Function Signature for __index
function(tbl, key) -> value
Parameters:
tbl
: The table being accessed.key
: The key that is missing in the table.
Returns:
value
- The default value for the missing key.
Example: Providing Default Configurations
Here’s an example of using __index
to provide default values for user configurations:
-- Default configuration table
local defaults = {
theme = "dark",
auto_save = false,
max_tabs = 10,
}
-- User configuration table (can be partially filled)
local user_config = {
auto_save = true, -- User overrides this setting
}
-- Set up a metatable to use defaults for missing keys
setmetatable(user_config, {
__index = function(tbl, key)
-- lookup the missing key from the defaults table
return defaults[key]
end
})
-- Example usage
print(user_config.theme) -- theme is missing, use the default -> "dark"
print(user_config.max_tabs) -- max_tabs is missing, use the default -> 10
print(user_config.auto_save) -- auto_save is in the user config -> true
How to Use __call
Metamethod in Lua
Learn how to define custom behavior for tables so they can be called like functions using the __call
metamethod. This guide provides step-by-step instructions with a code example, making it easy to implement in your Lua scripts.
What is the __call
Metamethod?
The __call
metamethod in Lua allows you to customize what happens when a table is used as a function. By setting it in a table's metatable, you can define dynamic behavior when the table is invoked as a callable object.
Function Signature
function(tbl, ...) -> value
Parameters:
tbl
: The table being accessed....
: Any arguments passed to the function.
Returns:
value
- The result that Lua returns when the table is invoked as a function.
Example
-- Define a table with a metatable implementing __call
local CallableTable = {}
-- Set the metatable
setmetatable(CallableTable, {
__call = function(self, ...)
return "Called with " .. table.concat({...}, ", ")
end
})
-- Use the table as a function
print(CallableTable("Lua", "arg1", "arg2")) -- Output: Called with Lua, arg1, arg2
Eliminates Explicit Function Calls with __call
When using __call
, you no longer need to explicitly reference a method or function name. This reduces verbosity and results in a cleaner syntax, particularly in scenarios where repeated calls are necessary.
Function Signature
function(tbl, ...) -> value
Parameters:
tbl
: The table being accessed....
: Any arguments passed to the function.
Returns:
value
- The result that Lua returns when the table is invoked as a function.
Example Without Using __call
:
local Logger = {}
function Logger.log(message, level)
level = level or "INFO"
print("[" .. level .. "]: " .. message)
end
-- Use the Logger via a method call
Logger.log("System initialized.") -- Output: [INFO]: System initialized.
Logger.log("Disk space low.", "WARNING") -- Output: [WARNING]: Disk space low.
Example Using __call
:
local Logger = {}
setmetatable(Logger, {
__call = function(self, message, level)
level = level or "INFO"
print("[" .. level .. "]: " .. message)
end
})
-- Use the Logger directly
Logger("System initialized.") -- Output: [INFO]: System initialized.
Logger("Disk space low.", "WARNING") -- Output: [WARNING]: Disk space low.
Using __call
for Matrix Operations in Lua
Let's see how we can use __call to make retrieving the elements of a matrix look more intuitive.
Implementation Without __call
:
Normally it would look something like this:
-- Define a Matrix table
local M = {}
-- Initialize the matrix
M.data = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
}
-- Function to access matrix elements
function M.get(row, col)
return M.data[row][col]
end
-- We have to call get function
print(M.get(0, 1)) -- Output: 2
print(M.get(1, 2)) -- Output: 6
However scientists would probably expect something like this:
print(M(0, 1)) -- Output: 2
print(M(1, 2)) -- Output: 6
Implementation With __call
:
-- Matrix metatable implementing __call
setmetatable(Matrix, {
__call = function(self, row, col)
return self.data[row][col]
end
})
-- Access matrix elements using __call
print(M(0, 1)) -- Output: 2
print(M(1, 2)) -- Output: 6
Cursor
Cómo Obtener la Posición Actual del Cursor Usando la API de Lua de Neovim
Aprende a recuperar y mostrar la posición actual del cursor usando la API de Neovim. Esta guía proporciona instrucciones paso a paso con un ejemplo de código, facilitando el uso de este código en tu plugin de Neovim.
¿Qué es vim.api.nvim_win_get_cursor
?
La función vim.api.nvim_win_get_cursor
en Neovim recupera la posición actual del cursor en una ventana especificada.
Firma de la Función
vim.api.nvim_win_get_cursor(win_id) -> { línea, columna }
Parámetros:
win_id
: El ID de la ventana a consultar. Usa0
para la ventana actual.
Retorno:
{ línea, columna }
- El número de línea (comienza en 1).
- El número de columna (comienza en 0).
Ejemplo
-- Función para obtener y mostrar la posición actual del cursor
local function print_cursor_position()
-- Obtiene la posición actual del cursor en la ventana actual
local cursor_pos = vim.api.nvim_win_get_cursor(0)
local line = cursor_pos[1] -- Número de línea basado en 1
local col = cursor_pos[2] -- Número de columna basado en 0
-- Muestra la posición del cursor en la línea de comandos
print("Posición del cursor: Línea " .. line .. ", Columna " .. col)
end
-- Asigna la función a una tecla
vim.keymap.set('n', ',,', print_cursor_position, { desc = "Imprimir posición del cursor" })
-- O ejecútala dentro de la función
vim.keymap.set('n', ',,', function()
print_cursor_position()
end, { desc = "Imprimir posición del cursor" })
Cómo Establecer la Posición del Cursor Usando la API de Lua de Neovim
Aprende a establecer programáticamente la posición del cursor en un buffer de Neovim utilizando su API de Lua. Esta guía proporciona instrucciones paso a paso con un ejemplo de código, haciéndolo fácil de integrar en tu configuración o plugin de Neovim.
¿Qué es vim.api.nvim_win_set_cursor
?
La función vim.api.nvim_win_set_cursor
en Neovim permite establecer la posición del cursor en una ventana específica.
Firma de la Función
vim.api.nvim_win_set_cursor(win_id, { line, column }) -> nil
Parámetros:
win_id
: El ID de la ventana a manipular. Usa0
para la ventana actual.{ line, column }
- El número de línea (base 1).
- El número de columna (base 0).
Retorna:
nil
Ejemplo
-- Ejemplo de uso: Saltar a la línea 10, columna 5
local function jump()
vim.api.nvim_win_set_cursor(0, { 10, 5 }) -- 0 es el ID de la ventana actual
end
-- Asigna la función a una tecla
vim.keymap.set('n', ',,', jump, { desc = "Establecer posición del cursor" })
-- O ejecútala dentro de la función
vim.keymap.set('n', ',,', function()
jump()
end, { desc = "Establecer posición del cursor" })
Cómo Mover el Cursor a una Línea Específica Usando el API de Lua de Neovim
Aprende cómo mover el cursor a una línea específica en un buffer de Neovim usando su API de Lua. Este tutorial te guía paso a paso con un ejemplo de código, lo que facilita integrar este código en tu configuración o plugin de Neovim.
¿Qué es vim.api.nvim_win_set_cursor
?
La función vim.api.nvim_win_set_cursor
en Neovim permite establecer la posición del cursor en una ventana específica.
Firma de la Función
vim.api.nvim_win_set_cursor(win_id, { line, column }) -> nil
Parámetros:
win_id
: El ID de la ventana que deseas manipular. Usa0
para la ventana actual.{ line, column }
- El número de línea (base 1).
- El número de columna (base 0).
Devuelve:
nil
Ejemplo
-- Función para mover el cursor a la línea 10
local function move_to_line_10()
vim.api.nvim_win_set_cursor(0, { 10, 0 }) -- 0 es el ID de la ventana actual
end
-- Asigna la función a una tecla
vim.keymap.set('n', ',,', move_to_line_10, { desc = "Mover el cursor a la línea 10" })
-- O ejecútala dentro de la función
vim.keymap.set('n', ',,', function()
move_to_line_10()
end, { desc = "Mover el cursor a la línea 10" })
Cómo Mover el Cursor Hacia Arriba o Abajo Usando la API de Lua de Neovim
Aprende cómo mover programáticamente el cursor hacia arriba o abajo un número especificado de líneas usando la API de Lua de Neovim. Esta guía incluye un ejemplo de código para facilitar su integración en tu configuración de Neovim o en un plugin.
APIs Necesarias:
Para mover el cursor, necesitas combinar la función vim.api.nvim_win_get_cursor
(para obtener la posición actual del cursor) con la función vim.api.nvim_win_set_cursor
(para establecer la nueva posición del cursor).
1. vim.api.nvim_win_get_cursor
Obtiene la posición actual del cursor en una ventana especificada.
- Firma:
vim.api.nvim_win_get_cursor(win_id) -> { line, column }
- Parámetros:
win_id
: Usa0
para la ventana actual.
- Devuelve:
{ line, column }
: la posición del cursor como una tabla con el número de línea (basado en 1) y el número de columna (basado en 0).
2. vim.api.nvim_win_set_cursor
Establece la posición del cursor en una ventana especificada.
- Firma:
vim.api.nvim_win_set_cursor(win_id, { line, column }) -> nil
- Parámetros:
win_id
: Usa0
para la ventana actual.{ line, column }
: la nueva posición del cursor como una tabla con el número de línea (basado en 1) y el número de columna (basado en 0).
Ejemplo: Mover el Cursor Hacia Arriba o Abajo
-- Función para mover el cursor un número especificado de líneas
local function move_cursor(offset)
-- Obtiene la posición actual del cursor
local cursor_pos = vim.api.nvim_win_get_cursor(0)
local current_line = cursor_pos[1] -- Número de línea basado en 1
local current_col = cursor_pos[2] -- Número de columna basado en 0
-- Calcula la nueva posición de línea
local new_line = current_line + offset
-- Actualiza la posición del cursor
vim.api.nvim_win_set_cursor(0, { new_line, current_col })
end
-- Ejemplo: Mover el cursor 5 líneas hacia abajo
vim.keymap.set('n', '<leader>j', function()
move_cursor(5)
end, { desc = "Mover el cursor hacia abajo 5 líneas" })
-- Ejemplo: Mover el cursor 5 líneas hacia arriba
vim.keymap.set('n', '<leader>k', function()
move_cursor(-5)
end, { desc = "Mover el cursor hacia arriba 5 líneas" })
Cómo Mover el Cursor Arriba y Abajo Usando feedkeys
en la API de Lua de Neovim
Aprende cómo mover el cursor programáticamente hacia arriba y abajo utilizando la función feedkeys
de Neovim. Esta guía proporciona un ejemplo de cómo invocar comandos en modo normal a través de Lua, permitiéndote manipular el cursor de manera eficiente.
¿Qué es vim.api.nvim_feedkeys
?
La función vim.api.nvim_feedkeys
te permite simular pulsaciones de teclas en Neovim, convirtiéndola en una herramienta versátil para invocar comandos de forma programada.
Firma de la función
vim.api.nvim_feedkeys(keys, mode, escape_ks)
Parámetros:
keys
: Una cadena que representa la secuencia de teclas a simular.mode
: Una cadena que indica el modo en el que se ejecutarán las teclas (por ejemplo, "n" para modo normal).escape_ks
: Un booleano o cadena que determina si las secuencias de teclas deben escapar caracteres especiales.
Ejemplo: Mover el Cursor Arriba y Abajo
-- Función para mover el cursor hacia arriba un número específico de líneas
local function move_cursor_up(lines)
vim.api.nvim_feedkeys(tostring(lines) .. "k", "n", false)
end
-- Función para mover el cursor hacia abajo un número específico de líneas
local function move_cursor_down(lines)
vim.api.nvim_feedkeys(tostring(lines) .. "j", "n", false)
end
-- Ejemplo de uso: Mover el cursor hacia arriba 5 líneas
vim.keymap.set('n', '<leader>k', function()
move_cursor_up(5)
end, { desc = "Mover cursor hacia arriba 5 líneas" })
-- Ejemplo de uso: Mover el cursor hacia abajo 5 líneas
vim.keymap.set('n', '<leader>j', function()
move_cursor_down(5)
end, { desc = "Mover cursor hacia abajo 5 líneas" })