How to lock vertical scroll view on a line? - vim

While going back and forward on history of undo/redo, I would like to keep vim screen vertically locked (let's say lock on line 100), is that possible? how?
I mean that line should be fixed on screen.

Possible, but requires work. Something like...
Make a mapping that will set (and possibly also reset) the lock. Something like <leader>l to set the b:lock_line variable to the current line. Then use nnoremap to change u, Ctrl-R to execute b:lock_line . "zz" after it does the original binding, if b:lock_line is set.
You can't change the operation of built-in commands like :earlier, :later etc., as Vim does not allow you to redefine them. You can define new commands like :Earlier that would do what you want instead.

No. It is not possible. At anytime, if you want to see the line no. 100, you can type :100 in the command mode or 100G to go to the line.
Once you are in line 100, you can type zz, zt, zb to move the cursor to middle of screen, top of screen, bottom of screen respectively.

Related

Vim: Only scroll the current line

I would like vim to scroll horizontally like nano does, by scrolling only the current line, not the whole screen.
I tried playing with nowrap and scrolloff settings, without success.
Here are some screenshots (with the cursor at the end of a long line) to explain myself.
Nano:
Vim (wrap):
Vim (nowrap):
Thanks!
No, Vim cannot do this, and I think it would be hard to implement this in a way that isn't inconsistent or confusing to the user. There would need to be an indicator (like with side scrolling) that only the current line is scrolled. Also in Vim, there are several commands (like j / k and i_CTRL-Y / i_CTRL-E) that refer to the same column in above / below lines. A partially scrolled view state would make it difficult to use those.
That said, you can sort-of achieve this with a hack: The foldtext of folded lines does not scroll horizontally. So if you fold each individual line (other than the current one) via a custom 'foldexpr', set the fold text to be the line's text, and automatically close all surrounding folds, you'll get this. However, as you'll lose syntax highlighting and "normal" folding, this is more for demonstration than an actual solution.

Vim, sync screen after selecting line

In Vim we can travel to different lines using ':<line-number>'.
And we can also sync the screen by typing 'zt' in normal mode.
But how do we have the screen get synced automatically every time we go to a specific line?
If by syncing you mean centering the line at the top (what zt does) / middle / bottom, you can achieve an always-on centering of the current line in the middle via:
:set scrolloff=999
For all other, I'd recommend a custom G mapping:
:nnoremap G Gzt
To make this also work with :[N] and all other jump commands, you'd have to define :autocmds, and I would recommend against that.

Perform operation on entire buffer, without changing the cursor position

Consider a scenario, when you are editing a C file in vim. & you have used a mix of spaces & tabss. & you need to convert all of them to spaces.
There is a utility, called expand, which performs this task intelligently & it's a preferred way than s/\t/<4 spaces>/g. We can use this command in vim using :%!expand -t4. Typically, I map a function key, say F11 for this.
Similarly, we can use any other command in vim.
The problem is when you run any such operation on entire buffer, the cursor position changes & can be irritating at times.
Hence, the question is, how to perform an operation on entire buffer, without changing cursor position?
The cursor position can be restored by using the latest jump mark:
``
If you also want to maintain the exact window view, use winsaveview() / winrestview().
The anwolib - Yet another vim library has a handy :KeepView command for that:
:KeepView %!expand -t4
For such a case, we can use marks (e.g. mA). The mapping would be:
:nmap <F11> mZ:%!expand -t4<CR>`Z
However, there is still a catch. The screen scroll position may change, when operating on entire buffer.
This can be handled by using 2 marks as below:
:nmap <F11> mZHmY:%!expand -t4<CR>'Yzt`Z
Explanation:
Mark current position. (mZ)
Go to top of screen. (H)
Mark this line. (mY)
Run your filter. (:%!expand -t4)
Go to line Y. ('Y)
Make it top of screen. (zt)
Go to your mark. (`Z)
Now, when you press the mapped key, F11, the filter runs on the buffer & the cursor remains at its proper location.
you can just:
:your expand cmd|norm! ``
you can map it to <F11> if you like. but better use nnoremap
I just saw you mentioned in your question:
Similarly, we can use any other command in vim
If you want to do that, the reliable solution would be wrap the "any other command" in a function, and before/after the main logic, save/restore the cursor position. Because "any other command" could change the (back tick) mark, even the marks you defined.

Vim Relative Numbering Reset on Scroll

When I scroll down a page the relative numbering is no longer based upon the cursor position.
Instead the line position relative to the top of the screen is displayed.
Sometimes I would like to delete or yank 200 lines and I dont want to have to do the subtraction and addition to figure out how many lines down my text is.
How can I show relative line numbers to the cursor even when scrolling?
I think what you want is, you scroll with mouse, and expect that vim keeps the cursor in original place. E.g. your cursor is at line 5, and you scroll down 5000 lines, you expect your cursor is still at line 5. That is, the cursor is out of the window.
AFAIK, the cursor won't go out of the window. That means, if you keep scrolling down, and the cursor line will be the top line of your current window. and the rnu are gonna re-calculated by the cursor line.
May be you could just explain what do you want to do. the cases in your question could be done by 200dd or 200Y but I guess it is not as simple as that.
You may want to find out the ending line by reading/scanning your text lines, and pick the line number (rnu), and do a xxxdd if this was the case. Here you should use normal line number. e.g. your cursor was at line 5, and you scroll down a lot, find the line you want to delete till from line 5. you could do :5,.d vim will delete from line 5 to your current line.
Or you can do 5, 23452d if you find out the lines between 5 and 23452 need to be removed.
If you can search your ending line by /pattern search, vim can do :.,/foo/d this will delete from current line till the next line, which matches foo.
You can still press V enter line-wise visual mode, and moving down by vim-motions. when it reaches the point you want to remove/yand press Y or d
You can take a look this Question/answer:
VIM to delete a range of lines into a register
At the end, I suggest you not using mouse in vim.
This is probably because the cursor moves down a page when you scroll down a page. In vim, the cursor is always on the screen. If you're scrolling down with, say, the mouse wheel, the cursor will just get "stuck" on the top line (modulo scrolloff) and stay there as you continue to scroll down.
Perhaps use ShiftV to start a line-based visual selection before scrolling, then use d or y on the selection?
I can confirm that the desired feature is available in Visual Studio Code (VSC) with the Vim extension installed. This is because VSC does not function like Vim by default and holds the cursor in place like other text editors do. This feature not only makes VSC bearable but proves more useful than vanilla Vim when coding large blocks of code also.
Additionally, VSC also allows for easy and language agnostic comment/uncomment toggling with <Ctrl> + / which is also very useful when used together with the above feature.

How can I add non mouse-selectable line numbers to vim? [duplicate]

This question already has answers here:
How to clear the line number in Vim when copying?
(12 answers)
Closed 6 years ago.
So I've figured out how to add line numbers to vim (:set no or :set number) but how can I make it so that when I use my mouse in a terminal emulator to select a block of lines, it does not also select the numbers?
For example, say I have three lines that look like so in vim:
1 First line
2 Second
3 Third
If I want to select the three lines with the mouse what I want is for it to ONLY select the actual text. But what ends up happening is it selects the line numbers as well as all the space to the left and right of the line numbers.
Is there any way to change this behavior? BTW, I'm using the gnome terminal editor in gnome if that makes a difference.
Use the following:
:set mouse=a
to turn on xterm style mousing in all modes. This will allow you to do what you want. Keep in mind if the vim is remote via ssh, you'll need X11 forwarding turned on for the selection to make it to your local clipboard.
AFAIK, that is not possible.
The only thing I can add at the moment is that you'd be better off with
:set invnumber
It will inverse the current condition, so you can map it to a key, and toggle it. That way you don't have to remember two commands.
I agree with the first answer. If you use gvim, you can experiment with using set mouse=n and set mouse=a, which should change the line number selecting behavior.
When I want to select text into a terminal, I remove line numbers.
:set nonu
When I finished
:set nu
You're probably not on a Macintosh, and I can't tell if you mean you want to use system copy rather than vim's yank.
But if you are both those things, you can use option-drag to select text. This creates a 2d box over the text, selecting things that are under it. It should be functionally the same as 'take columns x1 to x2 of rows y1 to y2'.
I'm pretty sure this is not possible in terminal-vim. There is no accepted standard (e.g. a TTY escape) for indicating blocks of characters that aren't highlightable by mouse, as far as I know.
I would use gvim if you want to be able to do this at any cost. Its behavior is as you describe.
My recommendation is to get used to the little box on the right hand corner of the screen which has the current line's number and character position information. Before I used vim I could never imagine living without line numbers, but since then I've moved beyond this. Not having line numbers clutter up the screen allows for distraction free code viewing, and do you really need to know that the line number above your current active line is one less than your current line's number, and the line below is one more?
A copy without mouse:
Enter Visual mode: Position your cursor, press v (For complete line V) move up or down until desired position
Press control + c to copy into clipboard (if +clipboard exists in :ve command output) press ESC and paste it wherever you want with control + v.
Or press y to yank into register and press p to put the text after the cursor

Resources