I have two shell functions in my ~/.zshrc
that are quite useful for this (I think they should work for bash as well, but I didn't test, and with minimal modification it should even work in standard POSIX shells):
# "ag edit" and "grep edit".
age() {
IFS=$'\n' files=($(ag "$@" | cut -d: -f1 | sort -u))
[[ -z "$files" ]] && return 1
vim \
+':silent! /\v'"${@[-1]/\//\\/}" \
+':silent! tabdo :1 | normal! n' \
+':tabfirst' \
-p $files
}
grepe() {
IFS=$'\n' files=($(ag "$@" | cut -d: -f1 | sort -u))
[[ -z "$files" ]] && return 1
vim \
+':silent! /\v'"${@[-1]/\//\\/}" \
+':silent! tabdo :1 | normal! n' \
+':tabfirst' \
-p $files
}
What I usually do is ag 'String field'
first to confirm that it matches what I expect, and then modify this to age 'String field'
to open all the files in Vim tabs (vim -p
opens every file in a new tab).
This sets the search pattern in Vim to whatever you typed on the commandline and goes to the first match, but this isn't perfect as the Vim syntax isn't the same as the syntax grep
and ag
use, so complex patterns tend to break. It's usually "good enough" for simpler patterns.
Then :%s/.../
whatever you want, and if you're confident you've got it right run :tabdo :%s/.../
so that it's run on all tabs. :wqa
and verify that it's all correct.
You can use ripgrep (rg
) instead of the_silver_searcher (ag
) as well; actually, ag
an alias for rg
for me, it's just that I was already so used to typing ag
when I switched from ag
to rg
that it made sense to keep using this command.
You don't need to use tabs, you can use buffers and :bufdo
as well. I just like to use tabs.
There are a myriad of other ways to do the same, B Layer's answer already mentioned some. But I find that my custom age
is super helpful, for this use case and many others, and probably the "custom command" I use the most.
field
(or always the same), or do you want to handle many different fields? Is the type alwaysString
? Are they always private? Is the comment a fixed string, such as alwaysfield comment
, or is it the point to grab whatever is there and pass it as an argument to@ApiModelProperty
? Can the indentation vary between files? Please edit the question to clarify what exactly you have in mind...//<comment><newline>private <type> <field>;
it could be hard to automatically target all the right places. But the answers provide some solid starting points. (And welcome!)