Searching across a range of lines

30 views
Skip to first unread message

Salman Halim

unread,
Jan 13, 2023, 4:41:59 PM1/13/23
to Vim Users
Hello,

I want to use something like search(), but only across a specific set of lines. The problem is that search() always starts at the current cursor line.

For example, I want to find a match for 'cat', but only in lines 50 to 100. If my cursor is before line 50 when I start, I can prefix my expression with \%>49 and pass 100 as the stopline, but that doesn't work if my cursor is AFTER line 50 as it starts the match at the cursor location.

I don't want to first move my cursor. I'm also hesitant to use getline() to grab all the lines, do an indexOf type search and then return the line number because that's going to get memory intensive if I have a large file.

Does anybody have any thoughts on this? I'd appreciate advice.

Thank you very much,

--
 
Salman

I, too, shall something make and glory in the making.

Gary Johnson

unread,
Jan 13, 2023, 5:14:10 PM1/13/23
to Vim Users
On 2023-01-13, Salman Halim wrote:
> Hello,
>
> I want to use something like search(), but only across a specific set of lines.
> The problem is that search() always starts at the current cursor line.
>
> For example, I want to find a match for 'cat', but only in lines 50 to 100. If
> my cursor is before line 50 when I start, I can prefix my expression with \%>49
> and pass 100 as the stopline, but that doesn't work if my cursor is AFTER line
> 50 as it starts the match at the cursor location.
>
> I don't want to first move my cursor. I'm also hesitant to use getline() to
> grab all the lines, do an indexOf type search and then return the line number
> because that's going to get memory intensive if I have a large file.
>
> Does anybody have any thoughts on this? I'd appreciate advice.

I don't know your specific requirements, but not wanting to move
your cursor should not prevent you from using search(). Just save
the cursor position, save the window position, move the cursor to
the start of the search range, and when you're done with the
searching, restore the window position and the cursor position.

I've done this in a number of plugins and I can't even tell that the
cursor ever moved.

Regards,
Gary

Tim Chase

unread,
Jan 13, 2023, 8:12:48 PM1/13/23
to vim...@googlegroups.com
On 2023-01-13 16:41, Salman Halim wrote:
> For example, I want to find a match for 'cat', but only in lines 50 to
> 100. If my cursor is before line 50 when I start, I can prefix my
> expression with \%>49 and pass 100 as the stopline, but that doesn't
> work if my cursor is AFTER line 50 as it starts the match at the cursor
> location.
> I don't want to first move my cursor.

While possibly not quite what you're looking for, if I want such, I use

:50,100g/cat

or, if I want to know which line-numberss:

:50,100g/cat/#


-tim





Salman Halim

unread,
Jan 13, 2023, 8:50:49 PM1/13/23
to vim...@googlegroups.com

I don't know your specific requirements, but not wanting to move
your cursor should not prevent you from using search().  Just save
the cursor position, save the window position, move the cursor to
the start of the search range, and when you're done with the
searching, restore the window position and the cursor position.

I've done this in a number of plugins and I can't even tell that the
cursor ever moved.

Regards,
Gary

Thanks, Gary. I've solved it with &lazyredraw, winsaveview() and winrestview(), but I really would prefer to not move the cursor. I'm trying to write a routine that will remove unused Java imports. My method is to find the import section of the file, read all the lines in, search each entry in the file (outside the import region) and remove any not found; lastly, I put the modified lines back into the buffer, after sorting them and removing duplicates, also.

That 'search each entry' currently requires me to move the cursor to just past the import section and then do a search. I would prefer not to move the cursor to do that as I can do everything else without moving the cursor.

Thanks again,

Salman

Salman Halim

unread,
Jan 13, 2023, 8:52:31 PM1/13/23
to vim...@googlegroups.com
Tim, this doesn't do what I'm trying to do, but the bigger problem is that :g absolutely moves the cursor, putting it on the last found match.

Thanks very much,

Salman

Owajigbanam Ogbuluijah

