Using lua to perform operations on neovim buffers. Specifically, showcasing operations related to using a buffer’s filename. By the end of this post, I will have showcased: copying all current buffers (w/ filenames), copying the current buffers filename, expanding a buffers filename to it’s absolute path, and formatting output from the lua code showcased here, so that it’s useful in a shell enviornment.
Motivation
I tend to have many open buffers when I program in neovim. In particularly nested project structures, I commonly run into the issue of where were all those files I was just editing? While I can certainly go find the files (most of the time), having their names accessible to my system’s clipboard signifcantly improves text-editing efficiency.
Simply Copying a File’s buffer name in Lua/Vim
If you’re not very experienced or haven’t ever cared to read vim/neovim’s manual, than the ‘simple’ operation
referred to above, might not be very straightforward. The demo below shows one possible method for implementing this operation.
local filename = vim.api.nvim_buf_get_name(0) -- `:lua print(vim.api.nvim_buf_get_name(0))`
local absolute_path = vim.fn.expand('%:p') -- `:lua print(vim.fn.expand('%p'))`
--- in vimscript this is made simple by the much shorter command, `:echo expand('%:p')`
Writing a function to copy all open filenames
local function copy_filenames_to_clipboard()
-- Get the list of all open buffers
local buffers = vim.api.nvim_list_bufs()
local filenames = {}
-- Loop through each buffer
for _, buf in ipairs(buffers) do
-- Check if the buffer is loaded and has a filename
if vim.api.nvim_buf_is_loaded(buf) and vim.api.nvim_buf_get_name(buf) ~= "" then
-- Get the expanded file name and add it to the list
table.insert(filenames, vim.fn.fnamemodify(vim.api.nvim_buf_get_name(buf), ":p"))
end
end
-- Join filenames with newline
local result = table.concat(filenames, clipboard_item_seperator)
-- Copy to clipboard
vim.fn.setreg('+', result)
print("Copied filenames to clipboard!")
end
Writing a function to copy a files absolute path
local function copy_abs_path_to_clipboard()
local fn = vim.fn.expand('%:p')
vim.api.nvim_exec("!echo -n "..fn.." | copy-to-clip", true)
print('Copied to absolute filepath clipboard: ' .. fn ..'')
end
Binding a function to a user command
We can call local functions from a vimscript user command, by modifying the example below.
local function hello_from_file()
local fn = vim.fn.expand('%:p')
print('Hello from file: ' .. fn ..'')
end
vim.api.nvim_create_user_command('HelloFromFile', hello_from_file, {})
After sourcing this snippet to the init.lua
/init.vim
configuration of neovim, we can execute the
command :HelloFromFile
. You could also improve on this general example, by binding the normal mode
input <cmd>HelloFromFile<cr>
to a keybind.
Putting it all together
Now, we can write a file that encapsulates all of the relevant ideas and make sure to
require
it in our ~/.config/nvim/init.lua
configuration. Where this file is defined is
entirely up to the user’s preference.
local clipboard_item_seperator = '\n' -- examples include: ' ' | ',' | '\n' | string
local function copy_filenames_to_clipboard()
-- Get the list of all open buffers
local buffers = vim.api.nvim_list_bufs()
local filenames = {}
-- Loop through each buffer
for _, buf in ipairs(buffers) do
-- Check if the buffer is loaded and has a filename
if vim.api.nvim_buf_is_loaded(buf) and vim.api.nvim_buf_get_name(buf) ~= "" then
-- Get the expanded file name and add it to the list
table.insert(filenames, vim.fn.fnamemodify(vim.api.nvim_buf_get_name(buf), ":p"))
end
end
-- Join filenames with newline
local result = table.concat(filenames, clipboard_item_seperator)
-- Copy to clipboard
vim.fn.setreg('+', result)
print("Copied filenames to clipboard!")
end
local function copy_abs_path_to_clipboard()
local fn = vim.fn.expand('%:p')
vim.api.nvim_exec("!echo -n "..fn.." | copy-to-clip", true)
print('Copied to absolute filepath clipboard: ' .. fn ..'')
end
--- Create a command to call the function
vim.api.nvim_create_user_command('CopyFilenamesToClipboard', copy_filenames_to_clipboard, {})
vim.api.nvim_create_user_command('CopyAbsolutePathToClipboard', copy_abs_path_to_clipboard, {})
Conclusion
The post above is meant to display simple method for familiarizing newcomers to neovim’s lua runtime. While remaining relatively straightforward, user’s can replicate the behavior achieved without needing any external decencies/plugins.
Here is a gist that includes a complete example.