serpl
is a terminal user interface (TUI) application that allows users to search and replace keywords in an entire folder, similar to the functionality available in VS Code.
cargo install serpl
cargo install serpl --features ast_grep
serpl
Check the releases page for the latest binaries.
serpl
can be installed using Homebrew:
brew install serpl
serpl
can be installed from the official repositories using pacman
:
pacman -S serpl
serpl
is included in nixpkgs since 24.11, and can be installed via Nix in different ways:
On standalone Nix setups:
nix profile install nixpkgs#serpl
On NixOS (via configuration.nix
or similar):
{pkgs, ...}: {
environment.systemPackages = [pkgs.serpl];
}
On Home-Manager:
{pkgs, ...}: {
home.packages = [pkgs.serpl];
}
serpl
serpl --project-root /path/to/project
Default key bindings can be customized through the config.json
file.
Key Combination | Action |
---|---|
Ctrl + c |
Quit |
Ctrl + b |
Help |
Tab |
Switch between tabs |
Backtab |
Switch to previous tabs |
Ctrl + o |
Process replace for all files |
r |
Process replace for selected file or line |
Ctrl + n |
Toggle search and replace modes |
Enter |
Execute search (for large folders) |
g / Left / h
|
Go to top of the list |
G / Right / l
|
Go to bottom of the list |
j / Down
|
Move to the next item |
k / Up
|
Move to the previous item |
/ |
Search results list |
d |
Delete selected file or line |
Esc |
Exit the current pane or dialog |
Enter (in dialogs) / y
|
Confirm action |
Esc (in dialogs) / n
|
Cancel action |
h , l , Tab (in dialogs) |
Navigate dialog options |
serpl
uses a configuration file to manage key bindings and other settings. By default, the path to the configuration file can be found by running serpl --version
. You can use various file formats for the configuration, such as JSON, JSON5, YAML, TOML, or INI.
{
"keybindings": {
"<Ctrl-d>": "Quit",
"<Ctrl-c>": "Quit",
"<Tab>": "LoopOverTabs",
"<Backtab>": "BackLoopOverTabs",
"<Ctrl-o>": "ProcessReplace",
"<Ctrl-b>": "ShowHelp"
}
}
{
keybindings: {
"<Ctrl-d>": "Quit",
"<Ctrl-c>": "Quit",
"<Tab>": "LoopOverTabs",
"<Backtab>": "BackLoopOverTabs",
"<Ctrl-o>": "ProcessReplace",
"<Ctrl-b>": "ShowHelp",
},
}
keybindings:
"<Ctrl-d>": "Quit"
"<Ctrl-c>": "Quit"
"<Tab>": "LoopOverTabs"
"<Backtab>": "BackLoopOverTabs"
"<Ctrl-o>": "ProcessReplace"
"<Ctrl-b>": "ShowHelp"
[keybindings]
"<Ctrl-d>" = "Quit"
"<Ctrl-c>" = "Quit"
"<Tab>" = "LoopOverTabs"
"<Backtab>" = "BackLoopOverTabs"
"<Ctrl-o>" = "ProcessReplace"
"<Ctrl-b>" = "ShowHelp"
[keybindings]
<Ctrl-d> = Quit
<Ctrl-c> = Quit
<Tab> = LoopOverTabs
<Backtab> = BackLoopOverTabs
<Ctrl-o> = ProcessReplace
<Ctrl-b> = ShowHelp
You can customize the key bindings by modifying the configuration file in the format of your choice.
Tip
If current directory is considerebly large, you have to click Enter
to start the search.
/
key.Ctrl + b
key combination to display the help dialog.Ctrl + o
key combination to process the replace for all files.r
key to process the replace for the selected file or line.Ctrl + n
key combination to toggle between search and replace modes.g
, G
, j
, and k
keys to navigate through the search results.d
key to delete the selected file or line.Check out the toggleterm.nvim plugin for Neovim, which provides a terminal that can be toggled with a key binding. Or you can use the following configuration, if you are using AstroNvim:
return {
"akinsho/toggleterm.nvim",
cmd = { "ToggleTerm", "TermExec" },
dependencies = {
{
"AstroNvim/astrocore",
opts = function(_, opts)
local maps = opts.mappings
local astro = require "astrocore"
maps.n["<Leader>t"] = vim.tbl_get(opts, "_map_sections", "t")
local serpl = {
callback = function()
astro.toggle_term_cmd "serpl"
end,
desc = "ToggleTerm serpl",
}
maps.n["<Leader>sr"] = { serpl.callback, desc = serpl.desc }
maps.n["<Leader>tf"] = { "<Cmd>ToggleTerm direction=float<CR>", desc = "ToggleTerm float" }
maps.n["<Leader>th"] = { "<Cmd>ToggleTerm size=10 direction=horizontal<CR>", desc = "ToggleTerm horizontal split" }
maps.n["<Leader>tv"] = { "<Cmd>ToggleTerm size=80 direction=vertical<CR>", desc = "ToggleTerm vertical split" }
maps.n["<F7>"] = { '<Cmd>execute v:count . "ToggleTerm"<CR>', desc = "Toggle terminal" }
maps.t["<F7>"] = { "<Cmd>ToggleTerm<CR>", desc = "Toggle terminal" }
maps.i["<F7>"] = { "<Esc><Cmd>ToggleTerm<CR>", desc = "Toggle terminal" }
maps.n["<C-'>"] = { '<Cmd>execute v:count . "ToggleTerm"<CR>', desc = "Toggle terminal" }
maps.t["<C-'>"] = { "<Cmd>ToggleTerm<CR>", desc = "Toggle terminal" }
maps.i["<C-'>"] = { "<Esc><Cmd>ToggleTerm<CR>", desc = "Toggle terminal" }
end,
},
},
opts = {
highlights = {
Normal = { link = "Normal" },
NormalNC = { link = "NormalNC" },
NormalFloat = { link = "NormalFloat" },
FloatBorder = { link = "FloatBorder" },
StatusLine = { link = "StatusLine" },
StatusLineNC = { link = "StatusLineNC" },
WinBar = { link = "WinBar" },
WinBarNC = { link = "WinBarNC" },
},
size = 10,
---@param t Terminal
on_create = function(t)
vim.opt_local.foldcolumn = "0"
vim.opt_local.signcolumn = "no"
if t.hidden then
local toggle = function() t:toggle() end
vim.keymap.set({ "n", "t", "i" }, "<C-'>", toggle, { desc = "Toggle terminal", buffer = t.bufnr })
vim.keymap.set({ "n", "t", "i" }, "<F7>", toggle, { desc = "Toggle terminal", buffer = t.bufnr })
end
end,
shading_factor = 2,
direction = "float",
float_opts = { border = "rounded" },
},
}
This project is licensed under the MIT License. See the LICENSE file for details.
(WIP)