sd
sd copied to clipboard
[Feature Request] Support Search - without replace
It would be really sweet if there was an easy way to preview the things sd finds, before committing to a replacement.
I realize this is a slightly different use cases and there are already tons of tools that are fast searchers (only) grep, ag, rg, etc. come to mind.
But really, search and replace is the killer feature, and not having to switch syntaxes for either.
Thanks for the feature request!
I think supporting just search would be a bit out of sd's domain although you can get a basic version by using the matching capture for the replacement (it does a lot of extra work though depending on how many and how large of files you're using)
$ echo 'find me' | sd 'find' '$0'
Some related things that I think would be in sd's domain are a much better preview and an interactive mode for doing replacements
I'd like to argue otherwise. In the workflow of replace, it is currently necessary to use one tool to find all places that should be replaced (grep, ag, rg, ...) and once one has determined that the search string is correct, one needs to switch tools to something like sd, only to be at the problem that one needs to re-tune the search string so it actually finds all the same occurrences, especially if I need to also tweak other parameters that I have used to restrict the found occurrences to just the ones that I want to replace.
This, to me, is the death of a special replace tool that only does replacing tool because it makes it so hard to be sure that one does the right thing, and the reason for this bug report.And for me the reason to use multi file replace ein an editor like VSCode, even though it kind of sucks.
I do think. that the '$0' trick is a good approximation, but I would really like to argue that proper support for search only is the correct way to support the refinement of the search string and other parameters to restrict to only the wanted set of hits.
Also I do like interactive mode, but having a non interactive mode first would IMO be superior.
We have now --preview/-p and in the near future --diff.
The argument of workflow is interesting. sd (in its current form) is basically a standalone substitution command of sed. Quote:
Conversely, for simpler operations, specialized Unix utilities such as grep (print lines matching a pattern), head (print the first part of a file), tail (print the last part of a file), and tr (translate or delete characters) are often preferable. For the specific tasks they are designed to carry out, such specialized utilities are usually simpler, clearer, and faster than a more general solution such as sed.
-- https://en.wikipedia.org/wiki/Sed, "Limitations and alternatives"
It's not nonsensical to want one for s//g.
On the other hand, asking to implement full search functionality on top of sd is basically asking to reimplement ripgrep. As reported by tokei, ripgrep 14.0.3 has 36274 lines of Rust code, while sd 1.0.0 has 1083.
Well, maybe joining forces with them could make sense? I recently learned that they support a --replace flag, which seems like a good start for my workflow until tools like sd support something more comprehensive.
Also, on the LOC - I am not sure I understand the argument correctly, as it would seem to me that adding a switch to do less (i.e. not doing the replacement), should not significantly add LOC to the project? I mean, you already implemented all the searching anyway, right?
sd didn't implement searching, frankly. Input is fed directly to its replacer. It has no awareness of whether there's a hit, until the replacement is done (or underway, at least).
Adding a search-only mode makes it a less featured ripgrep. I don't know if that's a good thing.
It's advisable to join forces with ripgrep and probably others, to agree on a general syntax so arguments can be interchanged.
Joining forces by agreeing on an exchangeable syntax sounds great, but also like a lot of work. That still leaves the uncertainty that there may be differences though, so I think that after all it would still make a lot of sense to provide a preview mode - something like --dry-run or --diff. You did provide the example that using $0 as the replacement string to see what happens might be good - that would mimic the default mode of search and replace in editors, where it uses $0 by default while the user hasn't entered anything into the replace field (and has hit search).
Using $0 as the replacement is still an incredibly expensive operation when it comes to just producing a preview. It's not something that I want to recommend people do in general, and I don't feel like maintaining the extra code required to making a just search performant
We're adding different preview modes (and we already have one), but it's for previewing doing a replacement still
Perhaps a different framing could help here? I would like to argue that the user (me in that case) should have a way to validate the correctness of a replace operation.
That is, it should be possible to check that only the wanted files are affected, i.e. that the file filters are set correctly and that the replace will only replace the wanted occurrences of the search string (i.e. the search string is correct).
Speed is (to me) actually only a secondary consideration, as a wrong replace operation will cost me (usually / potentially) far more time to undo than paying the price of the replace operation multiple times.
From this point of view, I hope to convince you, that even a preview operation that has the same complexity / time cost as the full replace operation is just fine for that purpose. Actually going through mostly the same code is (IMO) actually preferable as that will ensure that the matches shown are actually the matches that will be taken later.
So as I said once, --diff mode may be of help (once it got merged). You see a diff of original and replaced, just like git diff after the replacement is done, while nothing is actually written to disk. An interactive mode is also proposed, but that requires significantly more planning and work.
I am looking forward to it!