yassinebridi / serpl

A simple terminal UI for search and replace, ala VS Code.
MIT License
320 stars 1 forks source link
replace rust search terminal tui vscode

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/c63627da-7984-4e5f-b1e2-ff14a5d44453

Table of Contents

  1. Features
  2. Installation
  3. Usage
  4. Panes
  5. Neovim Integration using toggleterm
  6. License
  7. Contributing

Features

Installation and Update

Prerequisites

Steps

  1. Install the application using Cargo:
    cargo install serpl
  2. Update the application using Cargo:
    cargo install serpl
  3. Run the application:
    serpl

Binaries

Check the releases page for the latest binaries.

OS Specific Installation

Arch Linux

serpl can be installed from the official repositories using pacman:

pacman -S serpl

Usage

Basic Commands

Key Bindings

Default key bindings can be customized through the config.json file.

Default Key Bindings

Key Combination Action
Ctrl + c Quit
Tab Switch between tabs
Backtab Switch to previous tabs
Ctrl + o Process replace
Ctrl + n Toggle search and replace modes
Enter Execute search (for non-git repos)
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
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

Replace Input

Search Results Pane

Preview Pane

Neovim Integration using toggleterm

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" },
  },
}

License

This project is licensed under the MIT License. See the LICENSE file for details.

Contributing

(WIP)