diff options
Diffstat (limited to 'autoload/polyglot.vim')
-rw-r--r-- | autoload/polyglot.vim | 412 |
1 files changed, 364 insertions, 48 deletions
diff --git a/autoload/polyglot.vim b/autoload/polyglot.vim index 97a83752..ee03e989 100644 --- a/autoload/polyglot.vim +++ b/autoload/polyglot.vim @@ -1,16 +1,70 @@ +""" autoload/polyglot.vim + " Line continuation is used here, remove 'C' from 'cpoptions' let s:cpo_save = &cpo set cpo&vim +func! polyglot#ObserveShebang() + augroup polyglot-observer + au! CursorHold,CursorHoldI,BufWritePost <buffer> + \ if polyglot#Shebang() | au! polyglot-observer CursorHold,CursorHoldI,BufWritePost | endif + augroup END +endfunc + func! polyglot#Shebang() - " Try to detect filetype from shebang - let ft = polyglot#ShebangFiletype() - if ft != "" - let &ft = ft - return 1 + if getline(1) =~# "^#!" + let ft = polyglot#ShebangFiletype() + if ft != "" + let &ft = ft + endif + endif + + if &ft == "" + runtime! scripts.vim endif - return 0 + return &ft != "" +endfunc + +let s:r_hashbang = '^#!\s*\(\S\+\)\s*\(.*\)\s*' +let s:r_envflag = '%(\S\+=\S\+\|-[iS]\|--ignore-environment\|--split-string\)' +let s:r_env = '^\%(\' . s:r_envflag . '\s\+\)*\(\S\+\)' + +func! polyglot#ShebangFiletype() + let l:line1 = getline(1) + + if l:line1 !~# "^#!" + return + endif + + let l:pathrest = matchlist(l:line1, s:r_hashbang) + + if len(l:pathrest) == 0 + return + endif + + let [_, l:path, l:rest; __] = l:pathrest + + let l:script = split(l:path, "/")[-1] + + if l:script == "env" + let l:argspath = matchlist(l:rest, s:r_env) + if len(l:argspath) == 0 + return + endif + + let l:script = l:argspath[1] + endif + + if has_key(s:interpreters, l:script) + return s:interpreters[l:script] + endif + + for interpreter in keys(s:interpreters) + if l:script =~# '^' . interpreter + return s:interpreters[interpreter] + endif + endfor endfunc let s:interpreters = { @@ -83,48 +137,7 @@ let s:interpreters = { \ 'z3': 'smt2', \ 'deno': 'typescript', \ 'ts-node': 'typescript', - \ } - -let s:r_hashbang = '^#!\s*\(\S\+\)\s*\(.*\)\s*' -let s:r_envflag = '%(\S\+=\S\+\|-[iS]\|--ignore-environment\|--split-string\)' -let s:r_env = '^\%(\' . s:r_envflag . '\s\+\)*\(\S\+\)' - -func! polyglot#ShebangFiletype() - let l:line1 = getline(1) - - if l:line1 !~# "^#!" - return - endif - - let l:pathrest = matchlist(l:line1, s:r_hashbang) - - if len(l:pathrest) == 0 - return - endif - - let [_, l:path, l:rest; __] = l:pathrest - - let l:script = split(l:path, "/")[-1] - - if l:script == "env" - let l:argspath = matchlist(l:rest, s:r_env) - if len(l:argspath) == 0 - return - endif - - let l:script = l:argspath[1] - endif - - if has_key(s:interpreters, l:script) - return s:interpreters[l:script] - endif - - for interpreter in keys(s:interpreters) - if l:script =~# '^' . interpreter - return s:interpreters[interpreter] - endif - endfor -endfunc +\ } func! polyglot#DetectInpFiletype() let line = getline(nextnonblank(1)) @@ -382,6 +395,309 @@ func! polyglot#DetectHtmlFiletype() set ft=html | return endfunc + " Restore 'cpoptions' let &cpo = s:cpo_save unlet s:cpo_save + +""" ftdetect/polyglot.vim + +" don't spam the user when Vim is started in Vi compatibility mode +let s:cpo_save = &cpo +set cpo&vim + +" Disable all native vim ftdetect +if exists('g:polyglot_test') + autocmd! +endif + +let s:disabled_packages = {} +let s:new_polyglot_disabled = [] + +if exists('g:polyglot_disabled') + for pkg in g:polyglot_disabled + let base = split(pkg, '\.') + if len(base) > 0 + let s:disabled_packages[pkg] = 1 + call add(s:new_polyglot_disabled, base[0]) + endif + endfor +else + let g:polyglot_disabled_not_set = 1 +endif + +function! s:SetDefault(name, value) + if !exists(a:name) + let {a:name} = a:value + endif +endfunction + +call s:SetDefault('g:markdown_enable_spell_checking', 0) +call s:SetDefault('g:markdown_enable_input_abbreviations', 0) +call s:SetDefault('g:markdown_enable_mappings', 0) + +" Enable jsx syntax by default +call s:SetDefault('g:jsx_ext_required', 0) + +" Needed for sql highlighting +call s:SetDefault('g:javascript_sql_dialect', 'sql') + +" Make csv loading faster +call s:SetDefault('g:csv_start', 1) +call s:SetDefault('g:csv_end', 2) + +" Disable json concealing by default +call s:SetDefault('g:vim_json_syntax_conceal', 0) + +call s:SetDefault('g:filetype_euphoria', 'elixir') + +if !exists('g:python_highlight_all') + call s:SetDefault('g:python_highlight_builtins', 1) + call s:SetDefault('g:python_highlight_builtin_objs', 1) + call s:SetDefault('g:python_highlight_builtin_types', 1) + call s:SetDefault('g:python_highlight_builtin_funcs', 1) + call s:SetDefault('g:python_highlight_builtin_funcs_kwarg', 1) + call s:SetDefault('g:python_highlight_exceptions', 1) + call s:SetDefault('g:python_highlight_string_formatting', 1) + call s:SetDefault('g:python_highlight_string_format', 1) + call s:SetDefault('g:python_highlight_string_templates', 1) + call s:SetDefault('g:python_highlight_indent_errors', 1) + call s:SetDefault('g:python_highlight_space_errors', 1) + call s:SetDefault('g:python_highlight_doctests', 1) + call s:SetDefault('g:python_highlight_func_calls', 1) + call s:SetDefault('g:python_highlight_class_vars', 1) + call s:SetDefault('g:python_highlight_operators', 1) + call s:SetDefault('g:python_highlight_file_headers_as_comments', 1) + call s:SetDefault('g:python_slow_sync', 1) +endif + +" We need it because scripts.vim in vim uses "set ft=" which cannot be +" overridden with setf (and we can't use set ft= so our scripts.vim work) +func! s:Setf(ft) + if &filetype !~# '\<'.a:ft.'\>' + let &filetype = a:ft + endif +endfunc + +" Function used for patterns that end in a star: don't set the filetype if the +" file name matches ft_ignore_pat. +" When using this, the entry should probably be further down below with the +" other StarSetf() calls. +func! s:StarSetf(ft) + if expand("<amatch>") !~ g:ft_ignore_pat && &filetype !~# '\<'.a:ft.'\>' + let &filetype = a:ft + endif +endfunc + +augroup filetypedetect + +" scripts/build inserts here filetype detection autocommands + +au! BufNewFile,BufRead,StdinReadPost * if expand("<afile>") !~ g:ft_ignore_pat | + \ call polyglot#Shebang() | endif + +au BufEnter * if &ft == "" && expand("<afile>") !~ g:ft_ignore_pat | + \ call polyglot#ObserveShebang() | endif + +augroup END + +if !has_key(s:disabled_packages, 'autoindent') + " Code below re-implements sleuth for vim-polyglot + let g:loaded_sleuth = 1 + let g:loaded_foobar = 1 + + " Makes shiftwidth to be synchronized with tabstop by default + if &shiftwidth == &tabstop + let &shiftwidth = 0 + endif + + function! s:guess(lines) abort + let options = {} + let ccomment = 0 + let podcomment = 0 + let triplequote = 0 + let backtick = 0 + let xmlcomment = 0 + let heredoc = '' + let minindent = 10 + let spaces_minus_tabs = 0 + let i = 0 + + for line in a:lines + let i += 1 + + if !len(line) || line =~# '^\W*$' + continue + endif + + if line =~# '^\s*/\*' + let ccomment = 1 + endif + if ccomment + if line =~# '\*/' + let ccomment = 0 + endif + continue + endif + + if line =~# '^=\w' + let podcomment = 1 + endif + if podcomment + if line =~# '^=\%(end\|cut\)\>' + let podcomment = 0 + endif + continue + endif + + if triplequote + if line =~# '^[^"]*"""[^"]*$' + let triplequote = 0 + endif + continue + elseif line =~# '^[^"]*"""[^"]*$' + let triplequote = 1 + endif + + if backtick + if line =~# '^[^`]*`[^`]*$' + let backtick = 0 + endif + continue + elseif &filetype ==# 'go' && line =~# '^[^`]*`[^`]*$' + let backtick = 1 + endif + + if line =~# '^\s*<\!--' + let xmlcomment = 1 + endif + if xmlcomment + if line =~# '-->' + let xmlcomment = 0 + endif + continue + endif + + " This is correct order because both "<<EOF" and "EOF" matches end + if heredoc != '' + if line =~# heredoc + let heredoc = '' + endif + continue + endif + let herematch = matchlist(line, '\C<<\W*\([A-Z]\+\)\s*$') + if len(herematch) > 0 + let heredoc = herematch[1] . '$' + endif + + let spaces_minus_tabs += line[0] == "\t" ? 1 : -1 + + if line[0] == "\t" + setlocal noexpandtab + let &shiftwidth=&tabstop + let b:sleuth_culprit .= ':' . i + return 1 + elseif line[0] == " " + let indent = len(matchstr(line, '^ *')) + if (indent % 2 == 0 || indent % 3 == 0) && indent < minindent + let minindent = indent + endif + endif + endfor + + if minindent < 10 + setlocal expandtab + let &shiftwidth=minindent + let b:sleuth_culprit .= ':' . i + return 1 + endif + + return 0 + endfunction + + function! s:detect_indent() abort + if &buftype ==# 'help' + return + endif + + let b:sleuth_culprit = expand("<afile>:p") + if s:guess(getline(1, 32)) + return + endif + let pattern = sleuth#GlobForFiletype(&filetype) + if len(pattern) == 0 + return + endif + let pattern = '{' . pattern . ',.git,.svn,.hg}' + let dir = expand('%:p:h') + let level = 3 + while isdirectory(dir) && dir !=# fnamemodify(dir, ':h') && level > 0 + " Ignore files from homedir and root + if dir == expand('~') || dir == '/' + unlet b:sleuth_culprit + return + endif + for neighbor in glob(dir . '/' . pattern, 0, 1)[0:level] + let b:sleuth_culprit = neighbor + " Do not consider directories above .git, .svn or .hg + if fnamemodify(neighbor, ":h:t")[0] == "." + let level = 0 + continue + endif + if neighbor !=# expand('%:p') && filereadable(neighbor) + if s:guess(readfile(neighbor, '', 32)) + return + endif + endif + endfor + + let dir = fnamemodify(dir, ':h') + let level -= 1 + endwhile + + unlet b:sleuth_culprit + endfunction + + setglobal smarttab + + function! SleuthIndicator() abort + let sw = &shiftwidth ? &shiftwidth : &tabstop + if &expandtab + return 'sw='.sw + elseif &tabstop == sw + return 'ts='.&tabstop + else + return 'sw='.sw.',ts='.&tabstop + endif + endfunction + + augroup polyglot-sleuth + au! + au FileType * call s:detect_indent() + au User Flags call Hoist('buffer', 5, 'SleuthIndicator') + augroup END + + command! -bar -bang Sleuth call s:detect_indent() +endif + +func! s:verify() + if exists("g:polyglot_disabled_not_set") + if exists("g:polyglot_disabled") + echohl WarningMsg + echo "vim-polyglot: g:polyglot_disabled should be defined before loading vim-polyglot" + echohl None + endif + + unlet g:polyglot_disabled_not_set + endif +endfunc + +au VimEnter * call s:verify() + +" Save polyglot_disabled without postfixes +if exists('g:polyglot_disabled') + let g:polyglot_disabled = s:new_polyglot_disabled +endif + +" restore Vi compatibility settings +let &cpo = s:cpo_save |