4

I've tried every tip I can find on this and none of them work. I've cleared my .vimrc file. I have a syntax script in ./vim/syntax/test.vim. It consists of nothing but this:

highlight clear
syn keyword syntaxElementKeyword ok
hi def link syntaxElementKeyword Todo

When I first load a file with my text and enable and set the syntax file to test, it works. But if I do :e on the text file, the syntax highlighting turns off then I have to run :set syntax=test again. OK, fine. But then if I edit test.vim, I cannot get the changes I make to take effect unless I close out my text file and then reenable syntax highlighting. This makes for painful slow going for someone trying to learn how to do syntax highlighting.

So how do I reload the syntax file so I can see the changes reflected in my text file instantly?

7
  • See :h syntax-loading
    – Tommy A
    Commented Feb 28, 2017 at 20:51
  • Either I'm a dummy or that doesn't tell me how to reload the contents of the test.vim file so I can see the changes reflected in my text file.
    – StevieD
    Commented Feb 28, 2017 at 21:01
  • I would put highlight clear as the first line in test.vim, and then set up a key map to do: :source ./vim/syntax/test.vim (Or whatever your absolute path to your file is)
    – Tumbler41
    Commented Feb 28, 2017 at 21:30
  • Ugh, still doesn't work. Thanks though.
    – StevieD
    Commented Feb 28, 2017 at 21:35
  • 1
    @StevieD Keep reading beyond "Upon loading a file, Vim finds the relevant syntax file as follows". How auto-loading a syntax works is very well documented. filetype and syntax are closely related in this this regard, and you aren't using filetype.
    – Tommy A
    Commented Feb 28, 2017 at 21:47

2 Answers 2

5

It consists of nothing but this:

highlight clear
syn keyword syntaxElementKeyword ok
hi def link syntaxElementKeyword Todo

highlight clear will remove all the highlight groups, but not the syntax groups. They belong to 2 related but still different mechanisms. Their purpose is to answer 2 questions:

  • What do you want to color? The answer is given by the syntax groups defined in a syntax plugin.
  • How do you want to color it? The answer is given by the highlight groups defined in a colorscheme.

So, since you were writing a syntax plugin, and not a colorscheme, you probably wanted to write syntax clear.


But if I do :e on the text file, the syntax highlighting turns off then I have to run :set syntax=test again.

If your syntax plugin is not sourced, it means that the 'syntax' option was not (properly) set. Which means that the 'filetype' option was not (properly) set.
Which means that the filetype was not (properly) detected.

The filetype detection mechanism is explained in :h ftdetect. The help says that there are 4 ways to implement the detection and setting of a type of file. They are labeled A., B., C., and D.. Each of them is broken down into a set of 3 steps, prefixed with numbers (1., 2., 3.).

They all install autocmds. But they differ in 2 ways: their location, and the command they use to set the filetype.

The location is important, because depending on the one you choose, your autocmds will be installed before or after the default ones which are written inside $VIMRUNTIME/filetype.vim.

Here's a flowchart to help you decide where to write them (assuming you're working with the filetype test):

                             +--------------------------------+
                             |                                |
                             | Do you want them to be sourced |
                             | before the default ones?       |
                             |                                |
                 yes   +_____+--------------------------------+____+   no
                      /                                             \
                     /                                               \
                    v                                                 v
+-------------------------------------------+                       ***************
|                                           |                  *****               *****
| Does the filetype of your files depend on |               ***                         ***
| the extension in their names, or on       |               *   ~/.vim/ftdetect/test.vim  *
| their contents?                           |               ***                         ***
|                                           |                  *****               *****
+-------------------------------------------+                       ***************
                |                        |
   extension    |                        |    contents
                |                        |
                v                        v
       *************                  *************
  *****             *****         ****             ****
**                       **     **                     **
*   ~/.vim/filetype.vim   *     *   ~/.vim/scripts.vim  *
**                       **     **                     **
  *****             *****         ****             ****
       *************                  *************

