How to add custom messages to Vim quicklist? - vim

I have a file which contains code review comments by file and line numbers.
I'm writing a Vim plugin which uses Vim quicklist to display review comments when i open a file and navigate to the line number.
I've figured out that i can use :cex command to add entries to quicklist from this documentation
How do i add error message in a format like [file]:[line] [issue category][issue description] which allows me to jump to that location?

The help of :cexpr also provides the hint:
If {expr} is a String, then each new-line terminated
line in the String is processed using the global value
of 'errorformat' and the result is added to the
quickfix list.
:caddexpr printf('%s:%d:%s', expand('%'), line('.'), "entry")
Since the value of 'errorformat' is difficult and may not be completely under your control (ftplugins may change it), an alternative is to directly set / append items via the setqflist() Vimscript function:
:call setqflist([{'bufnr': bufnr(''), 'lnum': 42, 'text': 'entry'}], 'a')

Related

Read vim status line

Is there a way to read what the user sees in the statusline from a function in my vimrc?
I tried to look the content of &stl, but it contains the "formula" of the statusline I previously set it to, instead of the actual calculated content.
The screenchar() function has been introduced after the Vim 7.4 version. It is mainly intended for testing, has has some limitations with non-ASCII characters, but can be used to directly access any location within Vim's user interface. You basically just need to find out the screen line number that the status line you're interested in occupies:
:let lnum = screenrow() - 1 " Status line directly above the command-line.
:echo join(map(range(1, winwidth(0)), 'nr2char(screenchar(lnum, v:val))'), '')

How to make vim indicate the file has changed since last save?

I used to work with netbeans and it always put an asterisk and changed the tab color when the file had changed since last save. Is there any way to make vim do something similar, that is, remind me that I haven't saved the file?
I know that there is a way to have it save automatically once in a while, but I don't want to do that.
You can use the m flag in the 'statusline' option to add a [+] if file is modified. Note that in order to see the statusline, you'll need to set 'laststatus' to be greater than 0 (1-Only shows status line if there are two or more windows, 2-Always).
If you're using a GUI-version, such as MacVim, you may prefer to set 'titlestring', which uses the same syntax but will alter the name of the window in your window-manager.
Example:
:set laststatus=2
:set statusline=[%n]\ %<%f%h%m
This will display:
[: literal
%n: buffer number
]: literal
\<Space>: a space
%<: Truncate the field at the beginning if too long
%f: Path to the file in the buffer, as typed or relative to current
directory.
%h: Help buffer flag, text is "[help]".
%m: Modified flag, text is "[+]"; "[-]" if 'modifiable' is off.
For more information see:
:help status-line
Call :ls and you will see a + before unsaved buffers
If the terminal displays its title somewhere, it's possible to use
:set title
to display whether the file is modified: a + is displayed after the file name if it's modified.
However, a file can have + at the end of its file name. For most files this should work fine.
Source: https://stackoverflow.com/a/13244715/5267751
Pressing Ctrl+g (or equivalently :f) in normal mode will show the file status, which indicates whether the file is modified.
The status looks like this
"file_name" 100 lines --20%--
if the file is not modified, or
"file_name" [Modified] 100 lines --20%--
if the file is modified.
For more info see :help ^g.

VimL: How to know in which buffer Vim is, by buffer name

I'm currently modifying a plugin that I like, to suit my needs. I have come across the problem that I need to know in what buffer I'm in, within VimL's limitations.
I need to be able to refer to the buffer by name, specifically I need to know when I'm within Vim's own [Command Line] buffer. Which BTW, you can achieve using q:, q/ or q?.
The plugin I'm modifying is the following: https://github.com/jeffkreeftmeijer/vim-numbertoggle
And this is my fork: https://github.com/Greduan/vim-numbertoggle
What I want to do is know when I'm in this specific buffer, called [Command Line] and not use relative line numbers when I'm in it.
Thanks for any help you can provide!
Use vimscript function bufname('') with an empty string (for details, see :help bufname()). To get the number of the buffer, use bufnr('').
Also, you can get the name of file in the current buffer using register %:
let current_file = #%
You could check for some options set by Vim when it creates the command-line window.
create this file and directories:
~/after/ftpugin/vim.vim
What you put in this file is only executed by Vim when you edit a file with the corresponding filetype.
add the following self-explanatory code to that file:
if &buftype == "nofile"
setlocal number
endif
It works, here. I think that you can easily adapt it to your needs by adding &filetype == "vim".

send current line to external command in vim (without capture)

The goal is to use the current line as a TODO and send this to some external program. Something like this:
:! /usr/bin/todo "content of current line"
I know of the filtering command but this implies that I want to edit the current buffer which I do not want (:.! acts as a filter). I know how to get the current file with '%' but isn't there any way to get some other content ? Maybe by using :execute ...
:.! works as a filter, but :.w ! (mind the space!) just passes the output. See :help :w_c. I.e.
:.w !/usr/bin/todo -
You can insert contents of registers into command line, so doing something like:
"1y$ //yank current row to register 1
: CTRL-R 1 //CTRL-R followed by register id pastes register to command line
should do the trick.
You might like something like these mappings (i.e. saved in your .vimrc or pasted into a : prompt):
cmap <C-R>' <C-R>=shellescape(getline('.'))<CR>
cmap <C-R><C-R>' <C-R><C-R>=shellescape(getline('.'))<CR>
Once installed, you use them like this:
:!/usr/bin/todo ^R'
(type an actual Control‑R where the above example shows ^R).
You can think of them as command-line mode versions of the registere-based Control‑R and Control‑R Control‑R (see :help c_CTRL-R, and :help c_CTRL-R_CTRL-R) where the “imaginary” register ' always contains the shell-quoted contents of the current line.
Because these mappings use the same prefix as built-in mappings (see the :help topics mentioned above), you must enter the final single quote within timeoutlen milliseconds (see :set timeoutlen?), or it will default to the built-in mapping (see :help map-typing).

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