Vim: Incsearch for replace queries - regex

I noticed I could use regex functions with search in vim, and I could see hilights while I typed by setting incsearch. But that didn't work for search and replace queries like this one:
:%s/std::regex\s\([_a-zA-Z]*\)(/regex_t \1 = dregc(/gc
That one surprised me when it actually worked.
Are there settings or plugins for vim that, like incsearch but better, will highlight your replace query as you type? Just highlighting the matches would be pretty neat, but putting the old and new strings next to eachother in different highlighting colors would be a godsend, because I might not be sure about the backreference.

Not a direct answer to your question, but traditionally in Vim you craft your search regex first, as in:
/regex
Then you hit enter to execute it. The settings :set hlsearch and :set incsearch make this easy to see visually. Then you can just do:
:%s//replace
With no search specified, :%s (substitute acting on %, a shorctut meaning all lines in the file) will use the last search term you specified.
Going one step further, you could then do
:%s/~/replace2
Which replaces your last substitution (in this case, replace1) with replace2.
Unrelated, it may be useful for you to put this in your .vimrc:
set gdefault
Which will make all replaces global by default, so you don't need the /g flag after every :%s command.

You might be looking for vim-over?
This is a plugin that: (to clarify, let's say we're doing :%s/foo/bar/g.) i) highlights matches for substitutions in the buffer (foo) and optionally ii) previews what's after replacement (bar).

Related

Limit g flag in regex substitution to part of line?

I have a file like this:
"File_name_1.dat" "File_name_1.dat"
"File_name_2.dat" "File_name_2.dat"
"Some_other_thing.dat" "Some_other_thing.dat"
Is there a regex technique can I use to replace the underscores in only the second file name on each line, like this?
"File_name_1.dat" "File name 1.dat"
"File_name_2.dat" "File name 2.dat"
"Some_other_thing.dat" "Some other thing.dat"
I tried matching the column (\%XXc in Vim), but it seems to disable the g flag.
This only replaces the first underscore after column 25:
:%s/\%25c\([^_]*\)\zs_/ /g
This only replaces the last underscore in the line:
:%s/\%25c\(.*\)\zs_/ /g
I know I could repeat that command until they're gone, but I was wondering if there is a slicker way to do it.
Yes, there is an easy way to do this with visual selections. It's convenient that your data is layed out nicely, otherwise this wouldn't work.
Visually select all of the second filenames
Run this regex:
:'<,'>s/\%V_/ /g
The \%V will restrict your substitute to the inside of the current visual selection. Here's a screen shot of what I mean:
There are probably many ways to do this. Since the data is formatted nicely I would probably visually select and delete the first column (with <c-v>), Then run :%s/_/ /g. Then paste back the first column.
If you really wanted to do this in a single regex, you would need to use a lookbehind
:%s/\(\%25c.\{-}\)\#<=_/ /g
Where \#<= matches if the preceding element matches. :help \#<=

How to jump to first uncommented out statement in vim?

