Trigger command on buffer load and buffer save - vim

I want to write a vim plugin that does certain text transformations to the text while in the editor, but I don't want these transformations visible inside the file.
As an example, consider the word Gnarly in a text file I want to edit. Upon load I would want my vim script change that to G, but when I save the buffer I want it to expanded back to Gnarly.
My scenario is a little bit more complex because it will involve an external script, but I want to see exactly how that would be invoked.
Also I'd want to be able to apply this change only to some files based on their extension.

See :h autocmd. The events you need are BufRead and BufWrite.
Maybe you will be interested by :h conceal.

First of all, define your own filetype, e.g. gnarly. Read :help new-filetype for the details, but basically it's this autocmd:
:autocmd BufRead,BufNewFile *.gnarly set filetype=gnarly
Then, the conceal feature introduced in Vim 7.3 is the way to go. Write a syntax script ~/.vim/syntax/gnarly.vim. For your example it would contain:
:syntax keyword gnarlyConceal Gnarly conceal cchar=G
But you can also use :syntax match for more complex patterns.
Finally, concealment is off by default. To turn it on, put the following command into ~/.vim/ftplugin/gnarly.vim (you could put it into the syntax file, too, but this separation is recommended and done by all full plugins that ship with Vim):
:setlocal conceallevel=1
You can customize the 'concealcursor' behavior, too. If you still need help, have a look at the help pages, or existing plugins that use concealment.

Related

filetype and vim syntax highlighting for the output of ipython

In ipython, I can use ? to get the doc for the object preceding it, like os.path.join?<enter>. Then I get the output like this:
Signature: os.path.join(a, *p)
Docstring:
Join two or more pathname components, inserting '/' as needed.
If any component is an absolute path, all previous path components
will be discarded. An empty last part will result in a path that
ends with a separator.
File: ~/conda/envs/test/lib/python3.6/posixpath.py
Type: function
I want to load this output into Vim and get the syntax highlighting.
Which filetype should I set for it?
If no existing filetype describes this format, how to set the syntax highlight for it?
If Vim came with a syntax highlighting for it, there would most likely also be a filetype detection for it, as these usually come together. You could search the Internet whether someone has already created a syntax for that and published it, on vim.org and/or in a GitHub repository.
To start developing your own syntax see :help :syn-define and :help usr_44.txt.
For example, to highlight the Signature:, File:, ... prefixes, you'd use:
syntax match pythondocPrefix "^\a\+:"
Instead of defining custom colors, it is recommended to link to existing highlight groups; cp. :help highlight-groups.
highlight def link pythondocPrefix Type
This is just a start; you can define as many distinct elements as you like! It helps to look at existing syntax scripts (in $VIMRUNTIME/syntax/) to see how it's done. For the Python string after Signature:, it would be nice to include the Python syntax there; see :help :syn-include.
You'd put all these commands into a file ~/.vim/syntax/pythondoc.vim. :help 44.12 has additional tips.
Usually, you'd then define a :help new-filetype with detection, but as you apparently want to trigger the doc lookup via a custom mapping or command, you can just directly :setlocal syntax=pythondoc in that scratch buffer.

How can I apply custom syntax highlighting in VIM to all file types?

The most preferable way to do this would be in some like my .vimrc file or another location in my vimfiles that's easily persisted and not attached to an extra plugin.
The help files for VIM (along with almost all solutions found on the Internet abroad) relate directly to adding syntax highlighting for a specific file type.
However, how would one add highlights that apply to all files?
An example would be highlighting extra keywords as part of the Todo highlighting group - such as "NOTE", "INTERNAL", etc.
I've attempted to use vimfiles\after\syntax\..., but again, it seems to be predicated on the right file type getting used for the .vim file created in that directory.
So, something like vimfiles\after\syntax\cpp.vim with the following works to achieve this in C++:
syntax keyword cTodo contained NOTE INTERNAL IMPORTANT
for C++ files specifically, and this works how I would expect it to.
But how can this be generalized to all file types when a file is loaded into a buffer?
You can hook into the syntax script loading via the Syntax event. Be sure to define this after :syntax on in your .vimrc:
:autocmd Syntax * syntax keyword allTodo NOTE
If you also want to handle buffers that don't have any syntax (/ filetype) set, add the BufNewFile,BufReadPost events.
Alternative
Depending on the syntax, you may need to specify contained[in], or :syn cluster add=... to augment the existing syntax. That unfortunately cannot be generalized. An alternative approach would be using :match or :call matchadd(...), which goes on top of (and is totally independent of) syntax highlighting. Since this is window-local, the autocmd would be:
:autocmd VimEnter,WinEnter * match Todo /\<NOTE\>/

How to autocomplete file paths in Vim, just like in zsh?

In Zsh, I can use filename completion with slashes to target a file deep in my source tree. For instance if I type:
vim s/w/t/u/f >TAB<
zsh replaces the pattern with:
vim src/wp-contents/themes/us/functions.php
What I'd like is to be able to target files the same way at the Vim command line, so that typing
:vi s/w/t/u/f >TAB<
will autocomplete to:
:vi src/wp-contents/themes/us/functions.php
I'm trying to parse the Vim docs for wildmode, but I don't see what settings would give me this. It's doing autocompletion for individual filenames, but not file paths. Does Vim support this natively? Or how can I customize the autocomplete algorithm for files?
Thanks for any advice!
-mykle-
I couldn't find a plugin to do this, so I wrote one. It's called vim-zsh-path-completion. It does what you're looking for, although via <C-s> rather than <Tab>. You can use it with <Tab> for even more control over what matches, though.
It's got bugs, but for basic paths without spaces/special characters, it should work. I think it's useful enough in its current state to be helpful. I hope to iron out the bugs and clean up the code, but I figured I'd start soliciting feedback now.
Thanks for the idea!
Original (wrong) answer, but with some useful information about Vim's wildmode.
Put the following in your .vimrc:
set wildmenu
set wildmode=list:longest
That will complete to the longest unique match on <Tab>, including appending a / and descending into directories where appropriate. If there are multiple matches, it will show a list of matches for what you've entered so far. Then you can type more characters and <Tab> again to complete.
I prefer the following setting, which completes to the first unique match on <Tab>, and then pops up a menu if you hit <Tab> again, which you can navigate with the arrow keys and hit enter to select from:
set wildmode=list:longest,list:full
Check out :help wildmenu and :help wildmode. You might also want to set wildignore to a list of patterns to ignore when completing. I have mine as:
set wildignore=.git,*.swp,*/tmp/*
Vim doesn't have such a feature by default. The closest buil-in feature is the wildmenu/wildmode combo but it's still very different.
A quick look at the script section of vim.org didn't return anything but I didn't look too far: you should dig further. Maybe it's there, somewhere.
Did you try Command-T, LustyExplorer, FuzzyFinder, CtrlP or one of the many similar plugins?
I use CtrlP and fuzzy matching can be done on filepath or filename. When done on filepath, I can use the keysequence below to open src/wp-contents/themes/us/functions.php (assuming functions.php is the only file under us that starts with a f):
,f " my custom mapping for the :CtrlP command
swtuf<CR>
edit
In thinking about a possible solution I'm afraid I was a little myopic. I was focused on your exact requirements but Vim has cool tricks when it comes to opening files!
The :e[dit] command accepts two types of wildcards: * is like the * you would use in your shell and ** means "any subdirectory".
So it's entirely possible to do:
:e s*/w*/t*/u*/f*<Tab>
or something like:
:e **/us/f<Tab>
or even:
:e **/fun<Tab>
Combined with the wildmode settings in Jim's answer, I think you have got a pretty powerful file navigation tool, here.

Coda Clips for Vim

I'm currently trying to switch from Coda (a Mac IDE) to Vim. One thing I loved about Coda and my knowledge of Vim cannot replace were the so-called "clips". Basically, you type, say, "new", press TAB, and the text is replaced with a basic XHTML page. And you can add as many keyword/clips combinations as you want.
The most I could get with Vim so far was to create a new file containing my clip, and then use :r FILE in Vim in order to get it inserted, but this is not a very elegant solution, as I'd have to carry these clips around in every directory I have a file I want to use my clips with.
So assuming I've explained things properly, what would be my choices?
For various editors, there's a functionality called '''snippets''' which tab expands the beginnings of common text (like a HTML div, or C function definition) into a skeleton for that code.
There's a couple vim plugins that present this functionality. Two off the top of my bookmark list:
snippetsEmu
snipMate
I heard of another plugin for quick HTML editing that uses snippets recently:
zencoding
Check those out and see if they're near what you're looking for.
Also, you can define a default BufNewFile action in vim - which lets you read in a skeleton for a file if it doesn't already exist automatically.
*skeleton* *template*
To read a skeleton (template) file when opening a new file: >
:autocmd BufNewFile *.c 0r ~/vim/skeleton.c
:autocmd BufNewFile *.h 0r ~/vim/skeleton.h
:autocmd BufNewFile *.java 0r ~/vim/skeleton.java
Put those (or the equivalent) in your .vimrc (w/o the leading colon) to have them set up automatically every time you run vim.
Very late to the party, but:
I would recommend something like Dash for this, because the snippets are then available across all your apps.
This can be a significant bonus as your muscle-memory starts to rely on particular snippets, and can also ease the transition from one editor to the other, because your snippets are independent.
Sometimes I find myself using snippets in something like Mail to send to someone else, or in a Vim terminal on a remote machine I haven't configured, and it's great to have them all there at the ready.
Now all we need is a cross-platform solution which moves with you to a colleague's machine!
As well as the various snippet plugins, Vim also has an abbreviation feature built in, using the :ab[breviate] command.
For example you can define this:
:ab <h <head>^M</head>^M<body>^M<\body>
Then when you type <h<SPACE> it will expand into the full text. The ^M in the example above are actually carriage returns inserted in the string definition with <ctrl-V><RETURN>.

Is vim able to detect the natural language of a file, then load the correct dictionary?

I am using several languages, and currently I am obliged to indicate to vim with which of these the spell check must be done. Is there a way to set up vim so that it automatically detects the correct one? I vaguely remember that in a previous version of vim, when the spell check was not integrated, the vimspell script made this possible.
It would be even better if this could apply not only to a file but also to a portion of a file, since I frequently mix several languages in a single file. Of course, I would like to avoid to load several dictionaries simultaneously.
I don't know if there is a way to autodetect it, but if you put vim:spell:spelllang=foo,bar,baz at the bottom of the file, vim will set the spellchecking languages to foo, bar, and baz when the file is opened. Note that you must put at least one space before that text, or vim will think it's part of the file.
Since vim is missing this feature, I found it useful to define shortcuts like these in .vimrc:
command! Nb :set spelllang=nb
command! En :set spelllang=en

Resources