what function does vim call for completion with ctrl-n - vim

My vim is throwing nasty errors 50% of the time when I use ctrl-n for completion
E854: path too long for completion
I really want to remap this, and call it with the :silent option to suppress the error, but I have no idea what function provides completion, so I can't remap it.
So my question is where can I find exactly what C-N calls when it is invoked in insert mode
Solution:
As mentioned in the comment on my accepted answer I found a way round this. Based off the instructions on building your own vim here : brilliantcorners.org/2011/02/building-vim-on-osx-snow-leopard
I grepped the source directory for E854 and it only comes up in 1 file. If you open that file you see it is only referenced twice. I just removed those error calls and built vim
This doesn't solve whatever the actual problem is, but it's the same effect as doing ignore. It works great now and doesn't throw any errors, I hope anyone else with this problem is helped by this.

In insert mode, <C-n> usually completes words with the content of your buffers. I don't know how it works internally but it may complain about a buffer's associated file's path length.
But I can't find a reference to E854 in Vim's :help, which can be normal if it comes from a plugin I don't have.
You could:
try :verbose imap <c-n> to locate its origin or
search the help for the tag E854, :help E854 or
search the help for the sting E854, :helpgrep E854 or
grep for E854 in your ~/.vim folder, $ grep -r E854 ~/.vim.

I had an issue like this similar. Turns out it was blowing up because the current ruby.vim that's distributed with Vim calls a deprecated Gem.all_load_paths which puts a nasty error in your path variable. Check out https://github.com/rubygems/rubygems/issues/161 and https://groups.google.com/forum/#!msg/vim_dev/wrouKpIDraU/xLxUuMT3_6QJ for a fix :)

My copy of the vim source code (obtained at some point using Mercurial and hg clone https://vim.googlecode.com/hg/) finds that error being thrown only in one spot, in the internal function vim_findfile_init():
static char_u e_pathtoolong[] = N_("E854: path too long for completion");
...
/*
* copy wc_path and add restricts to the '**' wildcard.
* The octet after a '**' is used as a (binary) counter.
* So '**3' is transposed to '**^C' ('^C' is ASCII value 3)
* or '**76' is transposed to '**N'( 'N' is ASCII value 76).
* For EBCDIC you get different character values.
* If no restrict is given after '**' the default is used.
* Due to this technique the path looks awful if you print it as a
* string.
*/
len = 0;
while (*wc_part != NUL)
{
if (len + 5 >= MAXPATHL)
{
EMSG(_(e_pathtoolong));
break;
}
...
So it looks like it's doing arbitrary-depth wildcard expansion. If I had to take a wild stab I'd say you have a path somewhere in the filesystem that has a circular symbolic link (say c -> a), so you end up doing path completion and getting /foo/bar/a/b/c/a/b/c/a/b/c/a/b/c/..... and the limit gets hit.
Edit
Scratch that last theory; based on actually reading the code, it looks like it's trying to find a tag file and blowing up. Can you post what you get when you do :set tags ?
Edit 2
Sigh, it's late... Here's the answer you originally wanted that I just found: do :help completefunc and :help completion-functions. completefunc is the one you want, if I (finally) understand your question.

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 automatically name a file when saving in vim

I'm trying to emulate in vim a behaviour similar to that of TextEdit.app.
As I work I often open a lot of files to take notes, and keep them there without saving them. When I restart the laptop, the TextEdit files will still be there and open thanks to AutoSave. If I do the same thing with vim (specifically MacVim) the files are (as expected) not saved and I lose their content.
My recipe for solving this problem has two bits. The first one is to automatically save the files when I'm not using them, so using a command like:
autocmd BufLeave,FocusLost * silent! wall
This works fine with files that have already been saved, but it ignores ones that have not yet been saved. This is where the second bit comes into play, I would like vim to automatically give these files a default name if it tries to save them and they don't already have a name. Possibly I would also like there to be a default save directory.
The ideal solution would be that when an unnamed file/buffer loses focus it gets saved as ~/Documents/notes/note_1.txt, the second one note_2.txt, etc etc.
I did look around for any pointers that could help in either direction (default name and default directory - the latter is not fundamental though), but couldn't find anything.
Can anybody help?
I don't like your idea, but it is doable.
You need a function:
function! SaveIt()
if bufname("%")==''
exec 'w /path/note_'.localtime()
else
w
endif
endfunction
and in your autocommand, just call the function. Some points you need to note:
the filename would be /path/note_( ms since 1970). your 1,2,3.. index will make vim check filesystem to find out the index. It could be a better name, e.g note_2013-09-11_11:11:11.233 You just change the localtime()
this may throw exception when you try to save a readonly buffer. (help, qf ...) You could check for them though.
Note that I didn't add the ! in w cmd.
it may not work for your autocmd wall. if you want to do it, you have to loop through all buffers, and for each buffer call the function.
after all the function shows the direction how it could be done, it (the quality) is still very far away from "production" level.

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

How to tame vim's ":find" command

Say, I have files foo.js and bar.css in my project. There is a ":find" command in vim, which find files, matching string. But this command, alas, has some limitations. For example, if I launch this way - "vim", or even this way - "vim ." - there's nothing to be find in js subdirectory. But if I launch vim this way - "vim js/any_file_other_than_foo.js", then calling ":find foo.js" works pretty well.
Since it is not intuitive (i'm working in the same directory, "pwd" returns the same path), my first question is - can anybody explain how to circumvent this issue? And, even broader, is there any way to type something like find foo - and open first file, which name matches pattern foo.
thanks in advance.
You could try
:e[dit] **/*foo* and then press 'tab' to move to the first match.
the ** is a directory globbing pattern, while * is character matching.
If you were so inclined, you could write a simple fuzzy finder command, for more information you can check out the vim tips wiki: http://vim.wikia.com/wiki/Find_files_in_subdirectories
Vim's :find works by searching each directory in the path variable (and ignores pwd). By default, it does not search recursively. That's why find is only working for you when you open a js file. The '.' in path refers to the directory for the current file -- not pwd.
You can change path to include your desired directories:
set path+=$PROJECT/js
See :help path.
One of the magic bits to use is to add ** to a path to search that path recursively:
" search recursively in my project
set path+=$PROJECT/**
" search recursively from the current file's directory
set path+=./**
See :help file-searching for more magic.
A nice plugin that accomplishes a similar effect is Command-T.
The Command-T plug-in provides an
extremely fast, intuitive mechanism
for opening files with a minimal
number of keystrokes. It's named
"Command-T" because it is inspired by
the "Go to File" window bound to
Command-T in TextMate.
Files are selected by typing
characters that appear in their paths,
and are ordered by an algorithm which
knows that characters that appear in
certain locations (for example,
immediately after a path separator)
should be given more weight.should be given more weight.
Here is a screencast of Command-T in action.

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