Display relative and absolute line numbers simultaneously in Vim - vim

Is there any way to display both relative and absolute line numbers simultaneously in Vim? Either side-by-side, or some other interesting presentation are fine.

Yes, you can. Use RltvNmbr.vim to display the relative numbers, and use Vim to display the absolute ones:

Vim 7.4 (Patch 7.3.787) will show the absolute line number instead of "0", when both "relativenumber" and "number" are set.
From :h relativenumber, 7.3
When setting this option, 'number' is reset.
From :h relativenumber, 7.4
The number in front of the cursor line also depends on the value of
'number', see |number_relativenumber| for all combinations of the two
options.

Reasonably speaking, you can't. Line numbering is one-per-buffer, controlled solely by the 'number' option.
One crazy notion I tried: :vertical diffsplit plus :setlocal relativenumber. This gets two copies of the buffer next to one another, linked in scroll position because they're in diff mode. However, it really doesn't work properly. The relative numbers aren't updated successfully (on 7.3.154, bug potentially fixed later, but I doubt it—it's scarcely worth it), and even if they did, you'd be stuck with a great eyesore and harder management and navigation.
You could do it with a plugin writing to a special buffer which you would keep on the left, but the implementation would be ugly, and it would still make navigation hard (because it's another buffer). I for one am certainly not going to spend time writing such a plugin, though I must confess I'd like to show both forms of line numbering.

Many years later and this feature is now part of Vim and known as hybrid numbers.
You can turn this feature on by entering:
:set number relativenumber
No speed penalty either. As far as I can tell.

Combining plnx and Macario answers with vim 7.4.
autocmd WinEnter,FocusGained * :setlocal number relativenumber
autocmd WinLeave,FocusLost * :setlocal number norelativenumber
This displays Relative Numbering (with current line in Absolute) in the focused window, and Absolute in the non-focused window.

This are my mappings related to relative and absolute line numbers
toggles between relative and absolute.
Entering a window sets the window to relative numbers, while leaving it set it to absolute.
Then if you do a vertical split of the window you would se the same buffer with relative and absoulte numbers.
" setglobal relativenumber
autocmd WinEnter * :setlocal relativenumber
autocmd WinLeave,FocusLost * :setlocal number
autocmd InsertEnter * :setlocal number
autocmd InsertLeave * :setlocal relativenumber
function! g:ToggleNuMode()
if(&relativenumber == 1)
set number
else
set relativenumber
endif
endfunc
map <C-l> :call g:ToggleNuMode()<CR>

Related

How to turn off Vim relativenumber setting?

Today I have discovered vim's relativenumber option. I really would like to use it, but sometimes I need to swap between relative numbering and classic one.
I have tried to turn it off with :set relativenumber=off option (which returns me error attached above) and using :set number again but none of those works.
To turn on relative line numbering use this:
:set rnu
To turn it off use this:
:set nornu
By the way, if you had Googled around for your question, you would have found this great post which discusses things in more detail.
To turn on whatever option in vim:
:set <option>
To turn off whatever option in Vim:
:set no<option>
To toggle an option on/off:
:set <option>!
To check if an option is on or off:
:set <option>?
To set an option back to its default:
:set <option>&
I just use this toggle switch in my vimrc file.
function! NumberToggle()
if(&rnu == 1)
set nornu
else
set rnu
endif
endfunc
nnoremap <C-l> :call NumberToggle()<cr>
Relative Numbering is not turned on by default in vim, which means that you are probably turning it on through your ~/.vimrc file or one of your plugins. Look for set relativenumber or set rnu.
To turn it off for the current vim session you would simply run set norelativenumber or set nornu for short. This is a normal vim pattern for turning on and off settings like this. For example, spell check is set spell to activate and set nospell to deactivate.
To find this information and more on relative numbering, I recommend that you look in the vim help docs. For this case, while in vim run :h relativenumber
You actually have hybrid mode on (the line number your cursor is on is labelled as the absolute line number, not 0). In this case, both nu and rnu are on. You'll need to remove both to remove line numbers:
The following should work:
set nornu nonu

Run a command each time a file opens, or general syntax

I have a syntax rule that highlights trailing whitespace:
highlight Badspace ctermfg=red ctermbg=red
match Badspace /\s\+$/
This is in my .vimrc. It works fine, but the problem is I use splits a lot, and it seems that the match is only run on the first file you open, as well it should because the .vimrc should only run once.
Anyway, how can I get the above syntax to match any file that is opened? Is there a "general" syntax file? Is there any other way to run match each time a file opens rather than just once? I'd like to know both because I could end up using either one in the future.
The :match command applies the highlighting to a window, so you can use the WinEnter event to define an :autocmd.
:autocmd WinEnter * match Badspace /\s\+$/
Note that there are already a number of plugins for this purpose, most based on this VimTip: http://vim.wikia.com/wiki/Highlight_unwanted_spaces
They handle all that for you, and turn off the highlighting in insert mode; some can also automatically delete the whitespace. In fact, I have written a set of plugins for that, too: ShowTrailingWhitespace plugin.
You could accomplish this by using an autocmd:
highlight Badspace ctermfg=red ctermbg=red
autocmd BufEnter * match Badspace /\s\+$/
However, there's another way to accomplish your specific goal of marking trailing whitespace. Vim has a built-in feature for highlighting "special" whitespace, which includes tabs (to differentiate from spaces), trailing whitespace, and non-breaking spaces (character 160, which looks like a normal space but isn't).
See :help list and :help listchars. Here's what I use:
set list listchars=tab:>·,trail:·,nbsp:·,extends:>
listchars has the benefit of working with any file type, and marking up multiple whitespace types that are of interest. It is also a lot faster (match will be noticeably slow on giant files) and built-in already.
(Note that those are funky non-ASCII dot characters, which should work fine for you if you cut-and-paste into a UTF8-capable Vim. If they don't work for you, you can use any characters you like there, such as periods or underscores).
Here's what it looks like for me:
The correct approach to this problem is actually to use :syntax to define a custom syn-match.
Try putting this in your vimrc:
augroup BadWhitespace
au!
au Syntax * syn match customBadWhitespace /\s\+$/ containedin=ALL | hi link customBadWhitespace Error
augroup END
Edit: It should also be noted that there is built-in support for highlighting trailing whitespace with the 'list' option; see :help 'listchars' and :h hl-SpecialKey (SpecialKey is the highlight group used to highlight trailing whitespace characters when 'list' is on).
This is accomplished using autocmd. The events you're looking for are BufWinEnter and VimEnter. From the Vim manual:
BufWinEnter
After a buffer is displayed in a window. This
can be when the buffer is loaded (after
processing the modelines) or when a hidden
buffer is displayed in a window (and is no
longer hidden).
Does not happen for |:split| without
arguments, since you keep editing the same
buffer, or ":split" with a file that's already
open in a window, because it re-uses an
existing buffer. But it does happen for a
":split" with the name of the current buffer,
since it reloads that buffer.
VimEnter
After doing all the startup stuff, including
loading .vimrc files, executing the "-c cmd"
arguments, creating all windows and loading
the buffers in them.
Try putting this in your vimrc:
augroup BadWhitespace
au!
au VimEnter,BufWinEnter * match Badspace /\s\+$/
augroup END
Do :help autocmd for more info.
This is completely wrong because :match is window-local, not buffer-local. Ingo Karkat has the right idea. Unfortunately, there is no good way to avoid triggering the autocmd every time you enter the window.
More to the point, though, this is a job for a custom syntax, not match.

vim auto save current file when focus is lost

How to make vim automatically save only current buffer when focus is lost, not all files as described here http://vim.wikia.com/wiki/Auto_save_files_when_focus_is_lost
Based on your comments I can say that you have wrong question: you want not to “save only current buffer when focus is lost” (focus tends to have a meaning of “currently focused window”), but to “write buffer when switching to another one: when it is no longer in your focus of attention”. To complete this you may use
augroup AutoWrite
autocmd! BufLeave * :update
augroup END
, maybe combined with
set autowrite
and
set autowriteall
(sets of situations where first and second two variants are triggered intersect, but neither is a superset of another one).
Instead of :wa (write all), use :w.
Also you can try this
set updatetime=1000
autocmd CursorHoldI * silent w
just put it in your .vimrc

VIM Highlight the whole current line

What is the best way to highlight the whole current line in VIM? In some IDEs I am able to set some sort of 20% opacity of the line I am editing, this is great to find where I am rather quickly.
To highlight the current line use
:set cursorline
To highlight the current column use
:set cursorcolumn
The visual appearance of this can be modified. Have a look around :help hl-CursorLine or hl-CursorColumn.
See the Vim wiki on this subject for the complete story.
I especially found the following bit handy (when working with more than one window).
autocmd WinEnter * setlocal cursorline
autocmd WinLeave * setlocal nocursorline
Only highlight the current line in the active window.
Shift + V puts you in visual mode, highlighting the entire line.

Soft wrap at 80 characters in Vim in window of arbitrary width

I want to use Vim's soft wrap capability (:set wrap) to wrap some code at 80 characters, regardless of my actual window width.
I haven't been able to find a way to do this yet - all the soft wrapping seems tied to the width of the window
textwidth and wrapmargin are both for hard wrapping (they insert newline characters into the file)
vertical splitting into multiple windows and using :vertical resize 80 (possibly with :set breakat= to allow breaks on any character) on one of them sort of works (even though it's a bit hackish), but breaks when using :set number as the line numbers take up a variable number of columns (depending on the file length) and these are part of the 80.
Is there any way to do this in vim? It doesn't look promising, according to other sources.
Right now my approximation is just to have /^.\{80}\zs.\+ as my default search so it's at least highlighted. I thought about adding a :syntax item for it, but that broke when it overlapped other syntax items, so I dropped that idea.
You could
set a large minimum width for the line numbers column via :set numberwidth=6 and
then you could resize your window with :set columns=86 (or with the mouse) to the proper size.
If you edit a file with a million lines in it, you may have trouble, but that's unlikely. You're wasting 6 columns of screen real estate this way too. So there are still all kinds of problems.
You can highlight past the 80th column using :match like it says here and here.
Beyond that I can't see any way to do this. Seems like it'd be a nice feature though.
Try this:
set columns=80
autocmd VimResized * if (&columns > 80) | set columns=80 | endif
set wrap
set linebreak
set showbreak=+++
You can remove the if (&columns > 80) | if you always want 80 columns.
I don't have a solution to the soft wrap, but as for marking a column, as of Vim 7.3 (released 2010-08-15) :set colorcolumn=80 will highlight column 80. The color will depend on your syntax file.
See Vim 80 column layout concerns, :h colorcolumn.
Have you tried 'linebreak'?
*'linebreak'* *'lbr'* *'nolinebreak'* *'nolbr'*
'linebreak' 'lbr' boolean (default off)
local to window
{not in Vi}
{not available when compiled without the |+linebreak|
feature}
If on Vim will wrap long lines at a character in 'breakat' rather
than at the last character that fits on the screen. Unlike
'wrapmargin' and 'textwidth', this does not insert <EOL>s in the file,
it only affects the way the file is displayed, not its contents. The
value of 'showbreak' is used to put in front of wrapped lines.
This option is not used when the 'wrap' option is off or 'list' is on.
Note that <Tab> characters after an <EOL> are mostly not displayed
with the right amount of white space.
Combining eborisch's answer with some other answers I found here and things I had to work around, I came up with the following two-part solution:
This first part makes it easier to edit text with long lines:
" Allow enabling by running the command ":Freeform", or <leader>sw
command! Softwrap :call SetupSoftwrap()
map <Leader>sw :call SetupSoftwrap() <CR>
func! SetupFreeform()
" Use setlocal for all of these so they don't affect other buffers
" Enable line wrapping.
setlocal wrap
" Only break at words.
setlocal linebreak
" Turn on spellchecking
setlocal spell
" Make jk and 0$ work on visual lines.
nnoremap <buffer> j gj
nnoremap <buffer> k gk
nnoremap <buffer> 0 g0
nnoremap <buffer> $ g$
" Disable colorcolumn, in case you use it as a column-width indicator
" I use: let &colorcolumn = join(range(101, 300), ",")
" so this overrides that.
setlocal colorcolumn=
" cursorline and cursorcolumn don't work as well in wrap mode, so
" you may want to disable them. cursorline highlights the whole line,
" so if you write a whole paragraph on a single line, the whole
" paragraph will be highlighted. cursorcolumn only highlights the actual
" column number, not the visual line, so the highlighting will be broken
" up on wrapped lines.
setlocal nocursorline
setlocal nocursorcolumn
endfunc
With this alone you can get decent text wrapping for writing something like markdown, or a Readme.
As noted in other answers, getting wrapping at an exact column width requires telling vim exactly how many columns there are, and overwriting that each time vim gets resized:
command! -nargs=? Draft :call SetupDraftMode(<args>)
func! SetupDraftMode()
" I like 80 columns + 4 for line numbers
set columns=84
autocmd VimResized * if (&columns > 84) | set columns=84 | endif
:Softwrap
endfunc
There are still a couple of problems with this:
vim won't clear the screen outside of the columns you specify after calling set columns, and I can't figure out how to tell it to, so ideally you should call this immediately after opening vim
vim shows a prompt with the version number and some helpful commands when you open it, so these won't be cleared. You can add set shm+=I to disable that prompt
You can't open any vertical splits, because then both splits will be ~40 column. You would need to set columns to 2x your desired width and then always have a split open.
My vimscript is awful, but ideally someone could modify the Draft function above to take a column width as an argument, or use a global variable (g:explicit_vim_width?) that can be set manually if your window size changes.
There is no good way to do it. We can hack a makeshift setlocal softwrap with autocmd if we modify #eborisch answer. If we resize every time we enter a buffer, and we resize to a particular length when the local variable softwrap is set, we get the desired behaviour.
Let's suppose that we want to soft wrap to 80 columns, we can write the following in .vimrc.
augroup softwrap
autocmd VimResized * if (exists('b:softwrap') && &columns > 80) | set columns=80 | endif
autocmd BufEnter * set columns=999
augroup END
To turn on the mode for a particular buffer, use the following commands:
let b:softwrap=1
set columns=80

Resources