How do I organize a vim plugin with unique syntax elements? - vim

I've written a (basic) vim plugin for myself, and I'm having a difficult time organizing it. Right now, it lives in two files: one in syntax/ and one in ftplugin/ (both of which are in bundle/<plugin name>. I would like the plugin to be active for various file types, including those with existing syntax files.
So far, doing something like :set ft=<existing filetype>.<new filetype> in each file works, but I can't figure out how to (consistently) do this from, say, my .vimrc.
So, two questions:
Do I have the right organizational approach? Is there an easier way to (say) combine the syntax and plugin files?
If so, what's the "right" way to append my custom filetype?

Though you didn't include a lot of details, you're right in that syntax/ contains syntax definitions (i.e. mostly :syntax commands) and ftplugin/ is for filetype-specific settings (i.e. mostly :setlocal, :map <buffer>, etc.).
I would like the plugin to be active for various file types, including those with existing syntax files.
The correct approach depends a lot on the relationship between the original syntax and yours. It's hard to extend arbitrary syntaxes, because you have to consider overlaps and use the appropriate containedin=... specifiers in your syntax extension.
The compound filetype :setl filetype=c.doxygen works well when auto-detecting or manually setting it. If you don't want the extension to be so visible (and some plugins don't handle compound filetypes well), you can alternatively :runtime syntax/mine.vim in all ~/.vim/after/syntax/original.vim files (and do the same for ftplugin/).
Another alternative is hooking into :autocmd Syntax ... and :autocmd FileType ...; this avoids writing many short stub files that just :runtime your syntax / ftplugin additions.

Related

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\>/

Change recognized filetype of a plugin

I want to use 'plasticboy/vim-markdown' and 'nelstrom/vim-markdown-folding.' They require filetype=mkd and filetype-markdown, respectively. Is there a typical way to tell a plugin to recognize a certain filetype?
I've tried changing references of mkd to markdown in the former and markdown to mkd in the latter but that hasn't had any effect. As of now, I can only use one of the plugins because they require different filetypes.
The generic names for the filetype plugins are (:help ftplugin-name):
ftplugin/<filetype>.vim
ftplugin/<filetype>_<name>.vim
ftplugin/<filetype>/<name>.vim
Therefore, you need to rename the file names themselves (possibly in addition to the contents in the file, though there shouldn't be that many). Since that makes upgrading more difficult, you can also write linker scripts, e.g. ~/.vim/ftplugin/mkd_fold.vim which just contains the following command:
:runtime! ftplugin/markdown_fold.vim

Trigger command on buffer load and buffer save

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.

How do I combine two features of vim wiki plugins?

Sorry in advance for the newbie question. I've been trying to use vim for keeping a personal wiki, but I can't quite seem to decide on a good plugin. Vimwiki is great, and I really like the way it does checkboxes and uses the enter key to follow links. Notes.vim is simpler but I like it a lot better: it dynamically makes names of notes into links like Tomboy Notes, makes pretty bullet points, and has a search function built in. I can't get vimwiki to use files with no extension, but notes.vim does that automatically.
What I want to know is: is there an easy way (calling a vimscript file or something?) to combine some features of both of these plugins? I've tried doing some cutting-and-pasting but so far nothing has been working.
I doubt whether tbere is any simple automated way to do it. Both Vimwiki and notes.vim are "filetype" plugins. Generally in Vim any file (or buffer) can be set to just a single filetype.
It would depend on how the ftplugins were written, but it may be possible to apply them both to same buffer by making sure that the buffer is set to both filetypes, sequentially. That is, the buffer can be set to one filetype at a time, but setting it to both one after the other may do part of what you need.
For example, opening a notes.vim file will automatically set the buffer to a notes.vim filetype. Once open you could issue the command :setlocal filetype=vimwiki to change it to a vimwiki buffer. If vimwiki filetype initialization doesn't wipe out crucial notes.vim settings or have conflicting operation then you may then be able to access some functionality from both ftplugins. Not likely to get you very far, but maybe worth a try. Better would be to combine sections of their code into a single ftplugin.

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