I'm using /print to search for my uncommented-out print statements as I want to comment them out. I know I could use search and replace to first remove all the comments, and then apply them, but I simply want to find the next uncommented out print statement, and I can't work out how to.
E.g. I have :
#print fooVal
#... do stuff
#print barF
#... more stuff
print gold # <-- I want to use vim to jump straight to this line
I want to match this so I don't have to cycle through all the print statements (even the commented-out ones) just to find the one print statement that is without #.
I've tried using :s/^\s+print and /^print but vim does not like it. Also, I looked here, but I could not find the info.
In your case no spaces before print. So try to use '*' instead of '+'.
This works for me: /^\s*print
Less convenient pattern should highlight uncommented lines with print: /^[^#]*\s*print
In your case #Taky's solution is the best I think, but I noticed some comments on vim's regexp. I've studied this the last days, so perhaps it's a good idea to write it down.
In vimworld the use of e.g. *, ^ and $ as regexp special characters is called "magic" (set magic is default). As default + is not a regexp character and has to be used as \+ to mean "regexp +". However with small changes it can be "magic" too, read this: vim help - search patterns (the same as in vim editor, but as HTML, and with a good search function at the top).
See also vim help - pattern
Here is a little short guide (rules are overruling down the list):
settings:
:set ignorecase to ignore case in search and replace,
:set smartcase for ignoring case as long as no upper case letter is used (ignorecase must be on for it to work).
:set magic to be able to use some characters as regexp special characters, e.g. *, without having to precede them with \. This is default (I think).
Rules in search pattern (overrules settings)
\c ignore case, \C case sensitive
Use as e.g. /\cxxx for "ignore case", /\Cxxx for case sensitive (\c is the same as flag i in replace syntax as s/xxx/yyy/i.
\m use "magic" (same as setting magic), \M no "magic".
Here is the interesting part, to use + in vim patterns:
\v described as "very magic", that is what we all are used to when using regexp I think.
\V "very nomagic", ALL is literal, only \ has a special meaning.
Now, + can be used directly as in /\v\s+print (but for you it's better to use * in that particular case, + won't find "plugin" that starts the line).
E.g. also { expressions must have \ if \v isn't used.
Tip: do these mappings in .vimrc to always use \v in search patterns:
" To get 'normal' behavior for regexps (use "\V" to avoid)
nnoremap / /\v
vnoremap / /\v
(And it's very easy to just "backspace" away the \vwhen it's unwanted).

Search eclipse workspace where string not starting with

In the eclipse workspace search (CTRL+H) what regular expression could be used to find occurrences of a word that do not begin with 2 leading forward slashes (/) - or in other words, are not commented?
For example //var_dump and // var_dump is what is not to be matched, but var_dump is what is to be matched.
The following regex in the file search tab would do it:
(?<!//)[ \t]*var_dump
If you only care about the first word on a line, precede it with a caret:
^(?<!//)[ \t]*var_dump
The (?<!//) part is a negative lookbehind - it only matches thing that do not have the contents of the brackets before the thing you are looking for.
However, if you are looking for variables that are not commented rather than not preceded by the specific combo "//", you might be better off using a syntax-aware search, which depends on the language used. For example, this regex will still match /* var_dump */, which you may or may not want to happen. A syntax-aware search would know this is commented.
If you look in the Search window, you will see a "Java Search" tab and tabs for other plugins you might have (I have "C/C++ Search" and "Git Search" for example). In these tabs, you can choose to search only for functions, variable, classes, or whatever else makes sense in that language.
A further thing you might want is to hit Ctrl-Shift-G on a word and it will list all the references to this object in your code - very useful when trying to track down what is calling your function or using your variable.
If you're looking for a variable name (or the name of any other kind of Java element), you could use the Java search instead of the File search. You don't have regular expression support, but the search knows you're looking for a variable/class name and so you don't have to worry about surrounding syntax.

How many backslashes are required to escape regexps in emacs' "Customize" mode?

I'm trying to use emacs' customize-group packages to tweak some parts of my setup, and I'm stymied. I see things like this in my .emacs file after I make changes with customize:
'(tramp-backup-directory-alist (quote (("\\\\`.*\\\\'" . "~/.emacs.d/autobackups"))))
This was the result of putting the following into the customize text field:
Regexp matching filename: \\`.*\\'
This is a representative sample: I'm actually trying to change several things that want a regexp, and they all show this same problem. How many layers of quoting are there, really? I can't seem to find the magic number of backslashes to get the gosh-dang thing to do what I'm asking it to, even for the simplest regular expressions like .*. Right now, the given customization produces - nothing. It makes no change from emacs' default behavior.
Better yet, where on earth is this documented? It's a little difficult to Google for, but I've been trying quite a few things there as well as in the official documentation and the Emacs wiki. Where is an authoritative source for how many dang backslashes one needs to make a regular expression in customize-mode actually work - or at the very least, to fail with some kind of warning instead of failing silently?
EDIT: As so often happens with questions asked in anger, I was asking the wrong question. Fortunately the answers below, led me to the answer to the question that I needed, which was about quoting rules. I'm going to try to write down what I learned here, because I find the documentation and Googleable resources to be maddeningly obscure about this. So here are the quoting rules I found by trial and error, and I hope that they help someone else, inspire correction, or both.
When an emacs customize-mode buffer asks you for a "Regexp matching filename", it is being, as emacs often is, both terse and idiosyncratic (how often the creator's personality is imparted to the creation!). It means, for one thing, a regexp that will be compared to the whole path of the file in search of a match, not just to the name of the file itself as you might assume from the term "filename". This is the same sense of "filename" used in emacs' buffer-file-name function, for example.
Further, although if you put foo in the field, you'll see "foo" (with double-quotes) written to the actual file, that's not enough quoting and not the right quoting. You need to quote your regexp with the quoting style that, as far as I can tell, only emacs uses: the ``backtick-foo-single-quote'`scheme. And then you need to escape that, making it \`backslash-backtick-foo-backslash-single-quote\' (and if you think that's a headache to input in Markdown, it's more so in emacs).
On top of this, emacs appears to have a rule that the . regexp special character does not match a / at the beginning of filenames, so, as was happening to me above, the classic .* pattern will appear to match nothing: to match "all files", you actually need the regexp /.*, which then you stuff into the quote format of customize-mode to produce \`/.*\', after which customize paints another layer of escaping onto it and writes it to the customization file.
The final result for one of my efforts - a setting such that #autosave# files don't gunk up the directory you're working in, but instead all live in one place:
(custom-set variables
'(auto-save-file-name-transforms (quote (
("\\`/[^/]*:\\([^/]*/\\)*\\([^/]*\\)\\'" "~/.emacs.d/autobackups/\\2" t)
("\\`/.*/\\(.*?\\)\\'" "~/.emacs.d/autobackups/\\1" t)
))))
Backslashes in elisp are a far greater threat to your sanity than parentheses.
EDIT 2: Time for me to be wrong again. I finally found the relevant documentation (through reading another Stack Overflow question, of course!): Regexp Backslash Constructs. The crucial point of confusion for me: the backtick and single quote are not quoting in this context: they're the equivalent of perl's ^ and $ special characters. The backslash-backtick construct matches an empty string anchored at the beginning of the string being checked for a match, and the backslash-single-quote construct matches the empty string at the end of the string-under-consideration. And by "string under consideration," I mean "buffer, which just happens to contain only a file path in this case, but you need to match the whole dang thing if you want a match at all, since this is elisp's global regexp behavior."
Swear to god, it's like dealing with an alien civilization.
EDIT 3: In order to avoid confusing future readers -
\` is the emacs regex for "the beginning of the buffer." (cf Perl's \A)
\' is the emacs regex for "the end of the buffer." (cf Perl's \Z)
^ is the common-idiom regex for "the beginning of the line." It can be used in emacs.
$ is the common-idiom regex for "the end of the line." It can be used in emacs.
Because regex searches across multi-line bodies of text are more common in emacs than elsewhere (e.g. M-x occur), the backtick and single-quote special characters are used in emacs, and as best as I can tell, they're used in the context of customize-mode because if you are considering generic unknown input to a customize-mode field, it could contain newlines, and therefore you want to use the beginning-of-buffer and end-of-buffer special characters because the beginning and end of the input are not guaranteed to be the beginning and end of a line.
I am not sure whether to regret hijacking my own Stack Overflow question and essentially turning it into a blog post.
In the customize field, you'd enter the regexp according to the syntax described here. When customize writes the regexp into a string, any backslashes or double-quote chars in the regexp will be escaped, as per regular string escaping conventions.
So in short, just enter single backslashes in the regexp field, and they'll get correctly doubled up in the resulting custom-set-variables clause written to your .emacs.
Also: since your regexp is for matching filenames, you might try opening up a directory containing files you'd like to match, and then run M-x re-builder RET. You can then enter the regexp in string-escaped format to confirm that it matches those files. By typing % m in a dired buffer, you can enter a regexp in unescaped format (ie. just like in the customize field), and dired will mark matching filenames.

Interactive search/replace regex in Vim?

I know the regex for doing a global replace,
%s/old/new/g
How do you go about doing an interactive search-replace in Vim?
Add the flag c (in the vim command prompt):
:%s/old/new/gc
will give you a yes/no prompt at each occurrence of 'old'.
Vim's built-in help offers useful info on the options available once substitution with confirmation has been selected. Use:
:h :s
Then scroll to section on confirm options. Screenshot below:
For instance, to substitute this and all remaining matches, use a.
Mark Biek pointed out using:
%s/old/new/gc
for a global search replace with confirmation for each substitution. But, I also enjoy interactively verifying that the old text will match correctly. I first do a search with a regex, then I reuse that pattern:
/old.pattern.to.match
%s//replacement/gc
The s// will use the last search pattern.
I think you're looking for c, eg s/abc/123/gc, this will cause VIM to confirm the replacements. See :help :substitute for more information.
I usually use the find/substitute/next/repeat command :-)
/old<CR>3snew<ESC>n.n.n.n.n.n.n.
That's find "old", substitute 3 characters for "new", find next, repeat substitute, and so on.
It's a pain for massive substitutions but it lets you selectively ignore some occurrences of old (by just pressing n again to find the next one instead of . to repeat a substitution).
If you just want to count the number of occurrences of 'abc' then you can do %s/abc//gn. This doesn't replace anything but just reports the number of occurrences of 'abc'.
If your replacement text needs to change for each matched occurrence (i.e. not simply choosing Yes/No to apply a singular replacement) you can use a Vim plugin I made called interactive-replace.
Neovim now has a feature inccommand which allows you to preview the substitution:
inccommand has two options:
set inccommand=split previews substitutions in a split pane
set inccommand=nosplit previews substitution in the active buffer
Image taken from: https://medium.com/#eric.burel/stop-using-open-source-5cb19baca44d
Documentation of the feature: https://neovim.io/doc/user/options.html#'inccommand'