The syntax file does syntax highlighting for numbers, string literals, comments, etc. Also maintains a list of valid function names. The plugin does auto-indentation for Meson with two spaces by default. TODO: explicit errors for decimal numbers (right now, it's just unhighlighted), check kwargs, default options, etc.pull/1055/merge
parent
a32716f9fe
commit
ce09c5bb8c
4 changed files with 305 additions and 0 deletions
@ -0,0 +1,3 @@ |
||||
ftdetect sets the filetype |
||||
syntax does Meson syntax highlighting |
||||
plugin does Meson indentation |
@ -0,0 +1,2 @@ |
||||
au BufNewFile,BufRead meson.build set filetype=meson |
||||
au BufNewFile,BufRead meson_options.txt set filetype=meson |
@ -0,0 +1,183 @@ |
||||
" Vim indent file |
||||
" Language: Meson |
||||
" Maintainer: Nirbheek Chauhan <nirbheek.chauhan@gmail.com> |
||||
" Original Authors: David Bustos <bustos@caltech.edu> |
||||
" Bram Moolenaar <Bram@vim.org> |
||||
" Last Change: 2015 Feb 23 |
||||
|
||||
" Only load this indent file when no other was loaded. |
||||
if exists("b:did_indent") |
||||
finish |
||||
endif |
||||
let b:did_indent = 1 |
||||
|
||||
" Some preliminary settings |
||||
setlocal nolisp " Make sure lisp indenting doesn't supersede us |
||||
setlocal autoindent " indentexpr isn't much help otherwise |
||||
|
||||
setlocal indentexpr=GetMesonIndent(v:lnum) |
||||
setlocal indentkeys+==elif,=else,=endforeach,=endif,0) |
||||
|
||||
" Only define the function once. |
||||
if exists("*GetMesonIndent") |
||||
finish |
||||
endif |
||||
let s:keepcpo= &cpo |
||||
set cpo&vim |
||||
|
||||
" Come here when loading the script the first time. |
||||
|
||||
let s:maxoff = 50 " maximum number of lines to look backwards for () |
||||
|
||||
" Force sw=2 sts=2 because that's required by convention |
||||
set shiftwidth=2 |
||||
set softtabstop=2 |
||||
|
||||
function GetMesonIndent(lnum) |
||||
echom getline(line(".")) |
||||
|
||||
" If this line is explicitly joined: If the previous line was also joined, |
||||
" line it up with that one, otherwise add two 'shiftwidth' |
||||
if getline(a:lnum - 1) =~ '\\$' |
||||
if a:lnum > 1 && getline(a:lnum - 2) =~ '\\$' |
||||
return indent(a:lnum - 1) |
||||
endif |
||||
return indent(a:lnum - 1) + (exists("g:mesonindent_continue") ? eval(g:mesonindent_continue) : (shiftwidth() * 2)) |
||||
endif |
||||
|
||||
" If the start of the line is in a string don't change the indent. |
||||
if has('syntax_items') |
||||
\ && synIDattr(synID(a:lnum, 1, 1), "name") =~ "String$" |
||||
return -1 |
||||
endif |
||||
|
||||
" Search backwards for the previous non-empty line. |
||||
let plnum = prevnonblank(v:lnum - 1) |
||||
|
||||
if plnum == 0 |
||||
" This is the first non-empty line, use zero indent. |
||||
return 0 |
||||
endif |
||||
|
||||
" If the previous line is inside parenthesis, use the indent of the starting |
||||
" line. |
||||
" Trick: use the non-existing "dummy" variable to break out of the loop when |
||||
" going too far back. |
||||
call cursor(plnum, 1) |
||||
let parlnum = searchpair('(\|{\|\[', '', ')\|}\|\]', 'nbW', |
||||
\ "line('.') < " . (plnum - s:maxoff) . " ? dummy :" |
||||
\ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" |
||||
\ . " =~ '\\(Comment\\|Todo\\|String\\)$'") |
||||
if parlnum > 0 |
||||
let plindent = indent(parlnum) |
||||
let plnumstart = parlnum |
||||
else |
||||
let plindent = indent(plnum) |
||||
let plnumstart = plnum |
||||
endif |
||||
|
||||
|
||||
" When inside parenthesis: If at the first line below the parenthesis add |
||||
" two 'shiftwidth', otherwise same as previous line. |
||||
" i = (a |
||||
" + b |
||||
" + c) |
||||
call cursor(a:lnum, 1) |
||||
let p = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW', |
||||
\ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :" |
||||
\ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" |
||||
\ . " =~ '\\(Comment\\|Todo\\|String\\)$'") |
||||
if p > 0 |
||||
if p == plnum |
||||
" When the start is inside parenthesis, only indent one 'shiftwidth'. |
||||
let pp = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW', |
||||
\ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :" |
||||
\ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" |
||||
\ . " =~ '\\(Comment\\|Todo\\|String\\)$'") |
||||
if pp > 0 |
||||
return indent(plnum) + (exists("g:pyindent_nested_paren") ? eval(g:pyindent_nested_paren) : shiftwidth()) |
||||
endif |
||||
return indent(plnum) + (exists("g:pyindent_open_paren") ? eval(g:pyindent_open_paren) : (shiftwidth() * 2)) |
||||
endif |
||||
if plnumstart == p |
||||
return indent(plnum) |
||||
endif |
||||
return plindent |
||||
endif |
||||
|
||||
|
||||
" Get the line and remove a trailing comment. |
||||
" Use syntax highlighting attributes when possible. |
||||
let pline = getline(plnum) |
||||
let pline_len = strlen(pline) |
||||
if has('syntax_items') |
||||
" If the last character in the line is a comment, do a binary search for |
||||
" the start of the comment. synID() is slow, a linear search would take |
||||
" too long on a long line. |
||||
if synIDattr(synID(plnum, pline_len, 1), "name") =~ "\\(Comment\\|Todo\\)$" |
||||
let min = 1 |
||||
let max = pline_len |
||||
while min < max |
||||
let col = (min + max) / 2 |
||||
if synIDattr(synID(plnum, col, 1), "name") =~ "\\(Comment\\|Todo\\)$" |
||||
let max = col |
||||
else |
||||
let min = col + 1 |
||||
endif |
||||
endwhile |
||||
let pline = strpart(pline, 0, min - 1) |
||||
endif |
||||
else |
||||
let col = 0 |
||||
while col < pline_len |
||||
if pline[col] == '#' |
||||
let pline = strpart(pline, 0, col) |
||||
break |
||||
endif |
||||
let col = col + 1 |
||||
endwhile |
||||
endif |
||||
|
||||
" If the previous line ended the conditional/loop |
||||
if getline(plnum) =~ '^\s*\(endif\|endforeach\)\>\s*' |
||||
" Maintain indent |
||||
return -1 |
||||
endif |
||||
|
||||
" If the previous line ended with a builtin, indent this line |
||||
if pline =~ '^\s*\(foreach\|if\|else\|elif\)\>\s*' |
||||
return plindent + shiftwidth() |
||||
endif |
||||
|
||||
" If the current line begins with a header keyword, deindent |
||||
if getline(a:lnum) =~ '^\s*\(else\|elif\|endif\|endforeach\)' |
||||
|
||||
" Unless the previous line was a one-liner |
||||
if getline(plnumstart) =~ '^\s*\(foreach\|if\)\>\s*' |
||||
return plindent |
||||
endif |
||||
|
||||
" Or the user has already dedented |
||||
if indent(a:lnum) <= plindent - shiftwidth() |
||||
return -1 |
||||
endif |
||||
|
||||
return plindent - shiftwidth() |
||||
endif |
||||
|
||||
" When after a () construct we probably want to go back to the start line. |
||||
" a = (b |
||||
" + c) |
||||
" here |
||||
if parlnum > 0 |
||||
return plindent |
||||
endif |
||||
|
||||
return -1 |
||||
|
||||
endfunction |
||||
|
||||
let &cpo = s:keepcpo |
||||
unlet s:keepcpo |
||||
|
||||
" vim:sw=2 |
@ -0,0 +1,117 @@ |
||||
" Vim syntax file |
||||
" Language: Meson |
||||
" Maintainer: Nirbheek Chauhan <nirbheek.chauhan@gmail.com> |
||||
" Last Change: 2015 Feb 23 |
||||
" Credits: Zvezdan Petkovic <zpetkovic@acm.org> |
||||
" Neil Schemenauer <nas@meson.ca> |
||||
" Dmitry Vasiliev |
||||
" |
||||
" This version is copied and edited from python.vim |
||||
" It's very basic, and doesn't do many things I'd like it to |
||||
" For instance, it should show errors for syntax that is valid in |
||||
" Python but not in Meson. |
||||
" |
||||
" Optional highlighting can be controlled using these variables. |
||||
" |
||||
" let meson_space_error_highlight = 1 |
||||
" |
||||
|
||||
" For version 5.x: Clear all syntax items. |
||||
" For version 6.x: Quit when a syntax file was already loaded. |
||||
if version < 600 |
||||
syntax clear |
||||
elseif exists("b:current_syntax") |
||||
finish |
||||
endif |
||||
|
||||
" We need nocompatible mode in order to continue lines with backslashes. |
||||
" Original setting will be restored. |
||||
let s:cpo_save = &cpo |
||||
set cpo&vim |
||||
|
||||
" https://github.com/mesonbuild/meson/wiki/Syntax |
||||
syn keyword mesonConditional elif else if endif |
||||
syn keyword mesonRepeat foreach endforeach |
||||
syn keyword mesonOperator and not or |
||||
|
||||
syn match mesonComment "#.*$" contains=mesonTodo,@Spell |
||||
syn keyword mesonTodo FIXME NOTE NOTES TODO XXX contained |
||||
|
||||
" Strings can either be single quoted or triple counted across multiple lines, |
||||
" but always with a ' |
||||
syn region mesonString |
||||
\ start="\z('\)" end="\z1" skip="\\\\\|\\\z1" |
||||
\ contains=mesonEscape,@Spell |
||||
syn region mesonString |
||||
\ start="\z('''\)" end="\z1" keepend |
||||
\ contains=mesonEscape,mesonSpaceError,@Spell |
||||
|
||||
syn match mesonEscape "\\[abfnrtv'\\]" contained |
||||
syn match mesonEscape "\\\o\{1,3}" contained |
||||
syn match mesonEscape "\\x\x\{2}" contained |
||||
syn match mesonEscape "\%(\\u\x\{4}\|\\U\x\{8}\)" contained |
||||
" Meson allows case-insensitive Unicode IDs: http://www.unicode.org/charts/ |
||||
syn match mesonEscape "\\N{\a\+\%(\s\a\+\)*}" contained |
||||
syn match mesonEscape "\\$" |
||||
|
||||
" Meson only supports integer numbers |
||||
" https://github.com/mesonbuild/meson/wiki/Syntax#numbers |
||||
syn match mesonNumber "\<\d\+\>" |
||||
|
||||
" booleans |
||||
syn keyword mesonConstant false true |
||||
|
||||
" Built-in functions |
||||
syn keyword mesonBuiltin add_global_arguments add_languages benchmark |
||||
syn keyword mesonBuiltin build_target configuration_data configure_file |
||||
syn keyword mesonBuiltin custom_target declare_dependency dependency |
||||
syn keyword mesonBuiltin error executable find_program find_library |
||||
syn keyword mesonBuiltin files generator get_option get_variable |
||||
syn keyword mesonBuiltin gettext import include_directories install_data |
||||
syn keyword mesonBuiltin install_headers install_man install_subdir |
||||
syn keyword mesonBuiltin is_subproject is_variable jar library message |
||||
syn keyword mesonBuiltin project run_command run_target set_variable |
||||
syn keyword mesonBuiltin shared_library static_library subdir subproject |
||||
syn keyword mesonBuiltin test vcs_tag |
||||
|
||||
if exists("meson_space_error_highlight") |
||||
" trailing whitespace |
||||
syn match mesonSpaceError display excludenl "\s\+$" |
||||
" mixed tabs and spaces |
||||
syn match mesonSpaceError display " \+\t" |
||||
syn match mesonSpaceError display "\t\+ " |
||||
endif |
||||
|
||||
if version >= 508 || !exists("did_meson_syn_inits") |
||||
if version <= 508 |
||||
let did_meson_syn_inits = 1 |
||||
command -nargs=+ HiLink hi link <args> |
||||
else |
||||
command -nargs=+ HiLink hi def link <args> |
||||
endif |
||||
|
||||
" The default highlight links. Can be overridden later. |
||||
HiLink mesonStatement Statement |
||||
HiLink mesonConditional Conditional |
||||
HiLink mesonRepeat Repeat |
||||
HiLink mesonOperator Operator |
||||
HiLink mesonComment Comment |
||||
HiLink mesonTodo Todo |
||||
HiLink mesonString String |
||||
HiLink mesonEscape Special |
||||
HiLink mesonNumber Number |
||||
HiLink mesonBuiltin Function |
||||
HiLink mesonConstant Number |
||||
if exists("meson_space_error_highlight") |
||||
HiLink mesonSpaceError Error |
||||
endif |
||||
|
||||
delcommand HiLink |
||||
endif |
||||
|
||||
let b:current_syntax = "meson" |
||||
|
||||
let &cpo = s:cpo_save |
||||
unlet s:cpo_save |
||||
|
||||
" vim:set sw=2 sts=2 ts=8 noet: |
Loading…
Reference in new issue