I have my own detection of the file indent settings based on the file contents. All good and works ok for my needs but...

When I open a c source file of the vim itself it overrides options set by modeline:

/* vi:set ts=8 sts=4 sw=4 noet:
 * VIM - Vi IMproved›   by Bram Moolenaar
 * Do ":help uganda"  in Vim to read copying and usage conditions.
 * Do ":help credits" in Vim to see a list of people who contributed.
 * See README.txt for an overview of the Vim source code.

I would like not to set indent options based on the file contents(in my func) if file has corresponding modeline options set.

So is there a way I can detect it in vimscript?

  • Hmmm, I can probably detect modeline myself in the same function...
    – Maxim Kim
    Commented Aug 12, 2021 at 10:23
  • @D.BenKnoble I don't want to turn off the modeline -- I would like to conform to the settings provided there (PRs for vim)
    – Maxim Kim
    Commented Aug 12, 2021 at 12:08
  • 1
    ohhh I see—you want the modeline to take precedence. Hm. Perhaps some result of execute('verbose setlocal xxx?') can be parsed?
    – D. Ben Knoble
    Commented Aug 12, 2021 at 13:04

2 Answers 2


Assuming your locale is English-like, the following should work:

:echo (execute('verbose setlocal ts?')->split('\n')[-1] =~# 'Last set from modeline line \d\+')
        \ ? 'set from modeline' 
        \ : 'set elsewhere'

Not sure about handling different locales. For example, my system has LC_ALL=fr_FR.UTF-8, so the message appears differently:

    Modifié la dernière fois dans ligne de mode ligne 41

And the obvious function wrapper:

function IsSetFromModeline(opts) abort
  return mapnew(a:opts, {_, v -> execute(printf('verbose setlocal %s?', v))->split('\n')[-1] =~# 'Last set from modeline line \d\+'})

echo IsSetFromModeline(['tabstop', 'shiftwidth'])

You can install an OptionSet autocommand. If an option was triggered by a modeline, it will be in the special v variable: v:option_type. Note: there are a whole bunch of v:option... variables for all different kinds.

You could simply test the autocommand using the following example:

au OptionSet * echomsg printf("OptionSet: %s: option: %s old: %s new: %s, type: %s", strftime('%T'), expand("<amatch>"), v:option_old, v:option_new, v:option_command)

Another work-around would be to simply make Vim reprocess the BufReadPost autocommands, which should re-evaluate the modeline:

doauto BufReadPost <filename>

Not sure what would work better for your use-case.

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.