-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add "replace" text field in --json output that contains replace string for respective matches #1872
Comments
Just to make sure we are in the same page here, could you give an example input with desired output? Thank you for detailed use case. It is a little hard for me to follow, since I'm perhaps not as familiar with the inner workings of vim's search and replace system. It might help to describe it from the perspective of data flow. That is, how does the data flow from ripgrep's JSON output through vim? |
@BurntSushi Let's say for Command: rg -N --passthrough '^.*\\(.*)\{(.*)\}.*?$|^.*\\(.*)\[(.*)\].*?$' -r '\macro$1{option:$2}' temp.tex Input file: % temp.tex
\documentclass{article}
\usepackage{blindtext}
\usepackage{fancyhdr}
\usepackage{pdftexcmds}
\pagestyle{fancy}
\begin{document}
\blindtext[5]
\end{document} This will produce output: \macrodocumentclass{option:article}
\macrousepackage{option:blindtext}
\macrousepackage{option:fancyhdr}
\macrousepackage{option:pdftexcmds}
\macropagestyle{option:fancy}
\macrobegin{option:document}
\macro{option:}
\macroend{option:document}
As of today if {
"type": "match",
"data": {
"path": {
"text": "temp.tex"
},
"lines": {
"text": "\\documentclass{article}\n"
},
"line_number": null,
"absolute_offset": 0,
"submatches": [
{
"match": {
"text": "\\documentclass{article}"
},
"start": 0,
"end": 23
}
]
}
} There are multiple ways in which you could decide to add replace text information. It could be either 1) in existing list
{
"type": "match",
"data": {
"path": {
"text": "temp.tex"
},
"lines": {
"text": "\\documentclass{article}\n"
},
"line_number": null,
"absolute_offset": 0,
"submatches": [
{
"match": {
"text": "\\documentclass{article}",
"replacetext": "\\macrodocumentclass{option:article}"
},
"start": 0,
"end": 23
}
]
}
}
{
"type": "match",
"data": {
"path": {
"text": "temp.tex"
},
"lines": {
"text": "\\documentclass{article}\n"
},
"line_number": null,
"absolute_offset": 0,
"submatches": [
{
"match": {
"text": "\\documentclass{article}"
},
"replace": {
"text": "\\macrodocumentclass{option:article}"
},
"start": 0,
"end": 23
}
]
}
} Regarding flow of data from |
The examples help a lot, thanks. With respect to
Hmm so this wasn't quite what I was hoping for. I'm not particularly interested in Vim features. While I've used Vim for a long time, certain corners of it remain mysterious to me and I do not have the background knowledge necessary to write plugin. So talking about this in terms of Vim features doesn't aide understanding unfortunately. Let me take a guess at what I think you want to do:
If that's right, then I believe this should be doable and I agree that it sounds like a good thing to support. It might also be appropriate to provide a
It does, but ripgrep's regex engine's capturing groups don't work in the way you're trying to use them. For the regex ripgrep has very limited facilities for text replacements. The |
Yep thats a typo. I have updated the comment #1872 (comment) Yep your analysis is correct.
What about replacement with Not sure what you meant by |
Yes. It's inherent to how capture groups are indexed. With that said, I am not a PCRE2 expert and PCRE2 has many options. For example, the (There are competing concerns here. ripgrep's default regex engine is the main support for regexes for a full programming language. In that context, not being able to use duplicate capture group names is usually a minor annoyance. But in contexts such as yours, where your expressiveness is severely restricted, every little bit of extra juice you can squeeze out of the regex itself helps.) |
@BurntSushi I think what I need can be done with |
@reportaman It wouldn't work. ripgrep doesn't use PCRE2's replacement routines. |
@BurntSushi Ok sure, running batch replacement from within vim multiple times (to cover different sub pattern cases) on files of a project wouldn't hurt. If users want to do batch replacement on thousands of files they should anyway do it from command line. I look forward to playing with the replace strings you add to Curious why that decision though? Couldn't ripgrep just link to libpcre* and use that for fallback? |
@BurntSushi, Thanks for the excellent tool. I also need to replace matched strings in the files. Having a replacement string will make it a lot easier and most of all the replacement strings will be consistent with the ripgrep matching engine. Do you have any plans for this enhancement? Also, I'm curious that is there a specific reason you chose not to implement the file replacement functionality as, like you said, the tool is already doing 80% heavy lifting? |
@manikantag This issue isn't about replacing stuff in files. This issue is about the
What enhancement are you talking about? If you're talking about the one represented by this specific issue, then yes, it is open and marked as
That's not really what I said. I was alluding to the Pareto principle. That is, it hits the 80% use case with not much effort, but going the rest of the way takes quite a bit more work and complexity. So it is the opposite of "if you're already 80% of the way there, then why not just do a little bit more to get to 100%." |
@BurntSushi yes, I meant the JSON changes only as you clearly mention no option in ripgrep will change the actual file content (even My thought is if the tool includes the replacement string in the JSON output, then by consuming the JSON, one can built tool to the actual file replacement. May be I'm not clear enough, but I said 80% because the tool is already giving matching file, line, column & highlighting the word match too. Using the JSON output, I'm able to generate HTML markup like how vscode (or any other editor) is doing. Now with addition of replacement string in JSON output, my end objective to build 'File search & replace' feature will be 100% complete. I see you considered this as an enhancement. Looking forward for it. And hopefully the JSON output schema will not change in future which would break my logic. Thanks |
My plugin could also use this feature. Currently I am working around it by setting colors for matches like rgb(0,0,1) and parsing those from the output in order to figure out what to highlight. Having the replacement would allow me to use the json output instead and show a diff as well. |
@BurntSushi my rust skills are very tiny, but am I correct in thinking that this work would mainly involve doing the same "replacer" thing as in the standard printer: ripgrep/crates/printer/src/standard.rs Line 576 in e0f1000
(and all it's usages in that file) but in the json printer? https://github.com/BurntSushi/ripgrep/blob/e0f1000df67f82ab0e735bad40e9b45b2d774ef0/crates/printer/src/json.rs |
Currently
rg --json
provides full text of every match in submatch array item'smatch.text
field. This ticket is to request addition ofreplace.text
field in submatch array items. Thereplace.text
fields will only get added if user passed the replace flag-r
and the replace string. For usual searches without replace (-r
), replace.text will not get added & the json output will be same as it is today.Motivation: This will allow using
rg --json
to become a real alternative to Vim's internal search-and-replace functionality:%s/<match_pattern>/<replace_pattern>/g
that is based on legacy vim regex format. Given the start-end position of submatches are known, developers would just need replacement text information to deletematch.text
from text files, and replace it withreplace.text
. Given its in a clean json format, it would be easier to allow batch processing, replace an occurrence of interest, and even selectively rollback* easily. The same information can be used in other tools/scripts as well to do search-and-replace. Moreover, currently there is no way of doing this usingrg
with Vim & just having it integrated as a search tool makes it less preferred over vim's built in regex engine because: users will have to learn new regex syntax that they cannot use for capture group based complex text replace. This will force a user to either learn both syntaxes (vim regex, and rust regex), or just stick with vim regex (thus limiting adoption ofrg
). Having this feature will also bring the power of pcre2 search and replace to Vim.* Selective rollback is different from undo. Undo by its very nature is LIFO, whereas selective rollback can be in any order the user wishes (without having to undo all steps after it). It's easy to build something like that in Vim with information asked in this ticket.
The text was updated successfully, but these errors were encountered: