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

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".

Related

Vim long file paths break/split over multiple lines in quickfix window

A long file paths is broken up over multiple lines in the Vim quickfix window which then for example does not allow to jump to the error location displayed in the qf.
The file (and the lines around) are diplayed in the quickfix window as (the example is the output from neomakes pdflatex)
|| Enter file name:
|| /long/path/to/file/.../loca
tionOfTexFiles/myTexFile.tex|144 error| Emergency stop.
|| read
to be able to follow to the file line by lnext/cnext I should have
/long/path/to/file/.../locationOfTexFiles/myTexFile.tex|144 error| Emergency stop.
For quickfix files I have the following relevant (in my view) settings which are set to:
setlocal nolinebreak
setlocal nowrap
setlocal textwidth=9999
So I am wondering how I can display the file path in one line within the quickfix window?
On :make, Vim invokes 'makeprg', captures the output, and then parses it according to 'errorformat'. The latter does support multi-line error messages (cp. :help errorformat-multi-line), but that is mostly for what I would call intentional linebreaks, as specified by the compiler. What you suffer from is unintentional linebreaks because of line wrapping (due to overly long paths).
Now, I don't know about "neomakes pdflatex", but it looks like that tool creates the linebreaks, whereas it shouldn't, as Vim is capturing the output, and there's no receiving terminal (or user). Investigating in that direction (or opening an issue at the project's tracker) might be helpful.
The mentioned Vim options ('linebreak', 'wrap', etc.) have nothing to do with it. They apply to normal buffers; the quickfix buffer as such is not modifiable.
Workarounds
A possible workaround might be to :cd first to a directory that is "closer" to the processed files (or even :set autochdir); this might avoid the long paths in the output.
Alternatively, you may "unmangle" the output by adding a sed stage after the compiler:
let &makeprg .= "| sed -e 's/.../...'"
If I'm not mistaken, the issue is on pdflatex side. The || mark is a good indication: you'll have one per output line -- in case filename and/or lines numbers are recognized, they'll be fed in between the bars.
So. This means you'll need a way to fix the path names. It'll be better to do it outside vim. I'm not saying this is trivial. I'm just saying that if you can have a program able to fix pdflatex outputs, you'll just be one pipe away from the solution (plus a correct forwarding of error codes...).
If you prefer to implement it in vim script, this is possible. But you'll experience side-effects. In my BuildToolsWrapper plugin I'm able to post-process compilation output in vim side, but the result is far from being perfect. I'm working on getqflist() result, and parse each line. When I found a line where I want to fix the filename, it's not simply about fixing the filename but also about assigning a valid buffer number to it. See this function where I can replace a filename with another one. The magic happens where lh#buffer#get_nr() is used. Still you'd need to implement a vim script able to merge split filenames.
IOW: my understanding is that vim is not involved. It could be used to fix the issue, but IMO this is not the easier path to undertake.

How to add custom messages to Vim quicklist?

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')

What is the easiest way to rename the file you're currently editing in Vim?

What would be the most practical way to rename the file you're currently editing in Vim without messing up your current splits configuration?
Generally, one would need to ... save the file under a different name, delete the original one, and re-open the new one without making a mess of the current layout.
Anyone have any idea how to do that in one command (function) or less?
:saveas newname will save the buffer with the new name, make that name the current buffer, and set the alternate buffer to the old file.
:call delete(expand('#')) will then delete the file associated with the alternate buffer.
You can easily turn that into a command with something like
:command! -bang -complete=file -nargs=+ Rename saveas<bang> <args> | call delete(expand('#'))`
The user manual provides a thorough description of how to create user commands. Here's an explanation of the elements I'm using above.
-bang allows the command to called as either Rename or Rename! and <bang> in the constructed command is replaced by either an empty string or !, depending on how it is called. This is used to support the same functionality in the :saveas command.
-complete=file will let you tab-complete the path that will be used for the new file, similar to :e and :saveas do.
-nargs=+ specifies that :Rename requires at least one argument (the filename), but can take more. <args> is replaced with whatever arguments are given to :Rename. This allows you to specify the extra arguments that :saveas accepts, so you could do something like :Rename ++enc=latin1 newfile to rename the file to newfile and change the encoding to latin1.
Tim Pope has a plugin that has a function :Rename that does this: vim-eunuch.
You can also do the following sequence of steps:
:saveas newfile
:bw <buffer_for_the_old_file>
:!rm old_file
of course this is not as nice as renaming the file in the shell.
Call up the explorer with :Explorer or just :E, select your file, and then press r to rename.
Use :Move provided by eunuch.
eunuch also provides other useful file operations, like :Remove, sudoedit.

Run bash command on Vim and copy result to clipboard

How can I create a Vim command and copy it's results to clipboard?
I want to convert Markdown to HTML and copy the result to the clipboard. So far I got:
nmap md :%!/bin/markdown/Markdown.pl --html4tags
But this will substitute my opened file on Vim to the result of Markdown.
You didn't say which system you're using, but generally saving it in the +
register should work. You can call system():
:let #+=system("markdown --html4tags", join(getline(1,line("$")), "\n"))
The system() function takes the second parameter (optional) as input to the
command, and here I'm using a chain of other functions to retrieve the contents
of the current buffer. Not sure, but there should be a better way to do it (if
someone knows, please let me know).
Alternatively, you can pass markdown your file name as input directly:
:let #+=system("markdown --html4tags " . shellescape(expand("%:p")))
But keep in mind that you'll need to write the file before calling this.
Two important notes:
I didn't type your full path to markdown. Use it.
I didn't use maps here, the final result would be something like:
nnoremap md :let #+=system(...)
get the xsel package
and pipe stdout to xsel --clipboard
For instance:
cat /etc/passwd | xsel --clipboard
Is that what you're looking for?
Filling in a missing piece (2+ years late). With the clarification that the user was on a Mac and since the asker's "why doesn't it work for me?" question was not answered.
To redirect the output of a command to the system clipboard from within MacVim (GUI version) you need to set the '*' to be the "clipboard register" you need to change the clipboard setting to 'unnamed':
set clipboard 'unnamed' # 'cb' can be substituted for 'clipboard'
Then sidyll's answer should work except specify the '*' register and not the '+' register:
:let #*=system(...)
The clipboard feature is likely not compiled into the "terminal version" of MacVim and when it is available option setting is different from 'unnamed'. To see more details regarding what works where and how, see the documentation in MacVim using the Vim help command:
:help 'clipboard' (include the single quotes since it's a set option!)
(I'll skip the command mapping issue since it always takes me several tries and I still have to look it up; finding the help for the mapping commands should be easier than finding it for the * register.)

Get the file name without file extension in a Vim function

I want to get the file name without the file extension in Vim.
I wrote the following function in my .vimrc file to compile and run the Java program:
:function! JAVA_RUN()
:!javac %^M
:endfunction
map <F3> :execute JAVA_RUN()<CR> :source $HOME/.vimrc<CR>
How can I get the file name without the extension inside the function?
:help expand() should give you the answer, see expand().
You should use the r modifier for %, with %:r instead of % to get the file name without extension.
If you want to write functions to build and execute files, you should also have a look at the documentation for shellescape, in order to prevent problems with spaces in file name or path.
If you want to expand a filename (other than % etc) take a look at fnamemodify()
fnamemodify({fname}, {mods}) *fnamemodify()*
Modify file name {fname} according to {mods}. {mods} is a
string of characters like it is used for file names on the
command line. See |filename-modifiers|.
fnamemodify("main.java", ":r") returns main.
I literally just read a similar question to this (in that someone else seemed to be trying to configure vim to build automagically for them with the F-key), and wrote an answer about how you can leverage the power of vim's :make command without even needing to write a Makefile. In your case, it's less directly related to the question, but I thought I'd mention it in case you were interested.
Furthermore, someone seems to have written something on Vim Tips Wiki about how to set up vim's :make command to specifically work with Java projects built with ant. I haven't worked with Java in a while myself, but in your case specifically it might be a good place to get started.
I came here looking for an answer for a similar question. I wanted to be able to extract the current class name from the java file being edited. I found a very neat way to do this in vim with an abbreviation:
ab xclass <C-R>=expand('%:t:r')<CR>
Place this line in your .vimrc (or similar) for this to work. An abbreviation will auto-trigger as soon as you press space, and so I usually prefix them with 'x' to avoid their accidental expansion.
The trick here is the combination of :t and :r in the argument to expand(). % is the "current file name", :t selects just the tail of the path ("last path component only") and :r selects just the root ("one extension removed"). (quoted parts are from the official expand() documentation.)
So when you are creating a new class in file /a/b/ClassIAmAboutToCreate.java you would type:
public class xclass {
the moment you press space after "xclass", the abbreviation will be expanded to public class ClassIAmAboutToCreate, which is exactly what you need.
Also, note that an abbreviation can be triggered by pressing Ctrl+] which avoids inserting a space after the class name.

Resources