As for the command which you can use to set the filetype of a file:

  • use :set if you want to set it unconditionally: set filetype=test
  • use :setfiletype if you want to set it on the condition it hasn't been done before by another autocmd: setfiletype test

So, if you wanted to unconditionally set the filetype of a file whose extension is .test, before the default autocmds in $VIMRUNTIME/filetype.vim, you would need to choose an implementation similar to the one labeled C. in :h ftdetect. The example given there is:

" my filetype file
if exists("did_load_filetypes")
  finish
endif
augroup filetypedetect
  au! BufRead,BufNewFile *.mine             setfiletype mine
  au! BufRead,BufNewFile *.xyz              setfiletype drawing
augroup END

Adapted to your file whose extension is .test, it would give:

" my filetype file
if exists("did_load_filetypes")
  finish
endif
augroup filetypedetect
  au! BufRead,BufNewFile *.test             set filetype=test
augroup END

Once this file is created, you need to restart Vim. After that, whenever you reload a file whose extension is .test, here's what will happen:

  1. BufReadPost is fired
  2. au! BufRead,BufNewFile *.test set filetype=test is triggered
  3. the buffer-local option 'filetype' receives the value test
  4. FileType is fired with the value test
  5. the buffer-local option 'syntax' receives the value test
  6. Syntax is fired with the value test
  7. your test syntax plugin is sourced, if it's located in ~/.vim/syntax/test.vim or ~/.vim/after/syntax/test.vim (or in any file whose path is matched by the pattern {directory in $VIMRUNTIME}/syntax/test.vim or {directory in $VIMRUNTIME}/syntax/test/*.vim)

If you want your test syntax plugin to be sourced before a possible test syntax plugin present in $VIMRUNTIME, use ~/.vim/syntax/test.vim. Otherwise, use ~/.vim/after/syntax/test.vim.

Sourcing your syntax plugin before the one in $VIMRUNTIME is useful when you want to ignore the latter, and completely redefine it. Sourcing it after is useful when you just want to tweak a few syntax groups.


But then if I edit test.vim, I cannot get the changes I make to take effect unless I close out my text file and then reenable syntax highlighting.

As you found out in your answer, the issue comes from the def argument of the :highlight command, which is described in :h :hi-default.

The [default] argument is used for setting the default highlighting for a
group.      If highlighting has already been specified for the group the command
will be ignored.  Also when there is an existing link.

Using [default] is especially useful to overrule the highlighting of a
specific syntax file.  For example, the C syntax file contains:
        :highlight default link cComment Comment
If you like Question highlighting for C comments, put this in your vimrc file:
        :highlight link cComment Question
Without the "default" in the C syntax file, the highlighting would be
overruled when the syntax file is loaded.

def tells Vim that if the highlighting group has already been specified then the command should be ignored. IOW, the link you write is just a DEFault value, to be used as a fallback only if the group has not been configured.

In your case, it means that if you want to change how the syntax groups of your test file are colored during the same Vim session, you should avoid this argument, so that Vim applies your link unconditionally, and ignores any possible pre-existing link.


If you want more information about how to write a syntax plugin, you could read :help usr_44.
It's a chapter of the user manual (not the reference manual, so it should be easier to read).

2

Changing my test file to something like this:

syntax keyword Foo Foo 
highlight Foo cterm=underline

allowed me to change the colors after editing the test file. So there must be something special about the "def" keyword that gets treated differently.

2
  • Just so you don't think I'm crazy, I got def link code straight off of vim website: vim.wikia.com/wiki/Creating_your_own_syntax_files. I'm guessing it's just badly out of date.
    – StevieD
    Commented Feb 28, 2017 at 23:34
  • Nope, nothing has changed about creating syntax files from that page. I used those directions to create one myself.
    – Herb
    Commented Mar 1, 2017 at 2:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.