1

I know that it is, for example, an apache config file, but not the vim. There is no extension or some regexp (for the file content) for which it could be made clear for vim: it should syntax highlight as an apache configuration file.

I think, it would be very fine if somehow some metadata, embedded into file comments, could be given in the file content itself, to advice vim, how to syntax it.

Can it be done?

6
  • It would be good if you could give us an example. In the ftdetect folder you can add some scripts that can parse the entire file (although it is usually advised to restrict to the first few lines for performance reasons) and set the filetype depending of what is found. Commented Apr 19 at 18:57
  • 1
    @VivianDeSmedt I am thinking on some similar as if # vim-meta-info: filetype groovy in the first or last line of the file. And, that would activate the groovy syntax heighlighter even if no other would do. Somewhere I have seen, that for example, tab sizes can be affected on this tricky way (I am not sure if it was vi or emacs or what).
    – peterh
    Commented Apr 19 at 19:03
  • 2
    What you want is called a modeline. See :help modeline.
    – romainl
    Commented Apr 19 at 19:14
  • Do you still have something open in your question? How can we help you further? Otherwise maybe could you accept one of the solution using the v button next to the arrow voting buttons. It allow the question to rest :-) Commented Apr 21 at 14:15
  • 1
    @VivianDeSmedt No, thanks. I think it was not so bad question. Think also to the google hits.
    – peterh
    Commented Apr 21 at 18:08

2 Answers 2

4

some metadata, embedded into file comments, could be given in the file content itself

This is exactly what a modeline does. You can set (some) options for the current buffer from this line.

See :help modeline for the general idea and the syntax.

Your specific question, setting the filetype option from a modeline, is suggested in :help :filetype, last paragraph.

Assuming cfg is the file type you would want to use, the following line near the top or bottom of your configuration file will solve your problem:

# vim: filetype=cfg

or, using the option's short name:

# vim: ft=cfg

Make sure you have :set modeline on and :set modelines (with an 's') is set to a sufficient number of lines.

Note: several comments already suggested modeline and this answer isn't exactly rocket science. Nevertheless, I felt there should be a simple answer next to Vivian's very sophisticated one. A casual reader might miss the simple solution.

2
  • 1
    I personally would spell out filetype (instead of ft) in the modeline.
    – D. Ben Knoble
    Commented Apr 21 at 3:35
  • @D.BenKnoble edited. Funny, I always always always use verbose names in files except in modelines. Time to question my habits.
    – Friedrich
    Commented Apr 21 at 16:00
2

What in Vim set the filetype:

The filetype detection is made of several layers:

  1. $VIMRUTIME/filetype.vim set a number of autocmd to detect the filetype of the buffer
  2. vimfiles/ftdtect/*.vim set another user specific autocmd to detect the filetype of the buffer
  3. The file is parsed for modeline that can set (or not) the filetype of the buffer.

Remark: the first two mechanisms depend on the presence of filetype on in the vimrc (or the absence of vimrc that assumes filetype on).

Remark: the script in the first two mechanism usually use the setfiletype API that set the filetype only if it is not already set.

Remark: the modeline is executed last and override the filetype if present.

Remark: Nothing prevent you to define an autocmd in your vimrc to set the filetype but it is nowadays not the recommended way to do.

Proposition

You could use the second mechanism to define your own autocmd to set the filetype

You could add a ftdtect/metainfo.vim file with the following content:

function! s:getmetatype(line)
  let match = matchlist(a:line, 'vim-meta-info:\s\+filetype\s\+\(\w\+\)')
  if match == []
    return ""
  endif
  return match[1]
endfunction

function SetMetafiletype()
  let line = getline(1)
  let filetype = s:getmetatype(line)
  if filetype != ''
    execute "setfiletype" filetype
  endif

  let line = getline('$')
  let filetype = s:getmetatype(line)
  if filetype != ''
    execute "setfiletype" filetype
  endif
endfunction

autocmd BufNewFile,BufRead * call SetMetafiletype()

When a newfile is read its first line and last line are match against the pattern to detect the filetype that is set if found.

When the following file would be loaded its filetype would be set to groovy:

// vim-meta-info: filetype groovy

class Example {
   static void main(String[] args) {
      println('Hello World');
   }
}

The autocmd is based on the event BufRead so the action can access the full content of the buffer.

The SetMetalfiletype method is called:

  • It check the first (getline(1)) and the last (getline('$')) line of the buffer
  • For each of these lines it check a regular expression (vim-meta-info:\s\+filetype\s\+\(\w\+\))
  • If if match (the result of matchlist is not an empty line) it set the filetype to the first regular expression group (match[1])

Remark: It use the setfiletype API to only set the filetype if it has not already been set.

7
  • 3
    Why re-implement modelines? vim: filetype=groovy works
    – D. Ben Knoble
    Commented Apr 19 at 20:07
  • I suppose the idea is to have some more complex logic at the end (this code is just a example of what is possible in Vim). Commented Apr 19 at 20:09
  • 1
    This a) doesn't answer OP's question, and b) is all magical, without any explanation of what's going on.
    – romainl
    Commented Apr 21 at 9:53
  • 1
    OP is asking about about modelines, nothing more.
    – romainl
    Commented Apr 21 at 14:21
  • 1
    I believe item (1) also requires at least :filetype on
    – D. Ben Knoble
    Commented Apr 21 at 21:41

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.