Unable to search effectively in Emacs - search

I want to have a similar tool in Emacs as the following in Vim
:g/search/
to get a list of matches.
How can you get a list of matches in Emacs?

M-x occur?
From the manual:
M-x occur
Prompt for a regexp, and display a list showing each line in the buffer that contains a match for it. The text that matched is highlighted using the match face. To limit the search to part of the buffer, narrow to that part (see Narrowing). A numeric argument n specifies that n lines of context are to be displayed before and after each matching line. The default number of context lines is specified by the variable list-matching-lines-default-context-lines.
In the *Occur* buffer, you can click on each entry, or move point there and type RET, to visit the corresponding position in the buffer that was searched. o and C-o display the match in another window; C-o does not select it. Alternatively, you can use the C-x ` (next-error) command to visit the occurrences one by one (see Compilation Mode).
Typing e in the *Occur* buffer switches to Occur Edit mode, in which edits made to the entries are also applied to the text in the originating buffer. Type C-c C-c to return to Occur mode.
The command M-x list-matching-lines is a synonym for M-x occur.

In addition to M-x occurr check also M-x grep. This works in several files at once.

My usual workflow is not to get a list and choose (don't know how to do that), but to use the incremental search:
C-s <search target>
gets the fist match after the point. If you don't like it another C-s gets the next one. Continue until you're happy (you'll need an extra C-s to wrap around from the and of the buffer). New enough emacsen can also highlight all the matches that are visible.
As noted in the comments by Török Gábor, this is the typical keybinding of isearch-forward. In the event that your bindings are different, you need to modify the prescribed procedure.

Related

Emacs question: display regexp search matches on scroll bar?

Emacs question: Is there a way to display marks on the scrollbar where search matches are to be found in the buffer? Like hitting crtl-f in the new chrome? Best would be if multiple different searches could be displayed in different colours and different vertical bars?
I don't know how to display the matches on the scrollbar (I doubt it can be done in emacs-lisp).
But, as an alternative, you could use M-x occur RET <regexp> RET.
Emacs will open a buffer named *occur* containing the lines of the original buffer which match the regexp. Each line is preceded by its number in the original buffer and the strings which match the given regexp are highlighted. As emacs documentation says:
That buffer can serve as a menu for finding any of the matches
for REGEXP in the current buffer.
If you click or press RET on one of these lines, emacs will move the point to one of the items in the corresponding line in the original buffer.
You may then rename the buffer before calling again occur, in order to keep the two occur buffers active.
(and if you are smart enough, you may consider writing a function to mix the contents of the different occur buffers...)

How to go back to previous when doing find replace confirm in vi?

Frequently when I am doing a find and replace in vi I will do it like this:
:%s/find/replace/gc
This gives you the option to skip by pressing n, or replace by pressing y. But, sometimes I will accidentally skip over one in a large file by pressing n when I meant to press y.
How do I go backwards to the previous one and give me a second change?
Essentially, how to I find (search) the other direction temporarily? thanks.
I'm not sure if you would like to interrupt current find-replace operation and resume it again. But if that is acceptable, here is my suggestion:
Start your find-replace the way you mentioned:
:%s/find/replace/gc
After you accidentally skip over a substitution by pressing n, interrupt the search by pressing <ctrl-C>
Press <shift-N> to go back to the previous occurrence of your find term
Run find-replace a little differently while you are at this word: :.,$s/find/replace/gc
Continue the operation
All this functionality works with vim native capabilities without having to install any addon.
Note: The .,$ range specifier indicates to perform :s (substitute) operation over a range of lines that start with current line (indicated by .) and until last line (indicated by $).
Note2: It might be known to you, but reiterating for anyone else who stumbles upon this post searching for something similar - The % range specifier indicates to perform :s (substitute) operation over all lines of currently active buffer.
This is not answer to the question, but a very good alternative. I recently discovered the CtrlSF plugin and it improves the search /replace process dramatically.
Basically, you have the search results in a buffer and you can do all the replacements in this single buffer.
In your scenario, you first do :CtrlSF find, get a buffer with all the matches in all files and then you do /find and move with n over your targets and change them (of course, you can actually change only the first one and then repeat the replacement with .).
If you miss some target, you just hit N to go back to the previous result and replace it.
Seems like you can't back to previous match using this pattern. Appeared bar propose following commands y/n/a/q/l/^E/^Y but no one of them will return backward to previous match.
But you can use little different pattern described bellow:
Type this /pattern replacing pattern with interested word;
Your cursor is navigated to first occurrence, if you don't need to change it press n it will navigates you to the next occurrence;
Since you understand you need to replace a word, do this by typing cw, this command cuts the forward word and turns you to insertion mode;
Type in desired text on the released place and press ESC to switch back to command mode;
Now again press n until desired occurrence;
Since you realize that you need to change an occurrence, just press on . it will repeat previously mentioned actions;
If you want to go back just use N.

VIM: Change current highlighted search term matched with /search

Is there any command equivalent to "delete until the end of the current highlighted search match and enter insert mode"?
For example, I search for a term with:
/Element
It finds the string ExampleElementExample, places the cursor on the E in Element, and highlights Element.
I would like a generic command that applies to all searches that is equivalent to c7l or ctE in this particular case. However, I also want to be able to easily repeat this command to the next match by pressing n, ..
c//e basically does what I want, but falls short because it replaces the current search buffer, so n no longer takes me to the next match. Right now I'm using ctE or visual mode, but I feel like there must be a better option.
What is the fastest and most efficient way to execute this command?
If your Vim is recent enough (7.3 with a patch-level above 6xx), you can use gn:
barbazfoobazbar
/foo<CR>
barbaz[foo]bazbar
cgnvim<CR>
barbazvimbazbar
You can hit . to jump to the next foo and change it to vim in one go.
See :help gn.
I think the best option would be to use search and replace with the confirm flag.
:%s//replace/gc
If you leave the search string empty, it will automatically use the current search string. By the c flag, it asks you for permission to replace and upon decision, it will move to the next match. The g flag will find all matches, not just the first on a line, which I hope is what you are looking for.
You can use the following custom text object taken from Copy or change search hit on the Vim Tips Wiki:
" Make a simple "search" text object.
vnoremap <silent> s //e<C-r>=&selection=='exclusive'?'+1':''<CR><CR>
\:<C-u>call histdel('search',-1)<Bar>let #/=histget('search',-1)<CR>gv
omap s :normal vs<CR>

Easy motion vim plugin mapping issue

I have the vim EasyMotion plugin installed.
Pressing,
<Leader><Leader>f searches forward from the current line.
<Leader><Leader>F searches backward from the current line.
Is there a way to search the entire visible part of the buffer only using 'f'? I would ideally not want to use two different bindings for searching forwards and backward. One single binding to search the entire visible portion of the buffer would be most ideal.
You can try a mapping like this:
nnoremap <leader><leader>f :execute "/\\%>" . line('w0') . "1\\%<" . line('w$') . "l"<left>
That's a confusing syntax, so I'll unpack it.
line('w0') and line('w$') return the line numbers of the first and last visible lines in the buffer, respectively, so you use them to find the range for the visible part.
The / search command allows a range to be specified, but with an odd syntax. The format is /\%>Xl\%<Yl where X is the line to start from and Y is the line to end at.
It's not possible to just drop the results from line() into a normal / invocation, but we can build a string, using . to join segments together, and once the command is built, pass it in to :exec to make it happen.
Finally, there's the <left>. That's for cursor positioning. When you execute <leader><leader>f, the whole mapping fires as though you were typing it, so you end up with the full :exec command on the line, and it ends with a ", but you want to type inside those quotes. Alternatively, you could remove "<left> from the end of the mapping, but then you'll have to remember to close the quote after typing your search term.
I'm not familiar with EasyMotion, so this may not give you exactly what you were asking for (I realized this after I typed up the answer), but it will let you run a search in the currently visible part of a buffer only, and you can probably adapt it to EasyMotion's purposes without too much difficulty.

Search current line in ZSH (vi mode)

How do I search/navigate within the current line in zsh? For example, if the cursor is at the end of the line..
// [] indicates cursor position
user#hostname: vim /etx/apache2/sites-enabled/defaul[t]
In vi normal mode, I'd like to use backward-search (?), type etx and have the cursor move like so:
// [] indicates cursor position
user#hostname: vim /[e]tx/apache2/sites-enabled/default
However, / and ? are mapped to history search, not inline search.
I know I can just type 9b and get there, but I find searching and moving to the match is easier than counting the number of words to jump.
Not sure if this was clear at all, let me know if I need to clarify things.
I hope I understood you right. You want to in zsh command line, move your cursor faster when you type commands.
e.g.
user#hostname: vim /etx/apache2/sites-enabled/defaul[t]
You want to move to the first e
I don't use vi-binding, but f and F are your friends.
In that example, you could 5Fe move backwards to the 5th e . If you don't want to count, you could Fe, then press ;, till it moves to the right position.
check vim help for detail:
:h f
:h F
Also faster way would be 0fe, for this example. Moving cursor to beginning, then to e
If I misunderstood your question, please leave comment, I would remove the answer.
This script adds this functionality to zsh:
https://github.com/soheilpro/zsh-vi-search
Maybe the ~/.inputrc file has mapped these keys to something strange? Or you're not fully understanding how the search history works.
Let's start fresh:
Remap these keys with bindkey:
bindkey -M vicmd "?" history-incremental-search-backward
bindkey -M vicmd "/" history-incremental-search-forward
Now, when you press 'esc' (for vi normal mode) and '?' you'll get a bck-i-search command:
%user#hostname: vim /etx/apache2/sites-enabled/defaul[t]
bck-i-search:
At this point, you type what you want to search for, e.g. 'etx'. And, the cursor moves to that position in this line. Note: if it doesn't find that pattern in this current line, it keeps on searching your history. This behavior is considered a feature!
You might notice that you can not repeatedly search (like pressing 'N' in vim). In this case add a few isearch bindings:
bindkey -M isearch '^N' history-incremental-search-backward
bindkey -M isearch '^R' history-incremental-search-forward
Now, pressing control-N repeats your search, while pressing control-S reverses the direction of the repeated search (note: the default order of this keybinding is reversed from forward to backward, since one is more often looking from end of the history back).
In short: treat the current line as the 'top' of your history. Using the vicmd '/' or '?' searches the entirety of that history. The '?' searches top down, while '/' searches from wherever the cursor is currently located in your history towards the 'top'. Another way of thinking about this is to imagine your history as one big file, and the current line your on is at bottom of that file. If that helps you grok it, you may feel that '?' is more pertinent than '/'.
Type v when you are in command mode of your shell, you will be taken to real ViM editor itself. Upon saving & exiting, it will automatically get executed.
I had the same issue. I didn't manage to solve it as such but found a suitable workaroud: added a binding for the edit-command-line function, which drops me to $EDITOR with current line in buffer. There it's easy to navigate to the given pattern.
See /usr/share/zsh/functions/Zle/edit-command-line on how to bind the function.

Resources