I dunno, seems reasonable to me that we might have nice things without requiring everyone to use emacs. (And for those who do use emacs, I guess you're ahead of the curve?)
There was another comment about the difficulty in installing scooter and in the issues section, there are some requests to add more installation options.
You could also use vim in a loop. Say you want to replace "hello" in all files in the current dir with "world" and confirm every replace, then you would do:
for f in $(grep -l 'hello' *); do vim -c ':%s/hello/world/gc | wq' "$f"; done
Or if you want to use some more vim magic, this simpler command will do the same:
vim -c "argdo %s/hello/world/gce | update" -c "qall" *
"argdo" will do the replace command for each file, the additional e modifier in gce will ignore files that do not contain the search string and the second command "qall" is to quit vim after the work is done.
In Emacs, there is [helm-ag-edit](https://github.com/emacsorphanage/helm-ag) (but uses ripgrep if present). It's almost identical to your workflow, but all done inside the same app.
1. helm-ag <pattern> # the search results are updated as you type
2. helm-ag-edit # edit the search result as regular text. Use multi-cursors, macros, whatever.
3. helm-ag-edit-save # commits the changes to the affected files
All those commands have keybindings, so it's pretty fast. I'll often open up Emacs just to do that and then go back to my JetBrains IDE.
"For a Linux user, you can already build such a system yourself quite trivially by getting an FTP account, mounting it locally with curlftpfs, and then using SVN or CVS on the mounted filesystem"
It's great and clearly the community appreciates it! I'll put Show HN in the title since that's the convention for sharing one's projects on HN (https://news.ycombinator.com/showhn.html).
Btw, do you want to include some text giving the backstory of how you came to work on this, and explaining what's different about it? that's also the convention. If you post it in a reply to this comment, I'll move your text to the top of the thread.
I'm using this quickly put-together shell script called replace
#!/usr/bin/env bash
# Function to escape special characters for sed
escape_sed_string() {
printf '%s\n' "$1" | gsed -e 's/[]\/$*.^[]/\\&/g'
}
help() {
gum style --foreground cyan --italic "\
Usage (everything optional, you will be prompted):\n\
$0\n\
--ext .js --ext .ts\n\
--from \"source string\"\n\
--to \"replacement string\"\n\
--dir somePath"
}
# Parse command line arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
-h)
help
exit 0
;;
--help)
help
exit 0
;;
--ext) EXTENSIONS+=("$2"); shift ;;
--from) REPLACE_FROM="$2"; shift ;;
--to) REPLACE_TO="$2"; shift ;;
--dir) DIRECTORY="$2"; shift ;;
*) gum style --foreground red --bold "Unknown parameter: $1"; exit 1 ;;
esac
shift
done
# Check for missing parameters and prompt using gum
if [ -z "${EXTENSIONS+set}" ]; then
EXTENSIONS=($(gum choose \
--no-limit \
--selected .ts,.mts,.tsx,.vue,.js,.cjs,.mjs \
.ts .mts .tsx .vue .js .cjs .mjs .txt .md .html .json))
fi
# Exit if no extension is selected
if [ ${#EXTENSIONS[@]} -eq 0 ]; then
gum style --foreground red --bold " Error: No extensions selected. Exiting."
exit 1
fi
if [ -z "${REPLACE_FROM+set}" ]; then
REPLACE_FROM=$(gum input --placeholder "Search string:")
if [ -z "${REPLACE_FROM}" ]; then
echo "No replace from string, exiting"
exit 1
fi
fi
if [ -z "${REPLACE_TO+set}" ]; then
REPLACE_TO=$(gum input --placeholder "Replace string:")
fi
if [ -z "${DIRECTORY+set}" ]; then
DIRECTORY="."
fi
# Escape strings for sed
ESCAPED_FROM=$(escape_sed_string "$REPLACE_FROM")
ESCAPED_TO=$(escape_sed_string "$REPLACE_TO")
# Run the replacement
for ext in "${EXTENSIONS[@]}"; do
gum style --foreground blue " Replacing ${ext} files..."
find "$DIRECTORY" -type f -name "*$ext" ! -path "*/node_modules/*" -exec gsed -i "s/$ESCAPED_FROM/$ESCAPED_TO/g" {} \;
done
gum style --foreground green --bold " Replacement complete."
https://github.com/ms-jpq/sad
I'm adding scooter to my cargo install favorites:
https://github.com/sixarm/cargo-install-favorites
https://github.com/thomasschafer/scooter/issues/6
Not everyone has the Rust toolchain installed on their machine. The `cargo install` installation directive needs to be discouraged.
I assumed it uses ripgrep (or the underlying walkdir) because that's the established high-performance tool for this. But apparently not.
Being able to interactively ignore instances for replacement is great!
It opens the current command line in $EDITOR, which often defaults to vim.
For more advanced needs, I have a custom thing called greprep that let's you make changes using your favorite editor. Workflow is like this:
1. helm-ag <pattern> # the search results are updated as you type 2. helm-ag-edit # edit the search result as regular text. Use multi-cursors, macros, whatever. 3. helm-ag-edit-save # commits the changes to the affected files
All those commands have keybindings, so it's pretty fast. I'll often open up Emacs just to do that and then go back to my JetBrains IDE.
It's important, when people share something they've made on HN, that they don't run into this sort of bilious internet putdown.
Edit - these are other examples of the same thing (i.e. the thing we don't want in HN threads, and which we'd appreciate if you'd not do any more of):
https://news.ycombinator.com/item?id=41810426
https://news.ycombinator.com/item?id=41224056
https://news.ycombinator.com/item?id=8863
Btw, do you want to include some text giving the backstory of how you came to work on this, and explaining what's different about it? that's also the convention. If you post it in a reply to this comment, I'll move your text to the top of the thread.
If you're afraid of that - are you realistically going to be running a cli interactive find and replace?
If you want to package up an EXE for your specific system and host it somewhere - the license is MIT, go right ahead...
Thanks, not interested then