How can I set Vim up to search for and sort all lines containing a certain string?

1.4k Views Asked by At

I am using vim to manage a to-do list, and would like to set a hotkey to do the following:

  1. Find all lines which contain the word under the cursor. The world is always a tag formatted as: #mytaghere

  2. Sort all of these lines alphabetically by another tag contained within them. Again the tag is in #mytaghere format. For example, all lines with the tag #priorityA would be alphabetized and placed above all lines with the tag #priorityB, and so on.

  3. Put all of these lines into Vim's quickfix window.

I have managed to achieve a limited version of 1 and 3 by putting the following into my .vimrc file:

map <f2> :vimgrep <cword> % <bar> copen <enter>
set iskeyword=@,48-57,_,192-255,95,35 "lets cword include #s and _s

This setup fails whenever the word under the cursor contains a #, and it works whenever the character is something else (for example, an _ ) The error produced is: "E682: Invalid search pattern or delimiter" which seems like the # is interfering with vimgrep.

Also, I can't figure out how to sort the lines by priority tags.

Thanks in advance for any help. I am just learning Vim, and if I could just get this problem solved I'd be able to use it for all of my organizing.

2

There are 2 best solutions below

8
On

The :vimgrep command comes in two forms:

:vim[grep][!] /{pattern}/[g][j] {file} ...
:vim[grep][!] {pattern} {file} ...

For /{pattern}/, actually any non-keyword delimiter can be used. When your <cword> starts with #, Vim interprets this as the start delimiter, then complains because there's no end delimiter.

Choose a delimiter and put it around <cword>; to make the search literal, use \V and escape the current word, which is now inserted though the expression register =:

:noremap <f2> :vimgrep /<C-r>='\V'.escape(expand('<cword>'), '/\')<CR>/ % <bar> copen <enter>

Oh, and you should use :noremap; it makes the mapping immune to remapping and recursion.

0
On

Thanks to Ingo Karkat I was able to come up with the following solution:

noremap <f2> :vimgrep /<C-r>='\V'.escape(expand('<cword>'), '/\')<CR>/ % <bar> copen <enter>

The above will take everything under the cursor and put it into the quickfix window.

:set modifiable
:sort /.*|.*|/

The above will sort everything in the quick fix window ignoring the file name and line/column information.

To do everything at once (find all tagged lines and sort them by the first character of those lines):

noremap <f2> :vimgrep /<C-r>='\V'.escape(expand('<cword>'), '/\')<CR>/ % <bar> copen <enter> <bar> :set modifiable <enter> <bar> :sort /.*\|.*\|/ <enter>