Easier line referencing - vim

I was wondering if anyone knows of a plugin to enable easier line determination.
I have issues quickly scanning to see what line I was to reference in commands such as t and m
See this screenshot:
If I wanted to quickly reference line 5 (I do have line numbers switched on, I just accidentally cut it out in this screenshot) I find I have to look rather hard to find the correct line number.
so: Is there a plugin which makes referencing lines less eye-straining?

I guess your problem is with those deeper indented lines. sometime it is not easy to "connect" the line number and the line text. If this is the case, you may try followings:
set listchars=tab:>-
(see :h 'listchars' for detail) this line will show the <tab> with certain chars. for example, following screenshot is a formatted maven pom.xml, with relative deeper indent lines. I think it would be ok to read the line numbers of them. E.g. the line 1180-1184.
I hope it helps.
with plugin
If the above doesn't help, e.g. you have spaces not <tab>, you could try a plugin: indentLine, with this you could set a variable g:indentLine_char with the char you like. e.g. > to show indent level clearly.
The link of the plugin: https://github.com/Yggdroot/indentLine

:move and :copy are not limited to line numbers (absolute or relative) only, either as source or as target.
You can use search patterns too:
:m?foo
would move the current line just under the first line matching foo going upward,
:t/bar
would copy the current line just under the first line matching bar going downward,
:?foo?t/bar
would copy the first line matching foo above the current line to just below the first line matching bar going downward, and so on.
You can also use marks:
:'at'b
would copy the line marked a to below the line marked b,
:m''
would move the current line to just below the line you were before the last jump, and so on.

Related

Annoying vim behavior in visual mode

Let's say I have the following three lines and cursor is where ▐ is:
1. This is a slightly longer line.▐I want to delete this and the next line.
2. This is a shorter line
3. This is the third line
I want to delete the rest of the line from the cursor and line 2, so I do vjd, but that leaves my text like:
# This is a slightly longer line.# This is the third line
This is because when selecting text in visual mode, vim selects an additional virtual character at the end of the line. I've played around with virtualedit but that didn't seem to help.
Any clues on how I can get the original behavior that I wanted?
Try three keystrokes - sh-d, sh-j, sh-d
shift-d (delete to end-of-line)
shift-j (merge next line with this)
shift-d (delete the merged, i.e., second line
That will do the trick for you.
That's because if you don't have virtualedit set, vjd will delete everything including the new line character. So you just have to do vjhd instead, to keep the new line intact.
Otherwise with virtualedit=all, I don't face this problem.

Vim replacing in inverse direction

How can I replace in Vim from current line in inverse direction (upward) (for searching I'm using ?textToFind, for replacing from current position :,$s/a/b)?
You can use backwards range with :s command.
If you want to do replacement from line 1 to your current line, you can do :,1s/foo/bar/g vim will ask you if you are sure to apply command on a backwards range, press y
You can also do something like :,-3s/foo/bar/ to do replacement from current line (n) till line n-3
The range used for s// (and other Ex commands) can be made of:
line numbers, 1,23
relative lines, -5,+17
line shortcuts, .,$
marks, 'a,'g
searches, ?foo?,/bar/
or any combination of the above items, ?foo?,'g, 23,$, +5,/bar/, .,/baz/+6…
A range extending from the first instance of foo before the cursor to the last line could look like that:
?foo?,$
A range extending from the first instance of foo before the cursor to the current line could look like that:
?foo?,.
and even be shortened to:
?foo?,
There's no built-in way to visit the lines from the end to the beginning. Vim will issue a Backwards range given, OK to swap? query, and turn around the range if confirmed. The only way is by manually specifying the individual lines in reverse order:
:.s/a/b | .-1s/a/b | .-2s/a/b | ...
Of course, you can write a custom command for that.
If you also require reverse replacement inside a line (all of that only makes sense with the confirm flag, doesn't it?), you're out of luck with :substitute.

How to replace current string line with another line in vim?

I'd like to replace current string line with another (for example the another line is placed in 5 lines above current line). I can do it with a pair of commands
dd
:-5t-1
Is there the shorter way to obtain same goal?
dd
:-5t-1
is already pretty short if you ask me. But you can squeeze everything into a one-liner:
:d|-5t-1
and remove the 1 because it's implied by -:
:d|-5t-
Barring making a custom command or mapping I don't see how you could make it shorter.
:-5y<CR>Vp
is it shorter?
if you need do that really often, add this into your vimrc:
command! -range R d|<line1>,<line2>t-
then you can just do :-5R replace current line with -5 line
or 2,4R to cp line 2-4 (3 lines) to current line, and replace current line.
If you don't mind a plugin, my LineJuggler plugin offers a ]r command (and many more):
]r Fetch the line [count] visible lines above the current line and replace the current line with it.
With it, your example would be the short and easy 5]r
In addition, the companion LineJugglerCommands plugin now offers a similar :Replace Ex command. Again, your example would be
:Replace -5

How to know in VI which line the cursor is on?

I want to copy paste some lines in vi.
I have a text like
python class1 def:
code code code
...
code code code
last line class1
python class2 def:
code code code
...
code code code
I want to copy the whole class1. I was trying to do it with yNy, so I needed to get N, that is, to count the number of lines the class has.
Then I thought it would be good to get the line number of python class1 def: (let's say X) and the last line class1 (Y), calculate N=Y-X, go to the first line of the class and do the yNy. However, I could not figure out how I can get the line numbers.
So, is there any way to know which line I am in? And in general, is there any other way to copy paste a whole block like the one I indicated?
This is my vi version:
VIM - Vi IMproved 7.3 (2010 Aug 15, compiled Oct 26 2012 16:44:45)
Included patches: 1-547
The current line number can be obtained by :.=. Ctrl-g gives more details including filename, column information, ...
In order to copy a block, go to the start of the line to be copied 0. Hitting v would start the visual mode. Navigate to the last line to be copied. Yank y. (Visual selection is now in buffer.)
Using only normal mode commands:
You can do y} to yank everything from the current line to and including the next empty line, delimiting what Vim considers to be a "paragraph". This may or may not work depending on your coding style.
Still using the notion of "paragraph", you can do yip or yap from anywhere in a "paragraph".
You can set the number option which allows you to see absolute line numbers and therefore be able to do y10G, "yank everything from here to line 10".
You can set the relativenumber option which allows you to see relative line numbers and therefore be able to do y5j, "yank everything from here to 5 lines below".
You can do V/foo<CR>y to yank everything from here to foo linewise.
More generally, you can simply use visual mode to select what you want and yank it.
You can also set a mark on the first line of the class with ma, move the cursor to its last line and do y'a (which sounds like the name of a Lovecraftian deity).
Using Ex commands:
Because the aforementioned number option shows absolute line numbers, you can see that the class ends at line 10 and do :.,10y.
Because the aforementioned relativenumber option shows relative line numbers, you can see that the class ends 5 line below and do :,+5y (dropping the implied .).
Using your statusline (or not):
You can :set ruler to have the current line number displayed on the right side of your statusbar if you have one or on the right side of your command line if you don't have a statusline.
Using Vimscript:
You can use line('.') to retrieve the number of the current line.
Using custom text-objects:
There are a number of custom text-objects available on vim.org for indented blocks, function arguments and many other things. Maybe there is one for Python classes.
More generally, I'd advise you to set either ruler, number or relativenumber permanently in your ~/.vimrc and get used to it.
ruler is the least invasive of the bunch but it's also the most limited: you know where you are but it doesn't help at all when you want to define a target.
number is the most classical and can be used to easily target a specific line.
relativenumber is a bit weird at first and, like number, can be used easily to target a specific line.
Choosing number or relativenumber is, as far as I'm concerned, a matter of taste. I find relativenumber very intuitive, YMMV.
Try the following in command mode
:.= returns line number of current line at bottom of screen
yNy or Nyy copies the next N lines, including the current line
p pastes the copied text after the current line
Additionally,
:set nu! in command mode will turn on/off the line number at the beginning of each line.
let the vim registers do this task. why bother calculating lines
for example if you want to copy line X to line y
1) move your cursor to 1st character of line X.
2) type "ma" . this will save current cursor position in register "a".
3) move cursor to last char of line Y.
4) type "y`a". copy is done
5) p pastes the copied text
This method can work not only lines but block ,words even on characters.

