# Serpl `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. https://github.com/yassinebridi/serpl/assets/18403595/348506704-73336074-bfaf-4a9a-849c-bd4aa4e24afc ## Table of Contents 1. [Features](#features) 2. [Installation](#installation-and-update) - [Prerequisites](#prerequisites) - [Steps](#steps) - [Binaries](#binaries) - [OS Specific Installation](#os-specific-installation) 3. [Usage](#usage) - [Basic Commands](#basic-commands) - [Key Bindings](#key-bindings) - [Configuration](#configuration) 4. [Panes](#panes) - [Search Input](#search-input) - [Replace Input](#replace-input) - [Search Results Pane](#search-results-pane) - [Preview Pane](#preview-pane) 5. [Quick Hints](#quick-hints) 6. [Neovim Integration using toggleterm](#neovim-integration-using-toggleterm) 7. [License](#license) 8. [Contributing](#contributing) 9. [Acknowledgements](#acknowledgements) 10. [Similar Projects](#similar-projects) ## Features - Search for keywords across an entire project folder, with options for case sensitivity, AST Grep and more. - Replace keywords with options for preserving case, AST Grep and more. - Interactive preview of search results. - Keyboard navigation for efficient workflow. - Configurable key bindings and search modes. ## Installation and Update ### Prerequisites - [ripgrep](https://github.com/BurntSushi/ripgrep?tab=readme-ov-file#installation) installed on your system. - (Optional) [ast-grep](https://ast-grep.github.io) installed on your system, if you want to use the AST Grep functionality. ### Steps 1. Install the application using Cargo: ```bash cargo install serpl ``` - If you want to install the application with the AST Grep functionality, you can use the following command: ```bash cargo install serpl --features ast_grep ``` 2. Run the application: ```bash serpl ``` ### Binaries Check the [releases](https://github.com/yassinebridi/serpl/releases) page for the latest binaries. ### OS Specific Installation #### Brew `serpl` can be installed using [Homebrew](https://brew.sh/): ```bash brew install serpl ``` #### Arch Linux `serpl` can be installed from the [official repositories](https://archlinux.org/packages/extra/x86_64/serpl/) using [`pacman`](https://wiki.archlinux.org/title/Pacman): ```bash pacman -S serpl ``` #### Nix/NixOS `serpl` is included in [nixpkgs](https://github.com/nixos/nixpkgs) since 24.11, and can be installed via Nix in different ways: **On standalone Nix setups**: ```bash nix profile install nixpkgs#serpl ``` **On NixOS** (via `configuration.nix` or similar): ```nix {pkgs, ...}: { environment.systemPackages = [pkgs.serpl]; } ``` **On Home-Manager**: ```nix {pkgs, ...}: { home.packages = [pkgs.serpl]; } ``` ## Usage ### Basic Commands - Start the application in the current directory: ```bash serpl ``` - Start the application and provide the project root path: ```bash serpl --project-root /path/to/project ``` ### Key Bindings Default key bindings can be customized through the `config.json` file. #### Default Key Bindings | 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 | ### Configuration `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. #### Example Configurations
JSON ```json { "keybindings": { "": "Quit", "": "Quit", "": "LoopOverTabs", "": "BackLoopOverTabs", "": "ProcessReplace" } } ```
JSON5 ```json5 { keybindings: { "": "Quit", "": "Quit", "": "LoopOverTabs", "": "BackLoopOverTabs", "": "ProcessReplace", }, } ```
YAML ```yaml keybindings: "": "Quit" "": "Quit" "": "LoopOverTabs" "": "BackLoopOverTabs" "": "ProcessReplace" ```
TOML ```toml [keybindings] "" = "Quit" "" = "Quit" "" = "LoopOverTabs" "" = "BackLoopOverTabs" "" = "ProcessReplace" ```
INI ```ini [keybindings] = Quit = Quit = LoopOverTabs = BackLoopOverTabs = ProcessReplace ```
You can customize the key bindings by modifying the configuration file in the format of your choice. ## Panes ### Search Input - Input field for entering search keywords. - Toggle search modes (Simple, Match Case, Match Whole Word, Match Case Whole Word, Regex, AST Grep). - Simple: Search all occurrences of the keyword. - Match Case: Search occurrences with the same case as the keyword. - Match Whole Word: Search occurrences that match the keyword exactly. - Match Case Whole Word: Search occurrences that match the keyword exactly with the same case. - Regex: Search occurrences using a regular expression. - AST Grep: Search occurrences using AST Grep. > [!TIP] > If current directory is considerebly large, you have to click `Enter` to start the search. ### Replace Input - Input field for entering replacement text. - Toggle replace modes (Simple, Preserve Case, AST Grep). - Simple: Replace all occurrences of the keyword. - Preserve Case: Replace occurrences while preserving the case of the keyword. - AST Grep: Replace occurrences using AST Grep. ### Search Results Pane - List of files with search results. - Navigation to select and view files. - Option to delete files from the search results. - Search results count and current file count. - Ability to search the list using the `/` key. ### Preview Pane - Display of the selected file with highlighted search results, and context. - Navigation to view different matches within the file. - Option to delete individual lines containing matches. ## Quick Hints - Use the `Ctrl + b` key combination to display the help dialog. - Use the `Ctrl + o` key combination to process the replace for all files. - Use the `r` key to process the replace for the selected file or line. - Use the `Ctrl + n` key combination to toggle between search and replace modes. - Use the `g`, `G`, `j`, and `k` keys to navigate through the search results. - Use the `d` key to delete the selected file or line. ## Neovim Integration using toggleterm Check out the [toggleterm.nvim](https://github.com/akinsho/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](https://astronvim.com/): ```lua return { "akinsho/toggleterm.nvim", cmd = { "ToggleTerm", "TermExec" }, dependencies = { { "AstroNvim/astrocore", opts = function(_, opts) local maps = opts.mappings local astro = require "astrocore" maps.n["t"] = vim.tbl_get(opts, "_map_sections", "t") local serpl = { callback = function() astro.toggle_term_cmd "serpl" end, desc = "ToggleTerm serpl", } maps.n["sr"] = { serpl.callback, desc = serpl.desc } maps.n["tf"] = { "ToggleTerm direction=float", desc = "ToggleTerm float" } maps.n["th"] = { "ToggleTerm size=10 direction=horizontal", desc = "ToggleTerm horizontal split" } maps.n["tv"] = { "ToggleTerm size=80 direction=vertical", desc = "ToggleTerm vertical split" } maps.n[""] = { 'execute v:count . "ToggleTerm"', desc = "Toggle terminal" } maps.t[""] = { "ToggleTerm", desc = "Toggle terminal" } maps.i[""] = { "ToggleTerm", desc = "Toggle terminal" } maps.n[""] = { 'execute v:count . "ToggleTerm"', desc = "Toggle terminal" } maps.t[""] = { "ToggleTerm", desc = "Toggle terminal" } maps.i[""] = { "ToggleTerm", 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" }, "", toggle, { desc = "Toggle terminal", buffer = t.bufnr }) vim.keymap.set({ "n", "t", "i" }, "", toggle, { desc = "Toggle terminal", buffer = t.bufnr }) end end, shading_factor = 2, direction = "float", float_opts = { border = "rounded" }, }, } ``` ## License This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. ## Contributing (WIP) ## Acknowledgements - This project was inspired by the [VS Code](https://code.visualstudio.com/) search and replace functionality. - This project is built using the awesome [ratatui.rs](https://ratatui.rs) library, and build on top of their [Component Template](https://ratatui.rs/templates/component). - Thanks to the [ripgrep](https://github.com/BurntSushi/ripgrep) project for providing the search functionality. - Thanks to the [ast-grep](https://ast-grep.github.io) project for providing the AST Grep functionality. ## Similar Projects - [repgrep](https://github.com/acheronfail/repgrep): An interactive replacer for ripgrep that makes it easy to find and replace across files on the command line.