Lightweight and quick file operations without being a full-blown file manager. For when you prefer a fuzzy finder over a file tree, but still want some convenient file operations inside nvim.
Commands
Quality-of-life
import statements to the
renamed file (if the LSP supports workspace/willRenameFiles).Requirements
trash or gio trash.
(Since macOS 14+, there is a trash CLI already built-in, so there is no need
to install anything.)vim.ui.input and vim.ui.select such as
snacks.nvim. Enables vim motions in the
input field, and looks better.-- lazy.nvim
{ "chrisgrieser/nvim-genghis" }
-- packer
use { "chrisgrieser/nvim-genghis" }
The .setup() call is optional.
-- default config
require("genghis").setup {
fileOperations = {
-- automatically keep the extension when no file extension is given
-- (everything after the first non-leading dot is treated as the extension)
autoAddExt = true,
trashCmd = function() ---@type fun(): string|string[]
if jit.os == "OSX" then return "trash" end -- builtin since macOS 14
if jit.os == "Windows" then return "trash" end
if jit.os == "Linux" then return { "gio", "trash" } end
return "trash-cli"
end,
ignoreInFolderSelection = { -- using lua pattern matching (e.g., escape `-` as `%-`)
"/node_modules/", -- nodejs
"/typings/", -- python
"/doc/", -- vim help files folders
"%.app/", -- macOS pseudo-folders
"/%.", -- hidden folders
},
},
navigation = {
onlySameExtAsCurrentFile = false,
ignoreDotfiles = true,
ignoreExt = { "png", "svg", "webp", "jpg", "jpeg", "gif", "pdf", "zip" },
ignoreFilesWithName = { ".DS_Store" },
},
successNotifications = true,
icons = { -- set an icon to empty string to disable it
chmodx = "",
copyFile = "",
copyPath = "",
duplicate = "",
file = "",
move = "",
new = "",
nextFile = "",
prevFile = "",
rename = "",
trash = "",
},
}
A UI plugin for vim.ui.input and vim.ui.select, such as
snacks.nvim, is recommended since it
enables for vim motions in the input field. (It also looks better.)
-- minimal snacks.nvim config to use it for `vim.ui.input` and `vim.ui.select`
require("snacks").setup({
input = { enabled = true },
picker = { enabled = true },
}),
You can access a command as Lua function:
require("genghis").createNewFile()
Or you can use the ex command :Genghis with the respective sub-command:
:Genghis createNewFile
createNewFile: Create a new file in the same directory as the current file.createNewFileInFolder: Create a new file in a folder in the current working
directory.duplicateFile: Duplicate the current file.moveSelectionToNewFile: Create a new file and move the current selection
to it. (Visual Line command, the selection is moved linewise.)renameFile: Rename the current file.moveToFolderInCwd: Move the current file to an existing folder in the
current working directory.moveAndRenameFile: Move and rename the current file. Keeps the
old name if the new path ends with /. Works like the UNIX mv command.chmodx: Makes current file executable. Equivalent to chmod +x.trashFile: Move the current file to the trash. (Defaults to gio trash on
Linux, and trash on macOS or Windows.)showInSystemExplorer: Reveals the current file in the system explorer, such
as macOS Finder. (Currently only on macOS, PRs welcome.)The following applies to all commands above:
fileOperations.autoAddExt = false.)/, the new file is placed in the respective
subdirectory, creating any non-existing intermediate folders.import statements, if the LSP
supports workspace/willRenameFiles.copyFilename: Copy the filename.copyFilepath: Copy the absolute filepath.copyFilepathWithTilde: Copy the absolute filepath, replacing the home
directory with ~.copyRelativePath: Copy the relative filepath.copyDirectoryPath: Copy the absolute directory path.copyRelativeDirectoryPath: Copy the relative directory path.copyFileItself: Copies the file itself. This means you can paste it into
the browser or file manager. (Currently only on macOS, PRs welcome.)All commands use the system clipboard.
.navigateToFileInFolder("next"|"prev"): Move to the next/previous file in the
current folder of the current file, in alphabetical order.
snacks.nvim is installed, displays a cycling notification.A nod to vim.eunuch, an older vimscript plugin with a similar goal. As opposed to childless eunuchs, it is said that Genghis Khan has fathered thousands of children.
In my day job, I am a sociologist studying the social mechanisms underlying the digital economy. For my PhD project, I investigate the governance of the app economy and how software ecosystems manage the tension between innovation and compatibility. If you are interested in this subject, feel free to get in touch.