cmd-macro.nvim is a Neovim plugin that manages terminal windows within Neovim, and can be used to set up keymaps to quickly run shell commands.
- Smart terminal window toggle.
- Fully customizable window UI.
- General-purpose macros: Keymaps that can be used from any directory.
- Project-specific macros: Keymaps that can only be used from a specific directory.
- Simple macro editor: Window editor to configure project macros, with hot reloaded project macros.
- Automated persistence: Saves and restores project macros.
{
"cfung89/cmd-macro.nvim",
config = function()
require("cmdmacro").setup() -- For default options
end
}If the terminal window is open, there are 2 possible outcomes if the user attempts to open another terminal window:
- If the input location is the same as the open window, the window is closed.
- If the input location is not the same as the open window, the window is moved to the new location.
Thus, only 1 terminal managed by
cmd-macrocan be open at a time. The buffer keeps its state even if the window is closed.
A window can be opened to set up the macros for a specific project. In the editor, macros can be added by specifying an optional name attribute, the keymap, and the shell command. Keymaps can be strings or arrays. Different macros are separated by 3 or more hyphens (-).
Example:
name = "hello"
keymap = "<leader>th"
command = "echo hello"
---
keymap = [ "<leader>tc", "<leader>tb" ]
command = "cargo build"
interactive = true
Double-quotes must be used for strings.
Keybinds for macros send command to the terminal buffer and run it. If a terminal window is already open, the command will execute in that window. Otherwise, the default terminal window is opened. The cursor remains in its original position.
cmd-macro manges two different types of macros:
- General-purpose macros can be used from any directory. These are configured in your Neovim configuration.
- Project-specific macros can only be used from a specific directory. These are configured in the macro editor.
Macros are run instantly as soon as the the keybind is pressed by default (a new line character
'\n'is inserted by default at the end of the command). Macros will also cancel whatever was already in the terminal window by inserting a<C-c>character before inserting the macro.
Interactive is set to false by default for all macros. When a macro is interactive, if the keybind is pressed, the cursor will move to the terminal window and the macro is not instantly run.
The following is the provided default configuration:
{
commands = {
toggle_editor = "MacroEditor", -- toggle the editor window
terminal_close = "TerminalClose", -- close any open window (terminal and editor)
toggle_terminal = "TerminalCenter", -- toggle the center terminal
terminal_top = "TerminalTop", -- toggle the top terminal
terminal_bottom = "TerminalBottom", -- toggle the bottom terminal
terminal_left = "TerminalLeft", -- toggle the left terminal
terminal_right = "TerminalRight", -- toggle the right terminal
},
-- Keymaps have a corresponding user command defined above.
keymaps = {
toggle_editor = "<leader>te",
terminal_close = "<leader>tc",
toggle_terminal = "<leader>tt",
terminal_top = "<leader>tk",
terminal_bottom = "<leader>tj",
terminal_left = "<leader>th",
terminal_right = "<leader>tl",
},
-- Default terminal: if a macro is run and no terminal window is open,
-- opens the default terminal window and runs the command in it
default_terminal = "Right",
-- General terminal settings
terminal_settings = {
number = false, -- line numbers in terminal window
relativenumber = false, -- relative line numbers in terminal window
-- cmd-macro terminal specific keymaps
keymaps = {
-- Keymap to escape from terminal mode to normal mode.
-- Disable by setting this to `nil`.
term_to_normal = "<C-[><C-[>",
quit = { "q", "<Esc>" },
}
},
-- Window configurations for terminals
terminals = {
-- Top, Bottom, Left, and Right are split windows, identified by the presence of the `wincmd` attribute.
-- The `wincmd`, `height`, and `width` attributes are the only configurable UI attributes for split windows.
-- The `height` and `width` attributes can be an integer or a function that returns an integer.
-- Passing in a function allows cmd-macro to resize the Neovim window if the terminal emulator window is resized.
Top = {
wincmd = "K",
height = function() return math.floor(0.15 * vim.o.lines) end,
width = vim.o.columns
},
Bottom = {
wincmd = "J",
height = function() return math.floor(0.15 * vim.o.lines) end,
width = vim.o.columns
},
Left = {
wincmd = "H",
height = vim.o.lines,
width = function() return math.floor(0.5 * vim.o.columns) end
},
Right = {
wincmd = "L",
height = vim.o.lines,
width = function() return math.floor(0.5 * vim.o.columns) end
},
-- Center is a floating window, identified by the lack of the `wincmd` attribute.
-- The `height`, `width`, `row`, and `col` attributes can be an integer/number or a function that returns an integer/number.
-- Passing in a function allows cmd-macro to resize the Neovim window if the terminal emulator window is resized.
-- It has type `vim.api.keyset.win_config`, and with the exception of the `height`, `width`, `row`, and `col` attributes,
-- the table is passed directly to`vim.api.nvim_open_win({buffer}, {enter}, {config})` as the `config` argument.
Center = {
relative = "editor",
style = "minimal",
border = "rounded",
title = " cmd-macro terminal ",
title_pos = "center",
height = function() return math.floor(0.8 * vim.o.lines) end,
width = function() return math.floor(0.8 * vim.o.columns) end,
row = function() return math.floor(0.2 * vim.o.lines / 2) end,
col = function() return math.floor(0.2 * vim.o.columns / 2) end,
},
},
-- Window configurations for the macro editor
editor = {
number = true,
relativenumber = true,
-- The editor window is a floating window and can be configured the same way as the Center window above.
window = {
relative = "editor",
style = "minimal",
border = "rounded",
title = " cmd-macro editor ",
title_pos = "center",
height = function() return math.floor(0.6 * vim.o.lines) end,
width = function() return math.floor(0.6 * vim.o.columns) end,
row = function() return math.floor(0.4 * vim.o.lines / 2) end,
col = function() return math.floor(0.4 * vim.o.columns / 2) end,
},
-- Editor specific keymaps
keymaps = {
quit = { "q", "<Esc>" },
-- editor specific keymap to auto fill the keys of the next macro
-- default: typing "---" (the separation string) in insert mode in the editor
template = true
},
},
-- Set of general-purpose macros
macros = {
-- Macros are of the following form: { name = "", keymap = "", command = "", interactive = false },
-- Example: { name = "git_status", keymap = "<leader>gs", command = "git status", interactive = true },
}
}