vim-abolish icon indicating copy to clipboard operation
vim-abolish copied to clipboard

Backslashes escaped too much in substitution

Open ts826848 opened this issue 5 years ago • 1 comments

This is somewhat related to #87. While that PR prevents an exception with escaped delimiters, attempting to substitute something with backslashes still doesn't work properly.

For example, attempting to replace all backslashes with forward slashes using S/\\/\//g just replaces all double backslashes with \/. The equivalent vim command using a lowercase s does the intended replacement.

A different delimiter could be used to avoid the backslash in front of the forward slash, resulting in something like S;\\;/;g, but that still does something weird with the pattern to be substituted so that it replaces only double backslashes with a single forward slash. Single backslashes are left alone.

Using a single backslash in the pattern-to-replace slot (resulting in something like S;\;/;g) gives the intended behavior, but could be surprising since that is a search for ;/ with the standard vim s command.

As far as I could tell, this is because s:subvert_dispatcher gets an already-escaped substitution string through <q-args>:

cmd: exec s:subvert_dispatcher(0,1,54,54,";\\\\;/;g")

This results in the pattern-to-be-substituted being an already-escaped backslash (\\) throughout the abolish code. This escaped backslash is then escaped again in s:subesc before being concatenated with some other stuff and being passed back to vim:

:return 1,54substitute/\v\C%(\\\\)/\=Abolished()/g made pending

Removing the backslash from the list of characters to escape results in what looks like a correct command:

:return 1,54substitute/\v\C%(\\)/\=Abolished()/g made pending

But I'm not certain that that change doesn't break another use case.

In addition, the code still doesn't work, appearing to be a no-op instead. I have no idea why, since I'm not familiar enough with vimscript to be able to tell what Abolished() is supposed to return. echo Abolished() appears to print nothing, but that's also the case for a command that does perform a substitution correctly, so I'm not sure how to further debug the issue.

ts826848 avatar Feb 27 '20 02:02 ts826848

This code is ancient, but I'd say it's a safe guess I was aiming to specifically not to regexp escapes, limiting the magic to our own {} expressions. I was targeting plain language words and I imagine I wrote off backslashes entirely. If you wanna rectify that, you're probably gonna have to do it without much help from me.

tpope avatar Mar 20 '21 15:03 tpope