VIM: Zero-Indexed Line Numbers in :set number

Using VIM, it is easy to display line numbers for any given file with:
:set number
However, the line numbering is 1-indexed, this means that the numbering starts at 1.
Normally this is exactly what i want, however a particular tool I am using to compile my code reports zero-indexed line numbers - that is, line numbers start at zero.
How do I change vim's line numbering to compensate so that viewing the numbers in the vim buffer corresponds to the errors provided by the tool, and in addition jumping to a particular number corresponds to that of the tool as well.
That is, if the tool tells me that there is an error on line 98, I want to jump to that line by typing "98G", not "97G", and I want that line (which is really line 97 in vim) to display "98" in the line number list.
Edit:
While I can filter the output of the tools, while fairly simple it is not a trivial task because the tool also outputs hex values that correspond to each line, which has the same zero-indexed form, and this is is output in informational messages as well, not just for errors, and I have many such projects.
I don't think this is possible; however, assuming the output of your external tool is just text, it would probably be fairly easy to filter the output such that the numbering is 1-indexed to match Vim. Can you give us an example of your output?
Edit
Alternatively, if you call the external command from Vim, you could do something like (basically, add a blank line, run the external command and then delete the blank line):
command! RunMyExternalProgramme call RunMyExternalProgramme()
func! RunMyExternalProgramme()
" Save the old setting of makeprg
let s:savedMakePrg = &makeprg
" Save the screen layout
let s:savedView = winsaveview()
if config_file != ''
" Put a blank line at the start of the file
:1put! =''
" Save
write
" Change makeprg and run it
let &makeprg = '/path/to/programme -options etc'
make
" Delete the blank line
1d
" Save
write
endif
" Restore the screen layout (optional)
call winrestview(s:savedView)
" Restore the old setting of 'makeprg'
let &makeprg = s:savedMakePrg
endfunc
I suggest to wrap your tool in a small script. In the script, either copy the source code and add an empty line at the top of the source or use awk to fix the output (parse the error messages and add 1).
The only way to make vim display line numbers starting with 0 is to patch the source and create a new option (say lno for line number offset) and add this value to the line number. You'd need to patch this in quite a few places (display, goto commands, search patterns, etc). Shouldn't take more than one or two years to make it work :) Good luck on getting the author of Vim to accept this as a patch.
set relativenumber or for short "set rnu"
This starts the count from 0

Resources