From 0801eac01aab5940fc1e4409ba749383cc353bc2 Mon Sep 17 00:00:00 2001 From: Adam Stankiewicz Date: Thu, 23 Mar 2017 11:28:19 +0100 Subject: [PATCH] Update --- after/ftplugin/terraform.vim | 7 + after/syntax/c.vim | 10 + after/syntax/cpp.vim | 1 + after/syntax/html.vim | 16 + after/syntax/yaml.vim | 8 +- autoload/dart.vim | 81 ++ autoload/rubycomplete.vim | 12 +- autoload/xml/aria.vim | 240 +++++- autoload/xml/html5.vim | 45 +- ftdetect/polyglot.vim | 21 +- ftplugin/blade.vim | 3 +- ftplugin/dart.vim | 4 +- .../vue.vim => ftplugin/litcoffee.vim | 4 +- ftplugin/nginx.vim | 4 + ftplugin/vue.vim | 2 + indent/blade.vim | 94 +- indent/erlang.vim | 40 +- indent/eruby.vim | 1 + indent/haskell.vim | 58 +- indent/javascript.vim | 212 ++--- indent/litcoffee.vim | 26 + indent/ruby.vim | 808 +++++++++++------- indent/typescript.vim | 752 +++++++--------- syntax/blade.vim | 10 +- syntax/coffee.vim | 2 +- syntax/erlang.vim | 219 +++-- syntax/haskell.vim | 6 +- syntax/html.vim | 22 +- syntax/html/aria.vim | 25 +- syntax/html/electron.vim | 19 + syntax/javascript.vim | 27 +- syntax/javascript/html5.vim | 3 + syntax/layout/nginx.vim | 103 ++- syntax/litcoffee.vim | 27 + syntax/markdown.vim | 4 +- syntax/modules/afcgi.vim | 4 +- syntax/modules/geoip2.vim | 43 +- syntax/nginx.vim | 150 +++- syntax/plantuml.vim | 4 +- syntax/pug.vim | 12 +- syntax/swift.vim | 2 +- syntax/terraform.vim | 64 +- syntax/typescript.vim | 4 +- syntax/vala.vim | 14 +- syntax/vue.vim | 60 +- 45 files changed, 2015 insertions(+), 1258 deletions(-) rename after/ftplugin/vue.vim => ftplugin/litcoffee.vim (59%) create mode 100644 indent/litcoffee.vim create mode 100644 syntax/html/electron.vim create mode 100644 syntax/litcoffee.vim diff --git a/after/ftplugin/terraform.vim b/after/ftplugin/terraform.vim index f495e58..17115b1 100644 --- a/after/ftplugin/terraform.vim +++ b/after/ftplugin/terraform.vim @@ -18,4 +18,11 @@ if g:terraform_align && exists(':Tabularize') endfunction endif +" Match the identation put in place by Hashicorp and :TerraformFmt, https://github.com/hashivim/vim-terraform/issues/21 +if get(g:, "terraform_align", 1) + setlocal tabstop=2 + setlocal softtabstop=2 + setlocal shiftwidth=2 +endif + endif diff --git a/after/syntax/c.vim b/after/syntax/c.vim index aa4a31e..8cec90f 100644 --- a/after/syntax/c.vim +++ b/after/syntax/c.vim @@ -24,6 +24,16 @@ syn match cCustomParen "(" contains=cParen contains=cCppParen syn match cCustomFunc "\w\+\s*(\@=" contains=cCustomParen hi def link cCustomFunc Function +" ----------------------------------------------------------------------------- +" Highlight member variable names. +" ----------------------------------------------------------------------------- +if exists('g:cpp_member_variable_highlight') && g:cpp_member_variable_highlight + syn match cCustomDot "\." contained + syn match cCustomPtr "->" contained + syn match cCustomMemVar "\(\.\|->\)\w\+" contains=cCustomDot,cCustomPtr + hi def link cCustomMemVar Function +endif + " ----------------------------------------------------------------------------- " Source: aftersyntaxc.vim " ----------------------------------------------------------------------------- diff --git a/after/syntax/cpp.vim b/after/syntax/cpp.vim index 99d9f18..4faa0f6 100644 --- a/after/syntax/cpp.vim +++ b/after/syntax/cpp.vim @@ -557,6 +557,7 @@ syntax keyword cppSTLios defaultfloat syntax keyword cppSTLios endl syntax keyword cppSTLios ends syntax keyword cppSTLios fixed +syntax keyword cppSTLios floatfield syntax keyword cppSTLios flush syntax keyword cppSTLios get_money syntax keyword cppSTLios get_time diff --git a/after/syntax/html.vim b/after/syntax/html.vim index ab99117..43c0c41 100644 --- a/after/syntax/html.vim +++ b/after/syntax/html.vim @@ -34,6 +34,22 @@ syn region ShaderScript \ end=""me=s-1 \ contains=@GLSL,htmlScriptTag,@htmlPreproc +endif +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'html5') == -1 + +" Vim syntax file +" Language: HTML (version 5.1) +" Last Change: 2017 Feb 15 +" License: Public domain +" (but let me know if you like :) ) +" +" Maintainer: Kao, Wei-Ko(othree) ( othree AT gmail DOT com ) + +" Comment +" https://github.com/w3c/html/issues/694 +syntax region htmlComment start=++ contains=@Spell +syntax region htmlComment start=++ + endif if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'less') == -1 diff --git a/after/syntax/yaml.vim b/after/syntax/yaml.vim index 7f4808d..78983cc 100644 --- a/after/syntax/yaml.vim +++ b/after/syntax/yaml.vim @@ -21,9 +21,7 @@ if version < 600 endif syntax clear -syn match yamlDelimiter "[:,-]" syn match yamlBlock "[\[\]\{\}\|\>]" -syn match yamlOperator "[?^+-]\|=>" syn region yamlComment start="\#" end="$" syn match yamlIndicator "#YAML:\S\+" @@ -41,10 +39,11 @@ syn keyword yamlConstant TRUE True true YES Yes yes ON On on syn keyword yamlConstant FALSE False false NO No no OFF Off off syn match yamlKey "^\s*\zs\S\+\ze\s*:" +syn match yamlKey "^\s*-\s*\zs\S\+\ze\s*:" syn match yamlAnchor "&\S\+" syn match yamlAlias "*\S\+" -" Setupt the hilighting links +" Setup the highlighting links hi link yamlConstant Keyword hi link yamlIndicator PreCondit @@ -55,10 +54,7 @@ hi link yamlType Type hi link yamlComment Comment hi link yamlBlock Operator -hi link yamlOperator Operator -hi link yamlDelimiter Delimiter hi link yamlString String hi link yamlEscape Special - endif diff --git a/autoload/dart.vim b/autoload/dart.vim index df341b4..9f04fcc 100644 --- a/autoload/dart.vim +++ b/autoload/dart.vim @@ -68,5 +68,86 @@ function! dart#tojs(q_args) abort endif endfunction +" Finds the path to `uri`. +" +" If the file is a package: uri, looks for a .packages file to resolve the path. +" If the path cannot be resolved, or is not a package: uri, returns the +" original. +function! dart#resolveUri(uri) abort + if a:uri !~ 'package:' + return a:uri + endif + let package_name = substitute(a:uri, 'package:\(\w\+\)\/.*', '\1', '') + let [found, package_map] = s:PackageMap() + if !found + call s:error('cannot find .packages file') + return a:uri + endif + if !has_key(package_map, package_name) + call s:error('no package mapping for '.package_name) + return a:uri + endif + let package_lib = package_map[package_name] + return substitute(a:uri, + \ 'package:'.package_name, + \ escape(package_map[package_name], '\'), + \ '') +endfunction + +" A map from package name to lib directory parse from a '.packages' file. +" +" Returns [found, package_map] +function! s:PackageMap() abort + let [found, dot_packages] = s:DotPackagesFile() + if !found + return [v:false, {}] + endif + let dot_packages_dir = fnamemodify(dot_packages, ':p:h') + let lines = readfile(dot_packages) + let map = {} + for line in lines + if line =~ '\s*#' + continue + endif + let package = substitute(line, ':.*$', '', '') + let lib_dir = substitute(line, '^[^:]*:', '', '') + if lib_dir =~ 'file:/' + let lib_dir = substitute(lib_dir, 'file://', '', '') + if lib_dir =~ '/[A-Z]:/' + let lib_dir = lib_dir[1:] + endif + else + let lib_dir = resolve(dot_packages_dir.'/'.lib_dir) + endif + if lib_dir =~ '/$' + let lib_dir = lib_dir[:len(lib_dir) - 2] + endif + let map[package] = lib_dir + endfor + return [v:true, map] +endfunction + +" Finds a file name '.packages' in the cwd, or in any directory above the open +" file. +" +" Returns [found, file]. +function! s:DotPackagesFile() abort + if filereadable('.packages') + return [v:true, '.packages'] + endif + let dir_path = expand('%:p:h') + while v:true + let file_path = dir_path.'/.packages' + if filereadable(file_path) + return [v:true, file_path] + endif + let parent = fnamemodify(dir_path, ':h') + if dir_path == parent + break + endif + let dir_path = parent + endwhile + return [v:false, ''] +endfunction endif diff --git a/autoload/rubycomplete.vim b/autoload/rubycomplete.vim index 973be8e..8cb73fd 100644 --- a/autoload/rubycomplete.vim +++ b/autoload/rubycomplete.vim @@ -589,11 +589,13 @@ class VimRubyCompletion # {{{ main completion code def self.preload_rails a = VimRubyCompletion.new - require 'Thread' - Thread.new(a) do |b| - begin - b.load_rails - rescue + if VIM::evaluate("has('nvim')") == 0 + require 'thread' + Thread.new(a) do |b| + begin + b.load_rails + rescue + end end end a.load_rails diff --git a/autoload/xml/aria.vim b/autoload/xml/aria.vim index 8974526..2a3c88f 100644 --- a/autoload/xml/aria.vim +++ b/autoload/xml/aria.vim @@ -3,33 +3,220 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'html5') == -1 " Vim completion for WAI-ARIA data file " Language: HTML + WAI-ARIA " Maintainer: othree -" Last Change: 2010 Sep 09 +" Last Change: 2017 Mar 07 " WAI_ARIA: {{{ -" Ref: http://www.w3.org/TR/wai-aria/ -" Version: Draft 15 December 2009 +" Ref: https://www.w3.org/TR/wai-aria-1.1/ +" Version: W3C Candidate Recommendation 27 October 2016 let abstract_role = {} let role_attributes = {} let default_role = {} -" Ref: http://www.w3.org/TR/wai-aria/roles -" Version: Draft 15 December 2009 -let widget_role = ['alert', 'alertdialog', 'button', 'checkbox', 'combobox', 'dialog', 'gridcell', 'link', 'log', 'marquee', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'option', 'progressbar', 'radio', 'radiogroup', 'scrollbar', 'slider', 'spinbutton', 'status', 'tab', 'tabpanel', 'textbox', 'timer', 'tooltip', 'treeitem', 'combobox', 'grid', 'listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'] -let document_structure = ['article', 'columnheader', 'definition', 'directory', 'document', 'group', 'heading', 'img', 'list', 'listitem', 'math', 'note', 'presentation', 'region', 'row', 'rowheader', 'separator'] -let landmark_role = ['application', 'banner', 'complementary', 'contentinfo', 'form', 'main', 'navigation', 'search'] -let dpub_role = ['dpub-abstract', 'dpub-afterword', 'dpub-appendix', 'dpub-biblioentry', 'dpub-bibliography', 'dpub-biblioref', 'dpub-chapter', 'dpub-cover', 'dpub-epilogue', 'dpub-footnote', 'dpub-footnotes', 'dpub-foreword', 'dpub-glossary', 'dpub-glossdef', 'dpub-glossref', 'dpub-glossterm', 'dpub-index', 'dpub-locator', 'dpub-noteref', 'dpub-notice', 'dpub-pagebreak', 'dpub-pagelist', 'dpub-part', 'dpub-preface', 'dpub-prologue', 'dpub-pullquote', 'dpub-qna', 'dpub-subtitle', 'dpub-tip', 'dpub-title', 'dpub-toc'] +" Ref: https://www.w3.org/TR/wai-aria-1.1/#roles_categorization +" Version: W3C Candidate Recommendation 27 October 2016 +let widget_role = [ + \ 'alert', + \ 'alertdialog', + \ 'button', + \ 'checkbox', + \ 'combobox', + \ 'dialog', + \ 'gridcell', + \ 'link', + \ 'log', + \ 'marquee', + \ 'menuitem', + \ 'menuitemcheckbox', + \ 'menuitemradio', + \ 'option', + \ 'progressbar', + \ 'radio', + \ 'radiogroup', + \ 'scrollbar', + \ 'searchbox', + \ 'slider', + \ 'spinbutton', + \ 'status', + \ 'switch', + \ 'tab', + \ 'tabpanel', + \ 'textbox', + \ 'timer', + \ 'tooltip', + \ 'treeitem', + \ 'combobox', + \ 'grid', + \ 'listbox', + \ 'menu', + \ 'menubar', + \ 'radiogroup', + \ 'tablist', + \ 'tree', + \ 'treegrid' +\ ] + +let document_structure = [ + \ 'article', + \ 'cell', + \ 'columnheader', + \ 'definition', + \ 'directory', + \ 'document', + \ 'feed', + \ 'figure', + \ 'group', + \ 'heading', + \ 'img', + \ 'list', + \ 'listitem', + \ 'math', + \ 'none', + \ 'note', + \ 'presentation', + \ 'region', + \ 'row', + \ 'rowheader', + \ 'separator', + \ 'table', + \ 'term' +\ ] + +let landmark_role = [ + \ 'application', + \ 'banner', + \ 'complementary', + \ 'contentinfo', + \ 'form', + \ 'main', + \ 'navigation', + \ 'search' +\ ] + +" Ref: https://www.w3.org/TR/dpub-aria-1.0/ +" Version: W3C Candidate Recommendation 15 December 2016 +let dpub_role = [ + \ 'dpub-abstract', + \ 'dpub-afterword', + \ 'dpub-appendix', + \ 'dpub-biblioentry', + \ 'dpub-bibliography', + \ 'dpub-biblioref', + \ 'dpub-chapter', + \ 'dpub-cover', + \ 'dpub-epilogue', + \ 'dpub-footnote', + \ 'dpub-footnotes', + \ 'dpub-foreword', + \ 'dpub-glossary', + \ 'dpub-glossdef', + \ 'dpub-glossref', + \ 'dpub-glossterm', + \ 'dpub-index', + \ 'dpub-locator', + \ 'dpub-noteref', + \ 'dpub-notice', + \ 'dpub-pagebreak', + \ 'dpub-pagelist', + \ 'dpub-part', + \ 'dpub-preface', + \ 'dpub-prologue', + \ 'dpub-pullquote', + \ 'dpub-qna', + \ 'dpub-subtitle', + \ 'dpub-tip', + \ 'dpub-title', + \ 'dpub-toc' +\ ] + let role = extend(widget_role, document_structure) let role = extend(role, landmark_role) let role = extend(role, dpub_role) -" http://www.w3.org/TR/wai-aria/states_and_properties#state_prop_taxonomy -"let global_states_and_properties = {'aria-atomic': ['true', 'false'], 'aria-busy': ['true', 'false'], 'aria-controls': [], 'aria-describedby': [], 'aria-disabled': ['true', 'false'], 'aria-dropeffect': ['copy', 'move', 'link', 'execute', 'popup', 'none'], 'aria-flowto': [], 'aria-grabbed': ['true', 'false', 'undefined'], 'aria-haspopup': ['true', 'false'], 'aria-hidden': ['true', 'false'], 'aria-invalid': ['grammar', 'spelling', 'true', 'false'], 'aria-label': [], 'aria-labelledby': [], 'aria-live': ['off', 'polite', 'assertive'], 'aria-owns': [], 'aria-relevant': ['additions', 'removals', 'text', 'all']} -let widget_attributes = {'aria-autocomplete': ['inline', 'list', 'both', 'none'], 'aria-checked': ['true', 'false', 'mixed', 'undefined'], 'aria-disabled': ['true', 'false'], 'aria-expanded': ['true', 'false', 'undefined'], 'aria-haspopup': ['true', 'false'], 'aria-hidden': ['true', 'false'], 'aria-invalid': ['grammar', 'spelling', 'true', 'false'], 'aria-label': [], 'aria-level': [], 'aria-multiline': ['true', 'false'], 'aria-multiselectable': ['true', 'false'], 'aria-orientation': ['horizontal', 'vertical'], 'aria-pressed': ['true', 'false', 'mixed', 'undefined'], 'aria-readonly': ['true', 'false'], 'aria-required': ['true', 'false'], 'aria-selected': ['true', 'false', 'undefined'], 'aria-sort': ['ascending', 'descending', 'none', 'other'], 'aria-valuemax': [], 'aria-valuemin': [], 'aria-valuenow': [], 'aria-valuetext': []} -let live_region_attributes = {'aria-atomic': ['true', 'false'], 'aria-busy': ['true', 'false'], 'aria-live': ['off', 'polite', 'assertive'], 'aria-relevant': ['additions', 'removals', 'text', 'all', 'additions text']} -let drag_and_drop_attributes = {'aria-dropeffect': ['copy', 'move', 'link', 'execute', 'popup', 'none'], 'aria-grabbed': ['true', 'false', 'undefined']} -let relationship_attributes = {'aria-activedescendant': [], 'aria-controls': [], 'aria-describedby': [], 'aria-flowto': [], 'aria-labelledby': [], 'aria-owns': [], 'aria-posinset': [], 'aria-setsize': []} -let aria_attributes = widget_attributes +" https://www.w3.org/TR/wai-aria-1.1/#states_and_properties +let global_states_and_properties = { + \ 'aria-atomic': ['true', 'false'], + \ 'aria-busy': ['true', 'false'], + \ 'aria-controls': [], + \ 'aria-current': [], + \ 'aria-describedby': [], + \ 'aria-disabled': ['true', 'false'], + \ 'aria-dropeffect': ['copy', 'move', 'link', 'execute', 'popup', 'none'], + \ 'aria-errormessage': [], + \ 'aria-flowto': [], + \ 'aria-grabbed': ['true', 'false', 'undefined'], + \ 'aria-haspopup': ['true', 'false'], + \ 'aria-hidden': ['true', 'false'], + \ 'aria-invalid': ['grammar', 'spelling', 'true', 'false'], + \ 'aria-keyshortcuts': [], + \ 'aria-label': [], + \ 'aria-labelledby': [], + \ 'aria-live': ['off', 'polite', 'assertive'], + \ 'aria-owns': [], + \ 'aria-relevant': ['additions', 'removals', 'text', 'all'], + \ 'aria-roledescription': [], +\ } + +let widget_attributes = { + \ 'aria-autocomplete': ['inline', 'list', 'both', 'none'], + \ 'aria-checked': ['true', 'false', 'mixed', 'undefined'], + \ 'aria-disabled': ['true', 'false'], + \ 'aria-errormessage': [], + \ 'aria-expanded': ['true', 'false', 'undefined'], + \ 'aria-haspopup': ['true', 'false'], + \ 'aria-hidden': ['true', 'false'], + \ 'aria-invalid': ['grammar', 'spelling', 'true', 'false'], + \ 'aria-label': [], + \ 'aria-level': [], + \ 'aria-modal': ['true', 'false'], + \ 'aria-multiline': ['true', 'false'], + \ 'aria-multiselectable': ['true', 'false'], + \ 'aria-orientation': ['horizontal', 'vertical'], + \ 'aria-placeholder': [], + \ 'aria-pressed': ['true', 'false', 'mixed', 'undefined'], + \ 'aria-readonly': ['true', 'false'], + \ 'aria-required': ['true', 'false'], + \ 'aria-selected': ['true', 'false', 'undefined'], + \ 'aria-sort': ['ascending', 'descending', 'none', 'other'], + \ 'aria-valuemax': [], + \ 'aria-valuemin': [], + \ 'aria-valuenow': [], + \ 'aria-valuetext': [] +\ } + +let live_region_attributes = { + \ 'aria-atomic': ['true', 'false'], + \ 'aria-busy': ['true', 'false'], + \ 'aria-live': ['off', 'polite', 'assertive'], + \ 'aria-relevant': ['additions', 'removals', 'text', 'all', 'additions text'] +\ } + +let drag_and_drop_attributes = { + \ 'aria-dropeffect': ['copy', 'move', 'link', 'execute', 'popup', 'none'], + \ 'aria-grabbed': ['true', 'false', 'undefined'] +\ } + +let relationship_attributes = { + \ 'aria-activedescendant': [], + \ 'aria-colcount': [], + \ 'aria-colindex': [], + \ 'aria-colspan': [], + \ 'aria-controls': [], + \ 'aria-describedby': [], + \ 'aria-details': [], + \ 'aria-errormessage': [], + \ 'aria-flowto': [], + \ 'aria-labelledby': [], + \ 'aria-owns': [], + \ 'aria-posinset': [], + \ 'aria-rowcount': [], + \ 'aria-rowindex': [], + \ 'aria-rowspan': [], + \ 'aria-setsize': [] +\ } + +let aria_attributes = global_states_and_properties +let aria_attributes = extend(aria_attributes, widget_attributes) let aria_attributes = extend(aria_attributes, live_region_attributes) let aria_attributes = extend(aria_attributes, drag_and_drop_attributes) let aria_attributes = extend(aria_attributes, relationship_attributes) @@ -84,6 +271,8 @@ let role_attributes['status'] = abstract_role['composite'] + role_attributes['re let role_attributes['tab'] = abstract_role['sectionhead'] + abstract_role['widget'] + ['aria-selected'] let role_attributes['tabpanel'] = role_attributes['region'] let role_attributes['textbox'] = abstract_role['input'] + ['aria-autocomplete', 'aria-multiline', 'aria-readonly', 'aria-required'] +let role_attributes['searchbox'] = role_attributes['textbox'] +let role_attributes['switch'] = role_attributes['checkbox'] let role_attributes['timer'] = role_attributes['status'] let role_attributes['tooltip'] = abstract_role['section'] let role_attributes['treeitem'] = role_attributes['listitem'] + role_attributes['option'] @@ -101,16 +290,22 @@ let role_attributes['treegrid'] = role_attributes['grid'] + role_attributes['tre let role_attributes['document'] = abstract_role['structure'] + ['aria-expanded'] let role_attributes['article'] = role_attributes['document'] + role_attributes['region'] +let role_attributes['cell'] = abstract_role['section'] + ['aria-colindex', 'aria-colspan', 'aria-rowindex', 'aria-rowspan'] let role_attributes['columnheader'] = role_attributes['gridcell'] + abstract_role['sectionhead'] + ['aria-sort'] let role_attributes['definition'] = abstract_role['section'] +let role_attributes['feed'] = role_attributes['list'] +let role_attributes['figure'] = abstract_role['section'] let role_attributes['heading'] = abstract_role['sectionhead'] + ['aria-level'] let role_attributes['img'] = abstract_role['section'] let role_attributes['math'] = abstract_role['section'] let role_attributes['note'] = abstract_role['section'] let role_attributes['presentation'] = abstract_role['structure'] +let role_attributes['none'] = role_attributes['presentation'] let role_attributes['row'] = role_attributes['group'] + ['aria-level', 'aria-selected'] let role_attributes['rowheader'] = role_attributes['gridcell'] + abstract_role['sectionhead'] let role_attributes['separator'] = abstract_role['structure'] + ['aria-expanded'] +let role_attributes['table'] = abstract_role['section'] + ['aria-colcount', 'aria-rowcount'] +let role_attributes['term'] = abstract_role['section'] " Landmark Roles let role_attributes['application'] = abstract_role['landmark'] @@ -126,19 +321,30 @@ let role_attributes['search'] = abstract_role['landmark'] let aria_attributes_value = { \ 'aria-autocomplete': ['ID', ''], \ 'aria-checked': ['Token', ''], + \ 'aria-colcount': ['Number', ''], + \ 'aria-colindex': ['Number', ''], + \ 'aria-colspan': ['Number', ''], \ 'aria-disabled': ['true/false', ''], + \ 'aria-errormessage': ['ID', ''], \ 'aria-expanded': ['Token', ''], - \ 'aria-haspopup': ['true/false', ''], + \ 'aria-haspopup': ['Token', ''], \ 'aria-hidden': ['true/false', ''], \ 'aria-invalid': ['Token', ''], + \ 'aria-keyshortcuts': ['String', ''], \ 'aria-label': ['String', ''], \ 'aria-level': ['Int', ''], + \ 'aria-modal': ['true/false', ''], \ 'aria-multiline': ['true/false', ''], \ 'aria-multiselectable': ['true/false', ''], \ 'aria-orientation': ['Token', ''], + \ 'aria-placeholder': ['String', ''], \ 'aria-pressed': ['Token', ''], \ 'aria-readonly': ['true/false', ''], \ 'aria-required': ['true/false', ''], + \ 'aria-roledescription': ['String', ''], + \ 'aria-rowcount': ['Number', ''], + \ 'aria-rowindex': ['Number', ''], + \ 'aria-rowspan': ['Number', ''], \ 'aria-selected': ['Token', ''], \ 'aria-sort': ['Token', ''], \ 'aria-valuemax': ['Number', ''], diff --git a/autoload/xml/html5.vim b/autoload/xml/html5.vim index 12c6136..73b24a4 100644 --- a/autoload/xml/html5.vim +++ b/autoload/xml/html5.vim @@ -80,6 +80,9 @@ let attributes_value = { \ 'accept-charset': ['Charset', ''], \ 'accesskey': ['Character', ''], \ 'action': ['URL', ''], + \ 'allowfullscreen': ['Bool', ''], + \ 'allowpaymentrequest': ['Bool', ''], + \ 'allowusermedia': ['Bool', ''], \ 'alt': ['Text', ''], \ 'async': ['Bool', ''], \ 'autocomplete': ['*Token', ''], @@ -142,6 +145,7 @@ let attributes_value = { \ 'optimum': ['Number', ''], \ 'pattern': ['Pattern', ''], \ 'placeholder': ['Text', ''], + \ 'playsinline': ['Bool', ''], \ 'poster': ['URL', ''], \ 'preload': ['Token', ''], \ 'pubdate': ['Bool', ''], @@ -315,10 +319,10 @@ if !exists('g:html5_aria_attributes_complete') let g:html5_aria_attributes_complete = 1 endif if g:html5_aria_attributes_complete == 1 - " Ref: http://www.w3.org/TR/wai-aria/roles - " Version: Draft 15 December 2009 - let widget_role = ['alert', 'alertdialog', 'button', 'checkbox', 'combobox', 'dialog', 'gridcell', 'link', 'log', 'marquee', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'option', 'progressbar', 'radio', 'radiogroup', 'scrollbar', 'slider', 'spinbutton', 'status', 'tab', 'tabpanel', 'textbox', 'timer', 'tooltip', 'treeitem', 'combobox', 'grid', 'listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'] - let document_structure = ['article', 'columnheader', 'definition', 'directory', 'document', 'group', 'heading', 'img', 'list', 'listitem', 'math', 'note', 'presentation', 'region', 'row', 'rowheader', 'separator'] + " Ref: https://www.w3.org/TR/wai-aria-1.1/#role_definitions + " Version: W3C Candidate Recommendation 27 October 2016 + let widget_role = ['alert', 'alertdialog', 'button', 'checkbox', 'combobox', 'dialog', 'gridcell', 'link', 'log', 'marquee', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'option', 'progressbar', 'radio', 'radiogroup', 'scrollbar', 'searchbox', 'slider', 'spinbutton', 'status', 'switch', 'tab', 'tabpanel', 'textbox', 'timer', 'tooltip', 'treeitem', 'combobox', 'grid', 'listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'] + let document_structure = ['article', 'cell', 'columnheader', 'definition', 'directory', 'document', 'feed', 'figure', 'group', 'heading', 'img', 'list', 'listitem', 'math', 'none', 'note', 'presentation', 'region', 'row', 'rowheader', 'separator', 'table', 'term'] let landmark_role = ['application', 'banner', 'complementary', 'contentinfo', 'form', 'main', 'navigation', 'search'] let dpub_role = ['dpub-abstract', 'dpub-afterword', 'dpub-appendix', 'dpub-biblioentry', 'dpub-bibliography', 'dpub-biblioref', 'dpub-chapter', 'dpub-cover', 'dpub-epilogue', 'dpub-footnote', 'dpub-footnotes', 'dpub-foreword', 'dpub-glossary', 'dpub-glossdef', 'dpub-glossref', 'dpub-glossterm', 'dpub-index', 'dpub-locator', 'dpub-noteref', 'dpub-notice', 'dpub-pagebreak', 'dpub-pagelist', 'dpub-part', 'dpub-preface', 'dpub-prologue', 'dpub-pullquote', 'dpub-qna', 'dpub-subtitle', 'dpub-tip', 'dpub-title', 'dpub-toc'] let role = extend(widget_role, document_structure) @@ -336,10 +340,33 @@ let metadata_elements = ['link', 'style', 'meta', 'script', 'noscript', 'command let flow_elements = phrasing_elements + ['p', 'hr', 'pre', 'ul', 'ol', 'dl', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hgroup', 'address', 'blockquote', 'ins', 'del', 'element', 'object', 'main', 'map', 'noscript', 'section', 'nav', 'article', 'aside', 'header', 'footer', 'video', 'audio', 'figure', 'table', 'template', 'form', 'fieldset', 'menu', 'canvas', 'details'] -" http://dev.w3.org/html5/spec/Overview.html#linkTypes -let linktypes = ['alternate', 'author', 'bookmark', 'external', 'help', 'icon', 'license', 'next', 'nofollow', 'noreferrer', 'pingback', 'prefetch', 'prev', 'search', 'stylesheet', 'sidebar', 'tag'] +" https://html.spec.whatwg.org/#linkTypes +let linktypes = ['alternate', 'author', 'bookmark', 'dns-prefetch', 'external', 'help', 'icon', 'license', 'next', 'nofollow', 'noreferrer', 'noopener', 'pingback', 'preconnect', 'prefetch', 'preload', 'prerender', 'prev', 'search', 'stylesheet', 'tag'] +" https://w3c.github.io/manifest/ +let linkreltypes = linktypes +let linkreltypes = linkreltypes + ['manifest'] " http://googlewebmastercentral.blogspot.com/2009/02/specify-your-canonical.html -let linkreltypes = linktypes + ['canonical', 'import'] +" http://www.ysearchblog.com/2009/02/12/fighting-duplication-adding-more-arrows-to-your-quiver/ +" http://blogs.bing.com/webmaster/2009/02/12/partnering-to-help-solve-duplicate-content-issues +let linkreltypes = linkreltypes + ['canonical'] +" http://w3c.github.io/webcomponents/spec/imports/ +let linkreltypes = linkreltypes + ['import'] +" https://www.w3.org/TR/webmention/#sender-discovers-receiver-webmention-endpoint +let linkreltypes = linkreltypes + ['webmention'] +" http://www.opensearch.org/Specifications/OpenSearch/1.1#Autodiscovery_in_HTML.2FXHTML +let linkreltypes = linkreltypes + ['search'] +" http://microformats.org/wiki/rel-sitemap +let linkreltypes = linkreltypes + ['sitemap'] +" https://www.ampproject.org/docs/get_started/create/prepare_for_discovery +let linkreltypes = linkreltypes + ['amphtml'] +" https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html +let linkreltypes = linkreltypes + ['apple-touch-icon', 'apple-touch-icon-precomposed', 'apple-touch-startup-image'] +" https://developer.chrome.com/webstore/inline_installation +let linkreltypes = linkreltypes + ['chrome-webstore-item'] +" http://pubsubhubbub.github.io/PubSubHubbub/pubsubhubbub-core-0.4.html#rfc.section.4 +let linkreltypes = linkreltypes + ['hub'] +" https://golem.ph.utexas.edu/~distler/blog/archives/000320.html +let linkreltypes = linkreltypes + ['pgpkey'] " a and button are special elements for interactive, some element can't be its descendent let abutton_dec = 'details\\|embed\\|iframe\\|keygen\\|label\\|menu\\|select\\|textarea' @@ -551,7 +578,7 @@ let g:xmldata_html5 = { \ ], \ 'iframe': [ \ [], - \ extend(copy(global_attributes), {'src': [], 'srcdoc': [], 'name': [], 'width': [], 'height': [], 'sandbox': ['allow-same-origin', 'allow-forms', 'allow-scripts'], 'seamless': ['seamless', ''], 'referrerpolicy': ['no-referrer', 'no-referrer-when-downgrade', 'origin', 'origin-when-cross-origin', 'unsafe-url']}) + \ extend(copy(global_attributes), {'src': [], 'srcdoc': [], 'name': [], 'width': [], 'height': [], 'sandbox': ['allow-same-origin', 'allow-forms', 'allow-scripts'], 'seamless': ['seamless', ''], 'referrerpolicy': ['no-referrer', 'no-referrer-when-downgrade', 'origin', 'origin-when-cross-origin', 'unsafe-url'], 'allowfullscreen': [], 'allowpaymentrequest': [], 'allowusermedia': []}) \ ], \ 'img': [ \ [], @@ -807,7 +834,7 @@ let g:xmldata_html5 = { \ ], \ 'video': [ \ flow_elements + ['source', 'track'], - \ extend(copy(global_attributes), {'autoplay': ['autoplay', ''], 'preload': ['none', 'metadata', 'auto', ''], 'controls': ['controls', ''], 'loop': ['loop', ''], 'poster': [], 'height': [], 'width': [], 'src': []}) + \ extend(copy(global_attributes), {'autoplay': ['autoplay', ''], 'preload': ['none', 'metadata', 'auto', ''], 'controls': ['controls', ''], 'loop': ['loop', ''], 'playsinline': ['playsinline', ''], 'poster': [], 'height': [], 'width': [], 'src': []}) \ ], \ 'wbr': [ \ [], diff --git a/ftdetect/polyglot.vim b/ftdetect/polyglot.vim index 56508dc..edf87bb 100644 --- a/ftdetect/polyglot.vim +++ b/ftdetect/polyglot.vim @@ -985,14 +985,17 @@ endif if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'toml') == -1 " Rust uses several TOML config files that are not named with .toml. -autocmd BufNewFile,BufRead *.toml,Cargo.lock,.cargo/config set filetype=toml +autocmd BufNewFile,BufRead *.toml,Cargo.lock,*/.cargo/config set filetype=toml endif " ftdetect/typescript.vim if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'typescript') == -1 -autocmd BufNewFile,BufRead *.ts,*.tsx setlocal filetype=typescript +" use `set filetype` to override default filetype=xml for *.ts files +autocmd BufNewFile,BufRead *.ts set filetype=typescript +" use `setfiletype` to not override any other plugins like ianks/vim-tsx +autocmd BufNewFile,BufRead *.tsx setfiletype typescript endif @@ -1016,6 +1019,20 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vm') == -1 au BufRead,BufNewFile *.vm set ft=velocity syntax=velocity +endif + +" ftdetect/vim-literate-coffeescript.vim +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'coffee-script') == -1 + +" Language: Literate CoffeeScript +" Maintainer: Michael Smith +" URL: https://github.com/mintplant/vim-literate-coffeescript +" License: MIT + +autocmd BufNewFile,BufRead *.litcoffee set filetype=litcoffee +autocmd BufNewFile,BufRead *.coffee.md set filetype=litcoffee + + endif " ftdetect/vue.vim diff --git a/ftplugin/blade.vim b/ftplugin/blade.vim index 68e8088..3487961 100644 --- a/ftplugin/blade.vim +++ b/ftplugin/blade.vim @@ -23,7 +23,8 @@ setlocal comments+=s:{{--,m:\ \ \ \ ,e:--}} if exists('loaded_matchit') && exists('b:match_words') " Append to html matchit words let b:match_words .= ',' . - \ '@\%(section\|if\|unless\|foreach\|forelse\|for\|while\|push\|can\|cannot\|hasSection\|php\|verbatim\)\>' . + \ '@\%(section\s*([^\,]*)\|if\|unless\|foreach\|forelse\|for\|while\|push\|can\|cannot\|hasSection\|' . + \ 'php\s*(\@!\|verbatim\|component\|slot\|prepend\)' . \ ':' . \ '@\%(else\|elseif\|empty\|break\|continue\|elsecan\|elsecannot\)\>' . \ ':' . diff --git a/ftplugin/dart.vim b/ftplugin/dart.vim index 9b2e8d3..b3b7291 100644 --- a/ftplugin/dart.vim +++ b/ftplugin/dart.vim @@ -25,7 +25,9 @@ let &l:errorformat = \ '%m' \ ], ',') +setlocal includeexpr=dart#resolveUri(v:fname) +setlocal isfname+=: -let b:undo_ftplugin = 'setl et< fo< sw< sts< com< cms<' +let b:undo_ftplugin = 'setl et< fo< sw< sts< com< cms< inex< isf<' endif diff --git a/after/ftplugin/vue.vim b/ftplugin/litcoffee.vim similarity index 59% rename from after/ftplugin/vue.vim rename to ftplugin/litcoffee.vim index fd78692..ef4aee2 100644 --- a/after/ftplugin/vue.vim +++ b/ftplugin/litcoffee.vim @@ -1,5 +1,5 @@ -if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vue') == -1 +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'coffee-script') == -1 -setlocal suffixesadd+=.vue +runtime ftplugin/coffee.vim endif diff --git a/ftplugin/nginx.vim b/ftplugin/nginx.vim index efcccbd..5ae81d8 100644 --- a/ftplugin/nginx.vim +++ b/ftplugin/nginx.vim @@ -2,4 +2,8 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'nginx') == -1 setlocal commentstring=#\ %s +setlocal iskeyword+=. +setlocal iskeyword+=/ +setlocal iskeyword+=: + endif diff --git a/ftplugin/vue.vim b/ftplugin/vue.vim index 9b4ec9b..4bb5ae2 100644 --- a/ftplugin/vue.vim +++ b/ftplugin/vue.vim @@ -11,4 +11,6 @@ endif runtime! ftplugin/html.vim +setlocal suffixesadd+=.vue + endif diff --git a/indent/blade.vim b/indent/blade.vim index 97f7f29..95cc00a 100644 --- a/indent/blade.vim +++ b/indent/blade.vim @@ -4,22 +4,22 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'blade') == -1 " Language: Blade (Laravel) " Maintainer: Jason Walton -if exists("b:did_indent") +if exists('b:did_indent') finish endif runtime! indent/html.vim let s:htmlindent = &indentexpr -unlet! b:did_indent +unlet! b:did_indent runtime! indent/php.vim let s:phpindent = &indentexpr -unlet! b:did_indent let b:did_indent = 1 " Doesn't include 'foreach' and 'forelse' because these already get matched by 'for'. -let s:directives_start = 'if\|else\|unless\|for\|while\|empty\|push\|section\|can\|hasSection\|verbatim' +let s:directives_start = 'if\|else\|unless\|for\|while\|empty\|push\|section\|can\|hasSection\|verbatim\|php\|' . + \ 'component\|slot\|prepend' let s:directives_end = 'else\|end\|empty\|show\|stop\|append\|overwrite' if exists('g:blade_custom_directives_pairs') @@ -29,55 +29,71 @@ endif setlocal autoindent setlocal indentexpr=GetBladeIndent() -exe "setlocal indentkeys=o,O,<>>,!^F,0=}},0=!!},=@" . substitute(s:directives_end, '\\|', ',=@', 'g') +exe 'setlocal indentkeys=o,O,<>>,!^F,0=}},0=!!},=@' . substitute(s:directives_end, '\\|', ',=@', 'g') " Only define the function once. -if exists("*GetBladeIndent") +if exists('*GetBladeIndent') finish endif +function! s:IsStartingDelimiter(lnum) + let line = getline(a:lnum) + return line =~# '\%(\w\|@\)\@\)\@!' +endfunction + function! GetBladeIndent() - let lnum = prevnonblank(v:lnum-1) + let lnum = prevnonblank(v:lnum - 1) if lnum == 0 return 0 endif - let line = substitute(substitute(getline(lnum), '\s\+$', '', ''), '^\s\+', '', '') - let cline = substitute(substitute(getline(v:lnum), '\s\+$', '', ''), '^\s\+', '', '') + let line = getline(lnum) + let cline = getline(v:lnum) let indent = indent(lnum) - if cline =~# '@\%(' . s:directives_end . '\)' || - \ cline =~# '\%(\|\%({{.*\)\@\)\@!\|@php\%(\s*(\)\@!' - let indent = indent + &sw - else - if exists("*GetBladeIndentCustom") - let hindent = GetBladeIndentCustom() - " Don't use PHP indentation if line is a comment - elseif line !~# '^\s*\%(#\|//\)\|\*/\s*$' && ( - \ searchpair('@include\%(If\)\?\s*(', '', ')', 'bWr') || - \ searchpair('{!!', '', '!!}', 'bWr') || - \ searchpair('{{', '', '}}', 'bWr') || - \ searchpair('', 'bWr') || - \ searchpair('@php\%(\s*(\)\@!', '', '@endphp', 'bWr') ) - execute 'let hindent = ' . s:phpindent - else - execute 'let hindent = ' . s:htmlindent - endif - if hindent > -1 - let indent = hindent - endif - endif - let increase = indent + &sw - if line =~# '@\%(section\)\%(.*@end\)\@!' && line !~# '@\%(section\)\s*([^,]*)' - return indent - elseif line =~# '@\%(' . s:directives_start . '\)\%(.*@end\|.*@stop\)\@!' || - \ line =~# '{{\%(.*}}\)\@!' || line =~# '{!!\%(.*!!}\)\@!' - return increase - else + " 1. Check for special directives + " @section is a single-line directive if it has a second argument. + " @php is a single-line directive if it is followed by parentheses. + if (line =~# '@section\%(.*@end\)\@!' && line !~# '@section\s*([^,]*)') + \ || line =~# '@php\s*(' return indent endif + + " 2. When the current line is an ending delimiter: decrease indentation + " if the previous line wasn't a starting delimiter. + if cline =~# '^\s*@\%(' . s:directives_end . '\)' + \ || cline =~# '\%(' + \ || cline =~# '\%({{.*\)\@', 'bWr') || + \ searchpair('@php\s*(\@!', '', '@endphp', 'bWr') ) + " Only use PHP's indent if the region spans multiple lines + if !s:IsStartingDelimiter(v:lnum) + execute 'let indent = ' . s:phpindent + endif + endif + + return indent endfunction endif diff --git a/indent/erlang.vim b/indent/erlang.vim index b1186ca..64525bb 100644 --- a/indent/erlang.vim +++ b/indent/erlang.vim @@ -6,9 +6,9 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'erlang') == -1 " Contributors: Edwin Fine " Pawel 'kTT' Salata " Ricardo Catalinas Jiménez -" Last Update: 2013-Jul-21 +" Last Update: 2017-Feb-28 " License: Vim license -" URL: https://github.com/hcs42/vim-erlang +" URL: https://github.com/vim-erlang/vim-erlang-runtime " Note About Usage: " This indentation script works best with the Erlang syntax file created by @@ -528,7 +528,9 @@ endfunction " ok. % IsLineAtomContinuation = false function! s:IsLineAtomContinuation(lnum) if has('syntax_items') - return synIDattr(synID(a:lnum, 1, 0), 'name') =~# '^erlangQuotedAtom' + let syn_name = synIDattr(synID(a:lnum, 1, 0), 'name') + return syn_name =~# '^erlangQuotedAtom' || + \ syn_name =~# '^erlangQuotedRecord' else return 0 endif @@ -682,7 +684,7 @@ function! s:BeginningOfClauseFound(stack, token, stored_vcol, lnum, i) call s:Pop(a:stack) if empty(a:stack) call s:Log(' Stack is ["when"], so LTI is in a guard -> return') - return [1, a:stored_vcol + &sw + 2] + return [1, a:stored_vcol + shiftwidth() + 2] else return [1, s:UnexpectedToken(a:token, a:stack)] endif @@ -691,7 +693,7 @@ function! s:BeginningOfClauseFound(stack, token, stored_vcol, lnum, i) call s:Pop(a:stack) if empty(a:stack) call s:Log(' Stack is ["->"], so LTI is in function body -> return') - return [1, a:stored_vcol + &sw] + return [1, a:stored_vcol + shiftwidth()] elseif a:stack[0] ==# ';' call s:Pop(a:stack) @@ -843,7 +845,7 @@ function! s:ErlangCalcIndent2(lnum, stack) elseif token ==# 'begin' let [ret, res] = s:BeginElementFound(stack, token, curr_vcol, - \stored_vcol, 'end', &sw) + \stored_vcol, 'end', shiftwidth()) if ret | return res | endif " case EXPR of BRANCHES end @@ -894,11 +896,11 @@ function! s:ErlangCalcIndent2(lnum, stack) elseif stack == ['->'] call s:Log(' LTI is in a branch after ' . \'"of/receive/after/if/catch" -> return') - return stored_vcol + &sw + return stored_vcol + shiftwidth() elseif stack == ['when'] call s:Log(' LTI is in a guard after ' . \'"of/receive/after/if/catch" -> return') - return stored_vcol + &sw + return stored_vcol + shiftwidth() else return s:UnexpectedToken(token, stack) endif @@ -934,7 +936,7 @@ function! s:ErlangCalcIndent2(lnum, stack) if empty(stack) call s:Log(' LTI is in a condition; matching ' . \'"case/if/try/receive" found') - let stored_vcol = curr_vcol + &sw + let stored_vcol = curr_vcol + shiftwidth() elseif stack[0] ==# 'align_to_begin_element' call s:Pop(stack) let stored_vcol = curr_vcol @@ -943,23 +945,23 @@ function! s:ErlangCalcIndent2(lnum, stack) \'"case/if/try/receive" found') call s:Pop(stack) call s:Pop(stack) - let stored_vcol = curr_vcol + &sw + let stored_vcol = curr_vcol + shiftwidth() elseif stack[0] ==# '->' call s:Log(' LTI is in a branch; matching ' . \'"case/if/try/receive" found') call s:Pop(stack) - let stored_vcol = curr_vcol + 2 * &sw + let stored_vcol = curr_vcol + 2 * shiftwidth() elseif stack[0] ==# 'when' call s:Log(' LTI is in a guard; matching ' . \'"case/if/try/receive" found') call s:Pop(stack) - let stored_vcol = curr_vcol + 2 * &sw + 2 + let stored_vcol = curr_vcol + 2 * shiftwidth() + 2 endif endif let [ret, res] = s:BeginElementFound(stack, token, curr_vcol, - \stored_vcol, 'end', &sw) + \stored_vcol, 'end', shiftwidth()) if ret | return res | endif elseif token ==# 'fun' @@ -985,7 +987,7 @@ function! s:ErlangCalcIndent2(lnum, stack) " stack = ['when'] => LTI is in a guard if empty(stack) call s:Log(' LTI is in a condition; matching "fun" found') - let stored_vcol = curr_vcol + &sw + let stored_vcol = curr_vcol + shiftwidth() elseif len(stack) > 1 && stack[0] ==# '->' && stack[1] ==# ';' call s:Log(' LTI is in a condition; matching "fun" found') call s:Pop(stack) @@ -993,15 +995,15 @@ function! s:ErlangCalcIndent2(lnum, stack) elseif stack[0] ==# '->' call s:Log(' LTI is in a branch; matching "fun" found') call s:Pop(stack) - let stored_vcol = curr_vcol + 2 * &sw + let stored_vcol = curr_vcol + 2 * shiftwidth() elseif stack[0] ==# 'when' call s:Log(' LTI is in a guard; matching "fun" found') call s:Pop(stack) - let stored_vcol = curr_vcol + 2 * &sw + 2 + let stored_vcol = curr_vcol + 2 * shiftwidth() + 2 endif let [ret, res] = s:BeginElementFound(stack, token, curr_vcol, - \stored_vcol, 'end', &sw) + \stored_vcol, 'end', shiftwidth()) if ret | return res | endif else " Pass: we have a function reference (e.g. "fun f/0") @@ -1275,7 +1277,7 @@ function! s:ErlangCalcIndent2(lnum, stack) " when A, " LTI let [ret, res] = s:BeginElementFoundIfEmpty(stack, token, curr_vcol, - \stored_vcol, &sw) + \stored_vcol, shiftwidth()) if ret | return res | endif else " Example: @@ -1307,7 +1309,7 @@ function! s:ErlangCalcIndent2(lnum, stack) " If LTI is between an 'after' and the corresponding " 'end', then let's return let [ret, res] = s:BeginElementFoundIfEmpty(stack, token, curr_vcol, - \stored_vcol, &sw) + \stored_vcol, shiftwidth()) if ret | return res | endif endif diff --git a/indent/eruby.vim b/indent/eruby.vim index 3736f52..5b21ab9 100644 --- a/indent/eruby.vim +++ b/indent/eruby.vim @@ -97,6 +97,7 @@ function! GetErubyIndent(...) let ind = ind + sw endif if line !~# '^\s*<%' && line =~# '%>\s*$' && line !~# '^\s*end\>' + \ && synID(v:lnum, match(cline, '\S') + 1, 1) != hlID('htmlEndTag') let ind = ind - sw endif if cline =~# '^\s*[-=]\=%>\s*$' diff --git a/indent/haskell.vim b/indent/haskell.vim index b1e1bdc..43dc97a 100644 --- a/indent/haskell.vim +++ b/indent/haskell.vim @@ -13,12 +13,16 @@ if exists('b:did_indent') finish endif -let b:did_indent = 1 - if !exists('g:haskell_indent_disable') let g:haskell_indent_disable = 0 endif +if g:haskell_indent_disable != 0 + finish +endif + +let b:did_indent = 1 + if !exists('g:haskell_indent_if') " if x " >>>then ... @@ -63,22 +67,16 @@ if !exists('g:haskell_indent_guard') let g:haskell_indent_guard = 2 endif -if exists("g:haskell_indent_disable") && g:haskell_indent_disable == 0 - setlocal indentexpr=GetHaskellIndent() - setlocal indentkeys=0{,0},0(,0),0[,0],!^F,o,O,0\=,0=where,0=let,0=deriving, -else - setlocal nocindent - setlocal nosmartindent - setlocal autoindent -endif +setlocal indentexpr=GetHaskellIndent() +setlocal indentkeys=0},0),0],!^F,o,O,0\=,0=where,0=let,0=deriving, function! s:isInBlock(hlstack) - return index(a:hlstack, 'haskellParens') > -1 || index(a:hlstack, 'haskellBrackets') > -1 || index(a:hlstack, 'haskellBlock') > -1 || index(a:hlstack, 'haskellBlockComment') > -1 || index(a:hlstack, 'haskellPragma') > -1 + return index(a:hlstack, 'haskellDelimiter') > -1 || index(a:hlstack, 'haskellParens') > -1 || index(a:hlstack, 'haskellBrackets') > -1 || index(a:hlstack, 'haskellBlock') > -1 || index(a:hlstack, 'haskellBlockComment') > -1 || index(a:hlstack, 'haskellPragma') > -1 endfunction -function! s:stripTrailingComment(line) - if a:line =~ '^\s*--\(-\+\|\s\+\)' || a:line =~ '^\s*{-' - return a:line +function! s:stripComment(line) + if a:line =~ '^\s*--\(-*\s\+\|$\)' + return '' else let l:stripped = split(a:line, '-- ') if len(l:stripped) > 1 @@ -144,7 +142,7 @@ function! GetHaskellIndent() return -1 endif - let l:prevline = s:stripTrailingComment(getline(v:lnum - 1)) + let l:prevline = s:stripComment(getline(v:lnum - 1)) let l:line = getline(v:lnum) " indent multiline strings @@ -161,13 +159,14 @@ function! GetHaskellIndent() return 0 endif - " comment indentation - if l:line =~ '^\s*--' - return match(l:prevline, '-- ') - endif - if l:prevline =~ '^\s*--' - return match(l:prevline, '\S') - endif + " " comment indentation + " if l:line =~ '^\s*--' + " let l:s = match(l:prevline, '-- ') + " if l:s > -1 + " endif + " " if l:prevline =~ '^\s*--' + " " return match(l:prevline, '\S') + " " endif " { foo :: Int " >>, @@ -176,7 +175,7 @@ function! GetHaskellIndent() " ... " >>, if l:line =~ '^\s*,' - if s:isInBlock(l:hlstack) + if s:isInBlock(s:getHLStack(line('.'), col('.'))) normal! 0 call search(',', 'cW') let l:n = s:getNesting(s:getHLStack(line('.'), col('.'))) @@ -395,7 +394,7 @@ function! GetHaskellIndent() " foo " >>{ - if l:line =~ '^\s*{' && l:prevline !~ '^{' + if l:line =~ '^\s*{ ' let l:s = match(l:prevline, '\S') if l:s >= 0 return l:s + &shiftwidth @@ -477,16 +476,7 @@ function! GetHaskellIndent() return s:indentMatching(']') endif - " do not reindent indented lines - if match(l:prevline, '\S') < match(l:line, '\S') - return -1 - endif - - if l:line !~ '^\s*[=-]>\s' && l:line =~ '^\s*[!#$%&*+./<>?@\\^|~-]\+' - return -1 - endif - - return match(l:prevline, '\S') + return -1 endfunction endif diff --git a/indent/javascript.vim b/indent/javascript.vim index e5fc7c9..2237b4b 100644 --- a/indent/javascript.vim +++ b/indent/javascript.vim @@ -4,7 +4,7 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'javascript') == " Language: Javascript " Maintainer: Chris Paul ( https://github.com/bounceme ) " URL: https://github.com/pangloss/vim-javascript -" Last Change: January 24, 2017 +" Last Change: March 9, 2017 " Only load this indent file when no other was loaded. if exists('b:did_indent') @@ -16,6 +16,10 @@ let b:did_indent = 1 setlocal indentexpr=GetJavascriptIndent() setlocal autoindent nolisp nosmartindent setlocal indentkeys+=0],0) +" Testable with something like: +" vim -eNs "+filetype plugin indent on" "+syntax on" "+set ft=javascript" \ +" "+norm! gg=G" '+%print' '+:q!' testfile.js \ +" | diff -uBZ testfile.js - let b:undo_indent = 'setlocal indentexpr< smartindent< autoindent< indentkeys<' @@ -34,10 +38,14 @@ if exists('*shiftwidth') endfunction else function s:sw() - return &sw + return &l:shiftwidth == 0 ? &l:tabstop : &l:shiftwidth endfunction endif +" Performance for forwards search(): start search at pos rather than masking +" matches before pos. +let s:z = has('patch-7.4.984') ? 'z' : '' + " searchpair() wrapper if has('reltime') function s:GetPair(start,end,flags,skip,time,...) @@ -51,34 +59,40 @@ endif " Regex of syntax group names that are or delimit string or are comments. let s:syng_strcom = 'string\|comment\|regex\|special\|doc\|template\%(braces\)\@!' -let s:syng_str = 'string\|template' +let s:syng_str = 'string\|template\|special' let s:syng_com = 'comment\|doc' " Expression used to check whether we should skip a match with searchpair(). let s:skip_expr = "synIDattr(synID(line('.'),col('.'),0),'name') =~? '".s:syng_strcom."'" +function s:parse_cino(f) abort + return float2nr(eval(substitute(substitute(join(split( + \ matchstr(&cino,'\C.*'.a:f.'\zs[^,]*'), 's',1), '*'.s:W) + \ , '^-\=\zs\*','',''), '^-\=\zs\.','0.',''))) +endfunction + function s:skip_func() - if !s:free || search('\m`\|\${\|\*\/','nW',s:looksyn) - let s:free = !eval(s:skip_expr) - let s:looksyn = line('.') - return !s:free + if getline('.') =~ '\%<'.col('.').'c\/.\{-}\/\|\%>'.col('.').'c[''"]\|\\$' + return eval(s:skip_expr) + elseif s:checkIn || search('\m`\|\${\|\*\/','nW'.s:z,s:looksyn) + let s:checkIn = eval(s:skip_expr) endif let s:looksyn = line('.') - return getline('.') =~ '\%<'.col('.').'c\/.\{-}\/\|\%>'.col('.').'c[''"]\|\\$' && - \ eval(s:skip_expr) + return s:checkIn endfunction function s:alternatePair(stop) let pos = getpos('.')[1:2] - while search('\m[][(){}]','bW',a:stop) - if !s:skip_func() - let idx = stridx('])}',s:looking_at()) - if idx + 1 - if s:GetPair(['\[','(','{'][idx], '])}'[idx],'bW','s:skip_func()',2000,a:stop) <= 0 - break - endif - else - return + let pat = '[][(){};]' + while search('\m'.pat,'bW',a:stop) + if s:skip_func() | continue | endif + let idx = stridx('])};',s:looking_at()) + if idx is 3 | let pat = '[{}()]' | continue | endif + if idx + 1 + if s:GetPair(['\[','(','{'][idx], '])}'[idx],'bW','s:skip_func()',2000,a:stop) <= 0 + break endif + else + return endif endwhile call call('cursor',pos) @@ -104,14 +118,12 @@ function s:token() endfunction function s:previous_token() - let l:n = line('.') - if (s:looking_at() !~ '\k' || search('\m\<','cbW')) && search('\m\S','bW') - if (getline('.')[col('.')-2:col('.')-1] == '*/' || line('.') != l:n && + let l:pos = getpos('.')[1:2] + if search('\m\k\{1,}\|\S','ebW') + if (getline('.')[col('.')-2:col('.')-1] == '*/' || line('.') != l:pos[0] && \ getline('.') =~ '\%<'.col('.').'c\/\/') && s:syn_at(line('.'),col('.')) =~? s:syng_com - while search('\m\/\ze[/*]','cbW') - if !search('\m\S','bW') - break - elseif s:syn_at(line('.'),col('.')) !~? s:syng_com + while search('\m\S\ze\_s*\/[/*]','bW') + if s:syn_at(line('.'),col('.')) !~? s:syng_com return s:token() endif endwhile @@ -119,73 +131,77 @@ function s:previous_token() return s:token() endif endif + call call('cursor',l:pos) return '' endfunction -function s:others(p) - return "((line2byte(line('.')) + col('.')) <= ".(line2byte(a:p[0]) + a:p[1]).") || ".s:skip_expr -endfunction - -function s:tern_skip(p) - return s:GetPair('{','}','nbW',s:others(a:p),200,a:p[0]) > 0 -endfunction - -function s:tern_col(p) - return s:GetPair('?',':\@ 0 -endfunction - -function s:label_col() - let pos = getpos('.')[1:2] - let [s:looksyn,s:free] = pos - call s:alternatePair(0) - if s:save_pos('s:IsBlock') - let poss = getpos('.')[1:2] - return call('cursor',pos) || !s:tern_col(poss) - elseif s:looking_at() == ':' - return !s:tern_col([0,0]) +function s:expr_col() + if getline('.')[col('.')-2] == ':' + return 1 endif + let bal = 0 + while search('\m[{}?:;]','bW') + if eval(s:skip_expr) | continue | endif + " switch (looking_at()) + exe { '}': "if s:GetPair('{','}','bW',s:skip_expr,200) <= 0 | return | endif", + \ ';': "return", + \ '{': "return getpos('.')[1:2] != b:js_cache[1:] && !s:IsBlock()", + \ ':': "let bal -= getline('.')[max([col('.')-2,0]):col('.')] !~ '::'", + \ '?': "let bal += 1 | if bal > 0 | return 1 | endif" }[s:looking_at()] + endwhile endfunction " configurable regexes that define continuation lines, not including (, {, or [. let s:opfirst = '^' . get(g:,'javascript_opfirst', - \ '\%([<>=,?^%|*/&]\|\([-.:+]\)\1\@!\|!=\|in\%(stanceof\)\=\>\)') + \ '\C\%([<>=,?^%|*/&]\|\([-.:+]\)\1\@!\|!=\|in\%(stanceof\)\=\>\)') let s:continuation = get(g:,'javascript_continuation', - \ '\%([-+<>=,.~!?/*^%|&:]\|\<\%(typeof\|delete\|void\|in\|instanceof\)\)') . '$' + \ '\C\%([-+<>=,.~!?/*^%|&:]\|\<\%(typeof\|new\|delete\|void\|in\|instanceof\|await\)\)') . '$' function s:continues(ln,con) - return !cursor(a:ln, match(' '.a:con,s:continuation)) && - \ eval( (['s:syn_at(line("."),col(".")) !~? "regex"'] + - \ repeat(['getline(".")[col(".")-2] != tr(s:looking_at(),">","=")'],3) + - \ repeat(['s:previous_token() != "."'],5) + [1])[ - \ index(split('/ > - + typeof in instanceof void delete'),s:token())]) + if !cursor(a:ln, match(' '.a:con,s:continuation)) + let teol = s:looking_at() + if teol == '/' + return s:syn_at(line('.'),col('.')) !~? 'regex' + elseif teol =~ '[-+>]' + return getline('.')[col('.')-2] != tr(teol,'>','=') + elseif teol =~ '\l' + return s:previous_token() != '.' + elseif teol == ':' + return s:expr_col() + endif + return 1 + endif endfunction " get the line of code stripped of comments and move cursor to the last " non-comment char. function s:Trim(ln) - call cursor(a:ln+1,1) - call s:previous_token() - return strpart(getline('.'),0,col('.')) + let pline = substitute(getline(a:ln),'\s*$','','') + let l:max = max([strridx(pline,'//'), strridx(pline,'/*')]) + while l:max != -1 && s:syn_at(a:ln, strlen(pline)) =~? s:syng_com + let pline = pline[: l:max] + let l:max = max([strridx(pline,'//'), strridx(pline,'/*')]) + let pline = substitute(pline[:-2],'\s*$','','') + endwhile + return pline is '' || cursor(a:ln,strlen(pline)) ? pline : pline endfunction " Find line above 'lnum' that isn't empty or in a comment function s:PrevCodeLine(lnum) - let l:n = prevnonblank(a:lnum) + let [l:pos, l:n] = [getpos('.')[1:2], prevnonblank(a:lnum)] while l:n - if getline(l:n) =~ '^\s*\/[/*]' - if (stridx(getline(l:n),'`') > 0 || getline(l:n-1)[-1:] == '\') && - \ s:syn_at(l:n,1) =~? s:syng_str - return l:n - endif + if getline(l:n) =~ '^\s*\/[/*]' let l:n = prevnonblank(l:n-1) - elseif s:syn_at(l:n,1) =~? s:syng_com - let l:n = s:save_pos('eval', - \ 'cursor('.l:n.',1) + search(''\m\/\*'',"bW")') + elseif stridx(getline(l:n), '*/') + 1 && s:syn_at(l:n,1) =~? s:syng_com + call cursor(l:n,1) + keepjumps norm! [* + let l:n = search('\m\S','nbW') else - return l:n + break endif endwhile + call call('cursor',l:pos) + return l:n endfunction " Check if line 'lnum' has a balanced amount of parentheses. @@ -200,7 +216,9 @@ function s:Balanced(lnum) return endif endif - let pos = match(l:line, '[][(){}]', pos + 1) + let pos = match(l:line, (l:open ? + \ '['.escape(tr(l:line[pos],'({[]})',')}][{(').l:line[pos],']').']' : + \ '[][(){}]'), pos + 1) endwhile return !l:open endfunction @@ -209,11 +227,11 @@ function s:OneScope(lnum) let pline = s:Trim(a:lnum) let kw = 'else do' if pline[-1:] == ')' && s:GetPair('(', ')', 'bW', s:skip_expr, 100) > 0 - call s:previous_token() - let kw = 'for if let while with' - if index(split('await each'),s:token()) + 1 + if s:previous_token() =~# '^\%(await\|each\)$' call s:previous_token() let kw = 'for' + else + let kw = 'for if let while with' endif endif return pline[-2:] == '=>' || index(split(kw),s:token()) + 1 && @@ -245,18 +263,22 @@ function s:IsBlock() if s:looking_at() == '{' let l:n = line('.') let char = s:previous_token() - let syn = char =~ '[{>/]' ? s:syn_at(line('.'),col('.')-(char == '{')) : '' - if syn =~? 'xml\|jsx' + if match(s:stack,'\cxml\|jsx') + 1 && s:syn_at(line('.'),col('.')-1) =~? 'xml\|jsx' return char != '{' elseif char =~ '\k' - return index(split('return const let import export yield default delete var await void typeof throw case new in instanceof') - \ ,char) < (line('.') != l:n) || s:previous_token() == '.' + if char ==# 'type' + return s:previous_token() !~# '^\%(im\|ex\)port$' + endif + return index(split('return const let import export extends yield default delete var await void typeof throw case new of in instanceof') + \ ,char) < (line('.') != l:n) || s:save_pos('s:previous_token') == '.' elseif char == '>' - return getline('.')[col('.')-2] == '=' || syn =~? '^jsflow' + return getline('.')[col('.')-2] == '=' || s:syn_at(line('.'),col('.')) =~? '^jsflow' elseif char == ':' - return getline('.')[col('.')-2] != ':' && s:label_col() + return !s:save_pos('s:expr_col') + elseif char == '/' + return s:syn_at(line('.'),col('.')) =~? 'regex' endif - return syn =~? 'regex' || char !~ '[=~!<*,/?^%|&([]' && + return char !~ '[=~!<*,?^%|&([]' && \ (char !~ '[-+]' || l:n != line('.') && getline('.')[col('.')-2] == char) endif endfunction @@ -266,7 +288,9 @@ function GetJavascriptIndent() " Get the current line. call cursor(v:lnum,1) let l:line = getline('.') - let syns = s:syn_at(v:lnum, 1) + " use synstack as it validates syn state and works in an empty line + let s:stack = map(synstack(v:lnum,1),"synIDattr(v:val,'name')") + let syns = get(s:stack,-1,'') " start with strings,comments,etc. if syns =~? s:syng_com @@ -275,7 +299,7 @@ function GetJavascriptIndent() elseif l:line !~ '^\s*\/[/*]' return -1 endif - elseif syns =~? s:syng_str && l:line !~ '^[''"]' + elseif syns =~? s:syng_str if b:js_cache[0] == v:lnum - 1 && s:Balanced(v:lnum-1) let b:js_cache[0] = v:lnum endif @@ -300,11 +324,11 @@ function GetJavascriptIndent() \ (b:js_cache[0] > l:lnum || s:Balanced(l:lnum)) call call('cursor',b:js_cache[1:]) else - let [s:looksyn, s:free, top] = [v:lnum - 1, 1, (!indent(l:lnum) && + let [s:looksyn, s:checkIn, top] = [v:lnum - 1, 0, (!indent(l:lnum) && \ s:syn_at(l:lnum,1) !~? s:syng_str) * l:lnum] if idx + 1 - call s:GetPair(['\[','(','{'][idx], '])}'[idx],'bW','s:skip_func()',2000,top) - elseif indent(v:lnum) && syns =~? 'block' + call s:GetPair(['\[','(','{'][idx],'])}'[idx],'bW','s:skip_func()',2000,top) + elseif getline(v:lnum) !~ '^\S' && syns =~? 'block' call s:GetPair('{','}','bW','s:skip_func()',2000,top) else call s:alternatePair(top) @@ -324,31 +348,27 @@ function GetJavascriptIndent() if &cino !~ ':' let switch_offset = s:W else - let cinc = matchlist(&cino,'.*:\zs\(-\)\=\(\d*\)\(\.\d\+\)\=\(s\)\=\C') - let switch_offset = max([cinc[0] is '' ? 0 : (cinc[1].1) * - \ ((strlen(cinc[2].cinc[3]) ? str2nr(cinc[2].str2nr(cinc[3][1])) : 10) * - \ (cinc[4] is '' ? 1 : s:W)) / 10, -indent(num)]) + let switch_offset = max([-indent(num),s:parse_cino(':')]) endif if pline[-1:] != '.' && l:line =~# '^\%(default\|case\)\>' return indent(num) + switch_offset endif endif endif - if idx < 0 && pline !~ '[{;]$' - if pline =~# ':\@ 0 + return GetCoffeeIndent(v:lnum) + else + return -1 + endif +endfunc + + +endif diff --git a/indent/ruby.vim b/indent/ruby.vim index 84067fe..8fa929b 100644 --- a/indent/ruby.vim +++ b/indent/ruby.vim @@ -20,6 +20,11 @@ if !exists('g:ruby_indent_access_modifier_style') let g:ruby_indent_access_modifier_style = 'normal' endif +if !exists('g:ruby_indent_assignment_style') + " Possible values: "variable", "hanging" + let g:ruby_indent_assignment_style = 'hanging' +endif + if !exists('g:ruby_indent_block_style') " Possible values: "expression", "do" let g:ruby_indent_block_style = 'expression' @@ -144,7 +149,507 @@ let s:block_continuation_regex = '^\s*[^])}\t ].*'.s:block_regex " Regex that describes a leading operator (only a method call's dot for now) let s:leading_operator_regex = '^\s*[.]' -" 2. Auxiliary Functions {{{1 +" 2. GetRubyIndent Function {{{1 +" ========================= + +function GetRubyIndent(...) + " 2.1. Setup {{{2 + " ---------- + + let indent_info = {} + + " The value of a single shift-width + if exists('*shiftwidth') + let indent_info.sw = shiftwidth() + else + let indent_info.sw = &sw + endif + + " For the current line, use the first argument if given, else v:lnum + let indent_info.clnum = a:0 ? a:1 : v:lnum + let indent_info.cline = getline(indent_info.clnum) + + " Set up variables for restoring position in file. Could use clnum here. + let indent_info.col = col('.') + + " 2.2. Work on the current line {{{2 + " ----------------------------- + let indent_callback_names = [ + \ 's:AccessModifier', + \ 's:ClosingBracketOnEmptyLine', + \ 's:BlockComment', + \ 's:DeindentingKeyword', + \ 's:MultilineStringOrLineComment', + \ 's:ClosingHeredocDelimiter', + \ 's:LeadingOperator', + \ ] + + for callback_name in indent_callback_names +" Decho "Running: ".callback_name + let indent = call(function(callback_name), [indent_info]) + + if indent >= 0 +" Decho "Match: ".callback_name." indent=".indent." info=".string(indent_info) + return indent + endif + endfor + + " 2.3. Work on the previous line. {{{2 + " ------------------------------- + let indent_callback_names = [ + \ 's:EmptyInsideString', + \ 's:StartOfFile', + \ 's:AfterAccessModifier', + \ 's:ContinuedLine', + \ 's:AfterBlockOpening', + \ 's:AfterHangingSplat', + \ 's:AfterUnbalancedBracket', + \ 's:AfterLeadingOperator', + \ 's:AfterEndKeyword', + \ 's:AfterIndentKeyword', + \ ] + + " Previous line number + let indent_info.plnum = s:PrevNonBlankNonString(indent_info.clnum - 1) + let indent_info.pline = getline(indent_info.plnum) + + for callback_name in indent_callback_names +" Decho "Running: ".callback_name + let indent = call(function(callback_name), [indent_info]) + + if indent >= 0 +" Decho "Match: ".callback_name." indent=".indent." info=".string(indent_info) + return indent + endif + endfor + + " 2.4. Work on the MSL line. {{{2 + " -------------------------- + let indent_callback_names = [ + \ 's:PreviousNotMSL', + \ 's:IndentingKeywordInMSL', + \ 's:ContinuedHangingOperator', + \ ] + + " Most Significant line based on the previous one -- in case it's a + " contination of something above + let indent_info.plnum_msl = s:GetMSL(indent_info.plnum) + + for callback_name in indent_callback_names +" Decho "Running: ".callback_name + let indent = call(function(callback_name), [indent_info]) + + if indent >= 0 +" Decho "Match: ".callback_name." indent=".indent." info=".string(indent_info) + return indent + endif + endfor + + " }}}2 + + " By default, just return the previous line's indent +" Decho "Default case matched" + return indent(indent_info.plnum) +endfunction + +" 3. Indenting Logic Callbacks {{{1 +" ============================ + +function! s:AccessModifier(cline_info) + let info = a:cline_info + + " If this line is an access modifier keyword, align according to the closest + " class declaration. + if g:ruby_indent_access_modifier_style == 'indent' + if s:Match(info.clnum, s:access_modifier_regex) + let class_lnum = s:FindContainingClass() + if class_lnum > 0 + return indent(class_lnum) + info.sw + endif + endif + elseif g:ruby_indent_access_modifier_style == 'outdent' + if s:Match(info.clnum, s:access_modifier_regex) + let class_lnum = s:FindContainingClass() + if class_lnum > 0 + return indent(class_lnum) + endif + endif + endif + + return -1 +endfunction + +function! s:ClosingBracketOnEmptyLine(cline_info) + let info = a:cline_info + + " If we got a closing bracket on an empty line, find its match and indent + " according to it. For parentheses we indent to its column - 1, for the + " others we indent to the containing line's MSL's level. Return -1 if fail. + let col = matchend(info.cline, '^\s*[]})]') + + if col > 0 && !s:IsInStringOrComment(info.clnum, col) + call cursor(info.clnum, col) + let closing_bracket = info.cline[col - 1] + let bracket_pair = strpart('(){}[]', stridx(')}]', closing_bracket) * 2, 2) + + if searchpair(escape(bracket_pair[0], '\['), '', bracket_pair[1], 'bW', s:skip_expr) > 0 + if closing_bracket == ')' && col('.') != col('$') - 1 + let ind = virtcol('.') - 1 + elseif g:ruby_indent_block_style == 'do' + let ind = indent(line('.')) + else " g:ruby_indent_block_style == 'expression' + let ind = indent(s:GetMSL(line('.'))) + endif + endif + + return ind + endif + + return -1 +endfunction + +function! s:BlockComment(cline_info) + " If we have a =begin or =end set indent to first column. + if match(a:cline_info.cline, '^\s*\%(=begin\|=end\)$') != -1 + return 0 + endif + return -1 +endfunction + +function! s:DeindentingKeyword(cline_info) + let info = a:cline_info + + " If we have a deindenting keyword, find its match and indent to its level. + " TODO: this is messy + if s:Match(info.clnum, s:ruby_deindent_keywords) + call cursor(info.clnum, 1) + + if searchpair(s:end_start_regex, s:end_middle_regex, s:end_end_regex, 'bW', + \ s:end_skip_expr) > 0 + let msl = s:GetMSL(line('.')) + let line = getline(line('.')) + + if s:IsAssignment(line, col('.')) && + \ strpart(line, col('.') - 1, 2) !~ 'do' + " assignment to case/begin/etc, on the same line + if g:ruby_indent_assignment_style == 'hanging' + " hanging indent + let ind = virtcol('.') - 1 + else + " align with variable + let ind = indent(line('.')) + endif + elseif g:ruby_indent_block_style == 'do' + " align to line of the "do", not to the MSL + let ind = indent(line('.')) + elseif getline(msl) =~ '=\s*\(#.*\)\=$' + " in the case of assignment to the MSL, align to the starting line, + " not to the MSL + let ind = indent(line('.')) + else + " align to the MSL + let ind = indent(msl) + endif + endif + return ind + endif + + return -1 +endfunction + +function! s:MultilineStringOrLineComment(cline_info) + let info = a:cline_info + + " If we are in a multi-line string or line-comment, don't do anything to it. + if s:IsInStringOrDocumentation(info.clnum, matchend(info.cline, '^\s*') + 1) + return indent(info.clnum) + endif + return -1 +endfunction + +function! s:ClosingHeredocDelimiter(cline_info) + let info = a:cline_info + + " If we are at the closing delimiter of a "<<" heredoc-style string, set the + " indent to 0. + if info.cline =~ '^\k\+\s*$' + \ && s:IsInStringDelimiter(info.clnum, 1) + \ && search('\V<<'.info.cline, 'nbW') > 0 + return 0 + endif + + return -1 +endfunction + +function! s:LeadingOperator(cline_info) + " If the current line starts with a leading operator, add a level of indent. + if s:Match(a:cline_info.clnum, s:leading_operator_regex) + return indent(s:GetMSL(a:cline_info.clnum)) + a:cline_info.sw + endif + return -1 +endfunction + +function! s:EmptyInsideString(pline_info) + " If the line is empty and inside a string (plnum would not be the real + " prevnonblank in that case), use the previous line's indent + let info = a:pline_info + + if info.cline =~ '^\s*$' && info.plnum != prevnonblank(info.clnum - 1) + return indent(prevnonblank(info.clnum)) + endif + return -1 +endfunction + +function! s:StartOfFile(pline_info) + " At the start of the file use zero indent. + if a:pline_info.plnum == 0 + return 0 + endif + return -1 +endfunction + +function! s:AfterAccessModifier(pline_info) + let info = a:pline_info + + if g:ruby_indent_access_modifier_style == 'indent' + " If the previous line was a private/protected keyword, add a + " level of indent. + if s:Match(info.plnum, s:indent_access_modifier_regex) + return indent(info.plnum) + info.sw + endif + elseif g:ruby_indent_access_modifier_style == 'outdent' + " If the previous line was a private/protected/public keyword, add + " a level of indent, since the keyword has been out-dented. + if s:Match(info.plnum, s:access_modifier_regex) + return indent(info.plnum) + info.sw + endif + endif + return -1 +endfunction + +" Example: +" +" if foo || bar || +" baz || bing +" puts "foo" +" end +" +function! s:ContinuedLine(pline_info) + let info = a:pline_info + + let col = s:Match(info.plnum, s:ruby_indent_keywords) + if s:Match(info.plnum, s:continuable_regex) && + \ s:Match(info.plnum, s:continuation_regex) + if col > 0 && s:IsAssignment(info.pline, col) + if g:ruby_indent_assignment_style == 'hanging' + " hanging indent + let ind = col - 1 + else + " align with variable + let ind = indent(info.plnum) + endif + else + let ind = indent(s:GetMSL(info.plnum)) + endif + return ind + info.sw + info.sw + endif + return -1 +endfunction + +function! s:AfterBlockOpening(pline_info) + let info = a:pline_info + + " If the previous line ended with a block opening, add a level of indent. + if s:Match(info.plnum, s:block_regex) + if g:ruby_indent_block_style == 'do' + " don't align to the msl, align to the "do" + let ind = indent(info.plnum) + info.sw + else + let plnum_msl = s:GetMSL(info.plnum) + + if getline(plnum_msl) =~ '=\s*\(#.*\)\=$' + " in the case of assignment to the msl, align to the starting line, + " not to the msl + let ind = indent(info.plnum) + info.sw + else + let ind = indent(plnum_msl) + info.sw + endif + endif + + return ind + endif + + return -1 +endfunction + +function! s:AfterLeadingOperator(pline_info) + " If the previous line started with a leading operator, use its MSL's level + " of indent + if s:Match(a:pline_info.plnum, s:leading_operator_regex) + return indent(s:GetMSL(a:pline_info.plnum)) + endif + return -1 +endfunction + +function! s:AfterHangingSplat(pline_info) + let info = a:pline_info + + " If the previous line ended with the "*" of a splat, add a level of indent + if info.pline =~ s:splat_regex + return indent(info.plnum) + info.sw + endif + return -1 +endfunction + +function! s:AfterUnbalancedBracket(pline_info) + let info = a:pline_info + + " If the previous line contained unclosed opening brackets and we are still + " in them, find the rightmost one and add indent depending on the bracket + " type. + " + " If it contained hanging closing brackets, find the rightmost one, find its + " match and indent according to that. + if info.pline =~ '[[({]' || info.pline =~ '[])}]\s*\%(#.*\)\=$' + let [opening, closing] = s:ExtraBrackets(info.plnum) + + if opening.pos != -1 + if opening.type == '(' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0 + if col('.') + 1 == col('$') + return indent(info.plnum) + info.sw + else + return virtcol('.') + endif + else + let nonspace = matchend(info.pline, '\S', opening.pos + 1) - 1 + return nonspace > 0 ? nonspace : indent(info.plnum) + info.sw + endif + elseif closing.pos != -1 + call cursor(info.plnum, closing.pos + 1) + normal! % + + if s:Match(line('.'), s:ruby_indent_keywords) + return indent('.') + info.sw + else + return indent(s:GetMSL(line('.'))) + endif + else + call cursor(info.clnum, info.col) + end + endif + + return -1 +endfunction + +function! s:AfterEndKeyword(pline_info) + let info = a:pline_info + " If the previous line ended with an "end", match that "end"s beginning's + " indent. + let col = s:Match(info.plnum, '\%(^\|[^.:@$]\)\\s*\%(#.*\)\=$') + if col > 0 + call cursor(info.plnum, col) + if searchpair(s:end_start_regex, '', s:end_end_regex, 'bW', + \ s:end_skip_expr) > 0 + let n = line('.') + let ind = indent('.') + let msl = s:GetMSL(n) + if msl != n + let ind = indent(msl) + end + return ind + endif + end + return -1 +endfunction + +function! s:AfterIndentKeyword(pline_info) + let info = a:pline_info + let col = s:Match(info.plnum, s:ruby_indent_keywords) + + if col > 0 + call cursor(info.plnum, col) + let ind = virtcol('.') - 1 + info.sw + " TODO: make this better (we need to count them) (or, if a searchpair + " fails, we know that something is lacking an end and thus we indent a + " level + if s:Match(info.plnum, s:end_end_regex) + let ind = indent('.') + elseif s:IsAssignment(info.pline, col) + if g:ruby_indent_assignment_style == 'hanging' + " hanging indent + let ind = col + info.sw - 1 + else + " align with variable + let ind = indent(info.plnum) + info.sw + endif + endif + return ind + endif + + return -1 +endfunction + +function! s:PreviousNotMSL(msl_info) + let info = a:msl_info + + " If the previous line wasn't a MSL + if info.plnum != info.plnum_msl + " If previous line ends bracket and begins non-bracket continuation decrease indent by 1. + if s:Match(info.plnum, s:bracket_switch_continuation_regex) + " TODO (2016-10-07) Wrong/unused? How could it be "1"? + return indent(info.plnum) - 1 + " If previous line is a continuation return its indent. + " TODO: the || s:IsInString() thing worries me a bit. + elseif s:Match(info.plnum, s:non_bracket_continuation_regex) || s:IsInString(info.plnum, strlen(line)) + return indent(info.plnum) + endif + endif + + return -1 +endfunction + +function! s:IndentingKeywordInMSL(msl_info) + let info = a:msl_info + " If the MSL line had an indenting keyword in it, add a level of indent. + " TODO: this does not take into account contrived things such as + " module Foo; class Bar; end + let col = s:Match(info.plnum_msl, s:ruby_indent_keywords) + if col > 0 + let ind = indent(info.plnum_msl) + info.sw + if s:Match(info.plnum_msl, s:end_end_regex) + let ind = ind - info.sw + elseif s:IsAssignment(getline(info.plnum_msl), col) + if g:ruby_indent_assignment_style == 'hanging' + " hanging indent + let ind = col + info.sw - 1 + else + " align with variable + let ind = indent(info.plnum_msl) + info.sw + endif + endif + return ind + endif + return -1 +endfunction + +function! s:ContinuedHangingOperator(msl_info) + let info = a:msl_info + + " If the previous line ended with [*+/.,-=], but wasn't a block ending or a + " closing bracket, indent one extra level. + if s:Match(info.plnum_msl, s:non_bracket_continuation_regex) && !s:Match(info.plnum_msl, '^\s*\([\])}]\|end\)') + if info.plnum_msl == info.plnum + let ind = indent(info.plnum_msl) + info.sw + else + let ind = indent(info.plnum_msl) + endif + return ind + endif + + return -1 +endfunction + +" 4. Auxiliary Functions {{{1 " ====================== " Check if the character at lnum:col is inside a string, comment, or is ascii. @@ -167,6 +672,10 @@ function s:IsInStringDelimiter(lnum, col) return synIDattr(synID(a:lnum, a:col, 1), 'name') == 'rubyStringDelimiter' endfunction +function s:IsAssignment(str, pos) + return strpart(a:str, 0, a:pos - 1) =~ '=\s*$' +endfunction + " Find line above 'lnum' that isn't empty, in a comment, or in a string. function s:PrevNonBlankNonString(lnum) let in_block = 0 @@ -196,7 +705,6 @@ endfunction function s:GetMSL(lnum) " Start on the line we're at and use its indent. let msl = a:lnum - let msl_body = getline(msl) let lnum = s:PrevNonBlankNonString(a:lnum - 1) while lnum > 0 " If we have a continuation line, or we're in a string, use line as MSL. @@ -293,7 +801,6 @@ function s:GetMSL(lnum) endif endif - let msl_body = getline(msl) let lnum = s:PrevNonBlankNonString(lnum - 1) endwhile return msl @@ -398,301 +905,6 @@ function! s:FindContainingClass() return 0 endfunction -" 3. GetRubyIndent Function {{{1 -" ========================= - -function GetRubyIndent(...) - " 3.1. Setup {{{2 - " ---------- - - " The value of a single shift-width - if exists('*shiftwidth') - let sw = shiftwidth() - else - let sw = &sw - endif - - " For the current line, use the first argument if given, else v:lnum - let clnum = a:0 ? a:1 : v:lnum - - " Set up variables for restoring position in file. Could use clnum here. - let vcol = col('.') - - " 3.2. Work on the current line {{{2 - " ----------------------------- - - " Get the current line. - let line = getline(clnum) - let ind = -1 - - " If this line is an access modifier keyword, align according to the closest - " class declaration. - if g:ruby_indent_access_modifier_style == 'indent' - if s:Match(clnum, s:access_modifier_regex) - let class_line = s:FindContainingClass() - if class_line > 0 - return indent(class_line) + sw - endif - endif - elseif g:ruby_indent_access_modifier_style == 'outdent' - if s:Match(clnum, s:access_modifier_regex) - let class_line = s:FindContainingClass() - if class_line > 0 - return indent(class_line) - endif - endif - endif - - " If we got a closing bracket on an empty line, find its match and indent - " according to it. For parentheses we indent to its column - 1, for the - " others we indent to the containing line's MSL's level. Return -1 if fail. - let col = matchend(line, '^\s*[]})]') - if col > 0 && !s:IsInStringOrComment(clnum, col) - call cursor(clnum, col) - let bs = strpart('(){}[]', stridx(')}]', line[col - 1]) * 2, 2) - if searchpair(escape(bs[0], '\['), '', bs[1], 'bW', s:skip_expr) > 0 - if line[col-1]==')' && col('.') != col('$') - 1 - let ind = virtcol('.') - 1 - elseif g:ruby_indent_block_style == 'do' - let ind = indent(line('.')) - else " g:ruby_indent_block_style == 'expression' - let ind = indent(s:GetMSL(line('.'))) - endif - endif - return ind - endif - - " If we have a =begin or =end set indent to first column. - if match(line, '^\s*\%(=begin\|=end\)$') != -1 - return 0 - endif - - " If we have a deindenting keyword, find its match and indent to its level. - " TODO: this is messy - if s:Match(clnum, s:ruby_deindent_keywords) - call cursor(clnum, 1) - if searchpair(s:end_start_regex, s:end_middle_regex, s:end_end_regex, 'bW', - \ s:end_skip_expr) > 0 - let msl = s:GetMSL(line('.')) - let line = getline(line('.')) - - if strpart(line, 0, col('.') - 1) =~ '=\s*$' && - \ strpart(line, col('.') - 1, 2) !~ 'do' - " assignment to case/begin/etc, on the same line, hanging indent - let ind = virtcol('.') - 1 - elseif g:ruby_indent_block_style == 'do' - " align to line of the "do", not to the MSL - let ind = indent(line('.')) - elseif getline(msl) =~ '=\s*\(#.*\)\=$' - " in the case of assignment to the MSL, align to the starting line, - " not to the MSL - let ind = indent(line('.')) - else - " align to the MSL - let ind = indent(msl) - endif - endif - return ind - endif - - " If we are in a multi-line string or line-comment, don't do anything to it. - if s:IsInStringOrDocumentation(clnum, matchend(line, '^\s*') + 1) - return indent('.') - endif - - " If we are at the closing delimiter of a "<<" heredoc-style string, set the - " indent to 0. - if line =~ '^\k\+\s*$' - \ && s:IsInStringDelimiter(clnum, 1) - \ && search('\V<<'.line, 'nbW') > 0 - return 0 - endif - - " If the current line starts with a leading operator, add a level of indent. - if s:Match(clnum, s:leading_operator_regex) - return indent(s:GetMSL(clnum)) + sw - endif - - " 3.3. Work on the previous line. {{{2 - " ------------------------------- - - " Find a non-blank, non-multi-line string line above the current line. - let lnum = s:PrevNonBlankNonString(clnum - 1) - - " If the line is empty and inside a string, use the previous line. - if line =~ '^\s*$' && lnum != prevnonblank(clnum - 1) - return indent(prevnonblank(clnum)) - endif - - " At the start of the file use zero indent. - if lnum == 0 - return 0 - endif - - " Set up variables for the previous line. - let line = getline(lnum) - let ind = indent(lnum) - - if g:ruby_indent_access_modifier_style == 'indent' - " If the previous line was a private/protected keyword, add a - " level of indent. - if s:Match(lnum, s:indent_access_modifier_regex) - return indent(lnum) + sw - endif - elseif g:ruby_indent_access_modifier_style == 'outdent' - " If the previous line was a private/protected/public keyword, add - " a level of indent, since the keyword has been out-dented. - if s:Match(lnum, s:access_modifier_regex) - return indent(lnum) + sw - endif - endif - - if s:Match(lnum, s:continuable_regex) && s:Match(lnum, s:continuation_regex) - return indent(s:GetMSL(lnum)) + sw + sw - endif - - " If the previous line ended with a block opening, add a level of indent. - if s:Match(lnum, s:block_regex) - let msl = s:GetMSL(lnum) - - if g:ruby_indent_block_style == 'do' - " don't align to the msl, align to the "do" - let ind = indent(lnum) + sw - elseif getline(msl) =~ '=\s*\(#.*\)\=$' - " in the case of assignment to the msl, align to the starting line, - " not to the msl - let ind = indent(lnum) + sw - else - let ind = indent(msl) + sw - endif - return ind - endif - - " If the previous line started with a leading operator, use its MSL's level - " of indent - if s:Match(lnum, s:leading_operator_regex) - return indent(s:GetMSL(lnum)) - endif - - " If the previous line ended with the "*" of a splat, add a level of indent - if line =~ s:splat_regex - return indent(lnum) + sw - endif - - " If the previous line contained unclosed opening brackets and we are still - " in them, find the rightmost one and add indent depending on the bracket - " type. - " - " If it contained hanging closing brackets, find the rightmost one, find its - " match and indent according to that. - if line =~ '[[({]' || line =~ '[])}]\s*\%(#.*\)\=$' - let [opening, closing] = s:ExtraBrackets(lnum) - - if opening.pos != -1 - if opening.type == '(' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0 - if col('.') + 1 == col('$') - return ind + sw - else - return virtcol('.') - endif - else - let nonspace = matchend(line, '\S', opening.pos + 1) - 1 - return nonspace > 0 ? nonspace : ind + sw - endif - elseif closing.pos != -1 - call cursor(lnum, closing.pos + 1) - normal! % - - if s:Match(line('.'), s:ruby_indent_keywords) - return indent('.') + sw - else - return indent(s:GetMSL(line('.'))) - endif - else - call cursor(clnum, vcol) - end - endif - - " If the previous line ended with an "end", match that "end"s beginning's - " indent. - let col = s:Match(lnum, '\%(^\|[^.:@$]\)\\s*\%(#.*\)\=$') - if col > 0 - call cursor(lnum, col) - if searchpair(s:end_start_regex, '', s:end_end_regex, 'bW', - \ s:end_skip_expr) > 0 - let n = line('.') - let ind = indent('.') - let msl = s:GetMSL(n) - if msl != n - let ind = indent(msl) - end - return ind - endif - end - - let col = s:Match(lnum, s:ruby_indent_keywords) - if col > 0 - call cursor(lnum, col) - let ind = virtcol('.') - 1 + sw - " TODO: make this better (we need to count them) (or, if a searchpair - " fails, we know that something is lacking an end and thus we indent a - " level - if s:Match(lnum, s:end_end_regex) - let ind = indent('.') - endif - return ind - endif - - " 3.4. Work on the MSL line. {{{2 - " -------------------------- - - " Set up variables to use and search for MSL to the previous line. - let p_lnum = lnum - let lnum = s:GetMSL(lnum) - - " If the previous line wasn't a MSL. - if p_lnum != lnum - " If previous line ends bracket and begins non-bracket continuation decrease indent by 1. - if s:Match(p_lnum, s:bracket_switch_continuation_regex) - return ind - 1 - " If previous line is a continuation return its indent. - " TODO: the || s:IsInString() thing worries me a bit. - elseif s:Match(p_lnum, s:non_bracket_continuation_regex) || s:IsInString(p_lnum,strlen(line)) - return ind - endif - endif - - " Set up more variables, now that we know we wasn't continuation bound. - let line = getline(lnum) - let msl_ind = indent(lnum) - - " If the MSL line had an indenting keyword in it, add a level of indent. - " TODO: this does not take into account contrived things such as - " module Foo; class Bar; end - if s:Match(lnum, s:ruby_indent_keywords) - let ind = msl_ind + sw - if s:Match(lnum, s:end_end_regex) - let ind = ind - sw - endif - return ind - endif - - " If the previous line ended with [*+/.,-=], but wasn't a block ending or a - " closing bracket, indent one extra level. - if s:Match(lnum, s:non_bracket_continuation_regex) && !s:Match(lnum, '^\s*\([\])}]\|end\)') - if lnum == p_lnum - let ind = msl_ind + sw - else - let ind = msl_ind - endif - return ind - endif - - " }}}2 - - return ind -endfunction - " }}}1 let &cpo = s:cpo_save diff --git a/indent/typescript.vim b/indent/typescript.vim index ed2e6c0..6dead67 100644 --- a/indent/typescript.vim +++ b/indent/typescript.vim @@ -2,504 +2,362 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'typescript') == " Vim indent file " Language: Typescript -" Acknowledgement: Based off of vim-ruby maintained by Nikolai Weibull http://vim-ruby.rubyforge.org - -" 0. Initialization {{{1 -" ================= +" Acknowledgement: Almost direct copy from https://github.com/pangloss/vim-javascript " Only load this indent file when no other was loaded. -if exists("b:did_indent") +if exists('b:did_indent') || get(g:, 'typescript_indent_disable', 0) finish endif let b:did_indent = 1 -setlocal nosmartindent - " Now, set up our indentation expression and keys that trigger it. setlocal indentexpr=GetTypescriptIndent() -setlocal formatexpr=Fixedgq(v:lnum,v:count) -setlocal indentkeys=0{,0},0),0],0\,,!^F,o,O,e +setlocal autoindent nolisp nosmartindent +setlocal indentkeys+=0],0) + +let b:undo_indent = 'setlocal indentexpr< smartindent< autoindent< indentkeys<' " Only define the function once. -if exists("*GetTypescriptIndent") +if exists('*GetTypescriptIndent') finish endif let s:cpo_save = &cpo set cpo&vim -" 1. Variables {{{1 -" ============ +" Get shiftwidth value +if exists('*shiftwidth') + function s:sw() + return shiftwidth() + endfunction +else + function s:sw() + return &sw + endfunction +endif -let s:ts_keywords = '^\s*\(break\|case\|catch\|continue\|debugger\|default\|delete\|do\|else\|finally\|for\|function\|if\|in\|instanceof\|new\|return\|switch\|this\|throw\|try\|typeof\|var\|void\|while\|with\)' +" searchpair() wrapper +if has('reltime') + function s:GetPair(start,end,flags,skip,time,...) + return searchpair('\m'.a:start,'','\m'.a:end,a:flags,a:skip,max([prevnonblank(v:lnum) - 2000,0] + a:000),a:time) + endfunction +else + function s:GetPair(start,end,flags,skip,...) + return searchpair('\m'.a:start,'','\m'.a:end,a:flags,a:skip,max([prevnonblank(v:lnum) - 1000,get(a:000,1)])) + endfunction +endif " Regex of syntax group names that are or delimit string or are comments. -let s:syng_strcom = 'string\|regex\|comment\c' - -" Regex of syntax group names that are strings. -let s:syng_string = 'regex\c' - -" Regex of syntax group names that are strings or documentation. -let s:syng_multiline = 'comment\c' - -" Regex of syntax group names that are line comment. -let s:syng_linecom = 'linecomment\c' - +let s:syng_strcom = 'string\|comment\|regex\|special\|doc\|template\%(braces\)\@!' +let s:syng_str = 'string\|template\|special' +let s:syng_com = 'comment\|doc' " Expression used to check whether we should skip a match with searchpair(). -let s:skip_expr = "synIDattr(synID(line('.'),col('.'),1),'name') =~ '".s:syng_strcom."'" +let s:skip_expr = "synIDattr(synID(line('.'),col('.'),0),'name') =~? '".s:syng_strcom."'" -let s:line_term = '\s*\%(\%(\/\/\).*\)\=$' - -" Regex that defines continuation lines, not including (, {, or [. -let s:continuation_regex = '\%([\\*+/.:]\|\%(<%\)\@[^{;]*' . s:line_term - -" Regex that defines blocks. -let s:block_regex = '\%([{[]\)\s*\%(|\%([*@]\=\h\w*,\=\s*\)\%(,\s*[*@]\=\h\w*\)*|\)\=' . s:line_term - -let s:var_stmt = '^\s*var' - -let s:comma_first = '^\s*,' -let s:comma_last = ',\s*$' - -let s:ternary = '^\s\+[?|:]' -let s:ternary_q = '^\s\+?' - -" 2. Auxiliary Functions {{{1 -" ====================== - -" Check if the character at lnum:col is inside a string, comment, or is ascii. -function s:IsInStringOrComment(lnum, col) - return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_strcom -endfunction - -" Check if the character at lnum:col is inside a string. -function s:IsInString(lnum, col) - return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_string -endfunction - -" Check if the character at lnum:col is inside a multi-line comment. -function s:IsInMultilineComment(lnum, col) - return !s:IsLineComment(a:lnum, a:col) && synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_multiline -endfunction - -" Check if the character at lnum:col is a line comment. -function s:IsLineComment(lnum, col) - return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_linecom -endfunction - -" Find line above 'lnum' that isn't empty, in a comment, or in a string. -function s:PrevNonBlankNonString(lnum) - let in_block = 0 - let lnum = prevnonblank(a:lnum) - while lnum > 0 - " Go in and out of blocks comments as necessary. - " If the line isn't empty (with opt. comment) or in a string, end search. - let line = getline(lnum) - if line =~ '/\*' - if in_block - let in_block = 0 - else - break - endif - elseif !in_block && line =~ '\*/' - let in_block = 1 - elseif !in_block && line !~ '^\s*\%(//\).*$' && !(s:IsInStringOrComment(lnum, 1) && s:IsInStringOrComment(lnum, strlen(line))) - break - endif - let lnum = prevnonblank(lnum - 1) - endwhile - return lnum -endfunction - -" Find line above 'lnum' that started the continuation 'lnum' may be part of. -function s:GetMSL(lnum, in_one_line_scope) - " Start on the line we're at and use its indent. - let msl = a:lnum - let lnum = s:PrevNonBlankNonString(a:lnum - 1) - while lnum > 0 - " If we have a continuation line, or we're in a string, use line as MSL. - " Otherwise, terminate search as we have found our MSL already. - let line = getline(lnum) - let col = match(line, s:msl_regex) + 1 - if (col > 0 && !s:IsInStringOrComment(lnum, col)) || s:IsInString(lnum, strlen(line)) - let msl = lnum - else - " Don't use lines that are part of a one line scope as msl unless the - " flag in_one_line_scope is set to 1 - " - if a:in_one_line_scope - break - end - let msl_one_line = s:Match(lnum, s:one_line_scope_regex) - if msl_one_line == 0 - break - endif - endif - let lnum = s:PrevNonBlankNonString(lnum - 1) - endwhile - return msl -endfunction - -function s:RemoveTrailingComments(content) - let single = '\/\/\(.*\)\s*$' - let multi = '\/\*\(.*\)\*\/\s*$' - return substitute(substitute(a:content, single, '', ''), multi, '', '') -endfunction - -" Find if the string is inside var statement (but not the first string) -function s:InMultiVarStatement(lnum) - let lnum = s:PrevNonBlankNonString(a:lnum - 1) - -" let type = synIDattr(synID(lnum, indent(lnum) + 1, 0), 'name') - - " loop through previous expressions to find a var statement - while lnum > 0 - let line = getline(lnum) - - " if the line is a ts keyword - if (line =~ s:ts_keywords) - " check if the line is a var stmt - " if the line has a comma first or comma last then we can assume that we - " are in a multiple var statement - if (line =~ s:var_stmt) - return lnum - endif - - " other ts keywords, not a var - return 0 - endif - - let lnum = s:PrevNonBlankNonString(lnum - 1) - endwhile - - " beginning of program, not a var - return 0 -endfunction - -" Find line above with beginning of the var statement or returns 0 if it's not -" this statement -function s:GetVarIndent(lnum) - let lvar = s:InMultiVarStatement(a:lnum) - let prev_lnum = s:PrevNonBlankNonString(a:lnum - 1) - - if lvar - let line = s:RemoveTrailingComments(getline(prev_lnum)) - - " if the previous line doesn't end in a comma, return to regular indent - if (line !~ s:comma_last) - return indent(prev_lnum) - &sw - else - return indent(lvar) + &sw - endif +function s:skip_func() + if !s:free || search('\m`\|\${\|\*\/','nW',s:looksyn) + let s:free = !eval(s:skip_expr) + let s:looksyn = line('.') + return !s:free endif - - return -1 + let s:looksyn = line('.') + return getline('.') =~ '\%<'.col('.').'c\/.\{-}\/\|\%>'.col('.').'c[''"]\|\\$' && + \ eval(s:skip_expr) endfunction +function s:alternatePair(stop) + let pos = getpos('.')[1:2] + while search('\m[][(){}]','bW',a:stop) + if !s:skip_func() + let idx = stridx('])}',s:looking_at()) + if idx + 1 + if s:GetPair(['\[','(','{'][idx], '])}'[idx],'bW','s:skip_func()',2000,a:stop) <= 0 + break + endif + else + return + endif + endif + endwhile + call call('cursor',pos) +endfunction -" Check if line 'lnum' has more opening brackets than closing ones. -function s:LineHasOpeningBrackets(lnum) - let open_0 = 0 - let open_2 = 0 - let open_4 = 0 - let line = getline(a:lnum) - let pos = match(line, '[][(){}]', 0) +function s:save_pos(f,...) + let l:pos = getpos('.')[1:2] + let ret = call(a:f,a:000) + call call('cursor',l:pos) + return ret +endfunction + +function s:syn_at(l,c) + return synIDattr(synID(a:l,a:c,0),'name') +endfunction + +function s:looking_at() + return getline('.')[col('.')-1] +endfunction + +function s:token() + return s:looking_at() =~ '\k' ? expand('') : s:looking_at() +endfunction + +function s:previous_token() + let l:n = line('.') + if (s:looking_at() !~ '\k' || search('\m\<','cbW')) && search('\m\S','bW') + if (getline('.')[col('.')-2:col('.')-1] == '*/' || line('.') != l:n && + \ getline('.') =~ '\%<'.col('.').'c\/\/') && s:syn_at(line('.'),col('.')) =~? s:syng_com + while search('\m\/\ze[/*]','cbW') + if !search('\m\S','bW') + break + elseif s:syn_at(line('.'),col('.')) !~? s:syng_com + return s:token() + endif + endwhile + else + return s:token() + endif + endif + return '' +endfunction + +function s:others(p) + return "((line2byte(line('.')) + col('.')) <= ".(line2byte(a:p[0]) + a:p[1]).") || ".s:skip_expr +endfunction + +function s:tern_skip(p) + return s:GetPair('{','}','nbW',s:others(a:p),200,a:p[0]) > 0 +endfunction + +function s:tern_col(p) + return s:GetPair('?',':\@ 0 +endfunction + +function s:label_col() + let pos = getpos('.')[1:2] + let [s:looksyn,s:free] = pos + call s:alternatePair(0) + if s:save_pos('s:IsBlock') + let poss = getpos('.')[1:2] + return call('cursor',pos) || !s:tern_col(poss) + elseif s:looking_at() == ':' + return !s:tern_col([0,0]) + endif +endfunction + +" configurable regexes that define continuation lines, not including (, {, or [. +let s:opfirst = '^' . get(g:,'typescript_opfirst', + \ '\%([<>=,?^%|*/&]\|\([-.:+]\)\1\@!\|!=\|in\%(stanceof\)\=\>\)') +let s:continuation = get(g:,'typescript_continuation', + \ '\%([-+<>=,.~!?/*^%|&:]\|\<\%(typeof\|delete\|void\|in\|instanceof\)\)') . '$' + +function s:continues(ln,con) + return !cursor(a:ln, match(' '.a:con,s:continuation)) && + \ eval( (['s:syn_at(line("."),col(".")) !~? "regex"'] + + \ repeat(['getline(".")[col(".")-2] != tr(s:looking_at(),">","=")'],3) + + \ repeat(['s:previous_token() != "."'],5) + [1])[ + \ index(split('/ > - + typeof in instanceof void delete'),s:token())]) +endfunction + +" get the line of code stripped of comments and move cursor to the last +" non-comment char. +function s:Trim(ln) + call cursor(a:ln+1,1) + call s:previous_token() + return strpart(getline('.'),0,col('.')) +endfunction + +" Find line above 'lnum' that isn't empty or in a comment +function s:PrevCodeLine(lnum) + let l:n = prevnonblank(a:lnum) + while l:n + if getline(l:n) =~ '^\s*\/[/*]' + if (stridx(getline(l:n),'`') > 0 || getline(l:n-1)[-1:] == '\') && + \ s:syn_at(l:n,1) =~? s:syng_str + return l:n + endif + let l:n = prevnonblank(l:n-1) + elseif getline(l:n) =~ '\([/*]\)\1\@![/*]' && s:syn_at(l:n,1) =~? s:syng_com + let l:n = s:save_pos('eval', + \ 'cursor('.l:n.',1) + search(''\m\/\*'',"bW")') + else + return l:n + endif + endwhile +endfunction + +" Check if line 'lnum' has a balanced amount of parentheses. +function s:Balanced(lnum) + let l:open = 0 + let l:line = getline(a:lnum) + let pos = match(l:line, '[][(){}]', 0) while pos != -1 - if !s:IsInStringOrComment(a:lnum, pos + 1) - let idx = stridx('(){}[]', line[pos]) - if idx % 2 == 0 - let open_{idx} = open_{idx} + 1 - else - let open_{idx - 1} = open_{idx - 1} - 1 - endif - endif - let pos = match(line, '[][(){}]', pos + 1) + if s:syn_at(a:lnum,pos + 1) !~? s:syng_strcom + let l:open += match(' ' . l:line[pos],'[[({]') + if l:open < 0 + return + endif + endif + let pos = match(l:line, '[][(){}]', pos + 1) endwhile - return (open_0 > 0) . (open_2 > 0) . (open_4 > 0) + return !l:open endfunction -function s:Match(lnum, regex) - let col = match(getline(a:lnum), a:regex) + 1 - return col > 0 && !s:IsInStringOrComment(a:lnum, col) ? col : 0 -endfunction - -function s:IndentWithContinuation(lnum, ind, width) - " Set up variables to use and search for MSL to the previous line. - let p_lnum = a:lnum - let lnum = s:GetMSL(a:lnum, 1) - let line = getline(lnum) - - " If the previous line wasn't a MSL and is continuation return its indent. - " TODO: the || s:IsInString() thing worries me a bit. - if p_lnum != lnum - if s:Match(p_lnum,s:continuation_regex)||s:IsInString(p_lnum,strlen(line)) - return a:ind - endif +function s:OneScope(lnum) + let pline = s:Trim(a:lnum) + let kw = 'else do' + if pline[-1:] == ')' && s:GetPair('(', ')', 'bW', s:skip_expr, 100) > 0 + call s:previous_token() + let kw = 'for if let while with' + if index(split('await each'),s:token()) + 1 + call s:previous_token() + let kw = 'for' + endif endif - - " Set up more variables now that we know we aren't continuation bound. - let msl_ind = indent(lnum) - - " If the previous line ended with [*+/.-=], start a continuation that - " indents an extra level. - if s:Match(lnum, s:continuation_regex) - if lnum == p_lnum - return msl_ind + a:width - else - return msl_ind - endif - endif - - return a:ind + return pline[-2:] == '=>' || index(split(kw),s:token()) + 1 && + \ s:save_pos('s:previous_token') != '.' endfunction -function s:InOneLineScope(lnum) - let msl = s:GetMSL(a:lnum, 1) - if msl > 0 && s:Match(msl, s:one_line_scope_regex) - return msl - endif - return 0 +" returns braceless levels started by 'i' and above lines * &sw. 'num' is the +" lineNr which encloses the entire context, 'cont' if whether line 'i' + 1 is +" a continued expression, which could have started in a braceless context +function s:iscontOne(i,num,cont) + let [l:i, l:num, bL] = [a:i, a:num + !a:num, 0] + let pind = a:num ? indent(l:num) + s:W : 0 + let ind = indent(l:i) + (a:cont ? 0 : s:W) + while l:i >= l:num && (ind > pind || l:i == l:num) + if indent(l:i) < ind && s:OneScope(l:i) + let bL += s:W + let l:i = line('.') + elseif !a:cont || bL || ind < indent(a:i) + break + endif + let ind = min([ind, indent(l:i)]) + let l:i = s:PrevCodeLine(l:i - 1) + endwhile + return bL endfunction -function s:ExitingOneLineScope(lnum) - let msl = s:GetMSL(a:lnum, 1) - if msl > 0 - " if the current line is in a one line scope .. - if s:Match(msl, s:one_line_scope_regex) - return 0 - else - let prev_msl = s:GetMSL(msl - 1, 1) - if s:Match(prev_msl, s:one_line_scope_regex) - return prev_msl - endif - endif +" https://github.com/sweet-js/sweet.js/wiki/design#give-lookbehind-to-the-reader +function s:IsBlock() + if s:looking_at() == '{' + let l:n = line('.') + let char = s:previous_token() + if match(s:stack,'xml\|jsx') + 1 && s:syn_at(line('.'),col('.')-1) =~? 'xml\|jsx' + return char != '{' + elseif char =~ '\k' + return index(split('return const let import export yield default delete var await void typeof throw case new in instanceof') + \ ,char) < (line('.') != l:n) || s:previous_token() == '.' + elseif char == '>' + return getline('.')[col('.')-2] == '=' || s:syn_at(line('.'),col('.')) =~? '^jsflow' + elseif char == ':' + return getline('.')[col('.')-2] != ':' && s:label_col() + elseif char == '/' + return s:syn_at(line('.'),col('.')) =~? 'regex' + endif + return char !~ '[=~!<*,?^%|&([]' && + \ (char !~ '[-+]' || l:n != line('.') && getline('.')[col('.')-2] == char) endif - return 0 endfunction -" 3. GetTypescriptIndent Function {{{1 -" ========================= - function GetTypescriptIndent() - " 3.1. Setup {{{2 - " ---------- - - " Set up variables for restoring position in file. Could use v:lnum here. - let vcol = col('.') - - " 3.2. Work on the current line {{{2 - " ----------------------------- - - let ind = -1 + let b:js_cache = get(b:,'js_cache',[0,0,0]) " Get the current line. - let line = getline(v:lnum) - " previous nonblank line number - let prevline = prevnonblank(v:lnum - 1) + call cursor(v:lnum,1) + let l:line = getline('.') + " use synstack as it validates syn state and works in an empty line + let s:stack = synstack(v:lnum,1) + let syns = synIDattr(get(s:stack,-1),'name') - " If we got a closing bracket on an empty line, find its match and indent - " according to it. For parentheses we indent to its column - 1, for the - " others we indent to the containing line's MSL's level. Return -1 if fail. - let col = matchend(line, '^\s*[],})]') - if col > 0 && !s:IsInStringOrComment(v:lnum, col) - call cursor(v:lnum, col) - - let lvar = s:InMultiVarStatement(v:lnum) - if lvar - let prevline_contents = s:RemoveTrailingComments(getline(prevline)) - - " check for comma first - if (line[col - 1] =~ ',') - " if the previous line ends in comma or semicolon don't indent - if (prevline_contents =~ '[;,]\s*$') - return indent(s:GetMSL(line('.'), 0)) - " get previous line indent, if it's comma first return prevline indent - elseif (prevline_contents =~ s:comma_first) - return indent(prevline) - " otherwise we indent 1 level - else - return indent(lvar) + &sw - endif - endif - endif - - - let bs = strpart('(){}[]', stridx(')}]', line[col - 1]) * 2, 2) - if searchpair(escape(bs[0], '\['), '', bs[1], 'bW', s:skip_expr) > 0 - if line[col-1]==')' && col('.') != col('$') - 1 - let ind = virtcol('.')-1 - else - let ind = indent(s:GetMSL(line('.'), 0)) - endif - endif - return ind + " start with strings,comments,etc. + if syns =~? s:syng_com + if l:line =~ '^\s*\*' + return cindent(v:lnum) + elseif l:line !~ '^\s*\/[/*]' + return -1 + endif + elseif syns =~? s:syng_str && l:line !~ '^[''"]' + if b:js_cache[0] == v:lnum - 1 && s:Balanced(v:lnum-1) + let b:js_cache[0] = v:lnum + endif + return -1 + endif + let l:lnum = s:PrevCodeLine(v:lnum - 1) + if !l:lnum + return endif - " If the line is comma first, dedent 1 level - if (getline(prevline) =~ s:comma_first) - return indent(prevline) - &sw + let l:line = substitute(l:line,'^\s*','','') + if l:line[:1] == '/*' + let l:line = substitute(l:line,'^\%(\/\*.\{-}\*\/\s*\)*','','') + endif + if l:line =~ '^\/[/*]' + let l:line = '' endif - if (line =~ s:ternary) - if (getline(prevline) =~ s:ternary_q) - return indent(prevline) - else - return indent(prevline) + &sw - endif - endif - - " If we are in a multi-line comment, cindent does the right thing. - if s:IsInMultilineComment(v:lnum, 1) && !s:IsLineComment(v:lnum, 1) - return cindent(v:lnum) - endif - - " Check for multiple var assignments -" let var_indent = s:GetVarIndent(v:lnum) -" if var_indent >= 0 -" return var_indent -" endif - - " 3.3. Work on the previous line. {{{2 - " ------------------------------- - - " If the line is empty and the previous nonblank line was a multi-line - " comment, use that comment's indent. Deduct one char to account for the - " space in ' */'. - if line =~ '^\s*$' && s:IsInMultilineComment(prevline, 1) - return indent(prevline) - 1 - endif - - " Find a non-blank, non-multi-line string line above the current line. - let lnum = s:PrevNonBlankNonString(v:lnum - 1) - - " If the line is empty and inside a string, use the previous line. - if line =~ '^\s*$' && lnum != prevline - return indent(prevnonblank(v:lnum)) - endif - - " At the start of the file use zero indent. - if lnum == 0 - return 0 - endif - - " Set up variables for current line. - let line = getline(lnum) - let ind = indent(lnum) - - " If the previous line ended with a block opening, add a level of indent. - if s:Match(lnum, s:block_regex) - return indent(s:GetMSL(lnum, 0)) + &sw - endif - - " If the previous line contained an opening bracket, and we are still in it, - " add indent depending on the bracket type. - if line =~ '[[({]' - let counts = s:LineHasOpeningBrackets(lnum) - if counts[0] == '1' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0 - if col('.') + 1 == col('$') - return ind + &sw - else - return virtcol('.') - endif - elseif counts[1] == '1' || counts[2] == '1' - return ind + &sw - else - call cursor(v:lnum, vcol) - end - endif - - " 3.4. Work on the MSL line. {{{2 - " -------------------------- - - let ind_con = ind - let ind = s:IndentWithContinuation(lnum, ind_con, &sw) - - " }}}2 - " - " - let ols = s:InOneLineScope(lnum) - if ols > 0 - let ind = ind + &sw + " the containing paren, bracket, or curly. Many hacks for performance + let idx = index([']',')','}'],l:line[0]) + if b:js_cache[0] >= l:lnum && b:js_cache[0] < v:lnum && + \ (b:js_cache[0] > l:lnum || s:Balanced(l:lnum)) + call call('cursor',b:js_cache[1:]) else - let ols = s:ExitingOneLineScope(lnum) - while ols > 0 && ind > 0 - let ind = ind - &sw - let ols = s:InOneLineScope(ols - 1) - endwhile + let [s:looksyn, s:free, top] = [v:lnum - 1, 1, (!indent(l:lnum) && + \ s:syn_at(l:lnum,1) !~? s:syng_str) * l:lnum] + if idx + 1 + call s:GetPair(['\[','(','{'][idx],'])}'[idx],'bW','s:skip_func()',2000,top) + elseif getline(v:lnum) !~ '^\S' && syns =~? 'block' + call s:GetPair('{','}','bW','s:skip_func()',2000,top) + else + call s:alternatePair(top) + endif endif - return ind -endfunction + let b:js_cache = [v:lnum] + (line('.') == v:lnum ? [0,0] : getpos('.')[1:2]) + let num = b:js_cache[1] -" }}}1 + let [s:W, isOp, bL, switch_offset] = [s:sw(),0,0,0] + if !num || s:IsBlock() + let ilnum = line('.') + let pline = s:save_pos('s:Trim',l:lnum) + if num && s:looking_at() == ')' && s:GetPair('(', ')', 'bW', s:skip_expr, 100) > 0 + let num = ilnum == num ? line('.') : num + if idx < 0 && s:previous_token() ==# 'switch' && s:previous_token() != '.' + if &cino !~ ':' + let switch_offset = s:W + else + let cinc = matchlist(&cino,'.*:\zs\(-\)\=\(\d*\)\(\.\d\+\)\=\(s\)\=\C') + let switch_offset = max([cinc[0] is '' ? 0 : (cinc[1].1) * + \ ((strlen(cinc[2].cinc[3]) ? str2nr(cinc[2].str2nr(cinc[3][1])) : 10) * + \ (cinc[4] is '' ? 1 : s:W)) / 10, -indent(num)]) + endif + if pline[-1:] != '.' && l:line =~# '^\%(default\|case\)\>' + return indent(num) + switch_offset + endif + endif + endif + if idx < 0 && pline !~ '[{;]$' + if pline =~# ':\@ 1 - while l:count > 1 - let l:count -= 1 - normal J - endwhile - endif - - let l:winview = winsaveview() - - call cursor(a:lnum, l:tw + 1) - let orig_breakpoint = searchpairpos(' ', '', '\.', 'bcW', '', a:lnum) - call cursor(a:lnum, l:tw + 1) - let breakpoint = searchpairpos(' ', '', '\.', 'bcW', s:skip_expr, a:lnum) - - " No need for special treatment, normal gq handles edgecases better - if breakpoint[1] == orig_breakpoint[1] - call winrestview(l:winview) - return 1 - endif - - " Try breaking after string - if breakpoint[1] <= indent(a:lnum) - call cursor(a:lnum, l:tw + 1) - let breakpoint = searchpairpos('\.', '', ' ', 'cW', s:skip_expr, a:lnum) - endif - - - if breakpoint[1] != 0 - call feedkeys("r\") - else - let l:count = l:count - 1 - endif - - " run gq on new lines - if l:count == 1 - call feedkeys("gqq") - endif - - return 0 -endfunction endif diff --git a/syntax/blade.vim b/syntax/blade.vim index 4c04db7..7ae2786 100644 --- a/syntax/blade.vim +++ b/syntax/blade.vim @@ -32,13 +32,13 @@ syn region bladeEcho matchgroup=bladeDelimiter start="{!!" end="!!}" con syn region bladeComment matchgroup=bladeDelimiter start="{{--" end="--}}" contains=bladeTodo containedin=ALLBUT,@bladeExempt keepend syn keyword bladeKeyword @if @elseif @foreach @forelse @for @while @can @cannot @elsecan @elsecannot @include - \ @includeIf @each @inject @extends @section @stack @push @unless @yield @parent @hasSection @break @continue - \ @unset @lang @choice @component @slot + \ @includeIf @each @inject @extends @section @stack @push @unless @yield @parent @hasSection @break @continue + \ @unset @lang @choice @component @slot @prepend \ nextgroup=bladePhpParenBlock skipwhite containedin=ALLBUT,@bladeExempt -syn keyword bladeKeyword @else @endif @endunless @endfor @endforeach @empty @endforelse @endwhile @endcan +syn keyword bladeKeyword @else @endif @endunless @endfor @endforeach @empty @endforelse @endwhile @endcan \ @endcannot @stop @append @endsection @endpush @show @overwrite @verbatim @endverbatim @endcomponent - \ @endslot + \ @endslot @endprepend \ containedin=ALLBUT,@bladeExempt if exists('g:blade_custom_directives') @@ -49,7 +49,7 @@ if exists('g:blade_custom_directives_pairs') exe "syn keyword bladeKeyword @" . join(values(g:blade_custom_directives_pairs), ' @') . " containedin=ALLBUT,@bladeExempt" endif -syn region bladePhpRegion matchgroup=bladeKeyword start="\<@php\>\%(\s*(\)\@!" end="\<@endphp\>" contains=@bladePhp containedin=ALLBUT,@bladeExempt keepend +syn region bladePhpRegion matchgroup=bladeKeyword start="\<@php\>\s*(\@!" end="\<@endphp\>" contains=@bladePhp containedin=ALLBUT,@bladeExempt keepend syn match bladeKeyword "@php\ze\s*(" nextgroup=bladePhpParenBlock skipwhite containedin=ALLBUT,@bladeExempt syn region bladePhpParenBlock matchgroup=bladeDelimiter start="\s*(" end=")" contains=@bladePhp,bladePhpParenBlock skipwhite contained diff --git a/syntax/coffee.vim b/syntax/coffee.vim index 589b853..f11a7c5 100644 --- a/syntax/coffee.vim +++ b/syntax/coffee.vim @@ -34,7 +34,7 @@ hi def link coffeeConditional Conditional syn match coffeeException /\<\%(try\|catch\|finally\)\>/ display hi def link coffeeException Exception -syn match coffeeKeyword /\<\%(new\|in\|of\|by\|and\|or\|not\|is\|isnt\|class\|extends\|super\|do\|yield\|debugger\|import\|export\)\>/ +syn match coffeeKeyword /\<\%(new\|in\|of\|by\|and\|or\|not\|is\|isnt\|class\|extends\|super\|do\|yield\|debugger\|import\|export\|await\)\>/ \ display " The `own` keyword is only a keyword after `for`. syn match coffeeKeyword /\/ contained containedin=coffeeRepeat diff --git a/syntax/erlang.vim b/syntax/erlang.vim index 57b0a6a..c01c0b2 100644 --- a/syntax/erlang.vim +++ b/syntax/erlang.vim @@ -4,9 +4,9 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'erlang') == -1 " Language: Erlang (http://www.erlang.org) " Maintainer: Csaba Hoch " Contributor: Adam Rutkowski -" Last Update: 2013-Nov-23 +" Last Update: 2017-Mar-05 " License: Vim license -" URL: https://github.com/hcs42/vim-erlang +" URL: https://github.com/vim-erlang/vim-erlang-runtime " Acknowledgements: This script was originally created by Kresimir Marzic [1]. " The script was then revamped by Csaba Hoch [2]. During the revamp, the new @@ -31,11 +31,8 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'erlang') == -1 " " syn keyword erlangAttribute myattr1 myattr2 contained -" 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") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -45,9 +42,7 @@ set cpo&vim " Case sensitive syn case match -if version >= 600 - setlocal iskeyword+=$,@-@ -endif +setlocal iskeyword+=$,@-@ " Comments syn match erlangComment '%.*$' contains=erlangCommentAnnotation,erlangTodo @@ -88,6 +83,7 @@ syn match erlangMacro '??\=[[:alnum:]_@]\+' syn match erlangMacro '\%(-define(\)\@<=[[:alnum:]_@]\+' syn match erlangMap '#' syn match erlangRecord '#\s*\l[[:alnum:]_@]*' +syn region erlangQuotedRecord start=/#\s*'/ end=/'/ contains=erlangQuotedAtomModifier " Shebang (this line has to be after the ErlangMap) syn match erlangShebang '^#!.*' @@ -153,118 +149,109 @@ let b:erlang_syntax_synced = 1 let s:old_style = (exists("g:erlang_old_style_highlight") && \g:erlang_old_style_highlight == 1) -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_erlang_inits") - if version < 508 - let did_erlang_inits = 1 - command -nargs=+ HiLink hi link - else - command -nargs=+ HiLink hi def link - endif - " Comments - HiLink erlangComment Comment - HiLink erlangCommentAnnotation Special - HiLink erlangTodo Todo - HiLink erlangShebang Comment +" Comments +hi def link erlangComment Comment +hi def link erlangCommentAnnotation Special +hi def link erlangTodo Todo +hi def link erlangShebang Comment - " Numbers - HiLink erlangNumberInteger Number - HiLink erlangNumberFloat Float +" Numbers +hi def link erlangNumberInteger Number +hi def link erlangNumberFloat Float - " Strings, atoms, characters - HiLink erlangString String +" Strings, atoms, characters +hi def link erlangString String - if s:old_style - HiLink erlangQuotedAtom Type - else - HiLink erlangQuotedAtom String - endif - - HiLink erlangStringModifier Special - HiLink erlangQuotedAtomModifier Special - HiLink erlangModifier Special - - " Operators, separators - HiLink erlangOperator Operator - HiLink erlangRightArrow Operator - if s:old_style - HiLink erlangBracket Normal - HiLink erlangPipe Normal - else - HiLink erlangBracket Delimiter - HiLink erlangPipe Delimiter - endif - - " Atoms, functions, variables, macros - if s:old_style - HiLink erlangAtom Normal - HiLink erlangLocalFuncCall Normal - HiLink erlangLocalFuncRef Normal - HiLink erlangGlobalFuncCall Function - HiLink erlangGlobalFuncRef Function - HiLink erlangVariable Normal - HiLink erlangMacro Normal - HiLink erlangRecord Normal - HiLink erlangMap Normal - else - HiLink erlangAtom String - HiLink erlangLocalFuncCall Normal - HiLink erlangLocalFuncRef Normal - HiLink erlangGlobalFuncCall Normal - HiLink erlangGlobalFuncRef Normal - HiLink erlangVariable Identifier - HiLink erlangMacro Macro - HiLink erlangRecord Structure - HiLink erlangMap Structure - endif - - " Bitstrings - if !s:old_style - HiLink erlangBitType Type - endif - - " Constants and Directives - if s:old_style - HiLink erlangAttribute Type - HiLink erlangMacroDef Type - HiLink erlangUnknownAttribute Normal - HiLink erlangInclude Type - HiLink erlangRecordDef Type - HiLink erlangDefine Type - HiLink erlangPreCondit Type - HiLink erlangType Type - else - HiLink erlangAttribute Keyword - HiLink erlangMacroDef Macro - HiLink erlangUnknownAttribute Normal - HiLink erlangInclude Include - HiLink erlangRecordDef Keyword - HiLink erlangDefine Define - HiLink erlangPreCondit PreCondit - HiLink erlangType Type - endif - - " Keywords - HiLink erlangKeyword Keyword - - " Build-in-functions (BIFs) - HiLink erlangBIF Function - - if s:old_style - HiLink erlangBoolean Statement - HiLink erlangExtra Statement - HiLink erlangSignal Statement - else - HiLink erlangBoolean Boolean - HiLink erlangExtra Statement - HiLink erlangSignal Statement - endif - - delcommand HiLink +if s:old_style +hi def link erlangQuotedAtom Type +else +hi def link erlangQuotedAtom String endif +hi def link erlangStringModifier Special +hi def link erlangQuotedAtomModifier Special +hi def link erlangModifier Special + +" Operators, separators +hi def link erlangOperator Operator +hi def link erlangRightArrow Operator +if s:old_style +hi def link erlangBracket Normal +hi def link erlangPipe Normal +else +hi def link erlangBracket Delimiter +hi def link erlangPipe Delimiter +endif + +" Atoms, functions, variables, macros +if s:old_style +hi def link erlangAtom Normal +hi def link erlangLocalFuncCall Normal +hi def link erlangLocalFuncRef Normal +hi def link erlangGlobalFuncCall Function +hi def link erlangGlobalFuncRef Function +hi def link erlangVariable Normal +hi def link erlangMacro Normal +hi def link erlangRecord Normal +hi def link erlangQuotedRecord Normal +hi def link erlangMap Normal +else +hi def link erlangAtom String +hi def link erlangLocalFuncCall Normal +hi def link erlangLocalFuncRef Normal +hi def link erlangGlobalFuncCall Normal +hi def link erlangGlobalFuncRef Normal +hi def link erlangVariable Identifier +hi def link erlangMacro Macro +hi def link erlangRecord Structure +hi def link erlangQuotedRecord Structure +hi def link erlangMap Structure +endif + +" Bitstrings +if !s:old_style +hi def link erlangBitType Type +endif + +" Constants and Directives +if s:old_style +hi def link erlangAttribute Type +hi def link erlangMacroDef Type +hi def link erlangUnknownAttribute Normal +hi def link erlangInclude Type +hi def link erlangRecordDef Type +hi def link erlangDefine Type +hi def link erlangPreCondit Type +hi def link erlangType Type +else +hi def link erlangAttribute Keyword +hi def link erlangMacroDef Macro +hi def link erlangUnknownAttribute Normal +hi def link erlangInclude Include +hi def link erlangRecordDef Keyword +hi def link erlangDefine Define +hi def link erlangPreCondit PreCondit +hi def link erlangType Type +endif + +" Keywords +hi def link erlangKeyword Keyword + +" Build-in-functions (BIFs) +hi def link erlangBIF Function + +if s:old_style +hi def link erlangBoolean Statement +hi def link erlangExtra Statement +hi def link erlangSignal Statement +else +hi def link erlangBoolean Boolean +hi def link erlangExtra Statement +hi def link erlangSignal Statement +endif + + let b:current_syntax = "erlang" let &cpo = s:cpo_save diff --git a/syntax/haskell.vim b/syntax/haskell.vim index bc86fbe..e301742 100644 --- a/syntax/haskell.vim +++ b/syntax/haskell.vim @@ -24,14 +24,14 @@ endif syn spell notoplevel syn match haskellRecordField contained containedin=haskellBlock - \ "[_a-z][a-zA-Z0-9_']*\(,\s*[_a-z][a-zA-Z0-9_']*\)*\(\s*::\|\n\s\+::\)" + \ "[_a-z][a-zA-Z0-9_']*\(,\s*[_a-z][a-zA-Z0-9_']*\)*\_s\+::\s" \ contains= \ haskellIdentifier, \ haskellOperators, \ haskellSeparator, \ haskellParens syn match haskellTypeSig - \ "^\s*\(where\s\+\|let\s\+\|default\s\+\)\?[_a-z][a-zA-Z0-9_']*\(,\s*[_a-z][a-zA-Z0-9_']*\)*\(\s*::\|\n\s\+::\)" + \ "^\s*\(where\s\+\|let\s\+\|default\s\+\)\?[_a-z][a-zA-Z0-9_']*\(,\s*[_a-z][a-zA-Z0-9_']*\)*\_s\+::\s" \ contains= \ haskellWhere, \ haskellLet, @@ -47,7 +47,7 @@ syn match haskellDecl "\<\(type\|data\)\>\s\+\(\\)\?" syn keyword haskellDefault default syn keyword haskellImportKeywords import qualified safe as hiding contained syn keyword haskellForeignKeywords foreign export import ccall safe unsafe interruptible capi prim contained -syn region haskellForeignImport start="\" end="::" keepend +syn region haskellForeignImport start="\" end="\_s\+::\s" keepend \ contains= \ haskellString, \ haskellOperators, diff --git a/syntax/html.vim b/syntax/html.vim index da9117d..3f58cf0 100644 --- a/syntax/html.vim +++ b/syntax/html.vim @@ -2,8 +2,9 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'html5') == -1 " Vim syntax file " Language: HTML (version 5.1) -" SVG (SVG 1.1 (Second Edition) ) -" Last Change: 2016 Jan 20 +" SVG (SVG 1.1 Second Edition) +" MathML (MathML 3.0 Second Edition) +" Last Change: 2017 Mar 07 " License: Public domain " (but let me know if you like :) ) " @@ -18,6 +19,15 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'html5') == -1 " Modified: htdebeer " Changes: add common SVG elements and attributes for inline SVG +" Patch 7.4.1142 +if has("patch-7.4-1142") + if has("win32") + syn iskeyword @,48-57,_,128-167,224-235,- + else + syn iskeyword @,48-57,_,192-255,- + endif +endif + " HTML 5 tags syn keyword htmlTagName contained article aside audio canvas command syn keyword htmlTagName contained datalist details dialog embed figcaption figure footer @@ -90,7 +100,7 @@ syn keyword htmlArg contained xml:lang xml:space xml:base xmlns syn keyword htmlArg contained onafterprint onbeforeprint onbeforeunload onblur onerror onfocus onhashchange onload syn keyword htmlArg contained onmessage onoffline ononline onpopstate onredo onresize onstorage onundo onunload "