-*options.txt* For Vim version 9.2. Last change: 2026 May 17
+*options.txt* For Vim version 9.2. Last change: 2026 May 18
VIM REFERENCE MANUAL by Bram Moolenaar
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
+ As an exception, `set nomodeline` is honored from within a modeline
+ even when 'modelinestrict' is on. Other forms (`set modeline=0`,
+ `set modeline!`, `set invmodeline`) are still silently ignored.
+ This lets a file disable further modeline processing for itself.
+
The behaviour of 'modeline', 'modelinestrict' and 'modelineexpr' is
as follows:
* if it can be changed.
*/
static int
-validate_opt_idx(int opt_idx, int opt_flags, long_u flags, char **errmsg)
+validate_opt_idx(
+ int opt_idx,
+ int opt_flags,
+ long_u flags,
+ char **errmsg,
+ set_prefix_T prefix)
{
// Skip all options that are not window-local (used when showing
// an already loaded buffer in a window).
}
// When 'modelinestrict' is on, only whitelisted options may be
// set from a modeline. Silently skip others.
- if (p_mlstr && opt_idx >= 0
- && !is_modeline_whitelisted(options[opt_idx].fullname))
- return FAIL;
+ if (p_mlstr && opt_idx >= 0)
+ {
+ // special case: allow disabling modeline
+ if (options[opt_idx].indir == PV_ML && prefix == PREFIX_NO)
+ return OK;
+ else if (!is_modeline_whitelisted(options[opt_idx].fullname))
+ return FAIL;
+ }
#ifdef FEAT_DIFF
// In diff mode some options are overruled. This avoids that
// 'foldmethod' becomes "marker" instead of "diff" and that
}
// Make sure the option value can be changed.
- if (validate_opt_idx(opt_idx, opt_flags, flags, &errmsg) == FAIL)
+ if (validate_opt_idx(opt_idx, opt_flags, flags, &errmsg, prefix) == FAIL)
goto skip;
int cp_val = p_cp;
let &modeline = modeline
endfunc
+func Test_modeline_nomodeline_with_modelinestrict()
+ let modeline = &modeline
+ let modelinestrict = &modelinestrict
+ let modelines = &modelines
+ set modelinestrict modeline modelines=5
+ let ml_before = &g:modeline
+
+ call writefile(['# vim: set nomodeline:', 'line2'], 'Xnoml', 'D')
+ split Xnoml
+ call assert_equal(0, &l:modeline, 'b_p_ml should be off')
+ call assert_equal(ml_before, &g:modeline, 'global p_ml must not change')
+ bwipe!
+
+ " A fresh buffer must still inherit the unchanged global default
+ new
+ call assert_equal(ml_before, &l:modeline,
+ \ 'new buffer should inherit unchanged global')
+ bwipe!
+
+ let &modeline = modeline
+ let &modelinestrict = modelinestrict
+ let &modelines = modelines
+endfunc
+
+func Test_modeline_nomodeline_skips_trailing_modelines()
+ let modeline = &modeline
+ let modelinestrict = &modelinestrict
+ let ts_save = &ts
+ set modeline modelinestrict ts=8
+
+ " Line 1 disables modelines; the trailing modeline must therefore
+ " never execute even though 'tabstop' is whitelisted.
+ call writefile([
+ \ '# vim: set nomodeline :',
+ \ 'middle line 1',
+ \ 'middle line 2',
+ \ 'middle line 3',
+ \ '# vim: set ts=99 :',
+ \ ], 'Xmodeline_disable_top', 'D')
+ split Xmodeline_disable_top
+
+ call assert_equal(0, &l:modeline,
+ \ 'top modeline must have disabled b_p_ml')
+ call assert_equal(8, &ts,
+ \ 'trailing modeline must not have run after nomodeline')
+
+ bwipe!
+ let &modeline = modeline
+ let &modelinestrict = modelinestrict
+ let &ts = ts_save
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab