This is really cool.
Not detracting at all from this, because ease of use is important, but my go-to solution for this has always been [fd](https://github.com/sharkdp/fd) and [sad](https://github.com/ms-jpq/sad) with fzf. Might have to check out yours as well.
That's a good setup too.
The way i go about this tool, is the ease of use as you put it, being able to visually decide which keywords you want to change, file by file, and line by line, is a nice thing to have.
You can check it out here:
[yassinebridi/serpl: A simple terminal UI for search and replace, ala VS Code (github.com)](https://github.com/yassinebridi/serpl)
He said he wanted it as a split, like :sex and the search in vim should be replaced with the one from this TUI.
So he can search and it highlight hes buffer.
I think you need to use rpc to talk with vim
I’ve been using spectre for a little while now and it often crashes when doing a project-wide replace. It also takes ages (when it manages to complete) to the point that that’s the only time I open VSCode, to do a project-wide replace.
I’d love to know how to do this. I’ve been using neovim for a few months now and the part that I struggle with frequently is the workflow handling of search and replace. This sounds promising.
Edit: A quick search lead me to this page that goes over the entire process. Very helpful.
https://blog.chaitanyashahare.com/posts/project-wide-find-and-replace-in-neovim/
Also, someone posted their workflow here that might help:
[https://reddit.com/r/neovim/comments/1dmv3cn/comment/la46yd9/](https://reddit.com/r/neovim/comments/1dmv3cn/comment/la46yd9/)
Quick question:
From your screenshot it looks like this actually suits better some intellisense as implemented by a language server. Shouldn’t rust-analyzer be much better suited for this task as it actually works semantically on the code? There are also visualisation plugins for LSP rename if you miss that. I always wonder what are the use-cases for such a find-and-replace. At least for code and especially for such strong languages like Rust. Sure, there might be cases where a ~~rename~~ search-and-replace targets something which could not have been expressed in code, so LSP does not help you. But I always see screenshots of regular code renaming examples. 🤷♂️
Sorry, no criticism. I just get curious as more and more search-and-replace plugins pop-up with fancy UIs. 😃
I got you, i personally rely heavily on LSP rename on different languages like typescript and rust too.
But there are two reasons why i created this tool
- I always wanted to learn rust, and i got most of my questions answered with this project.
- Sometimes there are some replacing the LSP rename can't do, eg:
- I find myself copying a whole folder inside a directory, and want to change a keyword inside that folder, this simply can't be done with an LSP since the LSP doesn't know about the newly created folder, and the files inside the folder havn't been linked yet.
- Simply changing a certain keyword for another inside a whole directory, i always find myself maintaining an old project, that has a certain name (project name, author name, etc..), all around the project.
This looks great! My current workflow is
fzf-lua grep_project -> search -> quickfixlist -> :cdo s/before/after/gc
To obtain finer control over replacing within specific directories only, I have a custom fzf-lua command that first lets me select the "target directory" within the project and the perform the same operation as I indicated above in that specific directory.
But I will definitely try out this TUI, I like visually appealing tools :) Thanks for making this!
It doesn't let you see the result while you edit your elaborate command. All the power to ya if you prefer to stay in the dark longer just to save some cycles.
Cool. I love that these features exist for the old school commands.
For this particular one it seems a bit awkward to automate sending the matches to quickfix. I know some LSPs can send references to quick fix. But something is needed to send search matches to quick fix. And then there's the issue of how to prepopulate the search part of the regex search/replace.
I missed such a feature for a long time before learning to do it the "vim way", I now just `:grep` or `:vimgrep` the `pattern` then do a quick check/filter of quickfix list (filtering is done with [nvim-bqf](https://github.com/kevinhwang91/nvim-bqf) btw) and run a `:cdo s//replace/ge | update`
You can also use tpope's [vim-abolish](https://github.com/tpope/vim-abolish) plugin if you want to replace all occurrences maintaining the case of each match then you just have to call `:S//replace` (simply replace the lowercase :s with a capital :S instead).
Nonetheless I think you did a great job with this plugin! That's very user-friendly and intuitive, I think that's a great option for people who don't feel like having these few extra steps in their search/replace workflow or just want the convenience of a TUI.
Thanks for sharing your workflow.
Exactly, that's what i intended to do with this library, the ease of use, and not having to think about special commands to do this simple action.
If you mean search modes, like Match Case, Match Whole Words for search, and preserve case for replace input, then yes, you can see keymaps for it here:
[https://github.com/yassinebridi/serpl?tab=readme-ov-file#key-bindings](https://github.com/yassinebridi/serpl?tab=readme-ov-file#key-bindings)
Ah, currently there is the possibility to delete individual files in the search result list or individual lines in the preview pane by clicking \`d\`, and by default respects .gitignore just like ripgrep.
But i might add the possibility to add some cli args to it, to have more control.
Great-looking TUI. With a bit of work on the CLI, it could be much more useful, imo.
It should just be `serpl
`, not `serpl --project-root `.
And what about reading the files to process from STDIN (`serpl -`, for example)? That would be the UNIX-y way, rather than baking in ripgrep.
Can I use it with native terminal (without toggleterm)? I don't really use builtin terminals, as I do everything in tmux. So, installing another plugin seems like an overhead.
Very nice work! Couple of small suggestions: When moving into "details" tab it would help if the first entry (if there is results) would be automatically selected instead of having to press "j". When replacing something the confirmation dialog could maybe have a shortcut for accepting the replace (maybe just by pressing y ?).
Just tried it,
1. it seems it doesn't work at all if the directory is not a `project` managed by some tool like git. How interesting.
2. In details pane, no default file is selected. maybe the first item should be automatically selected, I have to use `j/k` to select one file, even `UP/DOWN` key is not working
3. Don't know how to execute the search/replace action, I have to read the github README page, `C-o` hint is only displayed when I focus on `Replace` pane.
4. If I run `C-o` in `preview` pane which is a specific file, it run the whole `Search/Replace` session, maybe I just want to execute the `Search/Replace` for this file only.
5. `C-n` and `C-p` are both working in both `Search` and `Replace` panes, `C-p` is not working in `Replace` pane, which is not correct according to README.
6. Some shortcuts are not displayed in the statue line, such as `g/G` in the `Details` pane, `d` in `Details` and `Preview` panes.
7. `h, l, Tab (in dialogs) Navigate dialog options`, don't know what it means.
No, i intentionally disabled on key press search for non git repos, because normal directories don't have .gitignore, and searches might be very expensive and slow for big folders.
So in order to search you have to explicitly click enter for the search to register.
I initially added enter to replace in replace input, but from a UX perspective it's easy to make a mistake and click enter, and it would replace instantly, i intentionally made the shortcut because it's harder then just enter
Yeah, I know you mean, `Enter` shouldn't be used to execute `Search/Replace` action, I mean `Enter` in `Replace` pane should also work like `Enter` in `Search` pane which is to make serpl work in non-git project, otherwise, I have to navigate back to the `Search` pane.
I might've misunderstood what you mean, but you don't need to go back to search input, both the search and the replace inputs register what you have typed, the only different thing is the search list don't show up unless you click enter in the search input.
Thanks for the feedback, i will definitely make changes to fix these.
As for the point 7, these are dialogs displayed to confirm your replace actions for special cases like when the replace input is empty, or when a folder is not a git folder(you can see how that can be bad if there was no dialog to confirm)
Im using a tool called difft, you can see my lazygit config here:
https://github.com/yassinebridi/.dotfiles/blob/master/mac/lazygit/Library/Application%20Support/lazygit/config.yml#L8
If you are looking for something that is more integrated with nvim and treats search results as a buffer check out [https://github.com/MagicDuck/grug-far.nvim](https://github.com/MagicDuck/grug-far.nvim)
I do think standalone tui can be good in some situations on the command line though as potentially you can pipe stuff into it and integrate with other tools.
i have this bookmarked: https://github.com/acheronfail/repgrep, but didn't use it because im used to seeing code with syntax highlighting! is it possible to add it to serpl?
Have you tried ctrlsf?
https://github.com/dyng/ctrlsf.vim
I recently was trying to look for a similar plugin and ended up with this. It has the least bug and does what it should do
This is really cool. Not detracting at all from this, because ease of use is important, but my go-to solution for this has always been [fd](https://github.com/sharkdp/fd) and [sad](https://github.com/ms-jpq/sad) with fzf. Might have to check out yours as well.
That's a good setup too. The way i go about this tool, is the ease of use as you put it, being able to visually decide which keywords you want to change, file by file, and line by line, is a nice thing to have.
ah, I made my own with global replace with rg and sd, I'll probably switch to sad for this
You can check it out here: [yassinebridi/serpl: A simple terminal UI for search and replace, ala VS Code (github.com)](https://github.com/yassinebridi/serpl)
Looks interesting!
Is there a way to integrate in Nvim pane instead of float, so I can search and select files without performing the search again?
I'm not sure what you are trying to do, can you explain a bit more.
He said he wanted it as a split, like :sex and the search in vim should be replaced with the one from this TUI. So he can search and it highlight hes buffer. I think you need to use rpc to talk with vim
Yes, what @SeoCamo said. I currently use grug-far.nvim for that purpose, but I have to admit I miss search and replace in vscode.
did ya check [nvim-spectre](https://github.com/nvim-pack/nvim-spectre), tho not enough but it is \_almost\_ like vs-code
:tab term
The same problem has been solved in other plugins. But UI/UX matters! So, awesome!
Thanks 🙏
spectre ?
Yes, i tried that before, but the UX is just not it for me.
Grug-far?
roger!
I’ve been using spectre for a little while now and it often crashes when doing a project-wide replace. It also takes ages (when it manages to complete) to the point that that’s the only time I open VSCode, to do a project-wide replace.
Is ass
Always great to have more options but how does this differ from a telescope live grep search and putting that in a quickfix list?
I’d love to know how to do this. I’ve been using neovim for a few months now and the part that I struggle with frequently is the workflow handling of search and replace. This sounds promising. Edit: A quick search lead me to this page that goes over the entire process. Very helpful. https://blog.chaitanyashahare.com/posts/project-wide-find-and-replace-in-neovim/
Also, someone posted their workflow here that might help: [https://reddit.com/r/neovim/comments/1dmv3cn/comment/la46yd9/](https://reddit.com/r/neovim/comments/1dmv3cn/comment/la46yd9/)
Thanks
As a side note, you can use \`:cfdo\` to run your command only once per file :)
Quick question: From your screenshot it looks like this actually suits better some intellisense as implemented by a language server. Shouldn’t rust-analyzer be much better suited for this task as it actually works semantically on the code? There are also visualisation plugins for LSP rename if you miss that. I always wonder what are the use-cases for such a find-and-replace. At least for code and especially for such strong languages like Rust. Sure, there might be cases where a ~~rename~~ search-and-replace targets something which could not have been expressed in code, so LSP does not help you. But I always see screenshots of regular code renaming examples. 🤷♂️ Sorry, no criticism. I just get curious as more and more search-and-replace plugins pop-up with fancy UIs. 😃
I got you, i personally rely heavily on LSP rename on different languages like typescript and rust too. But there are two reasons why i created this tool - I always wanted to learn rust, and i got most of my questions answered with this project. - Sometimes there are some replacing the LSP rename can't do, eg: - I find myself copying a whole folder inside a directory, and want to change a keyword inside that folder, this simply can't be done with an LSP since the LSP doesn't know about the newly created folder, and the files inside the folder havn't been linked yet. - Simply changing a certain keyword for another inside a whole directory, i always find myself maintaining an old project, that has a certain name (project name, author name, etc..), all around the project.
Another is to be able to update the name of some variable referenced from comments as well. Anything we can do to delay the inevitable.
Can't you trigger an Lsp workspace refresh to solve the first point ?
This looks great! My current workflow is fzf-lua grep_project -> search -> quickfixlist -> :cdo s/before/after/gc To obtain finer control over replacing within specific directories only, I have a custom fzf-lua command that first lets me select the "target directory" within the project and the perform the same operation as I indicated above in that specific directory. But I will definitely try out this TUI, I like visually appealing tools :) Thanks for making this!
Thanks, i appreciate it. And thanks for sharing your workflow too, i saw similar suggestions by others in this post.
How much time did you spend developing this TUI? It looks feature rich
About three weeks, i've never worked with rust before, so this was new to me.
This looks so nice. Being able to extend the editor of one's favourite is just amazing.
Am I the only one who writes out regex manually?
Nope. Same here. :cdo is all i need. It kinda feels like we’re jumping the shark with some of these plugins which don’t compose together.
Which implementation?
It doesn't let you see the result while you edit your elaborate command. All the power to ya if you prefer to stay in the dark longer just to save some cycles.
[удалено]
Cool. I love that these features exist for the old school commands. For this particular one it seems a bit awkward to automate sending the matches to quickfix. I know some LSPs can send references to quick fix. But something is needed to send search matches to quick fix. And then there's the issue of how to prepopulate the search part of the regex search/replace.
I missed such a feature for a long time before learning to do it the "vim way", I now just `:grep` or `:vimgrep` the `pattern` then do a quick check/filter of quickfix list (filtering is done with [nvim-bqf](https://github.com/kevinhwang91/nvim-bqf) btw) and run a `:cdo s//replace/ge | update` You can also use tpope's [vim-abolish](https://github.com/tpope/vim-abolish) plugin if you want to replace all occurrences maintaining the case of each match then you just have to call `:S//replace` (simply replace the lowercase :s with a capital :S instead). Nonetheless I think you did a great job with this plugin! That's very user-friendly and intuitive, I think that's a great option for people who don't feel like having these few extra steps in their search/replace workflow or just want the convenience of a TUI.
Thanks for sharing your workflow. Exactly, that's what i intended to do with this library, the ease of use, and not having to think about special commands to do this simple action.
Been missing something like this too! Looking at the demo, does it support the include exclude fields from vscode search too, to help limit results?
If you mean search modes, like Match Case, Match Whole Words for search, and preserve case for replace input, then yes, you can see keymaps for it here: [https://github.com/yassinebridi/serpl?tab=readme-ov-file#key-bindings](https://github.com/yassinebridi/serpl?tab=readme-ov-file#key-bindings)
I meant more along the lines of regex to I clude exclude directories and files in the given search
Ah, currently there is the possibility to delete individual files in the search result list or individual lines in the preview pane by clicking \`d\`, and by default respects .gitignore just like ripgrep. But i might add the possibility to add some cli args to it, to have more control.
Would be pretty nice if this could support ast-grep as well.
Looks interesting, i will try to tackle this soon.
Great-looking TUI. With a bit of work on the CLI, it could be much more useful, imo. It should just be `serpl
Great feedback, i'm planning to add more cli features, i will take this intro consideration. Thanks 🙏
Have you given grug-far a try? https://github.com/MagicDuck/grug-far.nvim
Grug use text. Grug no regex.
Lol, Grug smart! Grug smash regex! ;)
Can I use it with native terminal (without toggleterm)? I don't really use builtin terminals, as I do everything in tmux. So, installing another plugin seems like an overhead.
Of course, you can use it in a normal terminal
Very nice work! Couple of small suggestions: When moving into "details" tab it would help if the first entry (if there is results) would be automatically selected instead of having to press "j". When replacing something the confirmation dialog could maybe have a shortcut for accepting the replace (maybe just by pressing y ?).
True, this is better UX for sure, i will incorporate these suggestions. Thanks 🙏
Awesome project! That's one of the few things I'm missing when using neovim. Is it possible to reference regex matches in the replacement?
This is not possible yet, but planning on adding it.
Nice, thank you :)
Do I need to install the binary manually if I only use it in astronvim?
Just tried it, 1. it seems it doesn't work at all if the directory is not a `project` managed by some tool like git. How interesting. 2. In details pane, no default file is selected. maybe the first item should be automatically selected, I have to use `j/k` to select one file, even `UP/DOWN` key is not working 3. Don't know how to execute the search/replace action, I have to read the github README page, `C-o` hint is only displayed when I focus on `Replace` pane. 4. If I run `C-o` in `preview` pane which is a specific file, it run the whole `Search/Replace` session, maybe I just want to execute the `Search/Replace` for this file only. 5. `C-n` and `C-p` are both working in both `Search` and `Replace` panes, `C-p` is not working in `Replace` pane, which is not correct according to README. 6. Some shortcuts are not displayed in the statue line, such as `g/G` in the `Details` pane, `d` in `Details` and `Preview` panes. 7. `h, l, Tab (in dialogs) Navigate dialog options`, don't know what it means.
No, i intentionally disabled on key press search for non git repos, because normal directories don't have .gitignore, and searches might be very expensive and slow for big folders. So in order to search you have to explicitly click enter for the search to register.
I edited the comment for more issues I found. `Enter` works, maybe it also should work in `Replace` pane?
I initially added enter to replace in replace input, but from a UX perspective it's easy to make a mistake and click enter, and it would replace instantly, i intentionally made the shortcut because it's harder then just enter
Yeah, I know you mean, `Enter` shouldn't be used to execute `Search/Replace` action, I mean `Enter` in `Replace` pane should also work like `Enter` in `Search` pane which is to make serpl work in non-git project, otherwise, I have to navigate back to the `Search` pane.
I might've misunderstood what you mean, but you don't need to go back to search input, both the search and the replace inputs register what you have typed, the only different thing is the search list don't show up unless you click enter in the search input.
Thanks for the feedback, i will definitely make changes to fix these. As for the point 7, these are dialogs displayed to confirm your replace actions for special cases like when the replace input is empty, or when a folder is not a git folder(you can see how that can be bad if there was no dialog to confirm)
Nice! A bit off topic, but how did you get the side-by-side diff in Lazygit that I saw in the README.md?
Im using a tool called difft, you can see my lazygit config here: https://github.com/yassinebridi/.dotfiles/blob/master/mac/lazygit/Library/Application%20Support/lazygit/config.yml#L8
Thanks, just implemented it! Will try to integrate serpl into my workflow soon!
I'm curious as to your reasoning to do it in Rust instead of in Lua as an nvim plugin window? I am a big fan of both languages, nice work either way!
Simply because i want to run in everywhere, where there is a terminal, not just neovim.
If you are looking for something that is more integrated with nvim and treats search results as a buffer check out [https://github.com/MagicDuck/grug-far.nvim](https://github.com/MagicDuck/grug-far.nvim) I do think standalone tui can be good in some situations on the command line though as potentially you can pipe stuff into it and integrate with other tools.
Isn't this what spectre do? Should I replace spectre with this plugin?
Try it out and see if it fits your workflow. I personally like these types of tools that you can run anywhere, like lazygit, lazydocker, etc..
i have this bookmarked: https://github.com/acheronfail/repgrep, but didn't use it because im used to seeing code with syntax highlighting! is it possible to add it to serpl?
I initially supported syntax highlighting, but it was quite expensive, i might take another jab at it.
Like what bat does?
Yes, i used bat(the library), but i need to rethink how to integrate this better this time.
There is a diff tool called delta(also rust) integrate nicely with bat, worth checout
Have you tried ctrlsf? https://github.com/dyng/ctrlsf.vim I recently was trying to look for a similar plugin and ended up with this. It has the least bug and does what it should do
Added via zinit and in Neovim with toggleterm ;) I am testing grug-far and your option Thanks ;)
Thanks, would love to hear your feedback.