unread,
Jan 14, 2023, 12:53:26 PM1/14/23
to vim...@googlegroups.com
I don't know if you're into completion engines, but coc-java has an "Organize Imports" which does exactly what you're trying to do.

- Igbanam.

--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

---
You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vim_use+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/vim_use/CANuxnEcXzUyY%3Db8bEofU1yKQHWqbsOjmCrSKnApc57C9H%3DK3Gg%40mail.gmail.com.

Stan Brown

unread,
Jan 14, 2023, 1:55:56 PM1/14/23
to vim...@googlegroups.com
On 2023-01-13 17:52, Salman Halim wrote:
> On Fri, Jan 13, 2023 at 8:13 PM Tim Chase <v...@tim.thechases.com
> <mailto:v...@tim.thechases.com>> wrote:
>
> While possibly not quite what you're looking for, if I want such, I use
> ...>   :50,100g/cat/#
>
> Tim, this doesn't do what I'm trying to do, but the bigger problem is
> that :g absolutely moves the cursor, putting it on the last found match.

I use :g as Tim does. I don't particularly want the cursor moved, but
after looking at the results I simply type `` and the cursor is back
where it was.

Stan Brown
Tehachapi, CA, USA
https://BrownMath.com

Salman Halim

unread,
Jan 15, 2023, 4:24:28 PM1/15/23
to vim...@googlegroups.com
On Sat, Jan 14, 2023 at 12:53 PM Owajigbanam Ogbuluijah <xigb...@gmail.com> wrote:
I don't know if you're into completion engines, but coc-java has an "Organize Imports" which does exactly what you're trying to do.

- Igbanam.


Igbanam, I haven't really used completion engines much, to be honest. I had already written an optimize imports script a while ago and was more or less happy with it, but wanted to port it to Vim 9 as an exercise, so thought I would improve it a bit. The original did a lot of in-place manipulation, adding lines, changing import lines in the buffer, moving the cursor around (all with &lazyredraw on, of course), etc. I wanted the new one to read all the import lines into a list, manipulate that list and throw the changed lines down in one single operation. Ideally, also without moving the cursor.

I did get it working with winsaveview() and winrestview(), of course, and I take any added or removed lines into consideration and move the cursor up or down so it remains on the same line in the file as before. I did also come up with a and idea of a wrapper around search() that takes both a start line and (like search() already does, a stop line) and does the search without moving the cursor, but it's cumbersome and I'm not sure it'll be faster than just moving the cursor to the desired start line with winsaveview() and winrestview().

I just figured that if there is a stop line option, there should be a start line option that's not the current cursor position.

Thanks for all your help with this,

Salman

Salman Halim

unread,
Jan 15, 2023, 5:05:42 PM1/15/23
to vim...@googlegroups.com


On Sat, Jan 14, 2023 at 1:55 PM Stan Brown <the_sta...@fastmail.fm> wrote:
>     While possibly not quite what you're looking for, if I want such, I use
> ...>       :50,100g/cat/#
>
> Tim, this doesn't do what I'm trying to do, but the bigger problem is
> that :g absolutely moves the cursor, putting it on the last found match.

I use :g as Tim does. I don't particularly want the cursor moved, but
after looking at the results I simply type `` and the cursor is back
where it was.

I'm not questioning the utility of this at all; I use various versions of this myself. However, I was trying to build something that could be used in a script, not something I'm using to examine the results from the command-line.

Since you and Tim took time out to respond, here's a version I use for the word under the cursor, in case you find a use for it. It prints all lines that have the word under the cursor with a number before them and then prompts you for the number, jumping to the specified result:

nmap <F4> [I:let nr = input("Which one?  ")<Bar>if nr > 0<bar>execute "normal " . nr ."[\t"<bar>endif<CR>

If you prefix the last [ with a \<c-w> (inside the quotes), it'll jump to that line in a new split, instead, retaining your current cursor location.

All the best,

Salman
Reply all
Reply to author
Forward
0 new messages