aboutsummaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/CMakeLists.txt16
-rw-r--r--runtime/autoload/clojurecomplete.vim10
-rw-r--r--runtime/doc/api.txt61
-rw-r--r--runtime/doc/deprecated.txt3
-rw-r--r--runtime/doc/diagnostic.txt290
-rw-r--r--runtime/doc/eval.txt7
-rw-r--r--runtime/doc/indent.txt56
-rw-r--r--runtime/doc/lsp.txt30
-rw-r--r--runtime/doc/lua.txt60
-rw-r--r--runtime/doc/map.txt3
-rw-r--r--runtime/doc/options.txt9
-rw-r--r--runtime/doc/syntax.txt48
-rw-r--r--runtime/doc/tips.txt1
-rw-r--r--runtime/doc/various.txt6
-rw-r--r--runtime/ftplugin/changelog.vim26
-rw-r--r--runtime/ftplugin/clojure.vim12
-rw-r--r--runtime/ftplugin/mail.vim10
-rw-r--r--runtime/ftplugin/meson.vim23
-rw-r--r--runtime/ftplugin/nsis.vim4
-rw-r--r--runtime/ftplugin/spec.vim4
-rw-r--r--runtime/indent/clojure.vim19
-rw-r--r--runtime/indent/dosbatch.vim4
-rw-r--r--runtime/indent/meson.vim2
-rw-r--r--runtime/indent/nsis.vim4
-rw-r--r--runtime/indent/teraterm.vim4
-rw-r--r--runtime/indent/vim.vim4
-rw-r--r--runtime/lua/vim/diagnostic.lua717
-rw-r--r--runtime/lua/vim/lsp.lua185
-rw-r--r--runtime/lua/vim/lsp/buf.lua42
-rw-r--r--runtime/lua/vim/lsp/codelens.lua6
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua24
-rw-r--r--runtime/lua/vim/lsp/handlers.lua5
-rw-r--r--runtime/lua/vim/lsp/rpc.lua29
-rw-r--r--runtime/lua/vim/lsp/sync.lua381
-rw-r--r--runtime/lua/vim/lsp/util.lua247
-rw-r--r--runtime/lua/vim/shared.lua2
-rw-r--r--runtime/lua/vim/ui.lua38
-rw-r--r--runtime/pack/dist/opt/termdebug/plugin/termdebug.vim29
-rw-r--r--runtime/syntax/arduino.vim99
-rw-r--r--runtime/syntax/clojure.vim69
-rw-r--r--runtime/syntax/debchangelog.vim5
-rw-r--r--runtime/syntax/debsources.vim5
-rw-r--r--runtime/syntax/help_ru.vim4
-rw-r--r--runtime/syntax/meson.vim18
-rw-r--r--runtime/syntax/nsis.vim42
-rw-r--r--runtime/syntax/sh.vim8
-rw-r--r--runtime/syntax/vim.vim7
47 files changed, 1717 insertions, 961 deletions
diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt
index 4fdcfc0f33..37029874f2 100644
--- a/runtime/CMakeLists.txt
+++ b/runtime/CMakeLists.txt
@@ -21,12 +21,12 @@ add_custom_command(OUTPUT ${GENERATED_SYN_VIM}
${FUNCS_DATA}
)
-file(GLOB PACKAGES ${PROJECT_SOURCE_DIR}/runtime/pack/dist/opt/*)
+glob_wrapper(PACKAGES ${PROJECT_SOURCE_DIR}/runtime/pack/dist/opt/*)
set(GENERATED_PACKAGE_TAGS)
foreach(PACKAGE ${PACKAGES})
get_filename_component(PACKNAME ${PACKAGE} NAME)
- file(GLOB "${PACKNAME}_DOC_FILES" ${PACKAGE}/doc/*.txt)
+ glob_wrapper("${PACKNAME}_DOC_FILES" ${PACKAGE}/doc/*.txt)
if(${PACKNAME}_DOC_FILES)
file(MAKE_DIRECTORY ${GENERATED_PACKAGE_DIR}/${PACKNAME})
add_custom_command(OUTPUT "${GENERATED_PACKAGE_DIR}/${PACKNAME}/doc/tags"
@@ -54,7 +54,7 @@ foreach(PACKAGE ${PACKAGES})
endif()
endforeach()
-file(GLOB DOCFILES ${PROJECT_SOURCE_DIR}/runtime/doc/*.txt)
+glob_wrapper(DOCFILES ${PROJECT_SOURCE_DIR}/runtime/doc/*.txt)
set(BUILDDOCFILES)
foreach(DF ${DOCFILES})
@@ -114,9 +114,7 @@ if(NOT APPLE)
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps)
endif()
-file(GLOB_RECURSE RUNTIME_PROGRAMS
- RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
- *.awk *.sh *.bat)
+globrecurse_wrapper(RUNTIME_PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR} *.awk *.sh *.bat)
foreach(PROG ${RUNTIME_PROGRAMS})
get_filename_component(BASEDIR ${PROG} PATH)
@@ -124,10 +122,8 @@ foreach(PROG ${RUNTIME_PROGRAMS})
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/${BASEDIR})
endforeach()
-file(GLOB_RECURSE RUNTIME_FILES
- RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
- rgb.txt
- *.vim *.lua *.dict *.py *.rb *.ps *.spl *.tutor *.tutor.json)
+globrecurse_wrapper(RUNTIME_FILES ${CMAKE_CURRENT_SOURCE_DIR}
+ rgb.txt *.vim *.lua *.dict *.py *.rb *.ps *.spl *.tutor *.tutor.json)
foreach(F ${RUNTIME_FILES})
get_filename_component(BASEDIR ${F} PATH)
diff --git a/runtime/autoload/clojurecomplete.vim b/runtime/autoload/clojurecomplete.vim
index 2c0f0eacd4..9f2c39081a 100644
--- a/runtime/autoload/clojurecomplete.vim
+++ b/runtime/autoload/clojurecomplete.vim
@@ -1,15 +1,15 @@
" Vim completion script
" Language: Clojure
-" Maintainer: Alex Vear <av@axvr.io>
+" Maintainer: Alex Vear <alex@vear.uk>
" Former Maintainers: Sung Pae <self@sungpae.com>
" URL: https://github.com/clojure-vim/clojure.vim
" License: Vim (see :h license)
-" Last Change: 2021-02-13
+" Last Change: 2021-10-26
" -*- COMPLETION WORDS -*-
-" Generated from https://github.com/clojure-vim/clojure.vim/blob/f8594e7030cdfb0b7990ac92953c77a08a7220f0/clj/src/vim_clojure_static/generate.clj
-" Clojure version 1.10.2
-let s:words = ["*","*'","*1","*2","*3","*agent*","*allow-unresolved-vars*","*assert*","*clojure-version*","*command-line-args*","*compile-files*","*compile-path*","*compiler-options*","*data-readers*","*default-data-reader-fn*","*e","*err*","*file*","*flush-on-newline*","*fn-loader*","*in*","*math-context*","*ns*","*out*","*print-dup*","*print-length*","*print-level*","*print-meta*","*print-namespace-maps*","*print-readably*","*read-eval*","*reader-resolver*","*source-path*","*suppress-read*","*unchecked-math*","*use-context-classloader*","*verbose-defrecords*","*warn-on-reflection*","+","+'","-","-'","->","->>","->ArrayChunk","->Eduction","->Vec","->VecNode","->VecSeq","-cache-protocol-fn","-reset-methods",".","..","/","<","<=","=","==",">",">=","EMPTY-NODE","Inst","PrintWriter-on","StackTraceElement->vec","Throwable->map","accessor","aclone","add-classpath","add-tap","add-watch","agent","agent-error","agent-errors","aget","alength","alias","all-ns","alter","alter-meta!","alter-var-root","amap","ancestors","and","any?","apply","areduce","array-map","as->","aset","aset-boolean","aset-byte","aset-char","aset-double","aset-float","aset-int","aset-long","aset-short","assert","assoc!","assoc","assoc-in","associative?","atom","await","await-for","await1","bases","bean","bigdec","bigint","biginteger","binding","bit-and","bit-and-not","bit-clear","bit-flip","bit-not","bit-or","bit-set","bit-shift-left","bit-shift-right","bit-test","bit-xor","boolean","boolean-array","boolean?","booleans","bound-fn","bound-fn*","bound?","bounded-count","butlast","byte","byte-array","bytes","bytes?","case","case-fallthrough-err-impl","cast","cat","catch","char","char-array","char-escape-string","char-name-string","char?","chars","chunk","chunk-append","chunk-buffer","chunk-cons","chunk-first","chunk-next","chunk-rest","chunked-seq?","class","class?","clear-agent-errors","clojure-version","coll?","comment","commute","comp","comparator","compare","compare-and-set!","compile","complement","completing","concat","cond","cond->","cond->>","condp","conj!","conj","cons","constantly","construct-proxy","contains?","count","counted?","create-ns","create-struct","cycle","dec","dec'","decimal?","declare","dedupe","def","default-data-readers","definline","definterface","defmacro","defmethod","defmulti","defn","defn-","defonce","defprotocol","defrecord","defstruct","deftype","delay","delay?","deliver","denominator","deref","derive","descendants","destructure","disj!","disj","dissoc!","dissoc","distinct","distinct?","do","doall","dorun","doseq","dosync","dotimes","doto","double","double-array","double?","doubles","drop","drop-last","drop-while","eduction","empty","empty?","ensure","ensure-reduced","enumeration-seq","error-handler","error-mode","eval","even?","every-pred","every?","ex-cause","ex-data","ex-info","ex-message","extend","extend-protocol","extend-type","extenders","extends?","false?","ffirst","file-seq","filter","filterv","finally","find","find-keyword","find-ns","find-protocol-impl","find-protocol-method","find-var","first","flatten","float","float-array","float?","floats","flush","fn","fn","fn?","fnext","fnil","for","force","format","frequencies","future","future-call","future-cancel","future-cancelled?","future-done?","future?","gen-class","gen-interface","gensym","get","get-in","get-method","get-proxy-class","get-thread-bindings","get-validator","group-by","halt-when","hash","hash-combine","hash-map","hash-ordered-coll","hash-set","hash-unordered-coll","ident?","identical?","identity","if","if-let","if-not","if-some","ifn?","import","in-ns","inc","inc'","indexed?","init-proxy","inst-ms","inst-ms*","inst?","instance?","int","int-array","int?","integer?","interleave","intern","interpose","into","into-array","ints","io!","isa?","iterate","iterator-seq","juxt","keep","keep-indexed","key","keys","keyword","keyword?","last","lazy-cat","lazy-seq","let","let","letfn","line-seq","list","list*","list?","load","load-file","load-reader","load-string","loaded-libs","locking","long","long-array","longs","loop","loop","macroexpand","macroexpand-1","make-array","make-hierarchy","map","map-entry?","map-indexed","map?","mapcat","mapv","max","max-key","memfn","memoize","merge","merge-with","meta","method-sig","methods","min","min-key","mix-collection-hash","mod","monitor-enter","monitor-exit","munge","name","namespace","namespace-munge","nat-int?","neg-int?","neg?","new","newline","next","nfirst","nil?","nnext","not","not-any?","not-empty","not-every?","not=","ns","ns-aliases","ns-imports","ns-interns","ns-map","ns-name","ns-publics","ns-refers","ns-resolve","ns-unalias","ns-unmap","nth","nthnext","nthrest","num","number?","numerator","object-array","odd?","or","parents","partial","partition","partition-all","partition-by","pcalls","peek","persistent!","pmap","pop!","pop","pop-thread-bindings","pos-int?","pos?","pr","pr-str","prefer-method","prefers","primitives-classnames","print","print-ctor","print-dup","print-method","print-simple","print-str","printf","println","println-str","prn","prn-str","promise","proxy","proxy-call-with-super","proxy-mappings","proxy-name","proxy-super","push-thread-bindings","pvalues","qualified-ident?","qualified-keyword?","qualified-symbol?","quot","quote","rand","rand-int","rand-nth","random-sample","range","ratio?","rational?","rationalize","re-find","re-groups","re-matcher","re-matches","re-pattern","re-seq","read","read+string","read-line","read-string","reader-conditional","reader-conditional?","realized?","record?","recur","reduce","reduce-kv","reduced","reduced?","reductions","ref","ref-history-count","ref-max-history","ref-min-history","ref-set","refer","refer-clojure","reify","release-pending-sends","rem","remove","remove-all-methods","remove-method","remove-ns","remove-tap","remove-watch","repeat","repeatedly","replace","replicate","require","requiring-resolve","reset!","reset-meta!","reset-vals!","resolve","rest","restart-agent","resultset-seq","reverse","reversible?","rseq","rsubseq","run!","satisfies?","second","select-keys","send","send-off","send-via","seq","seq?","seqable?","seque","sequence","sequential?","set!","set","set-agent-send-executor!","set-agent-send-off-executor!","set-error-handler!","set-error-mode!","set-validator!","set?","short","short-array","shorts","shuffle","shutdown-agents","simple-ident?","simple-keyword?","simple-symbol?","slurp","some","some->","some->>","some-fn","some?","sort","sort-by","sorted-map","sorted-map-by","sorted-set","sorted-set-by","sorted?","special-symbol?","spit","split-at","split-with","str","string?","struct","struct-map","subs","subseq","subvec","supers","swap!","swap-vals!","symbol","symbol?","sync","tagged-literal","tagged-literal?","take","take-last","take-nth","take-while","tap>","test","the-ns","thread-bound?","throw","time","to-array","to-array-2d","trampoline","transduce","transient","tree-seq","true?","try","type","unchecked-add","unchecked-add-int","unchecked-byte","unchecked-char","unchecked-dec","unchecked-dec-int","unchecked-divide-int","unchecked-double","unchecked-float","unchecked-inc","unchecked-inc-int","unchecked-int","unchecked-long","unchecked-multiply","unchecked-multiply-int","unchecked-negate","unchecked-negate-int","unchecked-remainder-int","unchecked-short","unchecked-subtract","unchecked-subtract-int","underive","unquote","unquote-splicing","unreduced","unsigned-bit-shift-right","update","update-in","update-proxy","uri?","use","uuid?","val","vals","var","var-get","var-set","var?","vary-meta","vec","vector","vector-of","vector?","volatile!","volatile?","vreset!","vswap!","when","when-first","when-let","when-not","when-some","while","with-bindings","with-bindings*","with-in-str","with-loading-context","with-local-vars","with-meta","with-open","with-out-str","with-precision","with-redefs","with-redefs-fn","xml-seq","zero?","zipmap"]
+" Generated from https://github.com/clojure-vim/clojure.vim/blob/62b215f079ce0f3834fd295c7a7f6bd8cc54bcc3/clj/src/vim_clojure_static/generate.clj
+" Clojure version 1.10.3
+let s:words = ["*","*'","*1","*2","*3","*agent*","*allow-unresolved-vars*","*assert*","*clojure-version*","*command-line-args*","*compile-files*","*compile-path*","*compiler-options*","*data-readers*","*default-data-reader-fn*","*e","*err*","*file*","*flush-on-newline*","*fn-loader*","*in*","*math-context*","*ns*","*out*","*print-dup*","*print-length*","*print-level*","*print-meta*","*print-namespace-maps*","*print-readably*","*read-eval*","*reader-resolver*","*source-path*","*suppress-read*","*unchecked-math*","*use-context-classloader*","*verbose-defrecords*","*warn-on-reflection*","+","+'","-","-'","->","->>","->ArrayChunk","->Eduction","->Vec","->VecNode","->VecSeq","-cache-protocol-fn","-reset-methods",".","..","/","<","<=","=","==",">",">=","EMPTY-NODE","Inst","PrintWriter-on","StackTraceElement->vec","Throwable->map","accessor","aclone","add-classpath","add-tap","add-watch","agent","agent-error","agent-errors","aget","alength","alias","all-ns","alter","alter-meta!","alter-var-root","amap","ancestors","and","any?","apply","areduce","array-map","as->","aset","aset-boolean","aset-byte","aset-char","aset-double","aset-float","aset-int","aset-long","aset-short","assert","assoc!","assoc","assoc-in","associative?","atom","await","await-for","await1","bases","bean","bigdec","bigint","biginteger","binding","bit-and","bit-and-not","bit-clear","bit-flip","bit-not","bit-or","bit-set","bit-shift-left","bit-shift-right","bit-test","bit-xor","boolean","boolean-array","boolean?","booleans","bound-fn","bound-fn*","bound?","bounded-count","butlast","byte","byte-array","bytes","bytes?","case","cast","cat","catch","char","char-array","char-escape-string","char-name-string","char?","chars","chunk","chunk-append","chunk-buffer","chunk-cons","chunk-first","chunk-next","chunk-rest","chunked-seq?","class","class?","clear-agent-errors","clojure-version","coll?","comment","commute","comp","comparator","compare","compare-and-set!","compile","complement","completing","concat","cond","cond->","cond->>","condp","conj!","conj","cons","constantly","construct-proxy","contains?","count","counted?","create-ns","create-struct","cycle","dec","dec'","decimal?","declare","dedupe","def","default-data-readers","definline","definterface","defmacro","defmethod","defmulti","defn","defn-","defonce","defprotocol","defrecord","defstruct","deftype","delay","delay?","deliver","denominator","deref","derive","descendants","destructure","disj!","disj","dissoc!","dissoc","distinct","distinct?","do","doall","dorun","doseq","dosync","dotimes","doto","double","double-array","double?","doubles","drop","drop-last","drop-while","eduction","empty","empty?","ensure","ensure-reduced","enumeration-seq","error-handler","error-mode","eval","even?","every-pred","every?","ex-cause","ex-data","ex-info","ex-message","extend","extend-protocol","extend-type","extenders","extends?","false?","ffirst","file-seq","filter","filterv","finally","find","find-keyword","find-ns","find-protocol-impl","find-protocol-method","find-var","first","flatten","float","float-array","float?","floats","flush","fn","fn","fn?","fnext","fnil","for","force","format","frequencies","future","future-call","future-cancel","future-cancelled?","future-done?","future?","gen-class","gen-interface","gensym","get","get-in","get-method","get-proxy-class","get-thread-bindings","get-validator","group-by","halt-when","hash","hash-combine","hash-map","hash-ordered-coll","hash-set","hash-unordered-coll","ident?","identical?","identity","if","if-let","if-not","if-some","ifn?","import","in-ns","inc","inc'","indexed?","init-proxy","inst-ms","inst-ms*","inst?","instance?","int","int-array","int?","integer?","interleave","intern","interpose","into","into-array","ints","io!","isa?","iterate","iterator-seq","juxt","keep","keep-indexed","key","keys","keyword","keyword?","last","lazy-cat","lazy-seq","let","let","letfn","line-seq","list","list*","list?","load","load-file","load-reader","load-string","loaded-libs","locking","long","long-array","longs","loop","loop","macroexpand","macroexpand-1","make-array","make-hierarchy","map","map-entry?","map-indexed","map?","mapcat","mapv","max","max-key","memfn","memoize","merge","merge-with","meta","method-sig","methods","min","min-key","mix-collection-hash","mod","monitor-enter","monitor-exit","munge","name","namespace","namespace-munge","nat-int?","neg-int?","neg?","new","newline","next","nfirst","nil?","nnext","not","not-any?","not-empty","not-every?","not=","ns","ns-aliases","ns-imports","ns-interns","ns-map","ns-name","ns-publics","ns-refers","ns-resolve","ns-unalias","ns-unmap","nth","nthnext","nthrest","num","number?","numerator","object-array","odd?","or","parents","partial","partition","partition-all","partition-by","pcalls","peek","persistent!","pmap","pop!","pop","pop-thread-bindings","pos-int?","pos?","pr","pr-str","prefer-method","prefers","primitives-classnames","print","print-ctor","print-dup","print-method","print-simple","print-str","printf","println","println-str","prn","prn-str","promise","proxy","proxy-call-with-super","proxy-mappings","proxy-name","proxy-super","push-thread-bindings","pvalues","qualified-ident?","qualified-keyword?","qualified-symbol?","quot","quote","rand","rand-int","rand-nth","random-sample","range","ratio?","rational?","rationalize","re-find","re-groups","re-matcher","re-matches","re-pattern","re-seq","read","read+string","read-line","read-string","reader-conditional","reader-conditional?","realized?","record?","recur","reduce","reduce-kv","reduced","reduced?","reductions","ref","ref-history-count","ref-max-history","ref-min-history","ref-set","refer","refer-clojure","reify","release-pending-sends","rem","remove","remove-all-methods","remove-method","remove-ns","remove-tap","remove-watch","repeat","repeatedly","replace","replicate","require","requiring-resolve","reset!","reset-meta!","reset-vals!","resolve","rest","restart-agent","resultset-seq","reverse","reversible?","rseq","rsubseq","run!","satisfies?","second","select-keys","send","send-off","send-via","seq","seq?","seqable?","seque","sequence","sequential?","set!","set","set-agent-send-executor!","set-agent-send-off-executor!","set-error-handler!","set-error-mode!","set-validator!","set?","short","short-array","shorts","shuffle","shutdown-agents","simple-ident?","simple-keyword?","simple-symbol?","slurp","some","some->","some->>","some-fn","some?","sort","sort-by","sorted-map","sorted-map-by","sorted-set","sorted-set-by","sorted?","special-symbol?","spit","split-at","split-with","str","string?","struct","struct-map","subs","subseq","subvec","supers","swap!","swap-vals!","symbol","symbol?","sync","tagged-literal","tagged-literal?","take","take-last","take-nth","take-while","tap>","test","the-ns","thread-bound?","throw","time","to-array","to-array-2d","trampoline","transduce","transient","tree-seq","true?","try","type","unchecked-add","unchecked-add-int","unchecked-byte","unchecked-char","unchecked-dec","unchecked-dec-int","unchecked-divide-int","unchecked-double","unchecked-float","unchecked-inc","unchecked-inc-int","unchecked-int","unchecked-long","unchecked-multiply","unchecked-multiply-int","unchecked-negate","unchecked-negate-int","unchecked-remainder-int","unchecked-short","unchecked-subtract","unchecked-subtract-int","underive","unquote","unquote-splicing","unreduced","unsigned-bit-shift-right","update","update-in","update-proxy","uri?","use","uuid?","val","vals","var","var-get","var-set","var?","vary-meta","vec","vector","vector-of","vector?","volatile!","volatile?","vreset!","vswap!","when","when-first","when-let","when-not","when-some","while","with-bindings","with-bindings*","with-in-str","with-loading-context","with-local-vars","with-meta","with-open","with-out-str","with-precision","with-redefs","with-redefs-fn","xml-seq","zero?","zipmap"]
" Simple word completion for special forms and public vars in clojure.core
function! clojurecomplete#Complete(findstart, base)
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 878fc2b301..bb8e83f84a 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -1078,7 +1078,7 @@ nvim_get_keymap({mode}) *nvim_get_keymap()*
Array of maparg()-like dictionaries describing mappings.
The "buffer" key is always zero.
-nvim_get_mark({name}) *nvim_get_mark()*
+nvim_get_mark({name}, {opts}) *nvim_get_mark()*
Return a tuple (row, col, buffer, buffername) representing the
position of the uppercase/file named mark. See |mark-motions|.
@@ -1090,6 +1090,7 @@ nvim_get_mark({name}) *nvim_get_mark()*
Parameters: ~
{name} Mark name
+ {opts} Optional parameters. Reserved for future use.
Return: ~
4-tuple (row, col, buffer, buffername), (0, 0, 0, '') if
@@ -1877,7 +1878,7 @@ nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
callbacks.
{opts} Optional parameters.
• on_lines: Lua callback invoked on change.
- Return`true`to detach. Args:
+ Return `true` to detach. Args:
• the string "lines"
• buffer handle
• b:changedtick
@@ -1893,7 +1894,7 @@ nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
• on_bytes: lua callback invoked on change.
This callback receives more granular
information about the change compared to
- on_lines. Return`true`to detach. Args:
+ on_lines. Return `true` to detach. Args:
• the string "bytes"
• buffer handle
• b:changedtick
@@ -2332,7 +2333,7 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
• hl_mode : control how highlights are combined
with the highlights of the text. Currently
only affects virt_text highlights, but might
- affect`hl_group`in later versions.
+ affect `hl_group` in later versions.
• "replace": only show the virt_text color.
This is the default
• "combine": combine with background text
@@ -2420,7 +2421,7 @@ nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing}, {replacement})
{replacement} Array of lines to use as replacement
*nvim_buf_set_mark()*
-nvim_buf_set_mark({buffer}, {name}, {line}, {col})
+nvim_buf_set_mark({buffer}, {name}, {line}, {col}, {opts})
Sets a named mark in the given buffer, all marks are allowed
file/uppercase, visual, last change, etc. See |mark-motions|.
@@ -2434,6 +2435,7 @@ nvim_buf_set_mark({buffer}, {name}, {line}, {col})
{name} Mark name
{line} Line number
{col} Column/row number
+ {opts} Optional parameters. Reserved for future use.
Return: ~
true if the mark was set, else false.
@@ -2742,28 +2744,29 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
{buffer} Buffer to display, or 0 for current buffer
{enter} Enter the window (make it the current window)
{config} Map defining the window configuration. Keys:
- • `relative`: Sets the window layout to "floating", placed
- at (row,col) coordinates relative to:
+ • relative: Sets the window layout to
+ "floating", placed at (row,col) coordinates
+ relative to:
• "editor" The global editor grid
• "win" Window given by the `win` field, or
current window.
• "cursor" Cursor position in current window.
- • `win` : |window-ID| for relative="win".
- • `anchor`: Decides which corner of the float to place
- at (row,col):
+ • win: |window-ID| for relative="win".
+ • anchor: Decides which corner of the float to
+ place at (row,col):
• "NW" northwest (default)
• "NE" northeast
• "SW" southwest
• "SE" southeast
- • `width` : Window width (in character cells).
+ • width: Window width (in character cells).
Minimum of 1.
- • `height` : Window height (in character cells).
+ • height: Window height (in character cells).
Minimum of 1.
- • `bufpos`: Places float relative to buffer text (only
- when relative="win"). Takes a tuple of
- zero-indexed [line, column].`row`and`col`if given are applied relative to this
+ • bufpos: Places float relative to buffer text
+ (only when relative="win"). Takes a tuple of
+ zero-indexed [line, column]. `row` and `col` if given are applied relative to this
position, else they default to:
• `row=1` and `col=0` if `anchor` is "NW" or
"NE"
@@ -2771,19 +2774,19 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
"SE" (thus like a tooltip near the buffer
text).
- • `row` : Row position in units of "screen cell
+ • row: Row position in units of "screen cell
height", may be fractional.
- • `col` : Column position in units of "screen
- cell width", may be fractional.
- • `focusable` : Enable focus by user actions
+ • col: Column position in units of "screen cell
+ width", may be fractional.
+ • focusable: Enable focus by user actions
(wincmds, mouse events). Defaults to true.
Non-focusable windows can be entered by
|nvim_set_current_win()|.
- • `external` : GUI should display the window as
- an external top-level window. Currently
- accepts no other positioning configuration
- together with this.
- • `zindex`: Stacking order. floats with higher`zindex`go on top on floats with lower indices. Must
+ • external: GUI should display the window as an
+ external top-level window. Currently accepts
+ no other positioning configuration together
+ with this.
+ • zindex: Stacking order. floats with higher `zindex` go on top on floats with lower indices. Must
be larger than zero. The following screen
elements have hard-coded z-indices:
• 100: insert completion popupmenu
@@ -2794,7 +2797,7 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
are recommended, unless there is a good
reason to overshadow builtin elements.
- • `style`: Configure the appearance of the window.
+ • style: Configure the appearance of the window.
Currently only takes one non-empty value:
• "minimal" Nvim will display the window with
many UI options disabled. This is useful
@@ -2809,9 +2812,9 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
and clearing the |EndOfBuffer| region in
'winhighlight'.
- • `border`: Style of (optional) window border. This can
- either be a string or an array. The string
- values are
+ • border: Style of (optional) window border.
+ This can either be a string or an array. The
+ string values are
• "none": No border (default).
• "single": A single line box.
• "double": A double line box.
@@ -2841,7 +2844,7 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
It could also be specified by character: [
{"+", "MyCorner"}, {"x", "MyBorder"} ].
- • `noautocmd` : If true then no buffer-related
+ • noautocmd: If true then no buffer-related
autocommand events such as |BufEnter|,
|BufLeave| or |BufWinEnter| may fire from
calling this function.
diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt
index a7ce4135af..21a34178b3 100644
--- a/runtime/doc/deprecated.txt
+++ b/runtime/doc/deprecated.txt
@@ -85,6 +85,9 @@ For each of the functions below, use the corresponding function in
*vim.lsp.diagnostic.save()* Use |vim.diagnostic.set()| instead.
*vim.lsp.diagnostic.set_loclist()* Use |vim.diagnostic.setloclist()| instead.
*vim.lsp.diagnostic.set_qflist()* Use |vim.diagnostic.setqflist()| instead.
+
+The following have been replaced by |vim.diagnostic.open_float()|.
+
*vim.lsp.diagnostic.show_line_diagnostics()*
*vim.lsp.diagnostic.show_position_diagnostics()*
diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt
index 17d317522b..d53aae510e 100644
--- a/runtime/doc/diagnostic.txt
+++ b/runtime/doc/diagnostic.txt
@@ -75,6 +75,100 @@ Functions that take a severity as an optional parameter (e.g.
The latter form allows users to specify a range of severities.
==============================================================================
+HANDLERS *diagnostic-handlers*
+
+Diagnostics are shown to the user with |vim.diagnostic.show()|. The display of
+diagnostics is managed through handlers. A handler is a table with a "show"
+and (optionally) a "hide" function. The "show" function has the signature
+>
+ function(namespace, bufnr, diagnostics, opts)
+<
+and is responsible for displaying or otherwise handling the given
+diagnostics. The "hide" function takes care of "cleaning up" any actions taken
+by the "show" function and has the signature
+>
+ function(namespace, bufnr)
+<
+Handlers can be configured with |vim.diagnostic.config()| and added by
+creating a new key in `vim.diagnostic.handlers` (see
+|diagnostic-handlers-example|).
+
+The {opts} table passed to a handler is the full set of configuration options
+(that is, it is not limited to just the options for the handler itself). The
+values in the table are already resolved (i.e. if a user specifies a
+function for a config option, the function has already been evaluated).
+
+Nvim provides these handlers by default: "virtual_text", "signs", and
+"underline".
+
+ *diagnostic-handlers-example*
+The example below creates a new handler that notifies the user of diagnostics
+with |vim.notify()|: >
+
+ -- It's good practice to namespace custom handlers to avoid collisions
+ vim.diagnostic.handlers["my/notify"] = {
+ show = function(namespace, bufnr, diagnostics, opts)
+ -- In our example, the opts table has a "log_level" option
+ local level = opts["my/notify"].log_level
+
+ local name = vim.diagnostic.get_namespace(namespace).name
+ local msg = string.format("%d diagnostics in buffer %d from %s",
+ #diagnostics,
+ bufnr,
+ name)
+ vim.notify(msg, level)
+ end,
+ }
+
+ -- Users can configure the handler
+ vim.diagnostic.config({
+ ["my/notify"] = {
+ log_level = vim.log.levels.INFO
+ }
+ })
+<
+In this example, there is nothing to do when diagnostics are hidden, so we
+omit the "hide" function.
+
+Existing handlers can be overriden. For example, use the following to only
+show a sign for the highest severity diagnostic on a given line: >
+
+ -- Create a custom namespace. This will aggregate signs from all other
+ -- namespaces and only show the one with the highest severity on a
+ -- given line
+ local ns = vim.api.nvim_create_namespace("my_namespace")
+
+ -- Get a reference to the original signs handler
+ local orig_signs_handler = vim.diagnostic.handlers.signs
+
+ -- Override the built-in signs handler
+ vim.diagnostic.handlers.signs = {
+ show = function(_, bufnr, _, opts)
+ -- Get all diagnostics from the whole buffer rather than just the
+ -- diagnostics passed to the handler
+ local diagnostics = vim.diagnostic.get(bufnr)
+
+ -- Find the "worst" diagnostic per line
+ local max_severity_per_line = {}
+ for _, d in pairs(diagnostics) do
+ local m = max_severity_per_line[d.lnum]
+ if not m or d.severity < m.severity then
+ max_severity_per_line[d.lnum] = d
+ end
+ end
+
+ -- Pass the filtered diagnostics (with our custom namespace) to
+ -- the original handler
+ local filtered_diagnostics = vim.tbl_values(max_severity_per_line)
+ orig_signs_handler.show(ns, bufnr, filtered_diagnostics, opts)
+ end,
+ hide = function(_, bufnr)
+ orig_signs_handler.hide(ns, bufnr)
+ end,
+ }
+<
+
+==============================================================================
HIGHLIGHTS *diagnostic-highlights*
All highlights defined for diagnostics begin with `Diagnostic` followed by
@@ -202,51 +296,6 @@ Example: >
autocmd User DiagnosticsChanged lua vim.diagnostic.setqflist({open = false })
<
==============================================================================
-CUSTOMIZATION *diagnostic-config*
-
-If you need more customization over the way diagnostics are displayed than the
-built-in configuration options provide, you can override the display handler
-explicitly. For example, use the following to only show a sign for the highest
-severity diagnostic on a given line: >
-
- -- Disable the default signs handler
- vim.diagnostic.config({signs = false})
-
- -- Create a namespace. This won't be used to add any diagnostics,
- -- only to display them.
- local ns = vim.api.nvim_create_namespace("my_namespace")
-
- -- Create a reference to the original function
- local orig_show = vim.diagnostic.show
-
- local function set_signs(bufnr)
- -- Get all diagnostics from the current buffer
- local diagnostics = vim.diagnostic.get(bufnr)
-
- -- Find the "worst" diagnostic per line
- local max_severity_per_line = {}
- for _, d in pairs(diagnostics) do
- local m = max_severity_per_line[d.lnum]
- if not m or d.severity < m.severity then
- max_severity_per_line[d.lnum] = d
- end
- end
-
- -- Show the filtered diagnostics using the custom namespace. Use the
- -- reference to the original function to avoid a loop.
- local filtered_diagnostics = vim.tbl_values(max_severity_per_line)
- orig_show(ns, bufnr, filtered_diagnostics, {
- virtual_text=false,
- underline=false,
- signs=true
- })
- end
-
- function vim.diagnostic.show(namespace, bufnr, ...)
- orig_show(namespace, bufnr, ...)
- set_signs(bufnr)
- end
-<
==============================================================================
Lua module: vim.diagnostic *diagnostic-api*
@@ -262,12 +311,12 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
For example, if a user enables virtual text globally with >
- vim.diagnostic.config({virt_text = true})
+ vim.diagnostic.config({virtual_text = true})
<
and a diagnostic producer sets diagnostics with >
- vim.diagnostic.set(ns, 0, diagnostics, {virt_text = false})
+ vim.diagnostic.set(ns, 0, diagnostics, {virtual_text = false})
<
then virtual text will not be enabled for those diagnostics.
@@ -302,7 +351,7 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
• format: (function) A function that takes
a diagnostic as input and returns a
string. The return value is the text used
- to display the diagnostic. Example:>
+ to display the diagnostic. Example: >
function(diagnostic)
if diagnostic.severity == vim.diagnostic.severity.ERROR then
@@ -324,6 +373,29 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
Otherwise, all signs use the same
priority.
+ • float: Options for floating windows:
+ • severity: See |diagnostic-severity|.
+ • show_header: (boolean, default true) Show
+ "Diagnostics:" header
+ • source: (string) Include the diagnostic
+ source in the message. One of "always" or
+ "if_many".
+ • format: (function) A function that takes
+ a diagnostic as input and returns a
+ string. The return value is the text used
+ to display the diagnostic.
+ • prefix: (function or string) Prefix each
+ diagnostic in the floating window. If a
+ function, it must have the signature
+ (diagnostic, i, total) -> string, where
+ {i} is the index of the diagnostic being
+ evaluated and {total} is the total number
+ of diagnostics displayed in the window.
+ The returned string is prepended to each
+ diagnostic in the window. Otherwise, if
+ {prefix} is a string, it is prepended to
+ each diagnostic.
+
• update_in_insert: (default false) Update
diagnostics in Insert mode (if false,
diagnostics are updated on InsertLeave)
@@ -382,6 +454,15 @@ get({bufnr}, {opts}) *vim.diagnostic.get()*
Return: ~
table A list of diagnostic items |diagnostic-structure|.
+get_namespace({namespace}) *vim.diagnostic.get_namespace()*
+ Get namespace metadata.
+
+ Parameters: ~
+ {ns} number Diagnostic namespace
+
+ Return: ~
+ table Namespace metadata
+
get_namespaces() *vim.diagnostic.get_namespaces()*
Get current diagnostic namespaces.
@@ -442,12 +523,10 @@ goto_next({opts}) *vim.diagnostic.goto_next()*
• wrap: (boolean, default true) Whether to loop
around file or not. Similar to 'wrapscan'.
• severity: See |diagnostic-severity|.
- • enable_popup: (boolean, default true) Call
- |vim.diagnostic.show_line_diagnostics()| on
- jump.
- • popup_opts: (table) Table to pass as {opts}
- parameter to
- |vim.diagnostic.show_line_diagnostics()|
+ • float: (boolean or table, default true) If
+ "true", call |vim.diagnostic.open_float()| after
+ moving. If a table, pass the table as the {opts}
+ parameter to |vim.diagnostic.open_float()|.
• win_id: (number, default 0) Window ID
goto_prev({opts}) *vim.diagnostic.goto_prev()*
@@ -468,7 +547,9 @@ hide({namespace}, {bufnr}) *vim.diagnostic.hide()*
|vim.diagnostic.disable()|.
Parameters: ~
- {namespace} number The diagnostic namespace
+ {namespace} number|nil Diagnostic namespace. When
+ omitted, hide diagnostics from all
+ namespaces.
{bufnr} number|nil Buffer number. Defaults to the
current buffer.
@@ -508,6 +589,49 @@ match({str}, {pat}, {groups}, {severity_map}, {defaults})
diagnostic |diagnostic-structure| or `nil` if {pat} fails
to match {str}.
+open_float({bufnr}, {opts}) *vim.diagnostic.open_float()*
+ Show diagnostics in a floating window.
+
+ Parameters: ~
+ {bufnr} number|nil Buffer number. Defaults to the current
+ buffer.
+ {opts} table|nil Configuration table with the same keys
+ as |vim.lsp.util.open_floating_preview()| in
+ addition to the following:
+ • namespace: (number) Limit diagnostics to the
+ given namespace
+ • scope: (string, default "buffer") Show
+ diagnostics from the whole buffer ("buffer"),
+ the current cursor line ("line"), or the
+ current cursor position ("cursor").
+ • pos: (number or table) If {scope} is "line" or
+ "cursor", use this position rather than the
+ cursor position. If a number, interpreted as a
+ line number; otherwise, a (row, col) tuple.
+ • severity_sort: (default false) Sort diagnostics
+ by severity. Overrides the setting from
+ |vim.diagnostic.config()|.
+ • severity: See |diagnostic-severity|. Overrides
+ the setting from |vim.diagnostic.config()|.
+ • show_header: (boolean, default true) Show
+ "Diagnostics:" header. Overrides the setting
+ from |vim.diagnostic.config()|.
+ • source: (string) Include the diagnostic source
+ in the message. One of "always" or "if_many".
+ Overrides the setting from
+ |vim.diagnostic.config()|.
+ • format: (function) A function that takes a
+ diagnostic as input and returns a string. The
+ return value is the text used to display the
+ diagnostic. Overrides the setting from
+ |vim.diagnostic.config()|.
+ • prefix: (function or string) Prefix each
+ diagnostic in the floating window. Overrides
+ the setting from |vim.diagnostic.config()|.
+
+ Return: ~
+ tuple ({float_bufnr}, {win_id})
+
reset({namespace}, {bufnr}) *vim.diagnostic.reset()*
Remove all diagnostics from the given namespace.
@@ -518,7 +642,9 @@ reset({namespace}, {bufnr}) *vim.diagnostic.reset()*
|vim.diagnostic.hide()|.
Parameters: ~
- {namespace} number
+ {namespace} number|nil Diagnostic namespace. When
+ omitted, remove diagnostics from all
+ namespaces.
{bufnr} number|nil Remove diagnostics for the given
buffer. When omitted, diagnostics are removed
for all buffers.
@@ -569,7 +695,9 @@ show({namespace}, {bufnr}, {diagnostics}, {opts})
Display diagnostics for the given namespace and buffer.
Parameters: ~
- {namespace} number Diagnostic namespace
+ {namespace} number|nil Diagnostic namespace. When
+ omitted, show diagnostics from all
+ namespaces.
{bufnr} number|nil Buffer number. Defaults to the
current buffer.
{diagnostics} table|nil The diagnostics to display. When
@@ -577,55 +705,11 @@ show({namespace}, {bufnr}, {diagnostics}, {opts})
given namespace and buffer. This can be
used to display a list of diagnostics
without saving them or to display only a
- subset of diagnostics.
+ subset of diagnostics. May not be used when
+ {namespace} is nil.
{opts} table|nil Display options. See
|vim.diagnostic.config()|.
- *vim.diagnostic.show_line_diagnostics()*
-show_line_diagnostics({opts}, {bufnr}, {lnum})
- Open a floating window with the diagnostics from the given
- line.
-
- Parameters: ~
- {opts} table Configuration table. See
- |vim.diagnostic.show_position_diagnostics()|.
- {bufnr} number|nil Buffer number. Defaults to the current
- buffer.
- {lnum} number|nil Line number. Defaults to line number
- of cursor.
-
- Return: ~
- tuple ({popup_bufnr}, {win_id})
-
- *vim.diagnostic.show_position_diagnostics()*
-show_position_diagnostics({opts}, {bufnr}, {position})
- Open a floating window with the diagnostics at the given
- position.
-
- Parameters: ~
- {opts} table|nil Configuration table with the same
- keys as |vim.lsp.util.open_floating_preview()|
- in addition to the following:
- • namespace: (number) Limit diagnostics to the
- given namespace
- • severity: See |diagnostic-severity|.
- • show_header: (boolean, default true) Show
- "Diagnostics:" header
- • source: (string) Include the diagnostic
- source in the message. One of "always" or
- "if_many".
- • format: (function) A function that takes a
- diagnostic as input and returns a string.
- The return value is the text used to display
- the diagnostic.
- {bufnr} number|nil Buffer number. Defaults to the
- current buffer.
- {position} table|nil The (0,0)-indexed position. Defaults
- to the current cursor position.
-
- Return: ~
- tuple ({popup_bufnr}, {win_id})
-
toqflist({diagnostics}) *vim.diagnostic.toqflist()*
Convert a list of diagnostics to a list of quickfix items that
can be passed to |setqflist()| or |setloclist()|.
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 6549d0b5f3..1b949d749c 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -4933,7 +4933,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
behave :behave suboptions
cmdline |cmdline-completion| result
color color schemes
- command Ex command (and arguments)
+ command Ex command
compiler compilers
cscope |:cscope| suboptions
diff_buffer |:diffget| and |:diffput| completion
@@ -6833,6 +6833,7 @@ match({expr}, {pat} [, {start} [, {count}]]) *match()*
further down in the text.
Can also be used as a |method|: >
+ GetText()->match('word')
GetList()->match('word')
<
*matchadd()* *E798* *E799* *E801* *E957*
@@ -6992,8 +6993,10 @@ matchlist({expr}, {pat} [, {start} [, {count}]]) *matchlist()*
< Results in: ['acd', 'a', '', 'c', 'd', '', '', '', '', '']
When there is no match an empty list is returned.
+ You can pass in a List, but that is not very useful.
+
Can also be used as a |method|: >
- GetList()->matchlist('word')
+ GetText()->matchlist('word')
matchstr({expr}, {pat} [, {start} [, {count}]]) *matchstr()*
Same as |match()|, but return the matched string. Example: >
diff --git a/runtime/doc/indent.txt b/runtime/doc/indent.txt
index dfd81d7170..1b42092616 100644
--- a/runtime/doc/indent.txt
+++ b/runtime/doc/indent.txt
@@ -604,26 +604,22 @@ CLOJURE *ft-clojure-indent* *clojure-indent*
Clojure indentation differs somewhat from traditional Lisps, due in part to
the use of square and curly brackets, and otherwise by community convention.
These conventions are not universally followed, so the Clojure indent script
-offers a few configurable options, listed below.
+offers a few configuration options.
-If the current vim does not include searchpairpos(), the indent script falls
-back to normal 'lisp' indenting, and the following options are ignored.
*g:clojure_maxlines*
-Set maximum scan distance of searchpairpos(). Larger values trade performance
-for correctness when dealing with very long forms. A value of 0 will scan
-without limits.
->
- " Default
- let g:clojure_maxlines = 100
-<
+Sets maximum scan distance of `searchpairpos()`. Larger values trade
+performance for correctness when dealing with very long forms. A value of
+0 will scan without limits. The default is 300.
+
+
*g:clojure_fuzzy_indent*
*g:clojure_fuzzy_indent_patterns*
*g:clojure_fuzzy_indent_blacklist*
The 'lispwords' option is a list of comma-separated words that mark special
-forms whose subforms must be indented with two spaces.
+forms whose subforms should be indented with two spaces.
For example:
>
@@ -641,15 +637,11 @@ the fuzzy indent feature:
let g:clojure_fuzzy_indent_patterns = ['^with', '^def', '^let']
let g:clojure_fuzzy_indent_blacklist =
\ ['-fn$', '\v^with-%(meta|out-str|loading-context)$']
-
- " Legacy comma-delimited string version; the list format above is
- " recommended. Note that patterns are implicitly anchored with ^ and $
- let g:clojure_fuzzy_indent_patterns = 'with.*,def.*,let.*'
<
|g:clojure_fuzzy_indent_patterns| and |g:clojure_fuzzy_indent_blacklist| are
-|Lists| of patterns that will be matched against the unquoted, unqualified
-symbol at the head of a list. This means that a pattern like "^foo" will match
-all these candidates: "foobar", "my.ns/foobar", and "#'foobar".
+lists of patterns that will be matched against the unqualified symbol at the
+head of a list. This means that a pattern like `"^foo"` will match all these
+candidates: `foobar`, `my.ns/foobar`, and `#'foobar`.
Each candidate word is tested for special treatment in this order:
@@ -660,20 +652,22 @@ Each candidate word is tested for special treatment in this order:
|g:clojure_fuzzy_indent_patterns|
4. Return false and indent normally otherwise
+
*g:clojure_special_indent_words*
-Some forms in Clojure are indented so that every subform is indented only two
-spaces, regardless of 'lispwords'. If you have a custom construct that should
-be indented in this idiosyncratic fashion, you can add your symbols to the
-default list below.
+Some forms in Clojure are indented such that every subform is indented by only
+two spaces, regardless of 'lispwords'. If you have a custom construct that
+should be indented in this idiosyncratic fashion, you can add your symbols to
+the default list below.
>
" Default
let g:clojure_special_indent_words =
\ 'deftype,defrecord,reify,proxy,extend-type,extend-protocol,letfn'
<
+
*g:clojure_align_multiline_strings*
-Align subsequent lines in multiline strings to the column after the opening
+Align subsequent lines in multi-line strings to the column after the opening
quote, instead of the same column.
For example:
@@ -690,11 +684,7 @@ For example:
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.")
<
-This option is off by default.
->
- " Default
- let g:clojure_align_multiline_strings = 0
-<
+
*g:clojure_align_subforms*
By default, parenthesized compound forms that look like function calls and
@@ -705,18 +695,14 @@ two spaces relative to the opening paren:
bar
baz)
<
-Setting this option changes this behavior so that all subforms are aligned to
-the same column, emulating the default behavior of clojure-mode.el:
+Setting this option to `1` changes this behaviour so that all subforms are
+aligned to the same column, emulating the default behaviour of
+clojure-mode.el:
>
(foo
bar
baz)
<
-This option is off by default.
->
- " Default
- let g:clojure_align_subforms = 0
-<
FORTRAN *ft-fortran-indent*
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index c3421e6c82..83d201c23a 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -61,6 +61,10 @@ Example config (in init.vim): >
-- See `:help omnifunc` and `:help ins-completion` for more information.
vim.api.nvim_buf_set_option(0, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
+ -- Use LSP as the handler for formatexpr.
+ -- See `:help formatexpr` for more information.
+ vim.api.nvim_buf_set_option(0, 'formatexpr', 'v:lua.vim.lsp.formatexpr()')
+
-- For plugins with an `on_attach` callback, call them here. For example:
-- require('completion').on_attach()
end
@@ -452,6 +456,22 @@ LspSignatureActiveParameter
|vim.lsp.handlers.signature_help()|.
==============================================================================
+EVENTS *lsp-events*
+
+LspProgressUpdate *LspProgressUpdate*
+ Upon receipt of a progress notification from the server. See
+ |vim.lsp.util.get_progress_messages()|.
+
+LspRequest *LspRequest*
+ After a change to the active set of pending LSP requests. See {requests}
+ in |vim.lsp.client|.
+
+Example: >
+ autocmd User LspProgressUpdate redrawstatus
+ autocmd User LspRequest redrawstatus
+<
+
+==============================================================================
Lua module: vim.lsp *lsp-core*
buf_attach_client({bufnr}, {client_id}) *vim.lsp.buf_attach_client()*
@@ -608,6 +628,11 @@ client() *vim.lsp.client*
server.
• {handlers} (table): The handlers used by the client as
described in |lsp-handler|.
+ • {requests} (table): The current pending requests in flight
+ to the server. Entries are key-value pairs with the key
+ being the request ID while the value is a table with `type`,
+ `bufnr`, and `method` key-value pairs. `type` is either "pending"
+ for an active request, or "cancel" for a cancel request.
• {config} (table): copy of the table that was passed by the
user to |vim.lsp.start_client()|.
• {server_capabilities} (table): Response from the server
@@ -670,7 +695,7 @@ omnifunc({findstart}, {base}) *vim.lsp.omnifunc()*
{base} If findstart=0, text to match against
Return: ~
- (number) Decided by`findstart`:
+ (number) Decided by {findstart}:
• findstart=0: column where the completion starts, or -2
or -3
• findstart=1: list of matches (actually just calls
@@ -1075,7 +1100,8 @@ rename({new_name}) *vim.lsp.buf.rename()*
Parameters: ~
{new_name} (string) If not provided, the user will be
- prompted for a new name using |input()|.
+ prompted for a new name using
+ |vim.ui.input()|.
server_ready() *vim.lsp.buf.server_ready()*
Checks whether the language servers attached to the current
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index a6ccf9f35c..ef2d87949d 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -393,6 +393,14 @@ where the args are converted to Lua values. The expression >
is equivalent to the Lua chunk >
return somemod.func(...)
+In addition, functions of packages can be accessed like >
+ v:lua.require'mypack'.func(arg1, arg2)
+ v:lua.require'mypack.submod'.func(arg1, arg2)
+Note: only single quote form without parens is allowed. Using
+`require"mypack"` or `require('mypack')` as prefixes do NOT work (the latter
+is still valid as a function call of itself, in case require returns a useful
+value).
+
The `v:lua` prefix may be used to call Lua functions as |method|s. For
example: >
arg1->v:lua.somemod.func(arg2)
@@ -409,7 +417,8 @@ For example consider the following Lua omnifunc handler: >
end
vim.api.nvim_buf_set_option(0, 'omnifunc', 'v:lua.mymod.omnifunc')
-Note: the module ("mymod" in the above example) must be a Lua global.
+Note: the module ("mymod" in the above example) must either be a Lua global,
+or use the require syntax as specified above to access it from a package.
Note: `v:lua` without a call is not allowed in a Vimscript expression:
|Funcref|s cannot represent Lua functions. The following are errors: >
@@ -689,15 +698,14 @@ vim.diff({a}, {b}, {opts}) *vim.diff()*
------------------------------------------------------------------------------
VIM.MPACK *lua-mpack*
-The *vim.mpack* module provides packing and unpacking of lua objects to
-msgpack encoded strings. |vim.NIL| and |vim.empty_dict()| are supported.
+The *vim.mpack* module provides encoding and decoding of Lua objects to and
+from msgpack-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|.
-vim.mpack.pack({obj}) *vim.mpack.pack*
- Packs a lua object {obj} and returns the msgpack representation as
- a string
+vim.mpack.encode({obj}) *vim.mpack.encode*
+ Encodes (or "packs") Lua object {obj} as msgpack in a Lua string.
-vim.mpack.unpack({str}) *vim.mpack.unpack*
- Unpacks the msgpack encoded {str} and returns a lua object
+vim.mpack.decode({str}) *vim.mpack.decode*
+ Decodes (or "unpacks") the msgpack-encoded {str} to a Lua object.
------------------------------------------------------------------------------
VIM *lua-builtin*
@@ -928,6 +936,7 @@ Example: >
vim.g.foo = 5 -- Set the g:foo Vimscript variable.
print(vim.g.foo) -- Get and print the g:foo Vimscript variable.
vim.g.foo = nil -- Delete (:unlet) the Vimscript variable.
+ vim.b[2].foo = 6 -- Set b:foo for buffer 2
vim.g *vim.g*
Global (|g:|) editor variables.
@@ -935,15 +944,18 @@ vim.g *vim.g*
vim.b *vim.b*
Buffer-scoped (|b:|) variables for the current buffer.
- Invalid or unset key returns `nil`.
+ Invalid or unset key returns `nil`. Can be indexed with
+ an integer to access variables for a specific buffer.
vim.w *vim.w*
Window-scoped (|w:|) variables for the current window.
- Invalid or unset key returns `nil`.
+ Invalid or unset key returns `nil`. Can be indexed with
+ an integer to access variables for a specific window.
vim.t *vim.t*
Tabpage-scoped (|t:|) variables for the current tabpage.
- Invalid or unset key returns `nil`.
+ Invalid or unset key returns `nil`. Can be indexed with
+ an integer to access variables for a specific tabpage.
vim.v *vim.v*
|v:| variables.
@@ -1518,7 +1530,7 @@ tbl_flatten({t}) *vim.tbl_flatten()*
Flattened copy of the given list-like table.
See also: ~
- Fromhttps://github.com/premake/premake-core/blob/master/src/base/table.lua
+ From https://github.com/premake/premake-core/blob/master/src/base/table.lua
tbl_isempty({t}) *vim.tbl_isempty()*
Checks if a table is empty.
@@ -1554,7 +1566,7 @@ tbl_keys({t}) *vim.tbl_keys()*
list of keys
See also: ~
- Fromhttps://github.com/premake/premake-core/blob/master/src/base/table.lua
+ From https://github.com/premake/premake-core/blob/master/src/base/table.lua
tbl_map({func}, {t}) *vim.tbl_map()*
Apply a function to all values of a table.
@@ -1685,6 +1697,28 @@ uri_to_fname({uri}) *vim.uri_to_fname()*
==============================================================================
Lua module: ui *lua-ui*
+input({opts}, {on_confirm}) *vim.ui.input()*
+ Prompts the user for input
+
+ Parameters: ~
+ {opts} table Additional options. See |input()|
+ • prompt (string|nil) Text of the prompt.
+ Defaults to `Input:` .
+ • default (string|nil) Default reply to the
+ input
+ • completion (string|nil) Specifies type of
+ completion supported for input. Supported
+ types are the same that can be supplied to
+ a user-defined command using the
+ "-complete=" argument. See
+ |:command-completion|
+ • highlight (function) Function that will be
+ used for highlighting user inputs.
+ {on_confirm} function ((input|nil) -> ()) Called once the
+ user confirms or abort the input. `input` is
+ what the user typed. `nil` if the user
+ aborted the dialog.
+
select({items}, {opts}, {on_choice}) *vim.ui.select()*
Prompts the user to pick a single item from a collection of
entries
diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt
index 64c0d96aed..90d4c4de93 100644
--- a/runtime/doc/map.txt
+++ b/runtime/doc/map.txt
@@ -877,6 +877,9 @@ Also note that the 'clipboard' option is temporarily emptied to avoid
clobbering the `"*` or `"+` registers, if its value contains the item `unnamed`
or `unnamedplus`.
+The `mode()` function will return the state as it will be after applying the
+operator.
+
==============================================================================
2. Abbreviations *abbreviations* *Abbreviations*
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index d25d505728..399a59251a 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1115,6 +1115,8 @@ A jump table for the options with a short description can be found at |Q_op|.
Also see |win_gettype()|, which returns the type of the window.
Be careful with changing this option, it can have many side effects!
+ One such effect is that Vim will not check the timestamp of the file,
+ if the file is changed by another program this will not be noticed.
A "quickfix" buffer is only used for the error list and the location
list. This value is set by the |:cwindow| and |:lwindow| commands and
@@ -3703,9 +3705,10 @@ A jump table for the options with a short description can be found at |Q_op|.
*'list'* *'nolist'*
'list' boolean (default off)
local to window
- List mode: Show tabs as CTRL-I is displayed, display $ after end of
- line. Useful to see the difference between tabs and spaces and for
- trailing blanks. Further changed by the 'listchars' option.
+ List mode: By default, show tabs as ">", trailing spaces as "-", and
+ non-breakable space characters as "+". Useful to see the difference
+ between tabs and spaces and for trailing blanks. Further changed by
+ the 'listchars' option.
The cursor is displayed at the start of the space a Tab character
occupies, not at the end as usual in Normal mode. To get this cursor
diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index ebc7ff6b80..e423c59efe 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -1045,33 +1045,47 @@ This works immediately.
CLOJURE *ft-clojure-syntax*
-The default syntax groups can be augmented through the
-*g:clojure_syntax_keywords* and *b:clojure_syntax_keywords* variables. The
-value should be a |Dictionary| of syntax group names to a |List| of custom
-identifiers:
+ *g:clojure_syntax_keywords*
+
+Syntax highlighting of public vars in "clojure.core" is provided by default,
+but additional symbols can be highlighted by adding them to the
+|g:clojure_syntax_keywords| variable. The value should be a |Dictionary| of
+syntax group names, each containing a |List| of identifiers.
>
let g:clojure_syntax_keywords = {
- \ 'clojureMacro': ["defproject", "defcustom"],
- \ 'clojureFunc': ["string/join", "string/replace"]
+ \ 'clojureMacro': ["defproject", "defcustom"],
+ \ 'clojureFunc': ["string/join", "string/replace"]
\ }
<
Refer to the Clojure syntax script for valid syntax group names.
-If the |buffer-variable| *b:clojure_syntax_without_core_keywords* is set, only
-language constants and special forms are matched.
+There is also *b:clojure_syntax_keywords* which is a buffer-local variant of
+this variable intended for use by plugin authors to highlight symbols
+dynamically.
+
+By setting the *b:clojure_syntax_without_core_keywords* variable, vars from
+"clojure.core" will not be highlighted by default. This is useful for
+namespaces that have set `(:refer-clojure :only [])`
+
-Setting *g:clojure_fold* enables folding Clojure code via the syntax engine.
-Any list, vector, or map that extends over more than one line can be folded
-using the standard Vim |fold-commands|.
+ *g:clojure_fold*
-Please note that this option does not work with scripts that redefine the
-bracket syntax regions, such as rainbow-parentheses plugins.
+Setting |g:clojure_fold| to `1` will enable the folding of Clojure code. Any
+list, vector or map that extends over more than one line can be folded using
+the standard Vim |fold-commands|.
-This option is off by default.
+
+ *g:clojure_discard_macro*
+
+Set this variable to `1` to enable basic highlighting of Clojure's "discard
+reader macro".
>
- " Default
- let g:clojure_fold = 0
+ #_(defn foo [x]
+ (println x))
<
+Note that this option will not correctly highlight stacked discard macros
+(e.g. `#_#_`).
+
COBOL *cobol.vim* *ft-cobol-syntax*
@@ -4768,7 +4782,7 @@ in their own color.
Doesn't work recursively, thus you can't use
":colorscheme" in a color scheme script.
- To customize a colorscheme use another name, e.g.
+ To customize a color scheme use another name, e.g.
"~/.config/nvim/colors/mine.vim", and use `:runtime` to
load the original colorscheme: >
runtime colors/evening.vim
diff --git a/runtime/doc/tips.txt b/runtime/doc/tips.txt
index 27b6ca2885..b77c7d9a6d 100644
--- a/runtime/doc/tips.txt
+++ b/runtime/doc/tips.txt
@@ -464,6 +464,7 @@ the current window, try this custom `:HelpCurwin` command:
endif
if !empty(getcompletion(a:subject, 'help'))
execute mods .. ' edit ' .. &helpfile
+ set buftype=help
endif
return 'help ' .. a:subject
endfunction
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
index 5484e27797..b0e0bdcb84 100644
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -116,9 +116,9 @@ g8 Print the hex values of the bytes used in the
*:l* *:list*
:[range]l[ist] [count] [flags]
- Same as :print, but display unprintable characters
- with '^' and put $ after the line. This can be
- further changed with the 'listchars' option.
+ Same as :print, but show tabs as ">", trailing spaces
+ as "-", and non-breakable space characters as "+" by
+ default. Further changed by the 'listchars' option.
See |ex-flags| for [flags].
*:nu* *:number*
diff --git a/runtime/ftplugin/changelog.vim b/runtime/ftplugin/changelog.vim
index 257e9cd9d4..e9df63f8c9 100644
--- a/runtime/ftplugin/changelog.vim
+++ b/runtime/ftplugin/changelog.vim
@@ -2,7 +2,7 @@
" Language: generic Changelog file
" Maintainer: Martin Florian <marfl@posteo.de>
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2015-10-25
+" Latest Revision: 2021-10-17
" Variables:
" g:changelog_timeformat (deprecated: use g:changelog_dateformat instead) -
" description: the timeformat used in ChangeLog entries.
@@ -55,7 +55,7 @@ if &filetype == 'changelog'
elseif $EMAIL_ADDRESS != ""
return $EMAIL_ADDRESS
endif
-
+
let login = s:login()
return printf('%s <%s@%s>', s:name(login), login, s:hostname())
endfunction
@@ -223,12 +223,6 @@ if &filetype == 'changelog'
let &paste = save_paste
endfunction
- if exists(":NewChangelogEntry") != 2
- nnoremap <buffer> <silent> <Leader>o :<C-u>call <SID>new_changelog_entry('')<CR>
- xnoremap <buffer> <silent> <Leader>o :<C-u>call <SID>new_changelog_entry('')<CR>
- command! -nargs=0 NewChangelogEntry call s:new_changelog_entry('')
- endif
-
let b:undo_ftplugin = "setl com< fo< et< ai<"
setlocal comments=
@@ -241,14 +235,26 @@ if &filetype == 'changelog'
let b:undo_ftplugin .= " tw<"
endif
+ if !exists("no_plugin_maps") && !exists("no_changelog_maps") && exists(":NewChangelogEntry") != 2
+ nnoremap <buffer> <silent> <Leader>o :<C-u>call <SID>new_changelog_entry('')<CR>
+ xnoremap <buffer> <silent> <Leader>o :<C-u>call <SID>new_changelog_entry('')<CR>
+ command! -buffer -nargs=0 NewChangelogEntry call s:new_changelog_entry('')
+ let b:undo_ftplugin .= " | sil! exe 'nunmap <buffer> <Leader>o'" .
+ \ " | sil! exe 'vunmap <buffer> <Leader>o'" .
+ \ " | sil! delc NewChangelogEntry"
+ endif
+
let &cpo = s:cpo_save
unlet s:cpo_save
else
let s:cpo_save = &cpo
set cpo&vim
- " Add the Changelog opening mapping
- nnoremap <silent> <Leader>o :call <SID>open_changelog()<CR>
+ if !exists("no_plugin_maps") && !exists("no_changelog_maps")
+ " Add the Changelog opening mapping
+ nnoremap <silent> <Leader>o :call <SID>open_changelog()<CR>
+ let b:undo_ftplugin .= " | silent! exe 'nunmap <buffer> <Leader>o"
+ endif
function! s:open_changelog()
let path = expand('%:p:h')
diff --git a/runtime/ftplugin/clojure.vim b/runtime/ftplugin/clojure.vim
index cb75506dbb..81d53b1227 100644
--- a/runtime/ftplugin/clojure.vim
+++ b/runtime/ftplugin/clojure.vim
@@ -1,11 +1,11 @@
" Vim filetype plugin file
" Language: Clojure
-" Maintainer: Alex Vear <av@axvr.io>
+" Maintainer: Alex Vear <alex@vear.uk>
" Former Maintainers: Sung Pae <self@sungpae.com>
" Meikel Brandmeyer <mb@kotka.de>
" URL: https://github.com/clojure-vim/clojure.vim
" License: Vim (see :h license)
-" Last Change: 2021-02-13
+" Last Change: 2021-10-26
if exists("b:did_ftplugin")
finish
@@ -17,7 +17,7 @@ set cpo&vim
let b:undo_ftplugin = 'setlocal iskeyword< define< formatoptions< comments< commentstring< lispwords<'
-setlocal iskeyword+=?,-,*,!,+,/,=,<,>,.,:,$
+setlocal iskeyword+=?,-,*,!,+,/,=,<,>,.,:,$,%,&,\|
" There will be false positives, but this is better than missing the whole set
" of user-defined def* definitions.
@@ -43,7 +43,7 @@ setlocal commentstring=;\ %s
" specially and hence are not indented specially.
"
" -*- LISPWORDS -*-
-" Generated from https://github.com/clojure-vim/clojure.vim/blob/f8594e7030cdfb0b7990ac92953c77a08a7220f0/clj/src/vim_clojure_static/generate.clj
+" Generated from https://github.com/clojure-vim/clojure.vim/blob/62b215f079ce0f3834fd295c7a7f6bd8cc54bcc3/clj/src/vim_clojure_static/generate.clj
setlocal lispwords=as->,binding,bound-fn,case,catch,cond->,cond->>,condp,def,definline,definterface,defmacro,defmethod,defmulti,defn,defn-,defonce,defprotocol,defrecord,defstruct,deftest,deftest-,deftype,doseq,dotimes,doto,extend,extend-protocol,extend-type,fn,for,if,if-let,if-not,if-some,let,letfn,locking,loop,ns,proxy,reify,set-test,testing,when,when-first,when-let,when-not,when-some,while,with-bindings,with-in-str,with-local-vars,with-open,with-precision,with-redefs,with-redefs-fn,with-test
" Provide insert mode completions for special forms and clojure.core. As
@@ -64,8 +64,8 @@ if exists('loaded_matchit')
let b:undo_ftplugin .= ' | unlet! b:match_words b:match_skip'
endif
-" Win32 can filter files in the browse dialog
-if has("gui_win32") && !exists("b:browsefilter")
+" Filter files in the browse dialog
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter = "Clojure Source Files (*.clj)\t*.clj\n" .
\ "ClojureScript Source Files (*.cljs)\t*.cljs\n" .
\ "Java Source Files (*.java)\t*.java\n" .
diff --git a/runtime/ftplugin/mail.vim b/runtime/ftplugin/mail.vim
index 2a6bf4c046..f12022305f 100644
--- a/runtime/ftplugin/mail.vim
+++ b/runtime/ftplugin/mail.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Mail
" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2012 Nov 20
+" Last Change: 2021 Oct 23
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
@@ -26,6 +26,14 @@ setlocal fo+=tcql
" Add n:> to 'comments, in case it was removed elsewhere
setlocal comments+=n:>
+" .eml files are universally formatted with DOS line-endings, per RFC5322.
+" If the file was not DOS the it will be marked as changed, which is probably
+" a good thing.
+if expand('%:e') ==? 'eml'
+ let b:undo_ftplugin ..= " fileformat=" .. &fileformat
+ setlocal fileformat=dos
+endif
+
" Add mappings, unless the user doesn't want this.
if !exists("no_plugin_maps") && !exists("no_mail_maps")
" Quote text by inserting "> "
diff --git a/runtime/ftplugin/meson.vim b/runtime/ftplugin/meson.vim
index d48fa1dfd1..1ce9a03037 100644
--- a/runtime/ftplugin/meson.vim
+++ b/runtime/ftplugin/meson.vim
@@ -12,9 +12,28 @@ set cpo&vim
setlocal commentstring=#\ %s
setlocal comments=:#
+setlocal formatoptions+=croql formatoptions-=t
-setlocal shiftwidth=2
-setlocal softtabstop=2
+let b:undo_ftplugin = "setl com< cms< fo<"
+
+if get(g:, "meson_recommended_style", 1)
+ setlocal expandtab
+ setlocal shiftwidth=2
+ setlocal softtabstop=2
+ let b:undo_ftplugin .= " | setl et< sts< sw<"
+endif
+
+if exists("loaded_matchit") && !exists("b:match_words")
+ let b:match_words = '\<if\>:\<elif\>:\<else\>:\<endif\>,' .
+ \ '\<foreach\>:\<break\>:\<continue\>:\<endforeach\>'
+ let b:undo_ftplugin .= " | unlet! b:match_words"
+endif
+
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
+ let b:browsefilter = "Meson Build Files (meson.build)\tmeson.build\n" .
+ \ "All Files (*.*)\t*.*\n"
+ let b:undo_ftplugin .= " | unlet! b:browsefilter"
+endif
let &cpo = s:keepcpo
unlet s:keepcpo
diff --git a/runtime/ftplugin/nsis.vim b/runtime/ftplugin/nsis.vim
index 1a35127c86..3dc0d6318a 100644
--- a/runtime/ftplugin/nsis.vim
+++ b/runtime/ftplugin/nsis.vim
@@ -3,7 +3,7 @@
" Maintainer: Ken Takata
" URL: https://github.com/k-takata/vim-nsis
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Last Change: 2018-01-26
+" Last Change: 2021-10-18
if exists("b:did_ftplugin")
finish
@@ -15,7 +15,6 @@ set cpo&vim
let b:did_ftplugin = 1
let b:undo_ftplugin = "setl com< cms< fo< def< inc<"
- \ " | unlet! b:match_ignorecase b:match_words"
setlocal comments=s1:/*,mb:*,ex:*/,b:#,:; commentstring=;\ %s
setlocal formatoptions-=t formatoptions+=croql
@@ -37,6 +36,7 @@ if exists("loaded_matchit")
\ '\${MementoSection}:\${MementoSectionEnd},' .
\ '!if\%(\%(macro\)\?n\?def\)\?\>:!else\>:!endif\>,' .
\ '!macro\>:!macroend\>'
+ let b:undo_ftplugin .= " | unlet! b:match_ignorecase b:match_words"
endif
let &cpo = s:cpo_save
diff --git a/runtime/ftplugin/spec.vim b/runtime/ftplugin/spec.vim
index 75eebec56a..ce00021a69 100644
--- a/runtime/ftplugin/spec.vim
+++ b/runtime/ftplugin/spec.vim
@@ -18,8 +18,8 @@ if !exists("no_plugin_maps") && !exists("no_spec_maps")
endif
endif
-if !hasmapto("call SpecChangelog(\"\")<CR>")
- noremap <buffer> <unique> <script> <Plug>SpecChangelog :call SpecChangelog("")<CR>
+if !hasmapto("call <SID>SpecChangelog(\"\")<CR>")
+ noremap <buffer> <unique> <script> <Plug>SpecChangelog :call <SID>SpecChangelog("")<CR>
endif
if !exists("*s:GetRelVer")
diff --git a/runtime/indent/clojure.vim b/runtime/indent/clojure.vim
index 30a0b478e2..fadcaf4b4a 100644
--- a/runtime/indent/clojure.vim
+++ b/runtime/indent/clojure.vim
@@ -1,11 +1,11 @@
" Vim indent file
" Language: Clojure
-" Maintainer: Alex Vear <av@axvr.io>
+" Maintainer: Alex Vear <alex@vear.uk>
" Former Maintainers: Sung Pae <self@sungpae.com>
" Meikel Brandmeyer <mb@kotka.de>
" URL: https://github.com/clojure-vim/clojure.vim
" License: Vim (see :h license)
-" Last Change: 2021-02-13
+" Last Change: 2021-10-26
if exists("b:did_indent")
finish
@@ -24,7 +24,7 @@ setlocal indentkeys=!,o,O
if exists("*searchpairpos")
if !exists('g:clojure_maxlines')
- let g:clojure_maxlines = 100
+ let g:clojure_maxlines = 300
endif
if !exists('g:clojure_fuzzy_indent')
@@ -71,14 +71,10 @@ if exists("*searchpairpos")
return s:current_char() =~# '\v[\(\)\[\]\{\}]' && !s:ignored_region()
endfunction
- " Returns 1 if string matches a pattern in 'patterns', which may be a
- " list of patterns, or a comma-delimited string of implicitly anchored
- " patterns.
+ " Returns 1 if string matches a pattern in 'patterns', which should be
+ " a list of patterns.
function! s:match_one(patterns, string)
- let list = type(a:patterns) == type([])
- \ ? a:patterns
- \ : map(split(a:patterns, ','), '"^" . v:val . "$"')
- for pat in list
+ for pat in a:patterns
if a:string =~# pat | return 1 | endif
endfor
endfunction
@@ -215,9 +211,10 @@ if exists("*searchpairpos")
endfunction
" Check if form is a reader conditional, that is, it is prefixed by #?
- " or @#?
+ " or #?@
function! s:is_reader_conditional_special_case(position)
return getline(a:position[0])[a:position[1] - 3 : a:position[1] - 2] == "#?"
+ \|| getline(a:position[0])[a:position[1] - 4 : a:position[1] - 2] == "#?@"
endfunction
" Returns 1 for opening brackets, -1 for _anything else_.
diff --git a/runtime/indent/dosbatch.vim b/runtime/indent/dosbatch.vim
index aea2a184d4..d24b139242 100644
--- a/runtime/indent/dosbatch.vim
+++ b/runtime/indent/dosbatch.vim
@@ -2,7 +2,7 @@
" Language: MSDOS batch file (with NT command extensions)
" Maintainer: Ken Takata
" URL: https://github.com/k-takata/vim-dosbatch-indent
-" Last Change: 2017 May 10
+" Last Change: 2021-10-18
" Filenames: *.bat
" License: VIM License
@@ -17,6 +17,8 @@ setlocal indentexpr=GetDosBatchIndent(v:lnum)
setlocal indentkeys=!^F,o,O
setlocal indentkeys+=0=)
+let b:undo_indent = "setl ai< inde< indk< si<"
+
if exists("*GetDosBatchIndent")
finish
endif
diff --git a/runtime/indent/meson.vim b/runtime/indent/meson.vim
index 549209ca33..09131f5723 100644
--- a/runtime/indent/meson.vim
+++ b/runtime/indent/meson.vim
@@ -20,6 +20,8 @@ setlocal autoindent " indentexpr isn't much help otherwise
setlocal indentexpr=GetMesonIndent(v:lnum)
setlocal indentkeys+==elif,=else,=endforeach,=endif,0)
+let b:undo_indent = "setl ai< inde< indk< lisp<"
+
" Only define the function once.
if exists("*GetMesonIndent")
finish
diff --git a/runtime/indent/nsis.vim b/runtime/indent/nsis.vim
index 223f4fa28e..5d3decca37 100644
--- a/runtime/indent/nsis.vim
+++ b/runtime/indent/nsis.vim
@@ -2,7 +2,7 @@
" Language: NSIS script
" Maintainer: Ken Takata
" URL: https://github.com/k-takata/vim-nsis
-" Last Change: 2018-01-21
+" Last Change: 2021-10-18
" Filenames: *.nsi
" License: VIM License
@@ -17,6 +17,8 @@ setlocal indentexpr=GetNsisIndent(v:lnum)
setlocal indentkeys=!^F,o,O
setlocal indentkeys+==~${Else,=~${EndIf,=~${EndUnless,=~${AndIf,=~${AndUnless,=~${OrIf,=~${OrUnless,=~${Case,=~${Default,=~${EndSelect,=~${EndSwith,=~${Loop,=~${Next,=~${MementoSectionEnd,=~FunctionEnd,=~SectionEnd,=~SectionGroupEnd,=~PageExEnd,0=~!macroend,0=~!if,0=~!else,0=~!endif
+let b:undo_indent = "setl ai< inde< indk< si<"
+
if exists("*GetNsisIndent")
finish
endif
diff --git a/runtime/indent/teraterm.vim b/runtime/indent/teraterm.vim
index 35d7354290..181c9a343f 100644
--- a/runtime/indent/teraterm.vim
+++ b/runtime/indent/teraterm.vim
@@ -3,7 +3,7 @@
" Based on Tera Term Version 4.100
" Maintainer: Ken Takata
" URL: https://github.com/k-takata/vim-teraterm
-" Last Change: 2018-08-31
+" Last Change: 2021-10-18
" Filenames: *.ttl
" License: VIM License
@@ -18,6 +18,8 @@ setlocal indentexpr=GetTeraTermIndent(v:lnum)
setlocal indentkeys=!^F,o,O,e
setlocal indentkeys+==elseif,=endif,=loop,=next,=enduntil,=endwhile
+let b:undo_indent = "setl ai< inde< indk< si<"
+
if exists("*GetTeraTermIndent")
finish
endif
diff --git a/runtime/indent/vim.vim b/runtime/indent/vim.vim
index ee3d39490d..a98c75e541 100644
--- a/runtime/indent/vim.vim
+++ b/runtime/indent/vim.vim
@@ -1,7 +1,7 @@
" Vim indent file
" Language: Vim script
" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2021 Apr 18
+" Last Change: 2021 Nov 03
" Only load this indent file when no other was loaded.
if exists("b:did_indent")
@@ -107,7 +107,7 @@ function GetVimIndentIntern()
if i >= 0
let ind += shiftwidth()
if strpart(prev_text, i, 1) == '|' && has('syntax_items')
- \ && synIDattr(synID(lnum, i, 1), "name") =~ '\(Comment\|String\)$'
+ \ && synIDattr(synID(lnum, i, 1), "name") =~ '\(Comment\|String\|PatSep\)$'
let ind -= shiftwidth()
endif
endif
diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua
index 326932d982..b30a678eeb 100644
--- a/runtime/lua/vim/diagnostic.lua
+++ b/runtime/lua/vim/diagnostic.lua
@@ -1,3 +1,5 @@
+local if_nil = vim.F.if_nil
+
local M = {}
M.severity = {
@@ -19,10 +21,21 @@ local global_diagnostic_options = {
signs = true,
underline = true,
virtual_text = true,
+ float = true,
update_in_insert = false,
severity_sort = false,
}
+M.handlers = setmetatable({}, {
+ __newindex = function(t, name, handler)
+ vim.validate { handler = {handler, "t" } }
+ rawset(t, name, handler)
+ if not global_diagnostic_options[name] then
+ global_diagnostic_options[name] = true
+ end
+ end,
+})
+
-- Local functions {{{
---@private
@@ -54,7 +67,7 @@ end
local function prefix_source(source, diagnostics)
vim.validate { source = {source, function(v)
return v == "always" or v == "if_many"
- end, "Invalid value for option 'source'" } }
+ end, "'always' or 'if_many'" } }
if source == "if_many" then
local sources = {}
@@ -96,31 +109,9 @@ end
local all_namespaces = {}
---@private
-local function get_namespace(ns)
- if not all_namespaces[ns] then
- local name
- for k, v in pairs(vim.api.nvim_get_namespaces()) do
- if ns == v then
- name = k
- break
- end
- end
-
- assert(name, "namespace does not exist or is anonymous")
-
- all_namespaces[ns] = {
- name = name,
- sign_group = string.format("vim.diagnostic.%s", name),
- opts = {}
- }
- end
- return all_namespaces[ns]
-end
-
----@private
local function enabled_value(option, namespace)
- local ns = get_namespace(namespace)
- if type(ns.opts[option]) == "table" then
+ local ns = namespace and M.get_namespace(namespace) or {}
+ if ns.opts and type(ns.opts[option]) == "table" then
return ns.opts[option]
end
@@ -153,8 +144,9 @@ end
---@private
local function get_resolved_options(opts, namespace, bufnr)
- local ns = get_namespace(namespace)
- local resolved = vim.tbl_extend('keep', opts or {}, ns.opts, global_diagnostic_options)
+ local ns = namespace and M.get_namespace(namespace) or {}
+ -- Do not use tbl_deep_extend so that an empty table can be used to reset to default values
+ local resolved = vim.tbl_extend('keep', opts or {}, ns.opts or {}, global_diagnostic_options)
for k in pairs(global_diagnostic_options) do
if resolved[k] ~= nil then
resolved[k] = resolve_optional_value(k, resolved[k], namespace, bufnr)
@@ -323,7 +315,7 @@ end
---@private
local function save_extmarks(namespace, bufnr)
- bufnr = bufnr == 0 and vim.api.nvim_get_current_buf() or bufnr
+ bufnr = get_bufnr(bufnr)
if not diagnostic_attached_buffers[bufnr] then
vim.api.nvim_buf_attach(bufnr, false, {
on_lines = function(_, _, _, _, _, last)
@@ -341,7 +333,7 @@ local registered_autocmds = {}
---@private
local function make_augroup_key(namespace, bufnr)
- local ns = get_namespace(namespace)
+ local ns = M.get_namespace(namespace)
return string.format("DiagnosticInsertLeave:%s:%s", bufnr, ns.name)
end
@@ -354,19 +346,15 @@ local function schedule_display(namespace, bufnr, args)
local key = make_augroup_key(namespace, bufnr)
if not registered_autocmds[key] then
- vim.cmd(string.format("augroup %s", key))
- vim.cmd(" au!")
- vim.cmd(
- string.format(
- [[autocmd %s <buffer=%s> lua vim.diagnostic._execute_scheduled_display(%s, %s)]],
- table.concat(insert_leave_auto_cmds, ","),
- bufnr,
- namespace,
- bufnr
- )
- )
- vim.cmd("augroup END")
-
+ vim.cmd(string.format([[augroup %s
+ au!
+ autocmd %s <buffer=%s> lua vim.diagnostic._execute_scheduled_display(%s, %s)
+ augroup END]],
+ key,
+ table.concat(insert_leave_auto_cmds, ","),
+ bufnr,
+ namespace,
+ bufnr))
registered_autocmds[key] = true
end
end
@@ -376,77 +364,14 @@ local function clear_scheduled_display(namespace, bufnr)
local key = make_augroup_key(namespace, bufnr)
if registered_autocmds[key] then
- vim.cmd(string.format("augroup %s", key))
- vim.cmd(" au!")
- vim.cmd("augroup END")
-
+ vim.cmd(string.format([[augroup %s
+ au!
+ augroup END]], key))
registered_autocmds[key] = nil
end
end
---@private
---- Open a floating window with the provided diagnostics
----@param opts table Configuration table
---- - show_header (boolean, default true): Show "Diagnostics:" header
---- - all opts for |vim.util.open_floating_preview()| can be used here
----@param diagnostics table: The diagnostics to display
----@return table {popup_bufnr, win_id}
-local function show_diagnostics(opts, diagnostics)
- if not diagnostics or vim.tbl_isempty(diagnostics) then
- return
- end
- local lines = {}
- local highlights = {}
- local show_header = vim.F.if_nil(opts.show_header, true)
- if show_header then
- table.insert(lines, "Diagnostics:")
- table.insert(highlights, {0, "Bold"})
- end
-
- if opts.format then
- diagnostics = reformat_diagnostics(opts.format, diagnostics)
- end
-
- if opts.source then
- diagnostics = prefix_source(opts.source, diagnostics)
- end
-
- -- Use global setting for severity_sort since 'show_diagnostics' is namespace
- -- independent
- local severity_sort = global_diagnostic_options.severity_sort
- if severity_sort then
- if type(severity_sort) == "table" and severity_sort.reverse then
- table.sort(diagnostics, function(a, b) return a.severity > b.severity end)
- else
- table.sort(diagnostics, function(a, b) return a.severity < b.severity end)
- end
- end
-
- for i, diagnostic in ipairs(diagnostics) do
- local prefix = string.format("%d. ", i)
- local hiname = floating_highlight_map[diagnostic.severity]
- assert(hiname, 'unknown severity: ' .. tostring(diagnostic.severity))
-
- local message_lines = vim.split(diagnostic.message, '\n', true)
- table.insert(lines, prefix..message_lines[1])
- table.insert(highlights, {#prefix, hiname})
- for j = 2, #message_lines do
- table.insert(lines, string.rep(' ', #prefix) .. message_lines[j])
- table.insert(highlights, {0, hiname})
- end
- end
-
- local popup_bufnr, winnr = require('vim.lsp.util').open_floating_preview(lines, 'plaintext', opts)
- for i, hi in ipairs(highlights) do
- local prefixlen, hiname = unpack(hi)
- -- Start highlight after the prefix
- vim.api.nvim_buf_add_highlight(popup_bufnr, -1, hiname, i-1, prefixlen, -1)
- end
-
- return popup_bufnr, winnr
-end
-
----@private
local function set_list(loclist, opts)
opts = opts or {}
local open = vim.F.if_nil(opts.open, true)
@@ -469,6 +394,7 @@ local function set_list(loclist, opts)
end
---@private
+--- To (slightly) improve performance, modifies diagnostics in place.
local function clamp_line_numbers(bufnr, diagnostics)
local buf_line_count = vim.api.nvim_buf_line_count(bufnr)
if buf_line_count == 0 then
@@ -526,7 +452,7 @@ end
local function diagnostic_move_pos(opts, pos)
opts = opts or {}
- local enable_popup = vim.F.if_nil(opts.enable_popup, true)
+ local float = vim.F.if_nil(opts.float, true)
local win_id = opts.win_id or vim.api.nvim_get_current_win()
if not pos then
@@ -539,10 +465,13 @@ local function diagnostic_move_pos(opts, pos)
vim.api.nvim_win_set_cursor(win_id, {pos[1] + 1, pos[2]})
- if enable_popup then
- -- This is a bit weird... I'm surprised that we need to wait til the next tick to do this.
+ if float then
+ local float_opts = type(float) == "table" and float or {}
vim.schedule(function()
- M.show_position_diagnostics(opts.popup_opts, vim.api.nvim_win_get_buf(win_id))
+ M.open_float(
+ vim.api.nvim_win_get_buf(win_id),
+ vim.tbl_extend("keep", float_opts, {scope="cursor"})
+ )
end)
end
end
@@ -561,12 +490,12 @@ end
---
--- For example, if a user enables virtual text globally with
--- <pre>
---- vim.diagnostic.config({virt_text = true})
+--- vim.diagnostic.config({virtual_text = true})
--- </pre>
---
--- and a diagnostic producer sets diagnostics with
--- <pre>
---- vim.diagnostic.set(ns, 0, diagnostics, {virt_text = false})
+--- vim.diagnostic.set(ns, 0, diagnostics, {virtual_text = false})
--- </pre>
---
--- then virtual text will not be enabled for those diagnostics.
@@ -603,6 +532,19 @@ end
--- * priority: (number, default 10) Base priority to use for signs. When
--- {severity_sort} is used, the priority of a sign is adjusted based on
--- its severity. Otherwise, all signs use the same priority.
+--- - float: Options for floating windows:
+--- * severity: See |diagnostic-severity|.
+--- * show_header: (boolean, default true) Show "Diagnostics:" header
+--- * source: (string) Include the diagnostic source in
+--- the message. One of "always" or "if_many".
+--- * format: (function) A function that takes a diagnostic as input and returns a
+--- string. The return value is the text used to display the diagnostic.
+--- * prefix: (function or string) Prefix each diagnostic in the floating window. If
+--- a function, it must have the signature (diagnostic, i, total) -> string,
+--- where {i} is the index of the diagnostic being evaluated and {total} is
+--- the total number of diagnostics displayed in the window. The returned
+--- string is prepended to each diagnostic in the window. Otherwise,
+--- if {prefix} is a string, it is prepended to each diagnostic.
--- - update_in_insert: (default false) Update diagnostics in Insert mode (if false,
--- diagnostics are updated on InsertLeave)
--- - severity_sort: (default false) Sort diagnostics by severity. This affects the order in
@@ -620,7 +562,7 @@ function M.config(opts, namespace)
local t
if namespace then
- local ns = get_namespace(namespace)
+ local ns = M.get_namespace(namespace)
t = ns.opts
else
t = global_diagnostic_options
@@ -672,7 +614,7 @@ function M.set(namespace, bufnr, diagnostics, opts)
-- Clean up our data when the buffer unloads.
vim.api.nvim_buf_attach(bufnr, false, {
on_detach = function(_, b)
- clear_diagnostic_cache(b, namespace)
+ clear_diagnostic_cache(namespace, b)
diagnostic_cleanup[b][namespace] = nil
end
})
@@ -687,6 +629,32 @@ function M.set(namespace, bufnr, diagnostics, opts)
vim.api.nvim_command("doautocmd <nomodeline> User DiagnosticsChanged")
end
+--- Get namespace metadata.
+---
+---@param ns number Diagnostic namespace
+---@return table Namespace metadata
+function M.get_namespace(namespace)
+ vim.validate { namespace = { namespace, 'n' } }
+ if not all_namespaces[namespace] then
+ local name
+ for k, v in pairs(vim.api.nvim_get_namespaces()) do
+ if namespace == v then
+ name = k
+ break
+ end
+ end
+
+ assert(name, "namespace does not exist or is anonymous")
+
+ all_namespaces[namespace] = {
+ name = name,
+ opts = {},
+ user_data = {},
+ }
+ end
+ return all_namespaces[namespace]
+end
+
--- Get current diagnostic namespaces.
---
---@return table A list of active diagnostic namespaces |vim.diagnostic|.
@@ -825,10 +793,9 @@ end
--- |nvim_win_get_cursor()|. Defaults to the current cursor position.
--- - wrap: (boolean, default true) Whether to loop around file or not. Similar to 'wrapscan'.
--- - severity: See |diagnostic-severity|.
---- - enable_popup: (boolean, default true) Call |vim.diagnostic.show_line_diagnostics()|
---- on jump.
---- - popup_opts: (table) Table to pass as {opts} parameter to
---- |vim.diagnostic.show_line_diagnostics()|
+--- - float: (boolean or table, default true) If "true", call |vim.diagnostic.open_float()|
+--- after moving. If a table, pass the table as the {opts} parameter to
+--- |vim.diagnostic.open_float()|.
--- - win_id: (number, default 0) Window ID
function M.goto_next(opts)
return diagnostic_move_pos(
@@ -837,156 +804,171 @@ function M.goto_next(opts)
)
end
--- Diagnostic Setters {{{
-
---- Set signs for given diagnostics.
----
----@param namespace number The diagnostic namespace
----@param bufnr number Buffer number
----@param diagnostics table A list of diagnostic items |diagnostic-structure|. When omitted the
---- current diagnostics in the given buffer are used.
----@param opts table Configuration table with the following keys:
---- - priority: Set the priority of the signs |sign-priority|.
----@private
-function M._set_signs(namespace, bufnr, diagnostics, opts)
- vim.validate {
- namespace = {namespace, 'n'},
- bufnr = {bufnr, 'n'},
- diagnostics = {diagnostics, 't'},
- opts = {opts, 't', true},
- }
+M.handlers.signs = {
+ show = function(namespace, bufnr, diagnostics, opts)
+ vim.validate {
+ namespace = {namespace, 'n'},
+ bufnr = {bufnr, 'n'},
+ diagnostics = {diagnostics, 't'},
+ opts = {opts, 't', true},
+ }
- bufnr = get_bufnr(bufnr)
- opts = get_resolved_options({ signs = opts }, namespace, bufnr)
+ bufnr = get_bufnr(bufnr)
- if opts.signs and opts.signs.severity then
- diagnostics = filter_by_severity(opts.signs.severity, diagnostics)
- end
-
- local ns = get_namespace(namespace)
+ if opts.signs and opts.signs.severity then
+ diagnostics = filter_by_severity(opts.signs.severity, diagnostics)
+ end
- define_default_signs()
+ define_default_signs()
- -- 10 is the default sign priority when none is explicitly specified
- local priority = opts.signs and opts.signs.priority or 10
- local get_priority
- if opts.severity_sort then
- if type(opts.severity_sort) == "table" and opts.severity_sort.reverse then
- get_priority = function(severity)
- return priority + (severity - vim.diagnostic.severity.ERROR)
+ -- 10 is the default sign priority when none is explicitly specified
+ local priority = opts.signs and opts.signs.priority or 10
+ local get_priority
+ if opts.severity_sort then
+ if type(opts.severity_sort) == "table" and opts.severity_sort.reverse then
+ get_priority = function(severity)
+ return priority + (severity - vim.diagnostic.severity.ERROR)
+ end
+ else
+ get_priority = function(severity)
+ return priority + (vim.diagnostic.severity.HINT - severity)
+ end
end
else
- get_priority = function(severity)
- return priority + (vim.diagnostic.severity.HINT - severity)
+ get_priority = function()
+ return priority
end
end
- else
- get_priority = function()
- return priority
- end
- end
-
- for _, diagnostic in ipairs(diagnostics) do
- vim.fn.sign_place(
- 0,
- ns.sign_group,
- sign_highlight_map[diagnostic.severity],
- bufnr,
- {
- priority = get_priority(diagnostic.severity),
- lnum = diagnostic.lnum + 1
- }
- )
- end
-end
---- Set underline for given diagnostics.
----
----@param namespace number The diagnostic namespace
----@param bufnr number Buffer number
----@param diagnostics table A list of diagnostic items |diagnostic-structure|. When omitted the
---- current diagnostics in the given buffer are used.
----@param opts table Configuration table. Currently unused.
----@private
-function M._set_underline(namespace, bufnr, diagnostics, opts)
- vim.validate {
- namespace = {namespace, 'n'},
- bufnr = {bufnr, 'n'},
- diagnostics = {diagnostics, 't'},
- opts = {opts, 't', true},
- }
+ local ns = M.get_namespace(namespace)
+ if not ns.user_data.sign_group then
+ ns.user_data.sign_group = string.format("vim.diagnostic.%s", ns.name)
+ end
- bufnr = get_bufnr(bufnr)
- opts = get_resolved_options({ underline = opts }, namespace, bufnr).underline
+ local sign_group = ns.user_data.sign_group
+ for _, diagnostic in ipairs(diagnostics) do
+ vim.fn.sign_place(
+ 0,
+ sign_group,
+ sign_highlight_map[diagnostic.severity],
+ bufnr,
+ {
+ priority = get_priority(diagnostic.severity),
+ lnum = diagnostic.lnum + 1
+ }
+ )
+ end
+ end,
+ hide = function(namespace, bufnr)
+ local ns = M.get_namespace(namespace)
+ if ns.user_data.sign_group then
+ vim.fn.sign_unplace(ns.user_data.sign_group, {buffer=bufnr})
+ end
+ end,
+}
- if opts and opts.severity then
- diagnostics = filter_by_severity(opts.severity, diagnostics)
- end
+M.handlers.underline = {
+ show = function(namespace, bufnr, diagnostics, opts)
+ vim.validate {
+ namespace = {namespace, 'n'},
+ bufnr = {bufnr, 'n'},
+ diagnostics = {diagnostics, 't'},
+ opts = {opts, 't', true},
+ }
- for _, diagnostic in ipairs(diagnostics) do
- local higroup = underline_highlight_map[diagnostic.severity]
+ bufnr = get_bufnr(bufnr)
- if higroup == nil then
- -- Default to error if we don't have a highlight associated
- higroup = underline_highlight_map.Error
+ if opts.underline and opts.underline.severity then
+ diagnostics = filter_by_severity(opts.underline.severity, diagnostics)
end
- vim.highlight.range(
- bufnr,
- namespace,
- higroup,
- { diagnostic.lnum, diagnostic.col },
- { diagnostic.end_lnum, diagnostic.end_col }
- )
- end
-end
+ local ns = M.get_namespace(namespace)
+ if not ns.user_data.underline_ns then
+ ns.user_data.underline_ns = vim.api.nvim_create_namespace("")
+ end
---- Set virtual text for given diagnostics.
----
----@param namespace number The diagnostic namespace
----@param bufnr number Buffer number
----@param diagnostics table A list of diagnostic items |diagnostic-structure|. When omitted the
---- current diagnostics in the given buffer are used.
----@param opts table|nil Configuration table with the following keys:
---- - prefix: (string) Prefix to display before virtual text on line.
---- - spacing: (number) Number of spaces to insert before virtual text.
---- - source: (string) Include the diagnostic source in virtual text. One of "always" or
---- "if_many".
----@private
-function M._set_virtual_text(namespace, bufnr, diagnostics, opts)
- vim.validate {
- namespace = {namespace, 'n'},
- bufnr = {bufnr, 'n'},
- diagnostics = {diagnostics, 't'},
- opts = {opts, 't', true},
- }
+ local underline_ns = ns.user_data.underline_ns
+ for _, diagnostic in ipairs(diagnostics) do
+ local higroup = underline_highlight_map[diagnostic.severity]
- bufnr = get_bufnr(bufnr)
- opts = get_resolved_options({ virtual_text = opts }, namespace, bufnr).virtual_text
+ if higroup == nil then
+ -- Default to error if we don't have a highlight associated
+ higroup = underline_highlight_map.Error
+ end
- if opts and opts.format then
- diagnostics = reformat_diagnostics(opts.format, diagnostics)
+ vim.highlight.range(
+ bufnr,
+ underline_ns,
+ higroup,
+ { diagnostic.lnum, diagnostic.col },
+ { diagnostic.end_lnum, diagnostic.end_col }
+ )
+ end
+ save_extmarks(underline_ns, bufnr)
+ end,
+ hide = function(namespace, bufnr)
+ local ns = M.get_namespace(namespace)
+ if ns.user_data.underline_ns then
+ diagnostic_cache_extmarks[bufnr][ns.user_data.underline_ns] = {}
+ vim.api.nvim_buf_clear_namespace(bufnr, ns.user_data.underline_ns, 0, -1)
+ end
end
+}
- if opts and opts.source then
- diagnostics = prefix_source(opts.source, diagnostics)
- end
+M.handlers.virtual_text = {
+ show = function(namespace, bufnr, diagnostics, opts)
+ vim.validate {
+ namespace = {namespace, 'n'},
+ bufnr = {bufnr, 'n'},
+ diagnostics = {diagnostics, 't'},
+ opts = {opts, 't', true},
+ }
- local buffer_line_diagnostics = diagnostic_lines(diagnostics)
- for line, line_diagnostics in pairs(buffer_line_diagnostics) do
- if opts and opts.severity then
- line_diagnostics = filter_by_severity(opts.severity, line_diagnostics)
+ bufnr = get_bufnr(bufnr)
+
+ local severity
+ if opts.virtual_text then
+ if opts.virtual_text.format then
+ diagnostics = reformat_diagnostics(opts.virtual_text.format, diagnostics)
+ end
+ if opts.virtual_text.source then
+ diagnostics = prefix_source(opts.virtual_text.source, diagnostics)
+ end
+ if opts.virtual_text.severity then
+ severity = opts.virtual_text.severity
+ end
end
- local virt_texts = M._get_virt_text_chunks(line_diagnostics, opts)
- if virt_texts then
- vim.api.nvim_buf_set_extmark(bufnr, namespace, line, 0, {
- hl_mode = "combine",
- virt_text = virt_texts,
- })
+ local ns = M.get_namespace(namespace)
+ if not ns.user_data.virt_text_ns then
+ ns.user_data.virt_text_ns = vim.api.nvim_create_namespace("")
end
- end
-end
+
+ local virt_text_ns = ns.user_data.virt_text_ns
+ local buffer_line_diagnostics = diagnostic_lines(diagnostics)
+ for line, line_diagnostics in pairs(buffer_line_diagnostics) do
+ if severity then
+ line_diagnostics = filter_by_severity(severity, line_diagnostics)
+ end
+ local virt_texts = M._get_virt_text_chunks(line_diagnostics, opts.virtual_text)
+
+ if virt_texts then
+ vim.api.nvim_buf_set_extmark(bufnr, virt_text_ns, line, 0, {
+ hl_mode = "combine",
+ virt_text = virt_texts,
+ })
+ end
+ end
+ save_extmarks(virt_text_ns, bufnr)
+ end,
+ hide = function(namespace, bufnr)
+ local ns = M.get_namespace(namespace)
+ if ns.user_data.virt_text_ns then
+ diagnostic_cache_extmarks[bufnr][ns.user_data.virt_text_ns] = {}
+ vim.api.nvim_buf_clear_namespace(bufnr, ns.user_data.virt_text_ns, 0, -1)
+ end
+ end,
+}
--- Get virtual text chunks to display using |nvim_buf_set_extmark()|.
---
@@ -1055,46 +1037,54 @@ end
--- To hide diagnostics and prevent them from re-displaying, use
--- |vim.diagnostic.disable()|.
---
----@param namespace number The diagnostic namespace
+---@param namespace number|nil Diagnostic namespace. When omitted, hide
+--- diagnostics from all namespaces.
---@param bufnr number|nil Buffer number. Defaults to the current buffer.
function M.hide(namespace, bufnr)
vim.validate {
- namespace = { namespace, 'n' },
+ namespace = { namespace, 'n', true },
bufnr = { bufnr, 'n', true },
}
bufnr = get_bufnr(bufnr)
- diagnostic_cache_extmarks[bufnr][namespace] = {}
-
- local ns = get_namespace(namespace)
-
- -- clear sign group
- vim.fn.sign_unplace(ns.sign_group, {buffer=bufnr})
-
- -- clear virtual text namespace
- vim.api.nvim_buf_clear_namespace(bufnr, namespace, 0, -1)
+ local namespaces = namespace and {namespace} or vim.tbl_keys(diagnostic_cache[bufnr])
+ for _, iter_namespace in ipairs(namespaces) do
+ for _, handler in pairs(M.handlers) do
+ if handler.hide then
+ handler.hide(iter_namespace, bufnr)
+ end
+ end
+ end
end
-
--- Display diagnostics for the given namespace and buffer.
---
----@param namespace number Diagnostic namespace
+---@param namespace number|nil Diagnostic namespace. When omitted, show
+--- diagnostics from all namespaces.
---@param bufnr number|nil Buffer number. Defaults to the current buffer.
---@param diagnostics table|nil The diagnostics to display. When omitted, use the
--- saved diagnostics for the given namespace and
--- buffer. This can be used to display a list of diagnostics
--- without saving them or to display only a subset of
---- diagnostics.
+--- diagnostics. May not be used when {namespace} is nil.
---@param opts table|nil Display options. See |vim.diagnostic.config()|.
function M.show(namespace, bufnr, diagnostics, opts)
vim.validate {
- namespace = { namespace, 'n' },
+ namespace = { namespace, 'n', true },
bufnr = { bufnr, 'n', true },
diagnostics = { diagnostics, 't', true },
opts = { opts, 't', true },
}
bufnr = get_bufnr(bufnr)
+ if not namespace then
+ assert(not diagnostics, "Cannot show diagnostics without a namespace")
+ for iter_namespace in pairs(diagnostic_cache[bufnr]) do
+ M.show(iter_namespace, bufnr, nil, opts)
+ end
+ return
+ end
+
if is_disabled(namespace, bufnr) then
return
end
@@ -1129,83 +1119,154 @@ function M.show(namespace, bufnr, diagnostics, opts)
clamp_line_numbers(bufnr, diagnostics)
- if opts.underline then
- M._set_underline(namespace, bufnr, diagnostics, opts.underline)
- end
-
- if opts.virtual_text then
- M._set_virtual_text(namespace, bufnr, diagnostics, opts.virtual_text)
- end
-
- if opts.signs then
- M._set_signs(namespace, bufnr, diagnostics, opts.signs)
+ for handler_name, handler in pairs(M.handlers) do
+ if handler.show and opts[handler_name] then
+ handler.show(namespace, bufnr, diagnostics, opts)
+ end
end
-
- save_extmarks(namespace, bufnr)
end
---- Open a floating window with the diagnostics at the given position.
+--- Show diagnostics in a floating window.
---
+---@param bufnr number|nil Buffer number. Defaults to the current buffer.
---@param opts table|nil Configuration table with the same keys as
--- |vim.lsp.util.open_floating_preview()| in addition to the following:
--- - namespace: (number) Limit diagnostics to the given namespace
---- - severity: See |diagnostic-severity|.
---- - show_header: (boolean, default true) Show "Diagnostics:" header
---- - source: (string) Include the diagnostic source in
---- the message. One of "always" or "if_many".
+--- - scope: (string, default "buffer") Show diagnostics from the whole buffer ("buffer"),
+--- the current cursor line ("line"), or the current cursor position ("cursor").
+--- - pos: (number or table) If {scope} is "line" or "cursor", use this position rather
+--- than the cursor position. If a number, interpreted as a line number;
+--- otherwise, a (row, col) tuple.
+--- - severity_sort: (default false) Sort diagnostics by severity. Overrides the setting
+--- from |vim.diagnostic.config()|.
+--- - severity: See |diagnostic-severity|. Overrides the setting from
+--- |vim.diagnostic.config()|.
+--- - show_header: (boolean, default true) Show "Diagnostics:" header. Overrides the
+--- setting from |vim.diagnostic.config()|.
+--- - source: (string) Include the diagnostic source in the message. One of "always" or
+--- "if_many". Overrides the setting from |vim.diagnostic.config()|.
--- - format: (function) A function that takes a diagnostic as input and returns a
--- string. The return value is the text used to display the diagnostic.
----@param bufnr number|nil Buffer number. Defaults to the current buffer.
----@param position table|nil The (0,0)-indexed position. Defaults to the current cursor position.
----@return tuple ({popup_bufnr}, {win_id})
-function M.show_position_diagnostics(opts, bufnr, position)
+--- Overrides the setting from |vim.diagnostic.config()|.
+--- - prefix: (function or string) Prefix each diagnostic in the floating window.
+--- Overrides the setting from |vim.diagnostic.config()|.
+---@return tuple ({float_bufnr}, {win_id})
+function M.open_float(bufnr, opts)
vim.validate {
- opts = { opts, 't', true },
bufnr = { bufnr, 'n', true },
- position = { position, 't', true },
+ opts = { opts, 't', true },
}
opts = opts or {}
-
- opts.focus_id = "position_diagnostics"
bufnr = get_bufnr(bufnr)
- if not position then
- local curr_position = vim.api.nvim_win_get_cursor(0)
- curr_position[1] = curr_position[1] - 1
- position = curr_position
+ local scope = opts.scope or "buffer"
+ local lnum, col
+ if scope == "line" or scope == "cursor" then
+ if not opts.pos then
+ local pos = vim.api.nvim_win_get_cursor(0)
+ lnum = pos[1] - 1
+ col = pos[2]
+ elseif type(opts.pos) == "number" then
+ lnum = opts.pos
+ elseif type(opts.pos) == "table" then
+ lnum, col = unpack(opts.pos)
+ else
+ error("Invalid value for option 'pos'")
+ end
+ elseif scope ~= "buffer" then
+ error("Invalid value for option 'scope'")
end
- local match_position_predicate = function(diag)
- return position[1] == diag.lnum and
- position[2] >= diag.col and
- (position[2] <= diag.end_col or position[1] < diag.end_lnum)
+
+ do
+ -- Resolve options with user settings from vim.diagnostic.config
+ -- Unlike the other decoration functions (e.g. set_virtual_text, set_signs, etc.) `open_float`
+ -- does not have a dedicated table for configuration options; instead, the options are mixed in
+ -- with its `opts` table which also includes "keyword" parameters. So we create a dedicated
+ -- options table that inherits missing keys from the global configuration before resolving.
+ local t = global_diagnostic_options.float
+ local float_opts = vim.tbl_extend("keep", opts, type(t) == "table" and t or {})
+ opts = get_resolved_options({ float = float_opts }, nil, bufnr).float
end
+
local diagnostics = M.get(bufnr, opts)
clamp_line_numbers(bufnr, diagnostics)
- local position_diagnostics = vim.tbl_filter(match_position_predicate, diagnostics)
- return show_diagnostics(opts, position_diagnostics)
-end
---- Open a floating window with the diagnostics from the given line.
----
----@param opts table Configuration table. See |vim.diagnostic.show_position_diagnostics()|.
----@param bufnr number|nil Buffer number. Defaults to the current buffer.
----@param lnum number|nil Line number. Defaults to line number of cursor.
----@return tuple ({popup_bufnr}, {win_id})
-function M.show_line_diagnostics(opts, bufnr, lnum)
- vim.validate {
- opts = { opts, 't', true },
- bufnr = { bufnr, 'n', true },
- lnum = { lnum, 'n', true },
- }
+ if scope == "line" then
+ diagnostics = vim.tbl_filter(function(d)
+ return d.lnum == lnum
+ end, diagnostics)
+ elseif scope == "cursor" then
+ -- LSP servers can send diagnostics with `end_col` past the length of the line
+ local line_length = #vim.api.nvim_buf_get_lines(bufnr, lnum, lnum + 1, true)[1]
+ diagnostics = vim.tbl_filter(function(d)
+ return d.lnum == lnum
+ and math.min(d.col, line_length - 1) <= col
+ and (d.end_col >= col or d.end_lnum > lnum)
+ end, diagnostics)
+ end
- opts = opts or {}
- opts.focus_id = "line_diagnostics"
- bufnr = get_bufnr(bufnr)
- local diagnostics = M.get(bufnr, opts)
- clamp_line_numbers(bufnr, diagnostics)
- lnum = lnum or (vim.api.nvim_win_get_cursor(0)[1] - 1)
- local line_diagnostics = diagnostic_lines(diagnostics)[lnum]
- return show_diagnostics(opts, line_diagnostics)
+ if vim.tbl_isempty(diagnostics) then
+ return
+ end
+
+ local severity_sort = vim.F.if_nil(opts.severity_sort, global_diagnostic_options.severity_sort)
+ if severity_sort then
+ if type(severity_sort) == "table" and severity_sort.reverse then
+ table.sort(diagnostics, function(a, b) return a.severity > b.severity end)
+ else
+ table.sort(diagnostics, function(a, b) return a.severity < b.severity end)
+ end
+ end
+
+ local lines = {}
+ local highlights = {}
+ local show_header = vim.F.if_nil(opts.show_header, true)
+ if show_header then
+ table.insert(lines, "Diagnostics:")
+ table.insert(highlights, {0, "Bold"})
+ end
+
+ if opts.format then
+ diagnostics = reformat_diagnostics(opts.format, diagnostics)
+ end
+
+ if opts.source then
+ diagnostics = prefix_source(opts.source, diagnostics)
+ end
+
+ local prefix_opt = if_nil(opts.prefix, (scope == "cursor" and #diagnostics <= 1) and "" or function(_, i)
+ return string.format("%d. ", i)
+ end)
+ if prefix_opt then
+ vim.validate { prefix = { prefix_opt, function(v)
+ return type(v) == "string" or type(v) == "function"
+ end, "'string' or 'function'" } }
+ end
+
+ for i, diagnostic in ipairs(diagnostics) do
+ local prefix = type(prefix_opt) == "string" and prefix_opt or prefix_opt(diagnostic, i, #diagnostics)
+ local hiname = floating_highlight_map[diagnostic.severity]
+ local message_lines = vim.split(diagnostic.message, '\n')
+ table.insert(lines, prefix..message_lines[1])
+ table.insert(highlights, {#prefix, hiname})
+ for j = 2, #message_lines do
+ table.insert(lines, string.rep(' ', #prefix) .. message_lines[j])
+ table.insert(highlights, {0, hiname})
+ end
+ end
+
+ -- Used by open_floating_preview to allow the float to be focused
+ if not opts.focus_id then
+ opts.focus_id = scope
+ end
+ local float_bufnr, winnr = require('vim.lsp.util').open_floating_preview(lines, 'plaintext', opts)
+ for i, hi in ipairs(highlights) do
+ local prefixlen, hiname = unpack(hi)
+ -- Start highlight after the prefix
+ vim.api.nvim_buf_add_highlight(float_bufnr, -1, hiname, i-1, prefixlen, -1)
+ end
+
+ return float_bufnr, winnr
end
--- Remove all diagnostics from the given namespace.
@@ -1215,19 +1276,23 @@ end
--- simply remove diagnostic decorations in a way that they can be
--- re-displayed, use |vim.diagnostic.hide()|.
---
----@param namespace number
+---@param namespace number|nil Diagnostic namespace. When omitted, remove
+--- diagnostics from all namespaces.
---@param bufnr number|nil Remove diagnostics for the given buffer. When omitted,
--- diagnostics are removed for all buffers.
function M.reset(namespace, bufnr)
- if bufnr == nil then
- for iter_bufnr, namespaces in pairs(diagnostic_cache) do
- if namespaces[namespace] then
- M.reset(namespace, iter_bufnr)
- end
+ vim.validate {
+ namespace = {namespace, 'n', true},
+ bufnr = {bufnr, 'n', true},
+ }
+
+ local buffers = bufnr and {bufnr} or vim.tbl_keys(diagnostic_cache)
+ for _, iter_bufnr in ipairs(buffers) do
+ local namespaces = namespace and {namespace} or vim.tbl_keys(diagnostic_cache[iter_bufnr])
+ for _, iter_namespace in ipairs(namespaces) do
+ clear_diagnostic_cache(iter_namespace, iter_bufnr)
+ M.hide(iter_namespace, iter_bufnr)
end
- else
- clear_diagnostic_cache(namespace, bufnr)
- M.hide(namespace, bufnr)
end
vim.api.nvim_command("doautocmd <nomodeline> User DiagnosticsChanged")
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 9c35351608..0fc0a7a7aa 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -5,6 +5,7 @@ local log = require 'vim.lsp.log'
local lsp_rpc = require 'vim.lsp.rpc'
local protocol = require 'vim.lsp.protocol'
local util = require 'vim.lsp.util'
+local sync = require 'vim.lsp.sync'
local vim = vim
local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_buf_get_option
@@ -108,6 +109,12 @@ local valid_encodings = {
UTF8 = 'utf-8'; UTF16 = 'utf-16'; UTF32 = 'utf-32';
}
+local format_line_ending = {
+ ["unix"] = '\n',
+ ["dos"] = '\r\n',
+ ["mac"] = '\r',
+}
+
local client_index = 0
---@private
--- Returns a new, unused client id.
@@ -122,9 +129,6 @@ local active_clients = {}
local all_buffer_active_clients = {}
local uninitialized_clients = {}
--- Tracks all buffers attached to a client.
-local all_client_active_buffers = {}
-
---@private
--- Invokes a function for each LSP client attached to the buffer {bufnr}.
---
@@ -242,6 +246,7 @@ local function validate_client_config(config)
on_exit = { config.on_exit, "f", true };
on_init = { config.on_init, "f", true };
settings = { config.settings, "t", true };
+ commands = { config.commands, 't', true };
before_init = { config.before_init, "f", true };
offset_encoding = { config.offset_encoding, "s", true };
flags = { config.flags, "t", true };
@@ -353,15 +358,14 @@ do
end
end
- function changetracking.prepare(bufnr, firstline, new_lastline, changedtick)
+ function changetracking.prepare(bufnr, firstline, lastline, new_lastline, changedtick)
local incremental_changes = function(client)
local cached_buffers = state_by_client[client.id].buffers
- local lines = nvim_buf_get_lines(bufnr, 0, -1, true)
- local startline = math.min(firstline + 1, math.min(#cached_buffers[bufnr], #lines))
- local endline = math.min(-(#lines - new_lastline), -1)
- local incremental_change = vim.lsp.util.compute_diff(
- cached_buffers[bufnr], lines, startline, endline, client.offset_encoding or 'utf-16')
- cached_buffers[bufnr] = lines
+ local curr_lines = nvim_buf_get_lines(bufnr, 0, -1, true)
+ local line_ending = format_line_ending[vim.api.nvim_buf_get_option(0, 'fileformat')]
+ local incremental_change = sync.compute_diff(
+ cached_buffers[bufnr], curr_lines, firstline, lastline, new_lastline, client.offset_encoding or 'utf-16', line_ending or '\n')
+ cached_buffers[bufnr] = curr_lines
return incremental_change
end
local full_changes = once(function()
@@ -468,7 +472,11 @@ local function text_document_did_open_handler(bufnr, client)
-- Next chance we get, we should re-do the diagnostics
vim.schedule(function()
- vim.lsp.diagnostic.redraw(bufnr, client.id)
+ -- Protect against a race where the buffer disappears
+ -- between `did_open_handler` and the scheduled function firing.
+ if vim.api.nvim_buf_is_valid(bufnr) then
+ vim.lsp.diagnostic.redraw(bufnr, client.id)
+ end
end)
end
@@ -593,6 +601,11 @@ end
--- returned to the language server if requested via `workspace/configuration`.
--- Keys are case-sensitive.
---
+---@param commands table Table that maps string of clientside commands to user-defined functions.
+--- Commands passed to start_client take precedence over the global command registry. Each key
+--- must be a unique comand name, and the value is a function which is called if any LSP action
+--- (code action, code lenses, ...) triggers the command.
+---
---@param init_options Values to pass in the initialization request
--- as `initializationOptions`. See `initialize` in the LSP spec.
---
@@ -647,7 +660,9 @@ end
--- - debounce_text_changes (number, default nil): Debounce didChange
--- notifications to the server by the given number in milliseconds. No debounce
--- occurs if nil
----
+--- - exit_timeout (number, default 500): Milliseconds to wait for server to
+-- exit cleanly after sending the 'shutdown' request before sending kill -15.
+-- If set to false, nvim exits immediately after sending the 'shutdown' request to the server.
---@returns Client id. |vim.lsp.get_client_by_id()| Note: client may not be
--- fully initialized. Use `on_init` to do any actions once
--- the client has been initialized.
@@ -742,7 +757,6 @@ function lsp.start_client(config)
lsp.diagnostic.reset(client_id, all_buffer_active_clients)
changetracking.reset(client_id)
- all_client_active_buffers[client_id] = nil
for _, client_ids in pairs(all_buffer_active_clients) do
client_ids[client_id] = nil
end
@@ -771,10 +785,14 @@ function lsp.start_client(config)
rpc = rpc;
offset_encoding = offset_encoding;
config = config;
+ attached_buffers = {};
handlers = handlers;
+ commands = config.commands or {};
+
+ requests = {};
-- for $/progress report
- messages = { name = name, messages = {}, progress = {}, status = {} }
+ messages = { name = name, messages = {}, progress = {}, status = {} };
}
-- Store the uninitialized_clients for cleanup in case we exit before initialize finishes.
@@ -907,11 +925,21 @@ function lsp.start_client(config)
end
-- Ensure pending didChange notifications are sent so that the server doesn't operate on a stale state
changetracking.flush(client)
-
+ bufnr = resolve_bufnr(bufnr)
local _ = log.debug() and log.debug(log_prefix, "client.request", client_id, method, params, handler, bufnr)
- return rpc.request(method, params, function(err, result)
+ local success, request_id = rpc.request(method, params, function(err, result)
handler(err, result, {method=method, client_id=client_id, bufnr=bufnr, params=params})
+ end, function(request_id)
+ client.requests[request_id] = nil
+ nvim_command("doautocmd <nomodeline> User LspRequest")
end)
+
+ if success then
+ client.requests[request_id] = { type='pending', bufnr=bufnr, method=method }
+ nvim_command("doautocmd <nomodeline> User LspRequest")
+ end
+
+ return success, request_id
end
---@private
@@ -971,6 +999,11 @@ function lsp.start_client(config)
---@see |vim.lsp.client.notify()|
function client.cancel_request(id)
validate{id = {id, 'n'}}
+ local request = client.requests[id]
+ if request and request.type == 'pending' then
+ request.type = 'cancel'
+ nvim_command("doautocmd <nomodeline> User LspRequest")
+ end
return rpc.notify("$/cancelRequest", { id = id })
end
@@ -989,7 +1022,6 @@ function lsp.start_client(config)
lsp.diagnostic.reset(client_id, all_buffer_active_clients)
changetracking.reset(client_id)
- all_client_active_buffers[client_id] = nil
for _, client_ids in pairs(all_buffer_active_clients) do
client_ids[client_id] = nil
end
@@ -1032,6 +1064,7 @@ function lsp.start_client(config)
-- TODO(ashkan) handle errors.
pcall(config.on_attach, client, bufnr)
end
+ client.attached_buffers[bufnr] = true
end
initialize()
@@ -1044,22 +1077,14 @@ end
--- Notify all attached clients that a buffer has changed.
local text_document_did_change_handler
do
- text_document_did_change_handler = function(_, bufnr, changedtick,
- firstline, lastline, new_lastline, old_byte_size, old_utf32_size,
- old_utf16_size)
-
- local _ = log.debug() and log.debug(
- string.format("on_lines bufnr: %s, changedtick: %s, firstline: %s, lastline: %s, new_lastline: %s, old_byte_size: %s, old_utf32_size: %s, old_utf16_size: %s",
- bufnr, changedtick, firstline, lastline, new_lastline, old_byte_size, old_utf32_size, old_utf16_size),
- nvim_buf_get_lines(bufnr, firstline, new_lastline, true)
- )
+ text_document_did_change_handler = function(_, bufnr, changedtick, firstline, lastline, new_lastline)
-- Don't do anything if there are no clients attached.
if tbl_isempty(all_buffer_active_clients[bufnr] or {}) then
return
end
util.buf_versions[bufnr] = changedtick
- local compute_change_and_notify = changetracking.prepare(bufnr, firstline, new_lastline, changedtick)
+ local compute_change_and_notify = changetracking.prepare(bufnr, firstline, lastline, new_lastline, changedtick)
for_each_buffer_client(bufnr, compute_change_and_notify)
end
end
@@ -1142,12 +1167,6 @@ function lsp.buf_attach_client(bufnr, client_id)
})
end
- if not all_client_active_buffers[client_id] then
- all_client_active_buffers[client_id] = {}
- end
-
- table.insert(all_client_active_buffers[client_id], bufnr)
-
if buffer_client_ids[client_id] then return end
-- This is our first time attaching this client to this buffer.
buffer_client_ids[client_id] = true
@@ -1172,7 +1191,7 @@ end
--- Gets a client by id, or nil if the id is invalid.
--- The returned client may not yet be fully initialized.
--
----@param client_id client id number
+---@param client_id number client id
---
---@returns |vim.lsp.client| object, or nil
function lsp.get_client_by_id(client_id)
@@ -1181,15 +1200,11 @@ end
--- Returns list of buffers attached to client_id.
--
----@param client_id client id
+---@param client_id number client id
---@returns list of buffer ids
function lsp.get_buffers_by_client_id(client_id)
- local active_client_buffers = all_client_active_buffers[client_id]
- if active_client_buffers then
- return active_client_buffers
- else
- return {}
- end
+ local client = lsp.get_client_by_id(client_id)
+ return client and vim.tbl_keys(client.attached_buffers) or {}
end
--- Stops a client(s).
@@ -1239,9 +1254,41 @@ function lsp._vim_exit_handler()
client.stop()
end
- if not vim.wait(500, function() return tbl_isempty(active_clients) end, 50) then
- for _, client in pairs(active_clients) do
- client.stop(true)
+ local timeouts = {}
+ local max_timeout = 0
+ local send_kill = false
+
+ for client_id, client in pairs(active_clients) do
+ local timeout = if_nil(client.config.flags.exit_timeout, 500)
+ if timeout then
+ send_kill = true
+ timeouts[client_id] = timeout
+ max_timeout = math.max(timeout, max_timeout)
+ end
+ end
+
+ local poll_time = 50
+
+ local function check_clients_closed()
+ for client_id, timeout in pairs(timeouts) do
+ timeouts[client_id] = timeout - poll_time
+ end
+
+ for client_id, _ in pairs(active_clients) do
+ if timeouts[client_id] ~= nil and timeouts[client_id] > 0 then
+ return false
+ end
+ end
+ return true
+ end
+
+ if send_kill then
+ if not vim.wait(max_timeout, check_clients_closed, poll_time) then
+ for client_id, client in pairs(active_clients) do
+ if timeouts[client_id] ~= nil then
+ client.stop(true)
+ end
+ end
end
end
end
@@ -1282,7 +1329,7 @@ function lsp.buf_request(bufnr, method, params, handler)
if not tbl_isempty(all_buffer_active_clients[resolve_bufnr(bufnr)] or {}) and not method_supported then
vim.notify(lsp._unsupported_method(method), vim.log.levels.ERROR)
vim.api.nvim_command("redraw")
- return
+ return {}, function() end
end
local client_request_ids = {}
@@ -1430,7 +1477,7 @@ end
---@param findstart 0 or 1, decides behavior
---@param base If findstart=0, text to match against
---
----@returns (number) Decided by `findstart`:
+---@returns (number) Decided by {findstart}:
--- - findstart=0: column where the completion starts, or -2 or -3
--- - findstart=1: list of matches (actually just calls |complete()|)
function lsp.omnifunc(findstart, base)
@@ -1494,6 +1541,52 @@ function lsp.omnifunc(findstart, base)
return -2
end
+--- Provides an interface between the built-in client and a `formatexpr` function.
+---
+--- Currently only supports a single client. This can be set via
+--- `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` but will typically or in `on_attach`
+--- via `vim.api.nvim_buf_set_option(bufnr, 'formatexpr', 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})')`.
+---
+---@param opts table options for customizing the formatting expression which takes the
+--- following optional keys:
+--- * timeout_ms (default 500ms). The timeout period for the formatting request.
+function lsp.formatexpr(opts)
+ opts = opts or {}
+ local timeout_ms = opts.timeout_ms or 500
+
+ if vim.tbl_contains({'i', 'R', 'ic', 'ix'}, vim.fn.mode()) then
+ -- `formatexpr` is also called when exceeding `textwidth` in insert mode
+ -- fall back to internal formatting
+ return 1
+ end
+
+ local start_line = vim.v.lnum
+ local end_line = start_line + vim.v.count - 1
+
+ if start_line > 0 and end_line > 0 then
+ local params = {
+ textDocument = util.make_text_document_params();
+ range = {
+ start = { line = start_line - 1; character = 0; };
+ ["end"] = { line = end_line - 1; character = 0; };
+ };
+ };
+ params.options = util.make_formatting_params().options
+ local client_results = vim.lsp.buf_request_sync(0, "textDocument/rangeFormatting", params, timeout_ms)
+
+ -- Apply the text edits from one and only one of the clients.
+ for _, response in pairs(client_results) do
+ if response.result then
+ vim.lsp.util.apply_text_edits(response.result, 0)
+ return 0
+ end
+ end
+ end
+
+ -- do not run builtin formatter.
+ return 0
+end
+
---Checks whether a client is stopped.
---
---@param client_id (Number)
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 245f29943e..747d761730 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -247,22 +247,35 @@ end
--- Renames all references to the symbol under the cursor.
---
---@param new_name (string) If not provided, the user will be prompted for a new
----name using |input()|.
+---name using |vim.ui.input()|.
function M.rename(new_name)
- local params = util.make_position_params()
+ local opts = {
+ prompt = "New Name: "
+ }
+
+ ---@private
+ local function on_confirm(input)
+ if not (input and #input > 0) then return end
+ local params = util.make_position_params()
+ params.newName = input
+ request('textDocument/rename', params)
+ end
+
local function prepare_rename(err, result)
if err == nil and result == nil then
vim.notify('nothing to rename', vim.log.levels.INFO)
return
end
if result and result.placeholder then
- new_name = new_name or npcall(vfn.input, "New Name: ", result.placeholder)
+ opts.default = result.placeholder
+ if not new_name then npcall(vim.ui.input, opts, on_confirm) end
elseif result and result.start and result['end'] and
result.start.line == result['end'].line then
local line = vfn.getline(result.start.line+1)
local start_char = result.start.character+1
local end_char = result['end'].character
- new_name = new_name or npcall(vfn.input, "New Name: ", string.sub(line, start_char, end_char))
+ opts.default = string.sub(line, start_char, end_char)
+ if not new_name then npcall(vim.ui.input, opts, on_confirm) end
else
-- fallback to guessing symbol using <cword>
--
@@ -270,13 +283,12 @@ function M.rename(new_name)
-- returns an unexpected response, or requests for "default behavior"
--
-- see https://microsoft.github.io/language-server-protocol/specification#textDocument_prepareRename
- new_name = new_name or npcall(vfn.input, "New Name: ", vfn.expand('<cword>'))
+ opts.default = vfn.expand('<cword>')
+ if not new_name then npcall(vim.ui.input, opts, on_confirm) end
end
- if not (new_name and #new_name > 0) then return end
- params.newName = new_name
- request('textDocument/rename', params)
+ if new_name then on_confirm(new_name) end
end
- request('textDocument/prepareRename', params, prepare_rename)
+ request('textDocument/prepareRename', util.make_position_params(), prepare_rename)
end
--- Lists all the references to the symbol under the cursor in the quickfix window.
@@ -357,7 +369,7 @@ end
function M.list_workspace_folders()
local workspace_folders = {}
for _, client in pairs(vim.lsp.buf_get_clients()) do
- for _, folder in pairs(client.workspaceFolders) do
+ for _, folder in pairs(client.workspaceFolders or {}) do
table.insert(workspace_folders, folder.name)
end
end
@@ -377,7 +389,7 @@ function M.add_workspace_folder(workspace_folder)
local params = util.make_workspace_params({{uri = vim.uri_from_fname(workspace_folder); name = workspace_folder}}, {{}})
for _, client in pairs(vim.lsp.buf_get_clients()) do
local found = false
- for _, folder in pairs(client.workspaceFolders) do
+ for _, folder in pairs(client.workspaceFolders or {}) do
if folder.name == workspace_folder then
found = true
print(workspace_folder, "is already part of this workspace")
@@ -386,6 +398,9 @@ function M.add_workspace_folder(workspace_folder)
end
if not found then
vim.lsp.buf_notify(0, 'workspace/didChangeWorkspaceFolders', params)
+ if not client.workspaceFolders then
+ client.workspaceFolders = {}
+ end
table.insert(client.workspaceFolders, params.event.added[1])
end
end
@@ -480,11 +495,11 @@ local function on_code_action_results(results, ctx)
end
if action.command then
local command = type(action.command) == 'table' and action.command or action
- local fn = vim.lsp.commands[command.command]
+ local fn = client.commands[command.command] or vim.lsp.commands[command.command]
if fn then
local enriched_ctx = vim.deepcopy(ctx)
enriched_ctx.client_id = client.id
- fn(command, ctx)
+ fn(command, enriched_ctx)
else
M.execute_command(command)
end
@@ -529,6 +544,7 @@ local function on_code_action_results(results, ctx)
vim.ui.select(action_tuples, {
prompt = 'Code actions:',
+ kind = 'codeaction',
format_item = function(action_tuple)
local title = action_tuple[2].title:gsub('\r\n', '\\r\\n')
return title:gsub('\n', '\\n')
diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua
index 63fcbe430b..9eb64c9a2e 100644
--- a/runtime/lua/vim/lsp/codelens.lua
+++ b/runtime/lua/vim/lsp/codelens.lua
@@ -31,15 +31,15 @@ local function execute_lens(lens, bufnr, client_id)
local line = lens.range.start.line
api.nvim_buf_clear_namespace(bufnr, namespaces[client_id], line, line + 1)
+ local client = vim.lsp.get_client_by_id(client_id)
+ assert(client, 'Client is required to execute lens, client_id=' .. client_id)
local command = lens.command
- local fn = vim.lsp.commands[command.command]
+ local fn = client.commands[command.command] or vim.lsp.commands[command.command]
if fn then
fn(command, { bufnr = bufnr, client_id = client_id })
return
end
-- Need to use the client that returned the lens → must not use buf_request
- local client = vim.lsp.get_client_by_id(client_id)
- assert(client, 'Client is required to execute lens, client_id=' .. client_id)
local command_provider = client.server_capabilities.executeCommandProvider
local commands = type(command_provider) == 'table' and command_provider.commands or {}
if not vim.tbl_contains(commands, command.command) then
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index 0e63c0dd29..1e6f83c1ba 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -146,7 +146,8 @@ local _client_namespaces = {}
function M.get_namespace(client_id)
vim.validate { client_id = { client_id, 'n' } }
if not _client_namespaces[client_id] then
- local name = string.format("vim.lsp.client-%d", client_id)
+ local client = vim.lsp.get_client_by_id(client_id)
+ local name = string.format("vim.lsp.%s.%d", client and client.name or "unknown", client_id)
_client_namespaces[client_id] = vim.api.nvim_create_namespace(name)
end
return _client_namespaces[client_id]
@@ -551,14 +552,15 @@ end
---@param position table|nil The (0,0)-indexed position
---@return table {popup_bufnr, win_id}
function M.show_position_diagnostics(opts, buf_nr, position)
- if opts then
- if opts.severity then
- opts.severity = severity_lsp_to_vim(opts.severity)
- elseif opts.severity_limit then
- opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
- end
+ opts = opts or {}
+ opts.scope = "cursor"
+ opts.pos = position
+ if opts.severity then
+ opts.severity = severity_lsp_to_vim(opts.severity)
+ elseif opts.severity_limit then
+ opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
end
- return vim.diagnostic.show_position_diagnostics(opts, buf_nr, position)
+ return vim.diagnostic.open_float(buf_nr, opts)
end
--- Open a floating window with the diagnostics from {line_nr}
@@ -573,11 +575,13 @@ end
---@param client_id number|nil the client id
---@return table {popup_bufnr, win_id}
function M.show_line_diagnostics(opts, buf_nr, line_nr, client_id)
+ opts = opts or {}
+ opts.scope = "line"
+ opts.pos = line_nr
if client_id then
- opts = opts or {}
opts.namespace = M.get_namespace(client_id)
end
- return vim.diagnostic.show_line_diagnostics(opts, buf_nr, line_nr)
+ return vim.diagnostic.open_float(buf_nr, opts)
end
--- Redraw diagnostics for the given buffer and client
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index eff27807be..a561630c2b 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -28,6 +28,7 @@ local function progress_handler(_, result, ctx, _)
local client_name = client and client.name or string.format("id=%d", client_id)
if not client then
err_message("LSP[", client_name, "] client has shut down after sending the message")
+ return
end
local val = result.value -- unspecified yet
local token = result.token -- string or number
@@ -185,7 +186,7 @@ local function response_to_list(map_result, entity)
title = 'Language Server';
items = map_result(result, ctx.bufnr);
})
- api.nvim_command("copen")
+ api.nvim_command("botright copen")
end
end
end
@@ -349,7 +350,7 @@ M['textDocument/signatureHelp'] = M.signature_help
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight
M['textDocument/documentHighlight'] = function(_, result, ctx, _)
if not result then return end
- util.buf_highlight_references(ctx.bufnr, result)
+ util.buf_highlight_references(ctx.bufnr, result, ctx.client_id)
end
---@private
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index d9a684a738..bce1e9f35d 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -297,6 +297,7 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
local message_index = 0
local message_callbacks = {}
+ local notify_reply_callbacks = {}
local handle, pid
do
@@ -309,8 +310,9 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
stdout:close()
stderr:close()
handle:close()
- -- Make sure that message_callbacks can be gc'd.
+ -- Make sure that message_callbacks/notify_reply_callbacks can be gc'd.
message_callbacks = nil
+ notify_reply_callbacks = nil
dispatchers.on_exit(code, signal)
end
local spawn_params = {
@@ -375,10 +377,12 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
---@param method (string) The invoked LSP method
---@param params (table) Parameters for the invoked LSP method
---@param callback (function) Callback to invoke
+ ---@param notify_reply_callback (function) Callback to invoke as soon as a request is no longer pending
---@returns (bool, number) `(true, message_id)` if request could be sent, `false` if not
- local function request(method, params, callback)
+ local function request(method, params, callback, notify_reply_callback)
validate {
callback = { callback, 'f' };
+ notify_reply_callback = { notify_reply_callback, 'f', true };
}
message_index = message_index + 1
local message_id = message_index
@@ -388,8 +392,15 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
method = method;
params = params;
}
- if result and message_callbacks then
- message_callbacks[message_id] = schedule_wrap(callback)
+ if result then
+ if message_callbacks then
+ message_callbacks[message_id] = schedule_wrap(callback)
+ else
+ return false
+ end
+ if notify_reply_callback and notify_reply_callbacks then
+ notify_reply_callbacks[message_id] = schedule_wrap(notify_reply_callback)
+ end
return result, message_id
else
return false
@@ -466,6 +477,16 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
-- We sent a number, so we expect a number.
local result_id = tonumber(decoded.id)
+ -- Notify the user that a response was received for the request
+ local notify_reply_callback = notify_reply_callbacks and notify_reply_callbacks[result_id]
+ if notify_reply_callback then
+ validate {
+ notify_reply_callback = { notify_reply_callback, 'f' };
+ }
+ notify_reply_callback(result_id)
+ notify_reply_callbacks[result_id] = nil
+ end
+
-- Do not surface RequestCancelled to users, it is RPC-internal.
if decoded.error then
local mute_error = false
diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua
new file mode 100644
index 0000000000..37247c61b9
--- /dev/null
+++ b/runtime/lua/vim/lsp/sync.lua
@@ -0,0 +1,381 @@
+-- Notes on incremental sync:
+-- Per the protocol, the text range should be:
+--
+-- A position inside a document (see Position definition below) is expressed as
+-- a zero-based line and character offset. The offsets are based on a UTF-16
+-- string representation. So a string of the form a𐐀b the character offset
+-- of the character a is 0, the character offset of 𐐀 is 1 and the character
+-- offset of b is 3 since 𐐀 is represented using two code units in UTF-16.
+--
+-- To ensure that both client and server split the string into the same line
+-- representation the protocol specifies the following end-of-line sequences: ‘\n’, ‘\r\n’ and ‘\r’.
+--
+-- Positions are line end character agnostic. So you can not specify a position that
+-- denotes \r|\n or \n| where | represents the character offset. This means *no* defining
+-- a range than ends on the same line after a terminating character
+--
+-- Generic warnings about byte level changes in neovim. Many apparently "single"
+-- operations in on_lines callbacks are actually multiple operations.
+--
+-- Join operation (2 operations):
+-- * extends line 1 with the contents of line 2
+-- * deletes line 2
+--
+-- test 1 test 1 test 2 test 1 test 2
+-- test 2 -> test 2 -> test 3
+-- test 3 test 3
+--
+-- Deleting (and undoing) two middle lines (1 operation):
+--
+-- test 1 test 1
+-- test 2 -> test 4
+-- test 3
+-- test 4
+--
+-- Deleting partial lines (5 operations) deleting between asterisks below:
+--
+-- test *1 test * test * test * test *4 test *4*
+-- test 2 -> test 2 -> test *4 -> *4 -> *4 ->
+-- test 3 test 3
+-- test *4 test 4
+
+local M = {}
+
+-- local string.byte, unclear if this is necessary for JIT compilation
+local str_byte = string.byte
+local min = math.min
+local str_utfindex = vim.str_utfindex
+local str_utf_start = vim.str_utf_start
+local str_utf_end = vim.str_utf_end
+
+---@private
+-- Given a line, byte idx, and offset_encoding convert to the
+-- utf-8, utf-16, or utf-32 index.
+---@param line string the line to index into
+---@param byte integer the byte idx
+---@param offset_encoding string utf-8|utf-16|utf-32|nil (default: utf-8)
+--@returns integer the utf idx for the given encoding
+local function byte_to_utf(line, byte, offset_encoding)
+ -- convert to 0 based indexing for str_utfindex
+ byte = byte - 1
+
+ local utf_idx
+ local _
+ -- Convert the byte range to utf-{8,16,32} and convert 1-based (lua) indexing to 0-based
+ if offset_encoding == 'utf-16' then
+ _, utf_idx = str_utfindex(line, byte)
+ elseif offset_encoding == 'utf-32' then
+ utf_idx, _ = str_utfindex(line, byte)
+ else
+ utf_idx = byte
+ end
+
+ -- convert to 1 based indexing
+ return utf_idx + 1
+end
+
+---@private
+-- Given a line, byte idx, alignment, and offset_encoding convert to the aligned
+-- utf-8 index and either the utf-16, or utf-32 index.
+---@param line string the line to index into
+---@param byte integer the byte idx
+---@param align string when dealing with multibyte characters,
+-- to choose the start of the current character or the beginning of the next.
+-- Used for incremental sync for start/end range respectively
+---@param offset_encoding string utf-8|utf-16|utf-32|nil (default: utf-8)
+---@returns table<string, int> byte_idx and char_idx of first change position
+local function align_position(line, byte, align, offset_encoding)
+ local char
+ -- If on the first byte, or an empty string: the trivial case
+ if byte == 1 or #line == 0 then
+ char = byte
+ -- Called in the case of extending an empty line "" -> "a"
+ elseif byte == #line + 1 then
+ byte = byte + str_utf_end(line, #line)
+ char = byte_to_utf(line, byte, offset_encoding)
+ else
+ -- Modifying line, find the nearest utf codepoint
+ if align == 'start' then
+ byte = byte + str_utf_start(line, byte)
+ char = byte_to_utf(line, byte, offset_encoding)
+ elseif align == 'end' then
+ local offset = str_utf_end(line, byte)
+ -- If the byte does not fall on the start of the character, then
+ -- align to the start of the next character.
+ if offset > 0 then
+ char = byte_to_utf(line, byte, offset_encoding) + 1
+ byte = byte + offset
+ else
+ char = byte_to_utf(line, byte, offset_encoding)
+ byte = byte + offset
+ end
+ else
+ error('`align` must be start or end.')
+ end
+ -- Extending line, find the nearest utf codepoint for the last valid character
+ end
+ return byte, char
+end
+
+---@private
+--- Finds the first line, byte, and char index of the difference between the previous and current lines buffer normalized to the previous codepoint.
+---@param prev_lines table list of lines from previous buffer
+---@param curr_lines table list of lines from current buffer
+---@param firstline integer firstline from on_lines, adjusted to 1-index
+---@param lastline integer lastline from on_lines, adjusted to 1-index
+---@param new_lastline integer new_lastline from on_lines, adjusted to 1-index
+---@param offset_encoding string utf-8|utf-16|utf-32|nil (fallback to utf-8)
+---@returns table<int, int> line_idx, byte_idx, and char_idx of first change position
+local function compute_start_range(prev_lines, curr_lines, firstline, lastline, new_lastline, offset_encoding)
+ -- If firstline == lastline, no existing text is changed. All edit operations
+ -- occur on a new line pointed to by lastline. This occurs during insertion of
+ -- new lines(O), the new newline is inserted at the line indicated by
+ -- new_lastline.
+ -- If firstline == new_lastline, the first change occured on a line that was deleted.
+ -- In this case, the first byte change is also at the first byte of firstline
+ if firstline == new_lastline or firstline == lastline then
+ return { line_idx = firstline, byte_idx = 1, char_idx = 1 }
+ end
+
+ local prev_line = prev_lines[firstline]
+ local curr_line = curr_lines[firstline]
+
+ -- Iterate across previous and current line containing first change
+ -- to find the first different byte.
+ -- Note: *about -> a*about will register the second a as the first
+ -- difference, regardless of edit since we do not receive the first
+ -- column of the edit from on_lines.
+ local start_byte_idx = 1
+ for idx = 1, #prev_line + 1 do
+ start_byte_idx = idx
+ if str_byte(prev_line, idx) ~= str_byte(curr_line, idx) then
+ break
+ end
+ end
+
+ -- Convert byte to codepoint if applicable
+ local byte_idx, char_idx = align_position(prev_line, start_byte_idx, 'start', offset_encoding)
+
+ -- Return the start difference (shared for new and prev lines)
+ return { line_idx = firstline, byte_idx = byte_idx, char_idx = char_idx }
+end
+
+---@private
+--- Finds the last line and byte index of the differences between prev and current buffer.
+--- Normalized to the next codepoint.
+--- prev_end_range is the text range sent to the server representing the changed region.
+--- curr_end_range is the text that should be collected and sent to the server.
+--
+---@param prev_lines table list of lines
+---@param curr_lines table list of lines
+---@param start_range table
+---@param lastline integer
+---@param new_lastline integer
+---@param offset_encoding string
+---@returns (int, int) end_line_idx and end_col_idx of range
+local function compute_end_range(prev_lines, curr_lines, start_range, firstline, lastline, new_lastline, offset_encoding)
+ -- If firstline == new_lastline, the first change occured on a line that was deleted.
+ -- In this case, the last_byte...
+ if firstline == new_lastline then
+ return { line_idx = (lastline - new_lastline + firstline), byte_idx = 1, char_idx = 1 }, { line_idx = firstline, byte_idx = 1, char_idx = 1 }
+ end
+ if firstline == lastline then
+ return { line_idx = firstline, byte_idx = 1, char_idx = 1 }, { line_idx = new_lastline - lastline + firstline, byte_idx = 1, char_idx = 1 }
+ end
+ -- Compare on last line, at minimum will be the start range
+ local start_line_idx = start_range.line_idx
+
+ -- lastline and new_lastline were last lines that were *not* replaced, compare previous lines
+ local prev_line_idx = lastline - 1
+ local curr_line_idx = new_lastline - 1
+
+ local prev_line = prev_lines[lastline - 1]
+ local curr_line = curr_lines[new_lastline - 1]
+
+ local prev_line_length = #prev_line
+ local curr_line_length = #curr_line
+
+ local byte_offset = 0
+
+ -- Editing the same line
+ -- If the byte offset is zero, that means there is a difference on the last byte (not newline)
+ if prev_line_idx == curr_line_idx then
+ local max_length
+ if start_line_idx == prev_line_idx then
+ -- Search until beginning of difference
+ max_length = min(prev_line_length - start_range.byte_idx, curr_line_length - start_range.byte_idx) + 1
+ else
+ max_length = min(prev_line_length, curr_line_length) + 1
+ end
+ for idx = 0, max_length do
+ byte_offset = idx
+ if
+ str_byte(prev_line, prev_line_length - byte_offset) ~= str_byte(curr_line, curr_line_length - byte_offset)
+ then
+ break
+ end
+ end
+ end
+
+ -- Iterate from end to beginning of shortest line
+ local prev_end_byte_idx = prev_line_length - byte_offset + 1
+ local prev_byte_idx, prev_char_idx = align_position(prev_line, prev_end_byte_idx, 'start', offset_encoding)
+ local prev_end_range = { line_idx = prev_line_idx, byte_idx = prev_byte_idx, char_idx = prev_char_idx }
+
+ local curr_end_range
+ -- Deletion event, new_range cannot be before start
+ if curr_line_idx < start_line_idx then
+ curr_end_range = { line_idx = start_line_idx, byte_idx = 1, char_idx = 1 }
+ else
+ local curr_end_byte_idx = curr_line_length - byte_offset + 1
+ local curr_byte_idx, curr_char_idx = align_position(curr_line, curr_end_byte_idx, 'start', offset_encoding)
+ curr_end_range = { line_idx = curr_line_idx, byte_idx = curr_byte_idx, char_idx = curr_char_idx }
+ end
+
+ return prev_end_range, curr_end_range
+end
+
+---@private
+--- Get the text of the range defined by start and end line/column
+---@param lines table list of lines
+---@param start_range table table returned by first_difference
+---@param end_range table new_end_range returned by last_difference
+---@returns string text extracted from defined region
+local function extract_text(lines, start_range, end_range, line_ending)
+ if not lines[start_range.line_idx] then
+ return ""
+ end
+ -- Trivial case: start and end range are the same line, directly grab changed text
+ if start_range.line_idx == end_range.line_idx then
+ -- string.sub is inclusive, end_range is not
+ return string.sub(lines[start_range.line_idx], start_range.byte_idx, end_range.byte_idx - 1)
+
+ else
+ -- Handle deletion case
+ -- Collect the changed portion of the first changed line
+ local result = { string.sub(lines[start_range.line_idx], start_range.byte_idx) }
+
+ -- Collect the full line for intermediate lines
+ for idx = start_range.line_idx + 1, end_range.line_idx - 1 do
+ table.insert(result, lines[idx])
+ end
+
+ if lines[end_range.line_idx] then
+ -- Collect the changed portion of the last changed line.
+ table.insert(result, string.sub(lines[end_range.line_idx], 1, end_range.byte_idx - 1))
+ else
+ table.insert(result, "")
+ end
+
+ -- Add line ending between all lines
+ return table.concat(result, line_ending)
+ end
+end
+
+local function compute_line_length(line, offset_encoding)
+ local length
+ local _
+ if offset_encoding == 'utf-16' then
+ _, length = str_utfindex(line)
+ elseif offset_encoding == 'utf-32' then
+ length, _ = str_utfindex(line)
+ else
+ length = #line
+ end
+ return length
+end
+---@private
+-- rangelength depends on the offset encoding
+-- bytes for utf-8 (clangd with extenion)
+-- codepoints for utf-16
+-- codeunits for utf-32
+-- Line endings count here as 2 chars for \r\n (dos), 1 char for \n (unix), and 1 char for \r (mac)
+-- These correspond to Windows, Linux/macOS (OSX and newer), and macOS (version 9 and prior)
+local function compute_range_length(lines, start_range, end_range, offset_encoding, line_ending)
+ local line_ending_length = #line_ending
+ -- Single line case
+ if start_range.line_idx == end_range.line_idx then
+ return end_range.char_idx - start_range.char_idx
+ end
+
+ local start_line = lines[start_range.line_idx]
+ local range_length
+ if start_line and #start_line > 0 then
+ range_length = compute_line_length(start_line, offset_encoding) - start_range.char_idx + 1 + line_ending_length
+ else
+ -- Length of newline character
+ range_length = line_ending_length
+ end
+
+ -- The first and last range of the line idx may be partial lines
+ for idx = start_range.line_idx + 1, end_range.line_idx - 1 do
+ -- Length full line plus newline character
+ if #lines[idx] > 0 then
+ range_length = range_length + compute_line_length(lines[idx], offset_encoding) + #line_ending
+ else
+ range_length = range_length + line_ending_length
+ end
+ end
+
+ local end_line = lines[end_range.line_idx]
+ if end_line and #end_line > 0 then
+ range_length = range_length + end_range.char_idx - 1
+ end
+
+ return range_length
+end
+
+--- Returns the range table for the difference between prev and curr lines
+---@param prev_lines table list of lines
+---@param curr_lines table list of lines
+---@param firstline number line to begin search for first difference
+---@param lastline number line to begin search in old_lines for last difference
+---@param new_lastline number line to begin search in new_lines for last difference
+---@param offset_encoding string encoding requested by language server
+---@returns table TextDocumentContentChangeEvent see https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#textDocumentContentChangeEvent
+function M.compute_diff(prev_lines, curr_lines, firstline, lastline, new_lastline, offset_encoding, line_ending)
+ -- Find the start of changes between the previous and current buffer. Common between both.
+ -- Sent to the server as the start of the changed range.
+ -- Used to grab the changed text from the latest buffer.
+ local start_range = compute_start_range(
+ prev_lines,
+ curr_lines,
+ firstline + 1,
+ lastline + 1,
+ new_lastline + 1,
+ offset_encoding
+ )
+ -- Find the last position changed in the previous and current buffer.
+ -- prev_end_range is sent to the server as as the end of the changed range.
+ -- curr_end_range is used to grab the changed text from the latest buffer.
+ local prev_end_range, curr_end_range = compute_end_range(
+ prev_lines,
+ curr_lines,
+ start_range,
+ firstline + 1,
+ lastline + 1,
+ new_lastline + 1,
+ offset_encoding
+ )
+
+ -- Grab the changed text of from start_range to curr_end_range in the current buffer.
+ -- The text range is "" if entire range is deleted.
+ local text = extract_text(curr_lines, start_range, curr_end_range, line_ending)
+
+ -- Compute the range of the replaced text. Deprecated but still required for certain language servers
+ local range_length = compute_range_length(prev_lines, start_range, prev_end_range, offset_encoding, line_ending)
+
+ -- convert to 0 based indexing
+ local result = {
+ range = {
+ ['start'] = { line = start_range.line_idx - 1, character = start_range.char_idx - 1 },
+ ['end'] = { line = prev_end_range.line_idx - 1, character = prev_end_range.char_idx - 1 },
+ },
+ text = text,
+ rangeLength = range_length,
+ }
+
+ return result
+end
+
+return M
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 952926b67e..a4b7b9922b 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -151,7 +151,7 @@ end
--- Position is a https://microsoft.github.io/language-server-protocol/specifications/specification-current/#position
--- Returns a zero-indexed column, since set_lines() does the conversion to
--- 1-indexed
-local function get_line_byte_from_position(bufnr, position)
+local function get_line_byte_from_position(bufnr, position, offset_encoding)
-- LSP's line and characters are 0-indexed
-- Vim's line and columns are 1-indexed
local col = position.character
@@ -165,7 +165,13 @@ local function get_line_byte_from_position(bufnr, position)
local line = position.line
local lines = api.nvim_buf_get_lines(bufnr, line, line + 1, false)
if #lines > 0 then
- local ok, result = pcall(vim.str_byteindex, lines[1], col)
+ local ok, result
+
+ if offset_encoding == "utf-16" or not offset_encoding then
+ ok, result = pcall(vim.str_byteindex, lines[1], col, true)
+ elseif offset_encoding == "utf-32" then
+ ok, result = pcall(vim.str_byteindex, lines[1], col, false)
+ end
if ok then
return result
@@ -226,9 +232,10 @@ function M.get_progress_messages()
table.remove(client.messages, item.idx)
end
- for _, item in ipairs(progress_remove) do
- client.messages.progress[item.token] = nil
- end
+ end
+
+ for _, item in ipairs(progress_remove) do
+ item.client.messages.progress[item.token] = nil
end
return new_messages
@@ -275,7 +282,8 @@ function M.apply_text_edits(text_edits, bufnr)
-- Some LSP servers may return +1 range of the buffer content but nvim_buf_set_text can't accept it so we should fix it here.
local has_eol_text_edit = false
local max = vim.api.nvim_buf_line_count(bufnr)
- local len = vim.str_utfindex(vim.api.nvim_buf_get_lines(bufnr, -2, -1, false)[1] or '')
+ -- TODO handle offset_encoding
+ local _, len = vim.str_utfindex(vim.api.nvim_buf_get_lines(bufnr, -2, -1, false)[1] or '')
text_edits = vim.tbl_map(function(text_edit)
if max <= text_edit.range.start.line then
text_edit.range.start.line = max - 1
@@ -359,177 +367,6 @@ end
-- function M.glob_to_regex(glob)
-- end
----@private
---- Finds the first line and column of the difference between old and new lines
----@param old_lines table list of lines
----@param new_lines table list of lines
----@returns (int, int) start_line_idx and start_col_idx of range
-local function first_difference(old_lines, new_lines, start_line_idx)
- local line_count = math.min(#old_lines, #new_lines)
- if line_count == 0 then return 1, 1 end
- if not start_line_idx then
- for i = 1, line_count do
- start_line_idx = i
- if old_lines[start_line_idx] ~= new_lines[start_line_idx] then
- break
- end
- end
- end
- local old_line = old_lines[start_line_idx]
- local new_line = new_lines[start_line_idx]
- local length = math.min(#old_line, #new_line)
- local start_col_idx = 1
- while start_col_idx <= length do
- if string.sub(old_line, start_col_idx, start_col_idx) ~= string.sub(new_line, start_col_idx, start_col_idx) then
- break
- end
- start_col_idx = start_col_idx + 1
- end
- return start_line_idx, start_col_idx
-end
-
-
----@private
---- Finds the last line and column of the differences between old and new lines
----@param old_lines table list of lines
----@param new_lines table list of lines
----@param start_char integer First different character idx of range
----@returns (int, int) end_line_idx and end_col_idx of range
-local function last_difference(old_lines, new_lines, start_char, end_line_idx)
- local line_count = math.min(#old_lines, #new_lines)
- if line_count == 0 then return 0,0 end
- if not end_line_idx then
- end_line_idx = -1
- end
- for i = end_line_idx, -line_count, -1 do
- if old_lines[#old_lines + i + 1] ~= new_lines[#new_lines + i + 1] then
- end_line_idx = i
- break
- end
- end
- local old_line
- local new_line
- if end_line_idx <= -line_count then
- end_line_idx = -line_count
- old_line = string.sub(old_lines[#old_lines + end_line_idx + 1], start_char)
- new_line = string.sub(new_lines[#new_lines + end_line_idx + 1], start_char)
- else
- old_line = old_lines[#old_lines + end_line_idx + 1]
- new_line = new_lines[#new_lines + end_line_idx + 1]
- end
- local old_line_length = #old_line
- local new_line_length = #new_line
- local length = math.min(old_line_length, new_line_length)
- local end_col_idx = -1
- while end_col_idx >= -length do
- local old_char = string.sub(old_line, old_line_length + end_col_idx + 1, old_line_length + end_col_idx + 1)
- local new_char = string.sub(new_line, new_line_length + end_col_idx + 1, new_line_length + end_col_idx + 1)
- if old_char ~= new_char then
- break
- end
- end_col_idx = end_col_idx - 1
- end
- return end_line_idx, end_col_idx
-
-end
-
----@private
---- Get the text of the range defined by start and end line/column
----@param lines table list of lines
----@param start_char integer First different character idx of range
----@param end_char integer Last different character idx of range
----@param start_line integer First different line idx of range
----@param end_line integer Last different line idx of range
----@returns string text extracted from defined region
-local function extract_text(lines, start_line, start_char, end_line, end_char)
- if start_line == #lines + end_line + 1 then
- if end_line == 0 then return '' end
- local line = lines[start_line]
- local length = #line + end_char - start_char
- return string.sub(line, start_char, start_char + length + 1)
- end
- local result = string.sub(lines[start_line], start_char) .. '\n'
- for line_idx = start_line + 1, #lines + end_line do
- result = result .. lines[line_idx] .. '\n'
- end
- if end_line ~= 0 then
- local line = lines[#lines + end_line + 1]
- local length = #line + end_char + 1
- result = result .. string.sub(line, 1, length)
- end
- return result
-end
-
----@private
---- Compute the length of the substituted range
----@param lines table list of lines
----@param start_char integer First different character idx of range
----@param end_char integer Last different character idx of range
----@param start_line integer First different line idx of range
----@param end_line integer Last different line idx of range
----@returns (int, int) end_line_idx and end_col_idx of range
-local function compute_length(lines, start_line, start_char, end_line, end_char)
- local adj_end_line = #lines + end_line + 1
- local adj_end_char
- if adj_end_line > #lines then
- adj_end_char = end_char - 1
- else
- adj_end_char = #lines[adj_end_line] + end_char
- end
- if start_line == adj_end_line then
- return adj_end_char - start_char + 1
- end
- local result = #lines[start_line] - start_char + 1
- for line = start_line + 1, adj_end_line -1 do
- result = result + #lines[line] + 1
- end
- result = result + adj_end_char + 1
- return result
-end
-
---- Returns the range table for the difference between old and new lines
----@param old_lines table list of lines
----@param new_lines table list of lines
----@param start_line_idx int line to begin search for first difference
----@param end_line_idx int line to begin search for last difference
----@param offset_encoding string encoding requested by language server
----@returns table start_line_idx and start_col_idx of range
-function M.compute_diff(old_lines, new_lines, start_line_idx, end_line_idx, offset_encoding)
- local start_line, start_char = first_difference(old_lines, new_lines, start_line_idx)
- local end_line, end_char = last_difference(vim.list_slice(old_lines, start_line, #old_lines),
- vim.list_slice(new_lines, start_line, #new_lines), start_char, end_line_idx)
- local text = extract_text(new_lines, start_line, start_char, end_line, end_char)
- local length = compute_length(old_lines, start_line, start_char, end_line, end_char)
-
- local adj_end_line = #old_lines + end_line
- local adj_end_char
- if end_line == 0 then
- adj_end_char = 0
- else
- adj_end_char = #old_lines[#old_lines + end_line + 1] + end_char + 1
- end
-
- local _
- if offset_encoding == "utf-16" then
- _, start_char = vim.str_utfindex(old_lines[start_line], start_char - 1)
- _, end_char = vim.str_utfindex(old_lines[#old_lines + end_line + 1], adj_end_char)
- else
- start_char = start_char - 1
- end_char = adj_end_char
- end
-
- local result = {
- range = {
- start = { line = start_line - 1, character = start_char},
- ["end"] = { line = adj_end_line, character = end_char}
- },
- text = text,
- rangeLength = length + 1,
- }
-
- return result
-end
-
--- Can be used to extract the completion items from a
--- `textDocument/completion` request, which may return one of
--- `CompletionItem[]`, `CompletionList` or null.
@@ -712,18 +549,29 @@ end
-- ignoreIfExists? bool
function M.rename(old_fname, new_fname, opts)
opts = opts or {}
- local bufnr = vim.fn.bufadd(old_fname)
- vim.fn.bufload(bufnr)
local target_exists = vim.loop.fs_stat(new_fname) ~= nil
if target_exists and not opts.overwrite or opts.ignoreIfExists then
vim.notify('Rename target already exists. Skipping rename.')
return
end
+ local oldbuf = vim.fn.bufadd(old_fname)
+ vim.fn.bufload(oldbuf)
+
+ -- The there may be pending changes in the buffer
+ api.nvim_buf_call(oldbuf, function()
+ vim.cmd('w!')
+ end)
+
local ok, err = os.rename(old_fname, new_fname)
assert(ok, err)
- api.nvim_buf_call(bufnr, function()
- vim.cmd('saveas! ' .. vim.fn.fnameescape(new_fname))
- end)
+
+ local newbuf = vim.fn.bufadd(new_fname)
+ for _, win in pairs(api.nvim_list_wins()) do
+ if api.nvim_win_get_buf(win) == oldbuf then
+ api.nvim_win_set_buf(win, newbuf)
+ end
+ end
+ api.nvim_buf_delete(oldbuf, { force = true })
end
@@ -1494,18 +1342,30 @@ do --[[ References ]]
---@param bufnr buffer id
---@param references List of `DocumentHighlight` objects to highlight
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#documentHighlight
- function M.buf_highlight_references(bufnr, references)
+ function M.buf_highlight_references(bufnr, references, client_id)
validate { bufnr = {bufnr, 'n', true} }
+ local client = vim.lsp.get_client_by_id(client_id)
+ if not client then
+ return
+ end
for _, reference in ipairs(references) do
- local start_pos = {reference["range"]["start"]["line"], reference["range"]["start"]["character"]}
- local end_pos = {reference["range"]["end"]["line"], reference["range"]["end"]["character"]}
+ local start_line, start_char = reference["range"]["start"]["line"], reference["range"]["start"]["character"]
+ local end_line, end_char = reference["range"]["end"]["line"], reference["range"]["end"]["character"]
+
+ local start_idx = get_line_byte_from_position(bufnr, { line = start_line, character = start_char }, client.offset_encoding)
+ local end_idx = get_line_byte_from_position(bufnr, { line = start_line, character = end_char }, client.offset_encoding)
+
local document_highlight_kind = {
[protocol.DocumentHighlightKind.Text] = "LspReferenceText";
[protocol.DocumentHighlightKind.Read] = "LspReferenceRead";
[protocol.DocumentHighlightKind.Write] = "LspReferenceWrite";
}
local kind = reference["kind"] or protocol.DocumentHighlightKind.Text
- highlight.range(bufnr, reference_ns, document_highlight_kind[kind], start_pos, end_pos)
+ highlight.range(bufnr,
+ reference_ns,
+ document_highlight_kind[kind],
+ { start_line, start_idx },
+ { end_line, end_idx })
end
end
end
@@ -1719,7 +1579,9 @@ function M.symbols_to_items(symbols, bufnr)
})
if symbol.children then
for _, v in ipairs(_symbols_to_items(symbol.children, _items, _bufnr)) do
- vim.list_extend(_items, v)
+ for _, s in ipairs(v) do
+ table.insert(_items, s)
+ end
end
end
end
@@ -1787,7 +1649,9 @@ local function make_position_param()
if not line then
return { line = 0; character = 0; }
end
- col = str_utfindex(line, col)
+ -- TODO handle offset_encoding
+ local _
+ _, col = str_utfindex(line, col)
return { line = row; character = col; }
end
@@ -1837,11 +1701,14 @@ function M.make_given_range_params(start_pos, end_pos)
A[1] = A[1] - 1
B[1] = B[1] - 1
-- account for encoding.
+ -- TODO handle offset_encoding
if A[2] > 0 then
- A = {A[1], M.character_offset(0, A[1], A[2])}
+ local _, char = M.character_offset(0, A[1], A[2])
+ A = {A[1], char}
end
if B[2] > 0 then
- B = {B[1], M.character_offset(0, B[1], B[2])}
+ local _, char = M.character_offset(0, B[1], B[2])
+ B = {B[1], char}
end
-- we need to offset the end character position otherwise we loose the last
-- character of the selection, as LSP end position is exclusive
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index b57b7ad4ad..6e40b6ca52 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -605,7 +605,7 @@ do
function vim.validate(opt)
local ok, err_msg = is_valid(opt)
if not ok then
- error(debug.traceback(err_msg, 2), 2)
+ error(err_msg, 2)
end
end
end
diff --git a/runtime/lua/vim/ui.lua b/runtime/lua/vim/ui.lua
index 5eab20fc54..9568b60fd0 100644
--- a/runtime/lua/vim/ui.lua
+++ b/runtime/lua/vim/ui.lua
@@ -9,6 +9,11 @@ local M = {}
--- - format_item (function item -> text)
--- Function to format an
--- individual item from `items`. Defaults to `tostring`.
+--- - kind (string|nil)
+--- Arbitrary hint string indicating the item shape.
+--- Plugins reimplementing `vim.ui.select` may wish to
+--- use this to infer the structure or semantics of
+--- `items`, or the context in which select() was called.
---@param on_choice function ((item|nil, idx|nil) -> ())
--- Called once the user made a choice.
--- `idx` is the 1-based index of `item` within `item`.
@@ -32,5 +37,38 @@ function M.select(items, opts, on_choice)
end
end
+--- Prompts the user for input
+---
+---@param opts table Additional options. See |input()|
+--- - prompt (string|nil)
+--- Text of the prompt. Defaults to `Input: `.
+--- - default (string|nil)
+--- Default reply to the input
+--- - completion (string|nil)
+--- Specifies type of completion supported
+--- for input. Supported types are the same
+--- that can be supplied to a user-defined
+--- command using the "-complete=" argument.
+--- See |:command-completion|
+--- - highlight (function)
+--- Function that will be used for highlighting
+--- user inputs.
+---@param on_confirm function ((input|nil) -> ())
+--- Called once the user confirms or abort the input.
+--- `input` is what the user typed.
+--- `nil` if the user aborted the dialog.
+function M.input(opts, on_confirm)
+ vim.validate {
+ on_confirm = { on_confirm, 'function', false },
+ }
+
+ opts = opts or {}
+ local input = vim.fn.input(opts)
+ if #input > 0 then
+ on_confirm(input)
+ else
+ on_confirm(nil)
+ end
+end
return M
diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
index 8057d7f284..8de03dfab7 100644
--- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
+++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
@@ -2,7 +2,7 @@
"
" Author: Bram Moolenaar
" Copyright: Vim license applies, see ":help license"
-" Last Change: 2021 Aug 23
+" Last Change: 2021 Oct 26
"
" WORK IN PROGRESS - Only the basics work
" Note: On MS-Windows you need a recent version of gdb. The one included with
@@ -550,7 +550,7 @@ func s:GdbOutCallback(job_id, msgs, event)
let index = 0
for msg in a:msgs
- if msg =~ '^^error,msg='
+ if msg =~ '^\^error,msg='
if exists('s:evalexpr')
\ && s:DecodeMessage(msg[11:])
\ =~ 'A syntax error in expression, near\|No symbol .* in current context'
@@ -746,8 +746,8 @@ func s:HandleDisasmMsg(msg)
else
let value = substitute(a:msg, '^\~\"[ ]*', '', '')
let value = substitute(value, '^=>[ ]*', '', '')
- let value = substitute(value, '\\n\" $', '', '')
- let value = substitute(value, ' ', '', '')
+ let value = substitute(value, '\\n\"\r$', '', '')
+ let value = substitute(value, '\r', '', '')
let value = substitute(value, '\\t', ' ', 'g')
if value != '' || !empty(s:asm_lines)
@@ -965,8 +965,22 @@ func s:Run(args)
endfunc
func s:SendEval(expr)
- call s:SendCommand('-data-evaluate-expression "' . a:expr . '"')
- let s:evalexpr = a:expr
+ " clean up expression that may got in because of range
+ " (newlines and surrounding spaces)
+ let expr = a:expr
+ if &filetype ==# 'cobol'
+ " extra cleanup for COBOL: _every: expression ends with a period,
+ " a trailing comma is ignored as it commonly separates multiple expr.
+ let expr = substitute(expr, '\..*', '', '')
+ let expr = substitute(expr, '[;\n]', ' ', 'g')
+ let expr = substitute(expr, ',*$', '', '')
+ else
+ let expr = substitute(expr, '\n', ' ', 'g')
+ endif
+ let expr = substitute(expr, '^ *\(.*\) *', '\1', '')
+
+ call s:SendCommand('-data-evaluate-expression "' . expr . '"')
+ let s:evalexpr = expr
endfunc
" :Evaluate - evaluate what is under the cursor
@@ -1151,7 +1165,8 @@ func s:HandleError(msg)
let s:evalFromBalloonExpr = 0
return
endif
- echoerr substitute(a:msg, '.*msg="\(.*\)"', '\1', '')
+ let msgVal = substitute(a:msg, '.*msg="\(.*\)"', '\1', '')
+ echoerr substitute(msgVal, '\\"', '"', 'g')
endfunc
func s:GotoSourcewinOrCreateIt()
diff --git a/runtime/syntax/arduino.vim b/runtime/syntax/arduino.vim
index 4a4ef82072..2f06eb6e64 100644
--- a/runtime/syntax/arduino.vim
+++ b/runtime/syntax/arduino.vim
@@ -1,50 +1,79 @@
" Vim syntax file
" Language: Arduino
" Maintainer: Johannes Hoff <johannes@johanneshoff.com>
-" Last Change: 2011 June 3
+" Last Change: 21 October 2021
" License: VIM license (:help license, replace vim by arduino.vim)
" Syntax highlighting like in the Arduino IDE
-" Keywords extracted from <arduino>/build/shared/lib/keywords.txt (arduino
-" version 0021)
+" Automatically generated by the script available at
+" https://github.com/johshoff/arduino-vim-syntax
+" Using keywords from <arduino>/build/shared/lib/keywords.txt
+" From version: 1.8.16
-" Thanks to Rik, Erik Nomitch, Adam Obeng and Graeme Cross for helpful feedback!
+" Thanks to Rik, Erik Nomitch, Adam Obeng, Graeme Cross and Niall Parker
+" for helpful feedback!
-" quit when a syntax file was already loaded
-if exists("b:current_syntax")
+" For version 5.x: Clear all syntax items
+" For version 6.x: Quit when a syntax file was already loaded
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
finish
endif
" Read the C syntax to start with
-runtime! syntax/cpp.vim
-
-syn keyword arduinoConstant HIGH LOW INPUT OUTPUT
-syn keyword arduinoConstant DEC BIN HEX OCT BYTE
-syn keyword arduinoConstant PI HALF_PI TWO_PI
-syn keyword arduinoConstant LSBFIRST MSBFIRST
-syn keyword arduinoConstant CHANGE FALLING RISING
-syn keyword arduinoConstant SERIAL DISPLAY
-syn keyword arduinoConstant DEFAULT EXTERNAL INTERNAL INTERNAL1V1 INTERNAL2V56
-
-syn keyword arduinoStdFunc abs acos asin atan atan2 ceil constrain
-syn keyword arduinoStdFunc cos degrees exp floor log
-syn keyword arduinoStdFunc map max min pow radians
-syn keyword arduinoStdFunc round sin sq sqrt tan
-syn keyword arduinoStdFunc randomSeed random
-
-syn keyword arduinoFunc analogReference analogRead analogWrite
-syn keyword arduinoFunc attachInterrupt detachInterrupt interrupts noInterrupts
-syn keyword arduinoFunc lowByte highByte bitRead bitWrite bitSet bitClear
-syn keyword arduinoFunc millis micros delay delayMicroseconds
-syn keyword arduinoFunc pinMode digitalWrite digitalRead
-syn keyword arduinoFunc tone noTone pulseIn shiftOut
-
-syn keyword arduinoMethod setup loop
-syn keyword arduinoMethod begin end available read flush print println write peek
-
-syn keyword arduinoType boolean byte word String
-
-syn keyword arduinoModule Serial Serial1 Serial2 Serial3
+if version < 600
+ so <sfile>:p:h/cpp.vim
+else
+ runtime! syntax/cpp.vim
+endif
+
+syn keyword arduinoConstant BIN CHANGE DEC DEFAULT EXTERNAL FALLING HALF_PI HEX
+syn keyword arduinoConstant HIGH INPUT INPUT_PULLUP INTERNAL INTERNAL1V1
+syn keyword arduinoConstant INTERNAL2V56 LED_BUILTIN LED_BUILTIN_RX
+syn keyword arduinoConstant LED_BUILTIN_TX LOW LSBFIRST MSBFIRST OCT OUTPUT PI
+syn keyword arduinoConstant RISING TWO_PI
+
+syn keyword arduinoFunc analogRead analogReadResolution analogReference
+syn keyword arduinoFunc analogWrite analogWriteResolution attachInterrupt
+syn keyword arduinoFunc bit bitClear bitRead bitSet bitWrite delay
+syn keyword arduinoFunc delayMicroseconds detachInterrupt
+syn keyword arduinoFunc digitalPinToInterrupt digitalRead digitalWrite
+syn keyword arduinoFunc highByte interrupts lowByte micros millis
+syn keyword arduinoFunc noInterrupts noTone pinMode pulseIn pulseInLong
+syn keyword arduinoFunc shiftIn shiftOut tone yield
+
+syn keyword arduinoMethod available availableForWrite begin charAt compareTo
+syn keyword arduinoMethod concat end endsWith equals equalsIgnoreCase export
+syn keyword arduinoMethod final find findUntil flush getBytes indexOf
+syn keyword arduinoMethod lastIndexOf length loop override parseFloat
+syn keyword arduinoMethod parseInt peek print println read readBytes
+syn keyword arduinoMethod readBytesUntil readString readStringUntil replace
+syn keyword arduinoMethod setCharAt setTimeout setup startsWith Stream
+syn keyword arduinoMethod substring toCharArray toInt toLowerCase toUpperCase
+syn keyword arduinoMethod trim
+
+syn keyword arduinoModule Keyboard Mouse Serial Serial1 Serial2 Serial3
+syn keyword arduinoModule SerialUSB
+
+syn keyword arduinoStdFunc abs accept acos acosf asin asinf atan atan2 atan2f
+syn keyword arduinoStdFunc atanf cbrt cbrtf ceil ceilf click constrain
+syn keyword arduinoStdFunc copysign copysignf cos cosf cosh coshf degrees exp
+syn keyword arduinoStdFunc expf fabs fabsf fdim fdimf floor floorf fma fmaf
+syn keyword arduinoStdFunc fmax fmaxf fmin fminf fmod fmodf hypot hypotf
+syn keyword arduinoStdFunc isfinite isinf isnan isPressed ldexp ldexpf log
+syn keyword arduinoStdFunc log10 log10f logf lrint lrintf lround lroundf map
+syn keyword arduinoStdFunc max min move pow powf press radians random
+syn keyword arduinoStdFunc randomSeed release releaseAll round roundf signbit
+syn keyword arduinoStdFunc sin sinf sinh sinhf sq sqrt sqrtf tan tanf tanh
+syn keyword arduinoStdFunc tanhf trunc truncf
+
+syn keyword arduinoType _Bool _Complex _Imaginary array atomic_bool
+syn keyword arduinoType atomic_char atomic_int atomic_llong atomic_long
+syn keyword arduinoType atomic_schar atomic_short atomic_uchar atomic_uint
+syn keyword arduinoType atomic_ullong atomic_ulong atomic_ushort boolean
+syn keyword arduinoType byte char16_t char32_t complex NULL null PROGMEM
+syn keyword arduinoType String word
hi def link arduinoType Type
hi def link arduinoConstant Constant
diff --git a/runtime/syntax/clojure.vim b/runtime/syntax/clojure.vim
index 1037967d1c..9782dc41ad 100644
--- a/runtime/syntax/clojure.vim
+++ b/runtime/syntax/clojure.vim
@@ -1,13 +1,13 @@
" Vim indent file
" Language: Clojure
-" Maintainer: Alex Vear <av@axvr.io>
+" Maintainer: Alex Vear <alex@vear.uk>
" Former Maintainers: Sung Pae <self@sungpae.com>
" Meikel Brandmeyer <mb@kotka.de>
" Toralf Wittner <toralf.wittner@gmail.com>
" Contributors: Joel Holdbrooks <cjholdbrooks@gmail.com> (Regexp support, bug fixes)
" URL: https://github.com/clojure-vim/clojure.vim
" License: Vim (see :h license)
-" Last Change: 2021-02-13
+" Last Change: 2021-10-26
if exists("b:current_syntax")
finish
@@ -21,15 +21,15 @@ if has("folding") && exists("g:clojure_fold") && g:clojure_fold > 0
endif
" -*- KEYWORDS -*-
-" Generated from https://github.com/clojure-vim/clojure.vim/blob/f8594e7030cdfb0b7990ac92953c77a08a7220f0/clj/src/vim_clojure_static/generate.clj
-" Clojure version 1.10.2
+" Generated from https://github.com/clojure-vim/clojure.vim/blob/62b215f079ce0f3834fd295c7a7f6bd8cc54bcc3/clj/src/vim_clojure_static/generate.clj
+" Clojure version 1.10.3
let s:clojure_syntax_keywords = {
\ 'clojureBoolean': ["false","true"]
\ , 'clojureCond': ["case","clojure.core/case","clojure.core/cond","clojure.core/cond->","clojure.core/cond->>","clojure.core/condp","clojure.core/if-let","clojure.core/if-not","clojure.core/if-some","clojure.core/when","clojure.core/when-first","clojure.core/when-let","clojure.core/when-not","clojure.core/when-some","cond","cond->","cond->>","condp","if-let","if-not","if-some","when","when-first","when-let","when-not","when-some"]
\ , 'clojureConstant': ["nil"]
\ , 'clojureDefine': ["clojure.core/definline","clojure.core/definterface","clojure.core/defmacro","clojure.core/defmethod","clojure.core/defmulti","clojure.core/defn","clojure.core/defn-","clojure.core/defonce","clojure.core/defprotocol","clojure.core/defrecord","clojure.core/defstruct","clojure.core/deftype","definline","definterface","defmacro","defmethod","defmulti","defn","defn-","defonce","defprotocol","defrecord","defstruct","deftype"]
\ , 'clojureException': ["catch","finally","throw","try"]
- \ , 'clojureFunc': ["*","*'","+","+'","-","-'","->ArrayChunk","->Eduction","->Vec","->VecNode","->VecSeq","-cache-protocol-fn","-reset-methods","/","<","<=","=","==",">",">=","PrintWriter-on","StackTraceElement->vec","Throwable->map","accessor","aclone","add-classpath","add-tap","add-watch","agent","agent-error","agent-errors","aget","alength","alias","all-ns","alter","alter-meta!","alter-var-root","ancestors","any?","apply","array-map","aset","aset-boolean","aset-byte","aset-char","aset-double","aset-float","aset-int","aset-long","aset-short","assoc","assoc!","assoc-in","associative?","atom","await","await-for","await1","bases","bean","bigdec","bigint","biginteger","bit-and","bit-and-not","bit-clear","bit-flip","bit-not","bit-or","bit-set","bit-shift-left","bit-shift-right","bit-test","bit-xor","boolean","boolean-array","boolean?","booleans","bound-fn*","bound?","bounded-count","butlast","byte","byte-array","bytes","bytes?","case-fallthrough-err-impl","cast","cat","char","char-array","char?","chars","chunk","chunk-append","chunk-buffer","chunk-cons","chunk-first","chunk-next","chunk-rest","chunked-seq?","class","class?","clear-agent-errors","clojure-version","clojure.core/*","clojure.core/*'","clojure.core/+","clojure.core/+'","clojure.core/-","clojure.core/-'","clojure.core/->ArrayChunk","clojure.core/->Eduction","clojure.core/->Vec","clojure.core/->VecNode","clojure.core/->VecSeq","clojure.core/-cache-protocol-fn","clojure.core/-reset-methods","clojure.core//","clojure.core/<","clojure.core/<=","clojure.core/=","clojure.core/==","clojure.core/>","clojure.core/>=","clojure.core/PrintWriter-on","clojure.core/StackTraceElement->vec","clojure.core/Throwable->map","clojure.core/accessor","clojure.core/aclone","clojure.core/add-classpath","clojure.core/add-tap","clojure.core/add-watch","clojure.core/agent","clojure.core/agent-error","clojure.core/agent-errors","clojure.core/aget","clojure.core/alength","clojure.core/alias","clojure.core/all-ns","clojure.core/alter","clojure.core/alter-meta!","clojure.core/alter-var-root","clojure.core/ancestors","clojure.core/any?","clojure.core/apply","clojure.core/array-map","clojure.core/aset","clojure.core/aset-boolean","clojure.core/aset-byte","clojure.core/aset-char","clojure.core/aset-double","clojure.core/aset-float","clojure.core/aset-int","clojure.core/aset-long","clojure.core/aset-short","clojure.core/assoc","clojure.core/assoc!","clojure.core/assoc-in","clojure.core/associative?","clojure.core/atom","clojure.core/await","clojure.core/await-for","clojure.core/await1","clojure.core/bases","clojure.core/bean","clojure.core/bigdec","clojure.core/bigint","clojure.core/biginteger","clojure.core/bit-and","clojure.core/bit-and-not","clojure.core/bit-clear","clojure.core/bit-flip","clojure.core/bit-not","clojure.core/bit-or","clojure.core/bit-set","clojure.core/bit-shift-left","clojure.core/bit-shift-right","clojure.core/bit-test","clojure.core/bit-xor","clojure.core/boolean","clojure.core/boolean-array","clojure.core/boolean?","clojure.core/booleans","clojure.core/bound-fn*","clojure.core/bound?","clojure.core/bounded-count","clojure.core/butlast","clojure.core/byte","clojure.core/byte-array","clojure.core/bytes","clojure.core/bytes?","clojure.core/case-fallthrough-err-impl","clojure.core/cast","clojure.core/cat","clojure.core/char","clojure.core/char-array","clojure.core/char?","clojure.core/chars","clojure.core/chunk","clojure.core/chunk-append","clojure.core/chunk-buffer","clojure.core/chunk-cons","clojure.core/chunk-first","clojure.core/chunk-next","clojure.core/chunk-rest","clojure.core/chunked-seq?","clojure.core/class","clojure.core/class?","clojure.core/clear-agent-errors","clojure.core/clojure-version","clojure.core/coll?","clojure.core/commute","clojure.core/comp","clojure.core/comparator","clojure.core/compare","clojure.core/compare-and-set!","clojure.core/compile","clojure.core/complement","clojure.core/completing","clojure.core/concat","clojure.core/conj","clojure.core/conj!","clojure.core/cons","clojure.core/constantly","clojure.core/construct-proxy","clojure.core/contains?","clojure.core/count","clojure.core/counted?","clojure.core/create-ns","clojure.core/create-struct","clojure.core/cycle","clojure.core/dec","clojure.core/dec'","clojure.core/decimal?","clojure.core/dedupe","clojure.core/delay?","clojure.core/deliver","clojure.core/denominator","clojure.core/deref","clojure.core/derive","clojure.core/descendants","clojure.core/destructure","clojure.core/disj","clojure.core/disj!","clojure.core/dissoc","clojure.core/dissoc!","clojure.core/distinct","clojure.core/distinct?","clojure.core/doall","clojure.core/dorun","clojure.core/double","clojure.core/double-array","clojure.core/double?","clojure.core/doubles","clojure.core/drop","clojure.core/drop-last","clojure.core/drop-while","clojure.core/eduction","clojure.core/empty","clojure.core/empty?","clojure.core/ensure","clojure.core/ensure-reduced","clojure.core/enumeration-seq","clojure.core/error-handler","clojure.core/error-mode","clojure.core/eval","clojure.core/even?","clojure.core/every-pred","clojure.core/every?","clojure.core/ex-cause","clojure.core/ex-data","clojure.core/ex-info","clojure.core/ex-message","clojure.core/extend","clojure.core/extenders","clojure.core/extends?","clojure.core/false?","clojure.core/ffirst","clojure.core/file-seq","clojure.core/filter","clojure.core/filterv","clojure.core/find","clojure.core/find-keyword","clojure.core/find-ns","clojure.core/find-protocol-impl","clojure.core/find-protocol-method","clojure.core/find-var","clojure.core/first","clojure.core/flatten","clojure.core/float","clojure.core/float-array","clojure.core/float?","clojure.core/floats","clojure.core/flush","clojure.core/fn?","clojure.core/fnext","clojure.core/fnil","clojure.core/force","clojure.core/format","clojure.core/frequencies","clojure.core/future-call","clojure.core/future-cancel","clojure.core/future-cancelled?","clojure.core/future-done?","clojure.core/future?","clojure.core/gensym","clojure.core/get","clojure.core/get-in","clojure.core/get-method","clojure.core/get-proxy-class","clojure.core/get-thread-bindings","clojure.core/get-validator","clojure.core/group-by","clojure.core/halt-when","clojure.core/hash","clojure.core/hash-combine","clojure.core/hash-map","clojure.core/hash-ordered-coll","clojure.core/hash-set","clojure.core/hash-unordered-coll","clojure.core/ident?","clojure.core/identical?","clojure.core/identity","clojure.core/ifn?","clojure.core/in-ns","clojure.core/inc","clojure.core/inc'","clojure.core/indexed?","clojure.core/init-proxy","clojure.core/inst-ms","clojure.core/inst-ms*","clojure.core/inst?","clojure.core/instance?","clojure.core/int","clojure.core/int-array","clojure.core/int?","clojure.core/integer?","clojure.core/interleave","clojure.core/intern","clojure.core/interpose","clojure.core/into","clojure.core/into-array","clojure.core/ints","clojure.core/isa?","clojure.core/iterate","clojure.core/iterator-seq","clojure.core/juxt","clojure.core/keep","clojure.core/keep-indexed","clojure.core/key","clojure.core/keys","clojure.core/keyword","clojure.core/keyword?","clojure.core/last","clojure.core/line-seq","clojure.core/list","clojure.core/list*","clojure.core/list?","clojure.core/load","clojure.core/load-file","clojure.core/load-reader","clojure.core/load-string","clojure.core/loaded-libs","clojure.core/long","clojure.core/long-array","clojure.core/longs","clojure.core/macroexpand","clojure.core/macroexpand-1","clojure.core/make-array","clojure.core/make-hierarchy","clojure.core/map","clojure.core/map-entry?","clojure.core/map-indexed","clojure.core/map?","clojure.core/mapcat","clojure.core/mapv","clojure.core/max","clojure.core/max-key","clojure.core/memoize","clojure.core/merge","clojure.core/merge-with","clojure.core/meta","clojure.core/method-sig","clojure.core/methods","clojure.core/min","clojure.core/min-key","clojure.core/mix-collection-hash","clojure.core/mod","clojure.core/munge","clojure.core/name","clojure.core/namespace","clojure.core/namespace-munge","clojure.core/nat-int?","clojure.core/neg-int?","clojure.core/neg?","clojure.core/newline","clojure.core/next","clojure.core/nfirst","clojure.core/nil?","clojure.core/nnext","clojure.core/not","clojure.core/not-any?","clojure.core/not-empty","clojure.core/not-every?","clojure.core/not=","clojure.core/ns-aliases","clojure.core/ns-imports","clojure.core/ns-interns","clojure.core/ns-map","clojure.core/ns-name","clojure.core/ns-publics","clojure.core/ns-refers","clojure.core/ns-resolve","clojure.core/ns-unalias","clojure.core/ns-unmap","clojure.core/nth","clojure.core/nthnext","clojure.core/nthrest","clojure.core/num","clojure.core/number?","clojure.core/numerator","clojure.core/object-array","clojure.core/odd?","clojure.core/parents","clojure.core/partial","clojure.core/partition","clojure.core/partition-all","clojure.core/partition-by","clojure.core/pcalls","clojure.core/peek","clojure.core/persistent!","clojure.core/pmap","clojure.core/pop","clojure.core/pop!","clojure.core/pop-thread-bindings","clojure.core/pos-int?","clojure.core/pos?","clojure.core/pr","clojure.core/pr-str","clojure.core/prefer-method","clojure.core/prefers","clojure.core/print","clojure.core/print-ctor","clojure.core/print-dup","clojure.core/print-method","clojure.core/print-simple","clojure.core/print-str","clojure.core/printf","clojure.core/println","clojure.core/println-str","clojure.core/prn","clojure.core/prn-str","clojure.core/promise","clojure.core/proxy-call-with-super","clojure.core/proxy-mappings","clojure.core/proxy-name","clojure.core/push-thread-bindings","clojure.core/qualified-ident?","clojure.core/qualified-keyword?","clojure.core/qualified-symbol?","clojure.core/quot","clojure.core/rand","clojure.core/rand-int","clojure.core/rand-nth","clojure.core/random-sample","clojure.core/range","clojure.core/ratio?","clojure.core/rational?","clojure.core/rationalize","clojure.core/re-find","clojure.core/re-groups","clojure.core/re-matcher","clojure.core/re-matches","clojure.core/re-pattern","clojure.core/re-seq","clojure.core/read","clojure.core/read+string","clojure.core/read-line","clojure.core/read-string","clojure.core/reader-conditional","clojure.core/reader-conditional?","clojure.core/realized?","clojure.core/record?","clojure.core/reduce","clojure.core/reduce-kv","clojure.core/reduced","clojure.core/reduced?","clojure.core/reductions","clojure.core/ref","clojure.core/ref-history-count","clojure.core/ref-max-history","clojure.core/ref-min-history","clojure.core/ref-set","clojure.core/refer","clojure.core/release-pending-sends","clojure.core/rem","clojure.core/remove","clojure.core/remove-all-methods","clojure.core/remove-method","clojure.core/remove-ns","clojure.core/remove-tap","clojure.core/remove-watch","clojure.core/repeat","clojure.core/repeatedly","clojure.core/replace","clojure.core/replicate","clojure.core/require","clojure.core/requiring-resolve","clojure.core/reset!","clojure.core/reset-meta!","clojure.core/reset-vals!","clojure.core/resolve","clojure.core/rest","clojure.core/restart-agent","clojure.core/resultset-seq","clojure.core/reverse","clojure.core/reversible?","clojure.core/rseq","clojure.core/rsubseq","clojure.core/run!","clojure.core/satisfies?","clojure.core/second","clojure.core/select-keys","clojure.core/send","clojure.core/send-off","clojure.core/send-via","clojure.core/seq","clojure.core/seq?","clojure.core/seqable?","clojure.core/seque","clojure.core/sequence","clojure.core/sequential?","clojure.core/set","clojure.core/set-agent-send-executor!","clojure.core/set-agent-send-off-executor!","clojure.core/set-error-handler!","clojure.core/set-error-mode!","clojure.core/set-validator!","clojure.core/set?","clojure.core/short","clojure.core/short-array","clojure.core/shorts","clojure.core/shuffle","clojure.core/shutdown-agents","clojure.core/simple-ident?","clojure.core/simple-keyword?","clojure.core/simple-symbol?","clojure.core/slurp","clojure.core/some","clojure.core/some-fn","clojure.core/some?","clojure.core/sort","clojure.core/sort-by","clojure.core/sorted-map","clojure.core/sorted-map-by","clojure.core/sorted-set","clojure.core/sorted-set-by","clojure.core/sorted?","clojure.core/special-symbol?","clojure.core/spit","clojure.core/split-at","clojure.core/split-with","clojure.core/str","clojure.core/string?","clojure.core/struct","clojure.core/struct-map","clojure.core/subs","clojure.core/subseq","clojure.core/subvec","clojure.core/supers","clojure.core/swap!","clojure.core/swap-vals!","clojure.core/symbol","clojure.core/symbol?","clojure.core/tagged-literal","clojure.core/tagged-literal?","clojure.core/take","clojure.core/take-last","clojure.core/take-nth","clojure.core/take-while","clojure.core/tap>","clojure.core/test","clojure.core/the-ns","clojure.core/thread-bound?","clojure.core/to-array","clojure.core/to-array-2d","clojure.core/trampoline","clojure.core/transduce","clojure.core/transient","clojure.core/tree-seq","clojure.core/true?","clojure.core/type","clojure.core/unchecked-add","clojure.core/unchecked-add-int","clojure.core/unchecked-byte","clojure.core/unchecked-char","clojure.core/unchecked-dec","clojure.core/unchecked-dec-int","clojure.core/unchecked-divide-int","clojure.core/unchecked-double","clojure.core/unchecked-float","clojure.core/unchecked-inc","clojure.core/unchecked-inc-int","clojure.core/unchecked-int","clojure.core/unchecked-long","clojure.core/unchecked-multiply","clojure.core/unchecked-multiply-int","clojure.core/unchecked-negate","clojure.core/unchecked-negate-int","clojure.core/unchecked-remainder-int","clojure.core/unchecked-short","clojure.core/unchecked-subtract","clojure.core/unchecked-subtract-int","clojure.core/underive","clojure.core/unreduced","clojure.core/unsigned-bit-shift-right","clojure.core/update","clojure.core/update-in","clojure.core/update-proxy","clojure.core/uri?","clojure.core/use","clojure.core/uuid?","clojure.core/val","clojure.core/vals","clojure.core/var-get","clojure.core/var-set","clojure.core/var?","clojure.core/vary-meta","clojure.core/vec","clojure.core/vector","clojure.core/vector-of","clojure.core/vector?","clojure.core/volatile!","clojure.core/volatile?","clojure.core/vreset!","clojure.core/with-bindings*","clojure.core/with-meta","clojure.core/with-redefs-fn","clojure.core/xml-seq","clojure.core/zero?","clojure.core/zipmap","coll?","commute","comp","comparator","compare","compare-and-set!","compile","complement","completing","concat","conj","conj!","cons","constantly","construct-proxy","contains?","count","counted?","create-ns","create-struct","cycle","dec","dec'","decimal?","dedupe","delay?","deliver","denominator","deref","derive","descendants","destructure","disj","disj!","dissoc","dissoc!","distinct","distinct?","doall","dorun","double","double-array","double?","doubles","drop","drop-last","drop-while","eduction","empty","empty?","ensure","ensure-reduced","enumeration-seq","error-handler","error-mode","eval","even?","every-pred","every?","ex-cause","ex-data","ex-info","ex-message","extend","extenders","extends?","false?","ffirst","file-seq","filter","filterv","find","find-keyword","find-ns","find-protocol-impl","find-protocol-method","find-var","first","flatten","float","float-array","float?","floats","flush","fn?","fnext","fnil","force","format","frequencies","future-call","future-cancel","future-cancelled?","future-done?","future?","gensym","get","get-in","get-method","get-proxy-class","get-thread-bindings","get-validator","group-by","halt-when","hash","hash-combine","hash-map","hash-ordered-coll","hash-set","hash-unordered-coll","ident?","identical?","identity","ifn?","in-ns","inc","inc'","indexed?","init-proxy","inst-ms","inst-ms*","inst?","instance?","int","int-array","int?","integer?","interleave","intern","interpose","into","into-array","ints","isa?","iterate","iterator-seq","juxt","keep","keep-indexed","key","keys","keyword","keyword?","last","line-seq","list","list*","list?","load","load-file","load-reader","load-string","loaded-libs","long","long-array","longs","macroexpand","macroexpand-1","make-array","make-hierarchy","map","map-entry?","map-indexed","map?","mapcat","mapv","max","max-key","memoize","merge","merge-with","meta","method-sig","methods","min","min-key","mix-collection-hash","mod","munge","name","namespace","namespace-munge","nat-int?","neg-int?","neg?","newline","next","nfirst","nil?","nnext","not","not-any?","not-empty","not-every?","not=","ns-aliases","ns-imports","ns-interns","ns-map","ns-name","ns-publics","ns-refers","ns-resolve","ns-unalias","ns-unmap","nth","nthnext","nthrest","num","number?","numerator","object-array","odd?","parents","partial","partition","partition-all","partition-by","pcalls","peek","persistent!","pmap","pop","pop!","pop-thread-bindings","pos-int?","pos?","pr","pr-str","prefer-method","prefers","print","print-ctor","print-dup","print-method","print-simple","print-str","printf","println","println-str","prn","prn-str","promise","proxy-call-with-super","proxy-mappings","proxy-name","push-thread-bindings","qualified-ident?","qualified-keyword?","qualified-symbol?","quot","rand","rand-int","rand-nth","random-sample","range","ratio?","rational?","rationalize","re-find","re-groups","re-matcher","re-matches","re-pattern","re-seq","read","read+string","read-line","read-string","reader-conditional","reader-conditional?","realized?","record?","reduce","reduce-kv","reduced","reduced?","reductions","ref","ref-history-count","ref-max-history","ref-min-history","ref-set","refer","release-pending-sends","rem","remove","remove-all-methods","remove-method","remove-ns","remove-tap","remove-watch","repeat","repeatedly","replace","replicate","require","requiring-resolve","reset!","reset-meta!","reset-vals!","resolve","rest","restart-agent","resultset-seq","reverse","reversible?","rseq","rsubseq","run!","satisfies?","second","select-keys","send","send-off","send-via","seq","seq?","seqable?","seque","sequence","sequential?","set","set-agent-send-executor!","set-agent-send-off-executor!","set-error-handler!","set-error-mode!","set-validator!","set?","short","short-array","shorts","shuffle","shutdown-agents","simple-ident?","simple-keyword?","simple-symbol?","slurp","some","some-fn","some?","sort","sort-by","sorted-map","sorted-map-by","sorted-set","sorted-set-by","sorted?","special-symbol?","spit","split-at","split-with","str","string?","struct","struct-map","subs","subseq","subvec","supers","swap!","swap-vals!","symbol","symbol?","tagged-literal","tagged-literal?","take","take-last","take-nth","take-while","tap>","test","the-ns","thread-bound?","to-array","to-array-2d","trampoline","transduce","transient","tree-seq","true?","type","unchecked-add","unchecked-add-int","unchecked-byte","unchecked-char","unchecked-dec","unchecked-dec-int","unchecked-divide-int","unchecked-double","unchecked-float","unchecked-inc","unchecked-inc-int","unchecked-int","unchecked-long","unchecked-multiply","unchecked-multiply-int","unchecked-negate","unchecked-negate-int","unchecked-remainder-int","unchecked-short","unchecked-subtract","unchecked-subtract-int","underive","unreduced","unsigned-bit-shift-right","update","update-in","update-proxy","uri?","use","uuid?","val","vals","var-get","var-set","var?","vary-meta","vec","vector","vector-of","vector?","volatile!","volatile?","vreset!","with-bindings*","with-meta","with-redefs-fn","xml-seq","zero?","zipmap"]
+ \ , 'clojureFunc': ["*","*'","+","+'","-","-'","->ArrayChunk","->Eduction","->Vec","->VecNode","->VecSeq","-cache-protocol-fn","-reset-methods","/","<","<=","=","==",">",">=","PrintWriter-on","StackTraceElement->vec","Throwable->map","accessor","aclone","add-classpath","add-tap","add-watch","agent","agent-error","agent-errors","aget","alength","alias","all-ns","alter","alter-meta!","alter-var-root","ancestors","any?","apply","array-map","aset","aset-boolean","aset-byte","aset-char","aset-double","aset-float","aset-int","aset-long","aset-short","assoc","assoc!","assoc-in","associative?","atom","await","await-for","await1","bases","bean","bigdec","bigint","biginteger","bit-and","bit-and-not","bit-clear","bit-flip","bit-not","bit-or","bit-set","bit-shift-left","bit-shift-right","bit-test","bit-xor","boolean","boolean-array","boolean?","booleans","bound-fn*","bound?","bounded-count","butlast","byte","byte-array","bytes","bytes?","cast","cat","char","char-array","char?","chars","chunk","chunk-append","chunk-buffer","chunk-cons","chunk-first","chunk-next","chunk-rest","chunked-seq?","class","class?","clear-agent-errors","clojure-version","clojure.core/*","clojure.core/*'","clojure.core/+","clojure.core/+'","clojure.core/-","clojure.core/-'","clojure.core/->ArrayChunk","clojure.core/->Eduction","clojure.core/->Vec","clojure.core/->VecNode","clojure.core/->VecSeq","clojure.core/-cache-protocol-fn","clojure.core/-reset-methods","clojure.core//","clojure.core/<","clojure.core/<=","clojure.core/=","clojure.core/==","clojure.core/>","clojure.core/>=","clojure.core/PrintWriter-on","clojure.core/StackTraceElement->vec","clojure.core/Throwable->map","clojure.core/accessor","clojure.core/aclone","clojure.core/add-classpath","clojure.core/add-tap","clojure.core/add-watch","clojure.core/agent","clojure.core/agent-error","clojure.core/agent-errors","clojure.core/aget","clojure.core/alength","clojure.core/alias","clojure.core/all-ns","clojure.core/alter","clojure.core/alter-meta!","clojure.core/alter-var-root","clojure.core/ancestors","clojure.core/any?","clojure.core/apply","clojure.core/array-map","clojure.core/aset","clojure.core/aset-boolean","clojure.core/aset-byte","clojure.core/aset-char","clojure.core/aset-double","clojure.core/aset-float","clojure.core/aset-int","clojure.core/aset-long","clojure.core/aset-short","clojure.core/assoc","clojure.core/assoc!","clojure.core/assoc-in","clojure.core/associative?","clojure.core/atom","clojure.core/await","clojure.core/await-for","clojure.core/await1","clojure.core/bases","clojure.core/bean","clojure.core/bigdec","clojure.core/bigint","clojure.core/biginteger","clojure.core/bit-and","clojure.core/bit-and-not","clojure.core/bit-clear","clojure.core/bit-flip","clojure.core/bit-not","clojure.core/bit-or","clojure.core/bit-set","clojure.core/bit-shift-left","clojure.core/bit-shift-right","clojure.core/bit-test","clojure.core/bit-xor","clojure.core/boolean","clojure.core/boolean-array","clojure.core/boolean?","clojure.core/booleans","clojure.core/bound-fn*","clojure.core/bound?","clojure.core/bounded-count","clojure.core/butlast","clojure.core/byte","clojure.core/byte-array","clojure.core/bytes","clojure.core/bytes?","clojure.core/cast","clojure.core/cat","clojure.core/char","clojure.core/char-array","clojure.core/char?","clojure.core/chars","clojure.core/chunk","clojure.core/chunk-append","clojure.core/chunk-buffer","clojure.core/chunk-cons","clojure.core/chunk-first","clojure.core/chunk-next","clojure.core/chunk-rest","clojure.core/chunked-seq?","clojure.core/class","clojure.core/class?","clojure.core/clear-agent-errors","clojure.core/clojure-version","clojure.core/coll?","clojure.core/commute","clojure.core/comp","clojure.core/comparator","clojure.core/compare","clojure.core/compare-and-set!","clojure.core/compile","clojure.core/complement","clojure.core/completing","clojure.core/concat","clojure.core/conj","clojure.core/conj!","clojure.core/cons","clojure.core/constantly","clojure.core/construct-proxy","clojure.core/contains?","clojure.core/count","clojure.core/counted?","clojure.core/create-ns","clojure.core/create-struct","clojure.core/cycle","clojure.core/dec","clojure.core/dec'","clojure.core/decimal?","clojure.core/dedupe","clojure.core/delay?","clojure.core/deliver","clojure.core/denominator","clojure.core/deref","clojure.core/derive","clojure.core/descendants","clojure.core/destructure","clojure.core/disj","clojure.core/disj!","clojure.core/dissoc","clojure.core/dissoc!","clojure.core/distinct","clojure.core/distinct?","clojure.core/doall","clojure.core/dorun","clojure.core/double","clojure.core/double-array","clojure.core/double?","clojure.core/doubles","clojure.core/drop","clojure.core/drop-last","clojure.core/drop-while","clojure.core/eduction","clojure.core/empty","clojure.core/empty?","clojure.core/ensure","clojure.core/ensure-reduced","clojure.core/enumeration-seq","clojure.core/error-handler","clojure.core/error-mode","clojure.core/eval","clojure.core/even?","clojure.core/every-pred","clojure.core/every?","clojure.core/ex-cause","clojure.core/ex-data","clojure.core/ex-info","clojure.core/ex-message","clojure.core/extend","clojure.core/extenders","clojure.core/extends?","clojure.core/false?","clojure.core/ffirst","clojure.core/file-seq","clojure.core/filter","clojure.core/filterv","clojure.core/find","clojure.core/find-keyword","clojure.core/find-ns","clojure.core/find-protocol-impl","clojure.core/find-protocol-method","clojure.core/find-var","clojure.core/first","clojure.core/flatten","clojure.core/float","clojure.core/float-array","clojure.core/float?","clojure.core/floats","clojure.core/flush","clojure.core/fn?","clojure.core/fnext","clojure.core/fnil","clojure.core/force","clojure.core/format","clojure.core/frequencies","clojure.core/future-call","clojure.core/future-cancel","clojure.core/future-cancelled?","clojure.core/future-done?","clojure.core/future?","clojure.core/gensym","clojure.core/get","clojure.core/get-in","clojure.core/get-method","clojure.core/get-proxy-class","clojure.core/get-thread-bindings","clojure.core/get-validator","clojure.core/group-by","clojure.core/halt-when","clojure.core/hash","clojure.core/hash-combine","clojure.core/hash-map","clojure.core/hash-ordered-coll","clojure.core/hash-set","clojure.core/hash-unordered-coll","clojure.core/ident?","clojure.core/identical?","clojure.core/identity","clojure.core/ifn?","clojure.core/in-ns","clojure.core/inc","clojure.core/inc'","clojure.core/indexed?","clojure.core/init-proxy","clojure.core/inst-ms","clojure.core/inst-ms*","clojure.core/inst?","clojure.core/instance?","clojure.core/int","clojure.core/int-array","clojure.core/int?","clojure.core/integer?","clojure.core/interleave","clojure.core/intern","clojure.core/interpose","clojure.core/into","clojure.core/into-array","clojure.core/ints","clojure.core/isa?","clojure.core/iterate","clojure.core/iterator-seq","clojure.core/juxt","clojure.core/keep","clojure.core/keep-indexed","clojure.core/key","clojure.core/keys","clojure.core/keyword","clojure.core/keyword?","clojure.core/last","clojure.core/line-seq","clojure.core/list","clojure.core/list*","clojure.core/list?","clojure.core/load","clojure.core/load-file","clojure.core/load-reader","clojure.core/load-string","clojure.core/loaded-libs","clojure.core/long","clojure.core/long-array","clojure.core/longs","clojure.core/macroexpand","clojure.core/macroexpand-1","clojure.core/make-array","clojure.core/make-hierarchy","clojure.core/map","clojure.core/map-entry?","clojure.core/map-indexed","clojure.core/map?","clojure.core/mapcat","clojure.core/mapv","clojure.core/max","clojure.core/max-key","clojure.core/memoize","clojure.core/merge","clojure.core/merge-with","clojure.core/meta","clojure.core/method-sig","clojure.core/methods","clojure.core/min","clojure.core/min-key","clojure.core/mix-collection-hash","clojure.core/mod","clojure.core/munge","clojure.core/name","clojure.core/namespace","clojure.core/namespace-munge","clojure.core/nat-int?","clojure.core/neg-int?","clojure.core/neg?","clojure.core/newline","clojure.core/next","clojure.core/nfirst","clojure.core/nil?","clojure.core/nnext","clojure.core/not","clojure.core/not-any?","clojure.core/not-empty","clojure.core/not-every?","clojure.core/not=","clojure.core/ns-aliases","clojure.core/ns-imports","clojure.core/ns-interns","clojure.core/ns-map","clojure.core/ns-name","clojure.core/ns-publics","clojure.core/ns-refers","clojure.core/ns-resolve","clojure.core/ns-unalias","clojure.core/ns-unmap","clojure.core/nth","clojure.core/nthnext","clojure.core/nthrest","clojure.core/num","clojure.core/number?","clojure.core/numerator","clojure.core/object-array","clojure.core/odd?","clojure.core/parents","clojure.core/partial","clojure.core/partition","clojure.core/partition-all","clojure.core/partition-by","clojure.core/pcalls","clojure.core/peek","clojure.core/persistent!","clojure.core/pmap","clojure.core/pop","clojure.core/pop!","clojure.core/pop-thread-bindings","clojure.core/pos-int?","clojure.core/pos?","clojure.core/pr","clojure.core/pr-str","clojure.core/prefer-method","clojure.core/prefers","clojure.core/print","clojure.core/print-ctor","clojure.core/print-dup","clojure.core/print-method","clojure.core/print-simple","clojure.core/print-str","clojure.core/printf","clojure.core/println","clojure.core/println-str","clojure.core/prn","clojure.core/prn-str","clojure.core/promise","clojure.core/proxy-call-with-super","clojure.core/proxy-mappings","clojure.core/proxy-name","clojure.core/push-thread-bindings","clojure.core/qualified-ident?","clojure.core/qualified-keyword?","clojure.core/qualified-symbol?","clojure.core/quot","clojure.core/rand","clojure.core/rand-int","clojure.core/rand-nth","clojure.core/random-sample","clojure.core/range","clojure.core/ratio?","clojure.core/rational?","clojure.core/rationalize","clojure.core/re-find","clojure.core/re-groups","clojure.core/re-matcher","clojure.core/re-matches","clojure.core/re-pattern","clojure.core/re-seq","clojure.core/read","clojure.core/read+string","clojure.core/read-line","clojure.core/read-string","clojure.core/reader-conditional","clojure.core/reader-conditional?","clojure.core/realized?","clojure.core/record?","clojure.core/reduce","clojure.core/reduce-kv","clojure.core/reduced","clojure.core/reduced?","clojure.core/reductions","clojure.core/ref","clojure.core/ref-history-count","clojure.core/ref-max-history","clojure.core/ref-min-history","clojure.core/ref-set","clojure.core/refer","clojure.core/release-pending-sends","clojure.core/rem","clojure.core/remove","clojure.core/remove-all-methods","clojure.core/remove-method","clojure.core/remove-ns","clojure.core/remove-tap","clojure.core/remove-watch","clojure.core/repeat","clojure.core/repeatedly","clojure.core/replace","clojure.core/replicate","clojure.core/require","clojure.core/requiring-resolve","clojure.core/reset!","clojure.core/reset-meta!","clojure.core/reset-vals!","clojure.core/resolve","clojure.core/rest","clojure.core/restart-agent","clojure.core/resultset-seq","clojure.core/reverse","clojure.core/reversible?","clojure.core/rseq","clojure.core/rsubseq","clojure.core/run!","clojure.core/satisfies?","clojure.core/second","clojure.core/select-keys","clojure.core/send","clojure.core/send-off","clojure.core/send-via","clojure.core/seq","clojure.core/seq?","clojure.core/seqable?","clojure.core/seque","clojure.core/sequence","clojure.core/sequential?","clojure.core/set","clojure.core/set-agent-send-executor!","clojure.core/set-agent-send-off-executor!","clojure.core/set-error-handler!","clojure.core/set-error-mode!","clojure.core/set-validator!","clojure.core/set?","clojure.core/short","clojure.core/short-array","clojure.core/shorts","clojure.core/shuffle","clojure.core/shutdown-agents","clojure.core/simple-ident?","clojure.core/simple-keyword?","clojure.core/simple-symbol?","clojure.core/slurp","clojure.core/some","clojure.core/some-fn","clojure.core/some?","clojure.core/sort","clojure.core/sort-by","clojure.core/sorted-map","clojure.core/sorted-map-by","clojure.core/sorted-set","clojure.core/sorted-set-by","clojure.core/sorted?","clojure.core/special-symbol?","clojure.core/spit","clojure.core/split-at","clojure.core/split-with","clojure.core/str","clojure.core/string?","clojure.core/struct","clojure.core/struct-map","clojure.core/subs","clojure.core/subseq","clojure.core/subvec","clojure.core/supers","clojure.core/swap!","clojure.core/swap-vals!","clojure.core/symbol","clojure.core/symbol?","clojure.core/tagged-literal","clojure.core/tagged-literal?","clojure.core/take","clojure.core/take-last","clojure.core/take-nth","clojure.core/take-while","clojure.core/tap>","clojure.core/test","clojure.core/the-ns","clojure.core/thread-bound?","clojure.core/to-array","clojure.core/to-array-2d","clojure.core/trampoline","clojure.core/transduce","clojure.core/transient","clojure.core/tree-seq","clojure.core/true?","clojure.core/type","clojure.core/unchecked-add","clojure.core/unchecked-add-int","clojure.core/unchecked-byte","clojure.core/unchecked-char","clojure.core/unchecked-dec","clojure.core/unchecked-dec-int","clojure.core/unchecked-divide-int","clojure.core/unchecked-double","clojure.core/unchecked-float","clojure.core/unchecked-inc","clojure.core/unchecked-inc-int","clojure.core/unchecked-int","clojure.core/unchecked-long","clojure.core/unchecked-multiply","clojure.core/unchecked-multiply-int","clojure.core/unchecked-negate","clojure.core/unchecked-negate-int","clojure.core/unchecked-remainder-int","clojure.core/unchecked-short","clojure.core/unchecked-subtract","clojure.core/unchecked-subtract-int","clojure.core/underive","clojure.core/unreduced","clojure.core/unsigned-bit-shift-right","clojure.core/update","clojure.core/update-in","clojure.core/update-proxy","clojure.core/uri?","clojure.core/use","clojure.core/uuid?","clojure.core/val","clojure.core/vals","clojure.core/var-get","clojure.core/var-set","clojure.core/var?","clojure.core/vary-meta","clojure.core/vec","clojure.core/vector","clojure.core/vector-of","clojure.core/vector?","clojure.core/volatile!","clojure.core/volatile?","clojure.core/vreset!","clojure.core/with-bindings*","clojure.core/with-meta","clojure.core/with-redefs-fn","clojure.core/xml-seq","clojure.core/zero?","clojure.core/zipmap","coll?","commute","comp","comparator","compare","compare-and-set!","compile","complement","completing","concat","conj","conj!","cons","constantly","construct-proxy","contains?","count","counted?","create-ns","create-struct","cycle","dec","dec'","decimal?","dedupe","delay?","deliver","denominator","deref","derive","descendants","destructure","disj","disj!","dissoc","dissoc!","distinct","distinct?","doall","dorun","double","double-array","double?","doubles","drop","drop-last","drop-while","eduction","empty","empty?","ensure","ensure-reduced","enumeration-seq","error-handler","error-mode","eval","even?","every-pred","every?","ex-cause","ex-data","ex-info","ex-message","extend","extenders","extends?","false?","ffirst","file-seq","filter","filterv","find","find-keyword","find-ns","find-protocol-impl","find-protocol-method","find-var","first","flatten","float","float-array","float?","floats","flush","fn?","fnext","fnil","force","format","frequencies","future-call","future-cancel","future-cancelled?","future-done?","future?","gensym","get","get-in","get-method","get-proxy-class","get-thread-bindings","get-validator","group-by","halt-when","hash","hash-combine","hash-map","hash-ordered-coll","hash-set","hash-unordered-coll","ident?","identical?","identity","ifn?","in-ns","inc","inc'","indexed?","init-proxy","inst-ms","inst-ms*","inst?","instance?","int","int-array","int?","integer?","interleave","intern","interpose","into","into-array","ints","isa?","iterate","iterator-seq","juxt","keep","keep-indexed","key","keys","keyword","keyword?","last","line-seq","list","list*","list?","load","load-file","load-reader","load-string","loaded-libs","long","long-array","longs","macroexpand","macroexpand-1","make-array","make-hierarchy","map","map-entry?","map-indexed","map?","mapcat","mapv","max","max-key","memoize","merge","merge-with","meta","method-sig","methods","min","min-key","mix-collection-hash","mod","munge","name","namespace","namespace-munge","nat-int?","neg-int?","neg?","newline","next","nfirst","nil?","nnext","not","not-any?","not-empty","not-every?","not=","ns-aliases","ns-imports","ns-interns","ns-map","ns-name","ns-publics","ns-refers","ns-resolve","ns-unalias","ns-unmap","nth","nthnext","nthrest","num","number?","numerator","object-array","odd?","parents","partial","partition","partition-all","partition-by","pcalls","peek","persistent!","pmap","pop","pop!","pop-thread-bindings","pos-int?","pos?","pr","pr-str","prefer-method","prefers","print","print-ctor","print-dup","print-method","print-simple","print-str","printf","println","println-str","prn","prn-str","promise","proxy-call-with-super","proxy-mappings","proxy-name","push-thread-bindings","qualified-ident?","qualified-keyword?","qualified-symbol?","quot","rand","rand-int","rand-nth","random-sample","range","ratio?","rational?","rationalize","re-find","re-groups","re-matcher","re-matches","re-pattern","re-seq","read","read+string","read-line","read-string","reader-conditional","reader-conditional?","realized?","record?","reduce","reduce-kv","reduced","reduced?","reductions","ref","ref-history-count","ref-max-history","ref-min-history","ref-set","refer","release-pending-sends","rem","remove","remove-all-methods","remove-method","remove-ns","remove-tap","remove-watch","repeat","repeatedly","replace","replicate","require","requiring-resolve","reset!","reset-meta!","reset-vals!","resolve","rest","restart-agent","resultset-seq","reverse","reversible?","rseq","rsubseq","run!","satisfies?","second","select-keys","send","send-off","send-via","seq","seq?","seqable?","seque","sequence","sequential?","set","set-agent-send-executor!","set-agent-send-off-executor!","set-error-handler!","set-error-mode!","set-validator!","set?","short","short-array","shorts","shuffle","shutdown-agents","simple-ident?","simple-keyword?","simple-symbol?","slurp","some","some-fn","some?","sort","sort-by","sorted-map","sorted-map-by","sorted-set","sorted-set-by","sorted?","special-symbol?","spit","split-at","split-with","str","string?","struct","struct-map","subs","subseq","subvec","supers","swap!","swap-vals!","symbol","symbol?","tagged-literal","tagged-literal?","take","take-last","take-nth","take-while","tap>","test","the-ns","thread-bound?","to-array","to-array-2d","trampoline","transduce","transient","tree-seq","true?","type","unchecked-add","unchecked-add-int","unchecked-byte","unchecked-char","unchecked-dec","unchecked-dec-int","unchecked-divide-int","unchecked-double","unchecked-float","unchecked-inc","unchecked-inc-int","unchecked-int","unchecked-long","unchecked-multiply","unchecked-multiply-int","unchecked-negate","unchecked-negate-int","unchecked-remainder-int","unchecked-short","unchecked-subtract","unchecked-subtract-int","underive","unreduced","unsigned-bit-shift-right","update","update-in","update-proxy","uri?","use","uuid?","val","vals","var-get","var-set","var?","vary-meta","vec","vector","vector-of","vector?","volatile!","volatile?","vreset!","with-bindings*","with-meta","with-redefs-fn","xml-seq","zero?","zipmap"]
\ , 'clojureMacro': ["->","->>","..","amap","and","areduce","as->","assert","binding","bound-fn","clojure.core/->","clojure.core/->>","clojure.core/..","clojure.core/amap","clojure.core/and","clojure.core/areduce","clojure.core/as->","clojure.core/assert","clojure.core/binding","clojure.core/bound-fn","clojure.core/comment","clojure.core/declare","clojure.core/delay","clojure.core/dosync","clojure.core/doto","clojure.core/extend-protocol","clojure.core/extend-type","clojure.core/for","clojure.core/future","clojure.core/gen-class","clojure.core/gen-interface","clojure.core/import","clojure.core/io!","clojure.core/lazy-cat","clojure.core/lazy-seq","clojure.core/letfn","clojure.core/locking","clojure.core/memfn","clojure.core/ns","clojure.core/or","clojure.core/proxy","clojure.core/proxy-super","clojure.core/pvalues","clojure.core/refer-clojure","clojure.core/reify","clojure.core/some->","clojure.core/some->>","clojure.core/sync","clojure.core/time","clojure.core/vswap!","clojure.core/with-bindings","clojure.core/with-in-str","clojure.core/with-loading-context","clojure.core/with-local-vars","clojure.core/with-open","clojure.core/with-out-str","clojure.core/with-precision","clojure.core/with-redefs","comment","declare","delay","dosync","doto","extend-protocol","extend-type","for","future","gen-class","gen-interface","import","io!","lazy-cat","lazy-seq","letfn","locking","memfn","ns","or","proxy","proxy-super","pvalues","refer-clojure","reify","some->","some->>","sync","time","vswap!","with-bindings","with-in-str","with-loading-context","with-local-vars","with-open","with-out-str","with-precision","with-redefs"]
\ , 'clojureRepeat': ["clojure.core/doseq","clojure.core/dotimes","clojure.core/while","doseq","dotimes","while"]
\ , 'clojureSpecial': [".","clojure.core/fn","clojure.core/let","clojure.core/loop","def","do","fn","if","let","loop","monitor-enter","monitor-exit","new","quote","recur","set!","var"]
@@ -68,40 +68,23 @@ delfunction s:syntax_keyword
" * Must not end in a : or /
" * Must not have two adjacent colons except at the beginning
" * Must not contain any reader metacharacters except for ' and #
-syntax match clojureKeyword "\v<:{1,2}%([^ \n\r\t()\[\]{}";@^`~\\%/]+/)*[^ \n\r\t()\[\]{}";@^`~\\%/]+:@<!>"
+syntax match clojureKeyword "\v<:{1,2}([^ \n\r\t()\[\]{}";@^`~\\/]+/)*[^ \n\r\t()\[\]{}";@^`~\\/]+:@1<!>"
syntax match clojureStringEscape "\v\\%([\\btnfr"]|u\x{4}|[0-3]\o{2}|\o{1,2})" contained
syntax region clojureString matchgroup=clojureStringDelimiter start=/"/ skip=/\\\\\|\\"/ end=/"/ contains=clojureStringEscape,@Spell
-syntax match clojureCharacter "\\."
-syntax match clojureCharacter "\\o\%([0-3]\o\{2\}\|\o\{1,2\}\)"
-syntax match clojureCharacter "\\u\x\{4\}"
-syntax match clojureCharacter "\\space"
-syntax match clojureCharacter "\\tab"
-syntax match clojureCharacter "\\newline"
-syntax match clojureCharacter "\\return"
-syntax match clojureCharacter "\\backspace"
-syntax match clojureCharacter "\\formfeed"
+syntax match clojureCharacter "\v\\%(o%([0-3]\o{2}|\o{1,2})|u\x{4}|newline|tab|space|return|backspace|formfeed|.)"
-syntax match clojureSymbol "\v%([a-zA-Z!$&*_+=|<.>?-]|[^\x00-\x7F])+%(:?%([a-zA-Z0-9!#$%&*_+=|'<.>/?-]|[^\x00-\x7F]))*[#:]@<!"
+syntax match clojureSymbol "\v%([a-zA-Z!$&*_+=|<.>?-]|[^\x00-\x7F])+%(:?%([a-zA-Z0-9!#$%&*_+=|'<.>/?-]|[^\x00-\x7F]))*[#:]@1<!"
-let s:radix_chars = "0123456789abcdefghijklmnopqrstuvwxyz"
-for s:radix in range(2, 36)
- execute 'syntax match clojureNumber "\v\c<[-+]?' . s:radix . 'r[' . strpart(s:radix_chars, 0, s:radix) . ']+>"'
-endfor
-unlet! s:radix_chars s:radix
-
-syntax match clojureNumber "\v<[-+]?%(0\o*|0x\x+|[1-9]\d*)N?>"
-syntax match clojureNumber "\v<[-+]?%(0|[1-9]\d*|%(0|[1-9]\d*)\.\d*)%(M|[eE][-+]?\d+)?>"
-syntax match clojureNumber "\v<[-+]?%(0|[1-9]\d*)/%(0|[1-9]\d*)>"
+" NB. Correct matching of radix literals was removed for better performance.
+syntax match clojureNumber "\v<[-+]?%(%([2-9]|[12]\d|3[0-6])[rR][[:alnum:]]+|%(0\o*|0x\x+|[1-9]\d*)N?|%(0|[1-9]\d*|%(0|[1-9]\d*)\.\d*)%(M|[eE][-+]?\d+)?|%(0|[1-9]\d*)/%(0|[1-9]\d*))>"
syntax match clojureVarArg "&"
-syntax match clojureQuote "'"
-syntax match clojureQuote "`"
-syntax match clojureUnquote "\~"
-syntax match clojureUnquote "\~@"
+syntax match clojureQuote "\v['`]"
+syntax match clojureUnquote "\v\~\@?"
syntax match clojureMeta "\^"
syntax match clojureDeref "@"
syntax match clojureDispatch "\v#[\^'=<_]?"
@@ -114,8 +97,8 @@ syntax region clojureRegexpQuoted start=/\\Q/ms=e+1 skip=/\\\\\|\\"/ end=/\\E/me
syntax region clojureRegexpQuote start=/\\Q/ skip=/\\\\\|\\"/ end=/\\E/ end=/"/me=s-1 contains=clojureRegexpQuoted keepend contained
" -*- CHARACTER PROPERTY CLASSES -*-
-" Generated from https://github.com/clojure-vim/clojure.vim/blob/f8594e7030cdfb0b7990ac92953c77a08a7220f0/clj/src/vim_clojure_static/generate.clj
-" Java version 15.0.2
+" Generated from https://github.com/clojure-vim/clojure.vim/blob/62b215f079ce0f3834fd295c7a7f6bd8cc54bcc3/clj/src/vim_clojure_static/generate.clj
+" Java version 17
syntax match clojureRegexpPosixCharClass "\v\\[pP]\{%(Cntrl|A%(l%(pha|num)|SCII)|Space|Graph|Upper|P%(rint|unct)|Blank|XDigit|Digit|Lower)\}" contained display
syntax match clojureRegexpJavaCharClass "\v\\[pP]\{java%(Whitespace|JavaIdentifier%(Part|Start)|SpaceChar|Mirrored|TitleCase|I%(SOControl|de%(ographic|ntifierIgnorable))|D%(efined|igit)|U%(pperCase|nicodeIdentifier%(Part|Start))|L%(etter%(OrDigit)?|owerCase)|Alphabetic)\}" contained display
syntax match clojureRegexpUnicodeCharClass "\v\\[pP]\{\cIs%(l%(owercase|etter)|hex%(digit|_digit)|w%(hite%(_space|space)|ord)|noncharacter%(_code_point|codepoint)|p%(rint|unctuation)|ideographic|graph|a%(l%(num|phabetic)|ssigned)|uppercase|join%(control|_control)|titlecase|blank|digit|control)\}" contained display
@@ -134,14 +117,14 @@ syntax match clojureRegexpBoundary "[$^]" contained display
syntax match clojureRegexpQuantifier "[?*+][?+]\=" contained display
syntax match clojureRegexpQuantifier "\v\{\d+%(,|,\d+)?}\??" contained display
syntax match clojureRegexpOr "|" contained display
-syntax match clojureRegexpBackRef "\v\\%([1-9]\d*|k\<[a-zA-z]+\>)" contained display
+syntax match clojureRegexpBackRef "\v\\%([1-9]\d*|k\<[[:alpha:]]+\>)" contained display
" Mode modifiers, mode-modified spans, lookaround, regular and atomic
" grouping, and named-capturing.
syntax match clojureRegexpMod "\v\(@<=\?:" contained display
syntax match clojureRegexpMod "\v\(@<=\?[xdsmiuU]*-?[xdsmiuU]+:?" contained display
syntax match clojureRegexpMod "\v\(@<=\?%(\<?[=!]|\>)" contained display
-syntax match clojureRegexpMod "\v\(@<=\?\<[a-zA-Z]+\>" contained display
+syntax match clojureRegexpMod "\v\(@<=\?\<[[:alpha:]]+\>" contained display
syntax region clojureRegexpGroup start="(" skip=/\\\\\|\\)/ end=")" matchgroup=clojureRegexpGroup contained contains=clojureRegexpMod,clojureRegexpQuantifier,clojureRegexpBoundary,clojureRegexpEscape,@clojureRegexpCharClasses
syntax region clojureRegexp start=/\#"/ skip=/\\\\\|\\"/ end=/"/ contains=@clojureRegexpCharClasses,clojureRegexpEscape,clojureRegexpQuote,clojureRegexpBoundary,clojureRegexpQuantifier,clojureRegexpOr,clojureRegexpBackRef,clojureRegexpGroup keepend
@@ -150,10 +133,24 @@ syntax keyword clojureCommentTodo contained FIXME XXX TODO BUG NOTE HACK FIXME:
syntax match clojureComment ";.*$" contains=clojureCommentTodo,@Spell
syntax match clojureComment "#!.*$"
+syntax match clojureComment ","
+
+" Comment out discarded forms. <https://clojure.org/guides/weird_characters#_discard>
+if exists('g:clojure_discard_macro') && g:clojure_discard_macro
+ syntax region clojureDiscard matchgroup=clojureDiscard start=/#_[ ,\t\n`'~]*/ end=/[, \t\n()\[\]{}";]/me=e-1
+ syntax region clojureDiscard matchgroup=clojureDiscard start=/#_[ ,\t\n`'~]*"/ skip=/\\[\\"]/ end=/"/
+ syntax region clojureDiscard matchgroup=clojureDiscard start=/#_[ ,\t\n`'~]*(/ end=/)/ contains=clojureDiscardForm
+ syntax region clojureDiscard matchgroup=clojureDiscard start=/#_[ ,\t\n`'~]*\[/ end=/\]/ contains=clojureDiscardForm
+ syntax region clojureDiscard matchgroup=clojureDiscard start=/#_[ ,\t\n`'~]*{/ end=/}/ contains=clojureDiscardForm
+
+ syntax region clojureDiscardForm start="(" end=")" contained contains=clojureDiscardForm
+ syntax region clojureDiscardForm start="{" end="}" contained contains=clojureDiscardForm
+ syntax region clojureDiscardForm start="\[" end="\]" contained contains=clojureDiscardForm
+endif
" -*- TOP CLUSTER -*-
-" Generated from https://github.com/clojure-vim/clojure.vim/blob/f8594e7030cdfb0b7990ac92953c77a08a7220f0/clj/src/vim_clojure_static/generate.clj
-syntax cluster clojureTop contains=@Spell,clojureAnonArg,clojureBoolean,clojureCharacter,clojureComment,clojureCond,clojureConstant,clojureDefine,clojureDeref,clojureDispatch,clojureError,clojureException,clojureFunc,clojureKeyword,clojureMacro,clojureMap,clojureMeta,clojureNumber,clojureQuote,clojureRegexp,clojureRepeat,clojureSexp,clojureSpecial,clojureString,clojureSymbol,clojureUnquote,clojureVarArg,clojureVariable,clojureVector
+" Generated from https://github.com/clojure-vim/clojure.vim/blob/62b215f079ce0f3834fd295c7a7f6bd8cc54bcc3/clj/src/vim_clojure_static/generate.clj
+syntax cluster clojureTop contains=@Spell,clojureAnonArg,clojureBoolean,clojureCharacter,clojureComment,clojureCond,clojureConstant,clojureDefine,clojureDeref,clojureDiscard,clojureDispatch,clojureError,clojureException,clojureFunc,clojureKeyword,clojureMacro,clojureMap,clojureMeta,clojureNumber,clojureQuote,clojureRegexp,clojureRepeat,clojureSexp,clojureSpecial,clojureString,clojureSymbol,clojureUnquote,clojureVarArg,clojureVariable,clojureVector
syntax region clojureSexp matchgroup=clojureParen start="(" end=")" contains=@clojureTop fold
syntax region clojureVector matchgroup=clojureParen start="\[" end="]" contains=@clojureTop fold
@@ -208,6 +205,8 @@ highlight default link clojureDispatch SpecialChar
highlight default link clojureComment Comment
highlight default link clojureCommentTodo Todo
+highlight default link clojureDiscard clojureComment
+highlight default link clojureDiscardForm clojureDiscard
highlight default link clojureError Error
diff --git a/runtime/syntax/debchangelog.vim b/runtime/syntax/debchangelog.vim
index 93b03ae06d..79352c0827 100644
--- a/runtime/syntax/debchangelog.vim
+++ b/runtime/syntax/debchangelog.vim
@@ -3,7 +3,7 @@
" Maintainer: Debian Vim Maintainers
" Former Maintainers: Gerfried Fuchs <alfie@ist.org>
" Wichert Akkerman <wakkerma@debian.org>
-" Last Change: 2021 Aug 03
+" Last Change: 2021 Oct 19
" URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/syntax/debchangelog.vim
" Standard syntax initialization
@@ -24,7 +24,8 @@ let s:supported = [
\ 'jessie', 'stretch', 'buster', 'bullseye', 'bookworm',
\ 'trixie', 'sid', 'rc-buggy',
\
- \ 'trusty', 'xenial', 'bionic', 'focal', 'hirsute', 'impish', 'devel'
+ \ 'trusty', 'xenial', 'bionic', 'focal', 'hirsute', 'impish', 'jammy',
+ \ 'devel'
\ ]
let s:unsupported = [
\ 'frozen', 'buzz', 'rex', 'bo', 'hamm', 'slink', 'potato',
diff --git a/runtime/syntax/debsources.vim b/runtime/syntax/debsources.vim
index 8aa96fcb58..4b4c497f18 100644
--- a/runtime/syntax/debsources.vim
+++ b/runtime/syntax/debsources.vim
@@ -2,7 +2,7 @@
" Language: Debian sources.list
" Maintainer: Debian Vim Maintainers
" Former Maintainer: Matthijs Mohlmann <matthijs@cacholong.nl>
-" Last Change: 2021 Aug 03
+" Last Change: 2021 Oct 19
" URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/syntax/debsources.vim
" Standard syntax initialization
@@ -26,7 +26,8 @@ let s:supported = [
\ 'jessie', 'stretch', 'buster', 'bullseye', 'bookworm',
\ 'trixie', 'sid', 'rc-buggy',
\
- \ 'trusty', 'xenial', 'bionic', 'focal', 'hirsute', 'impish', 'devel'
+ \ 'trusty', 'xenial', 'bionic', 'focal', 'hirsute', 'impish', 'jammy',
+ \ 'devel'
\ ]
let s:unsupported = [
\ 'buzz', 'rex', 'bo', 'hamm', 'slink', 'potato',
diff --git a/runtime/syntax/help_ru.vim b/runtime/syntax/help_ru.vim
index 8fcd63a917..67df7e1240 100644
--- a/runtime/syntax/help_ru.vim
+++ b/runtime/syntax/help_ru.vim
@@ -1,12 +1,12 @@
" Vim syntax file
" Language: Russian Vim program help files *.rux
-" Maintainer: Restorer (restorers@users.sourceforge.net)
+" Maintainer: Restorer (restorers@users.sourceforge.net DEFUNCT)
" Last Change: 04 Aprl 2017
"
" Проверяем язык локали и установки опции 'helplang'
" Если не русский, то выходим из скрипта.
-if ('ru' !~? v:lang || 'russian' !~? v:lang) && 'ru' !~? &helplang
+if (v:lang !~? 'ru' || v:lang !~? 'russian') && &helplang !~? 'ru'
finish
endif
diff --git a/runtime/syntax/meson.vim b/runtime/syntax/meson.vim
index 7e6b565f19..0af0d776f8 100644
--- a/runtime/syntax/meson.vim
+++ b/runtime/syntax/meson.vim
@@ -3,7 +3,7 @@
" License: VIM License
" Maintainer: Nirbheek Chauhan <nirbheek.chauhan@gmail.com>
" Liam Beguin <liambeguin@gmail.com>
-" Last Change: 2019 Oct 18
+" Last Change: 2021 Aug 16
" Credits: Zvezdan Petkovic <zpetkovic@acm.org>
" Neil Schemenauer <nas@meson.ca>
" Dmitry Vasiliev
@@ -56,9 +56,11 @@ syn match mesonEscape "\\$"
" Meson only supports integer numbers
" http://mesonbuild.com/Syntax.html#numbers
syn match mesonNumber "\<\d\+\>"
+syn match mesonNumber "\<0x\x\+\>"
+syn match mesonNumber "\<0o\o\+\>"
" booleans
-syn keyword mesonConstant false true
+syn keyword mesonBoolean false true
" Built-in functions
syn keyword mesonBuiltin
@@ -97,6 +99,7 @@ syn keyword mesonBuiltin
\ install_headers
\ install_man
\ install_subdir
+ \ install_emptydir
\ is_disabler
\ is_variable
\ jar
@@ -118,6 +121,7 @@ syn keyword mesonBuiltin
\ summary
\ target_machine
\ test
+ \ unset_variable
\ vcs_tag
\ warning
\ range
@@ -133,15 +137,15 @@ endif
" The default highlight links. Can be overridden later.
hi def link mesonStatement Statement
hi def link mesonConditional Conditional
-hi def link mesonRepeat Repeat
+hi def link mesonRepeat Repeat
hi def link mesonOperator Operator
hi def link mesonComment Comment
hi def link mesonTodo Todo
-hi def link mesonString String
-hi def link mesonEscape Special
-hi def link mesonNumber Number
+hi def link mesonString String
+hi def link mesonEscape Special
+hi def link mesonNumber Number
hi def link mesonBuiltin Function
-hi def link mesonConstant Number
+hi def link mesonBoolean Boolean
if exists("meson_space_error_higlight")
hi def link mesonSpaceError Error
endif
diff --git a/runtime/syntax/nsis.vim b/runtime/syntax/nsis.vim
index 3389771b78..3a73fe0989 100644
--- a/runtime/syntax/nsis.vim
+++ b/runtime/syntax/nsis.vim
@@ -1,9 +1,9 @@
" Vim syntax file
-" Language: NSIS script, for version of NSIS 3.03 and later
+" Language: NSIS script, for version of NSIS 3.08 and later
" Maintainer: Ken Takata
" URL: https://github.com/k-takata/vim-nsis
" Previous Maintainer: Alex Jakushev <Alex.Jakushev@kemek.lt>
-" Last Change: 2018-10-02
+" Last Change: 2020-10-18
" quit when a syntax file was already loaded
if exists("b:current_syntax")
@@ -97,6 +97,8 @@ syn match nsisSysVar "$RESOURCES_LOCALIZED"
syn match nsisSysVar "$CDBURN_AREA"
syn match nsisSysVar "$HWNDPARENT"
syn match nsisSysVar "$PLUGINSDIR"
+syn match nsisSysVar "$\%(USERTEMPLATES\|USERSTARTMENU\|USERSMPROGRAMS\|USERDESKTOP\)"
+syn match nsisSysVar "$\%(COMMONTEMPLATES\|COMMONSTARTMENU\|COMMONSMPROGRAMS\|COMMONDESKTOP\|COMMONPROGRAMDATA\)"
syn match nsisSysVar "$\\r"
syn match nsisSysVar "$\\n"
syn match nsisSysVar "$\\t"
@@ -149,7 +151,7 @@ syn keyword nsisStatement contained Section nextgroup=nsisSectionOpt skipwhite
syn region nsisSectionOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisSectionKwd
syn match nsisSectionKwd contained "/o\>"
-syn keyword nsisStatement contained SectionIn nextgroup=nsisSectionInOpt skipwhite
+syn keyword nsisStatement contained SectionInstType SectionIn nextgroup=nsisSectionInOpt skipwhite
syn region nsisSectionInOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisSectionInKwd
syn keyword nsisSectionInKwd contained RO
@@ -269,10 +271,22 @@ syn keyword nsisAttribute contained ManifestDPIAware nextgroup=nsisManifestDPIAw
syn region nsisManifestDPIAwareOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisManifestDPIAwareKwd
syn keyword nsisManifestDPIAwareKwd contained notset true false
+syn keyword nsisAttribute contained ManifestLongPathAware nextgroup=nsisManifestLongPathAwareOpt skipwhite
+syn region nsisManifestLongPathAwareOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisManifestLongPathAwareKwd
+syn match nsisManifestLongPathAwareKwd contained "\<\%(notset\|true\|false\)\>"
+
syn keyword nsisAttribute contained ManifestSupportedOS nextgroup=nsisManifestSupportedOSOpt skipwhite
syn region nsisManifestSupportedOSOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisManifestSupportedOSKwd
syn match nsisManifestSupportedOSKwd contained "\<\%(none\|all\|WinVista\|Win7\|Win8\|Win8\.1\|Win10\)\>"
+syn keyword nsisAttribute contained PEAddResource nextgroup=nsisPEAddResourceOpt skipwhite
+syn region nsisPEAddResourceOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisPEAddResourceKwd
+syn match nsisPEAddResourceKwd contained "/\%(OVERWRITE\|REPLACE\)\>"
+
+syn keyword nsisAttribute contained PERemoveResource nextgroup=nsisPERemoveResourceOpt skipwhite
+syn region nsisPERemoveResourceOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisPERemoveResourceKwd
+syn match nsisPERemoveResourceKwd contained "/NOERRORS\>"
+
syn keyword nsisAttribute contained RequestExecutionLevel nextgroup=nsisRequestExecutionLevelOpt skipwhite
syn region nsisRequestExecutionLevelOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisRequestExecutionLevelKwd
syn keyword nsisRequestExecutionLevelKwd contained none user highest admin
@@ -353,7 +367,7 @@ syn keyword nsisInstruction contained ExpandEnvStrings ReadEnvStr
syn keyword nsisInstruction contained DeleteRegKey nextgroup=nsisDeleteRegKeyOpt skipwhite
syn region nsisDeleteRegKeyOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisDeleteRegKeyKwd,nsisRegistry
-syn match nsisDeleteRegKeyKwd contained "/ifempty\>"
+syn match nsisDeleteRegKeyKwd contained "/\%(ifempty\|ifnosubkeys\|ifnovalues\)\>"
syn keyword nsisInstruction contained nextgroup=nsisRegistryOpt skipwhite
\ DeleteRegValue EnumRegKey EnumRegValue ReadRegDWORD ReadRegStr WriteRegBin WriteRegDWORD WriteRegExpandStr WriteRegStr
@@ -368,8 +382,8 @@ syn region nsisSetRegViewOpt contained start="" end="$" transparent keepend cont
syn keyword nsisSetRegViewKwd contained default lastused
"FUNCTIONS - general purpose (4.9.3)
-syn keyword nsisInstruction contained CallInstDLL CreateDirectory GetDLLVersion
-syn keyword nsisInstruction contained GetDLLVersionLocal GetFileTime GetFileTimeLocal
+syn keyword nsisInstruction contained CallInstDLL CreateDirectory GetWinVer
+syn keyword nsisInstruction contained GetFileTime GetFileTimeLocal GetKnownFolderPath
syn keyword nsisInstruction contained GetTempFileName SearchPath RegDLL UnRegDLL
syn keyword nsisInstruction contained CopyFiles nextgroup=nsisCopyFilesOpt skipwhite
@@ -380,6 +394,10 @@ syn keyword nsisInstruction contained CreateShortcut nextgroup=nsisCreateShortcu
syn region nsisCreateShortcutOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisCreateShortcutKwd
syn match nsisCreateShortcutKwd contained "/NoWorkingDir\>"
+syn keyword nsisInstruction contained GetDLLVersion GetDLLVersionLocal nextgroup=nsisGetDLLVersionOpt skipwhite
+syn region nsisGetDLLVersionOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisGetDLLVersionKwd
+syn match nsisGetDLLVersionKwd contained "/ProductVersion\>"
+
syn keyword nsisInstruction contained GetFullPathName nextgroup=nsisGetFullPathNameOpt skipwhite
syn region nsisGetFullPathNameOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisGetFullPathNameKwd
syn match nsisGetFullPathNameKwd contained "/SHORT\>"
@@ -395,6 +413,7 @@ syn keyword nsisFileAttrib contained FILE_ATTRIBUTE_TEMPORARY
syn keyword nsisInstruction contained Abort Call ClearErrors GetCurrentAddress
syn keyword nsisInstruction contained GetFunctionAddress GetLabelAddress Goto
syn keyword nsisInstruction contained IfAbort IfErrors IfFileExists IfRebootFlag IfSilent
+syn keyword nsisInstruction contained IfShellVarContextAll IfRtlLanguage
syn keyword nsisInstruction contained IntCmp IntCmpU Int64Cmp Int64CmpU IntPtrCmp IntPtrCmpU
syn keyword nsisInstruction contained Return Quit SetErrors StrCmp StrCmpS
@@ -460,6 +479,10 @@ syn keyword nsisInstruction contained CreateFont nextgroup=nsisFontOpt skipwhite
syn keyword nsisInstruction contained nextgroup=nsisBooleanOpt skipwhite
\ LockWindow SetAutoClose
+syn keyword nsisInstruction contained LoadAndSetImage nextgroup=nsisLoadAndSetImageOpt skipwhite
+syn region nsisLoadAndSetImageOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisLoadAndSetImageKwd
+syn match nsisLoadAndSetImageKwd contained "/\%(EXERESOURCE\|STRINGID\|RESIZETOFIT\%(WIDTH\|HEIGHT\)\)\>"
+
syn keyword nsisInstruction contained SendMessage nextgroup=nsisSendMessageOpt skipwhite
syn region nsisSendMessageOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisSendMessageKwd
syn match nsisSendMessageKwd contained "/TIMEOUT\>"
@@ -556,7 +579,7 @@ syn keyword nsisVerboseKwd contained push pop
"PREPROCESSOR (5.4)
syn match nsisDefine contained "!define\>" nextgroup=nsisDefineOpt skipwhite
syn region nsisDefineOpt contained start="" end="$" transparent keepend contains=@nsisAnyOpt,nsisDefineKwd
-syn match nsisDefineKwd contained "/\%(ifndef\|redef\|date\|utcdate\|math\|file\)\>"
+syn match nsisDefineKwd contained "/\%(ifndef\|redef\|date\|utcdate\|file\|intfmt\|math\)\>"
syn match nsisDefine contained "!undef\>"
syn match nsisPreCondit contained "!ifdef\>"
@@ -615,7 +638,10 @@ hi def link nsisInstTypeKwd Constant
hi def link nsisLicenseBkColorKwd Constant
hi def link nsisLicenseForceSelectionKwd Constant
hi def link nsisManifestDPIAwareKwd Constant
+hi def link nsisManifestLongPathAwareKwd Constant
hi def link nsisManifestSupportedOSKwd Constant
+hi def link nsisPEAddResourceKwd Constant
+hi def link nsisPERemoveResourceKwd Constant
hi def link nsisRequestExecutionLevelKwd Constant
hi def link nsisShowInstDetailsKwd Constant
hi def link nsisSilentInstallKwd Constant
@@ -633,11 +659,13 @@ hi def link nsisWriteRegMultiStrKwd Constant
hi def link nsisSetRegViewKwd Constant
hi def link nsisCopyFilesKwd Constant
hi def link nsisCreateShortcutKwd Constant
+hi def link nsisGetDLLVersionKwd Constant
hi def link nsisGetFullPathNameKwd Constant
hi def link nsisFileAttrib Constant
hi def link nsisMessageBox Constant
hi def link nsisFileWriteUTF16LEKwd Constant
hi def link nsisSetShellVarContextKwd Constant
+hi def link nsisLoadAndSetImageKwd Constant
hi def link nsisSendMessageKwd Constant
hi def link nsisSetBrandingImageKwd Constant
hi def link nsisSetDetailsViewKwd Constant
diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim
index 0ab9c0ad58..731a514cb2 100644
--- a/runtime/syntax/sh.vim
+++ b/runtime/syntax/sh.vim
@@ -2,8 +2,8 @@
" Language: shell (sh) Korn shell (ksh) bash (sh)
" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
" Previous Maintainer: Lennart Schultz <Lennart.Schultz@ecmwf.int>
-" Last Change: Feb 18, 2021
-" Version: 198
+" Last Change: Oct 26, 2021
+" Version: 199
" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH
" For options and settings, please use: :help ft-sh-syntax
" This file includes many ideas from Eric Brunet (eric.brunet@ens.fr) and heredoc fixes from Felipe Contreras
@@ -147,7 +147,7 @@ if exists("b:is_kornshell") || exists("b:is_bash")
endif
syn cluster shCommandSubList contains=shAlias,shArithmetic,shCmdParenRegion,shCommandSub,shComment,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shEcho,shEscape,shExDoubleQuote,shExpr,shExSingleQuote,shHereDoc,shNumber,shOperator,shOption,shPosnParm,shHereString,shRedir,shSingleQuote,shSpecial,shStatement,shSubSh,shTest,shVariable
syn cluster shCurlyList contains=shNumber,shComma,shDeref,shDerefSimple,shDerefSpecial
-" COMBAK: removing shEscape fromshDblQuoteList fails ksh04:43
+" COMBAK: removing shEscape from shDblQuoteList fails ksh04:43
syn cluster shDblQuoteList contains=shArithmetic,shCommandSub,shCommandSubBQ,shDeref,shDerefSimple,shPosnParm,shCtrlSeq,shSpecial,shSpecialDQ
syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPSR,shDerefPPS
syn cluster shDerefVarList contains=shDerefOffset,shDerefOp,shDerefVarArray,shDerefOpError
@@ -401,7 +401,7 @@ endif
syn match shComment "^\s*\zs#.*$" contains=@shCommentGroup
syn match shComment "\s\zs#.*$" contains=@shCommentGroup
syn match shComment contained "#.*$" contains=@shCommentGroup
-syn match shQuickComment contained "#.*$"
+syn match shQuickComment contained "#.*$" contains=@shCommentGroup
syn match shBQComment contained "#.\{-}\ze`" contains=@shCommentGroup
" Here Documents: {{{1
diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim
index f695a1a1bf..67756fa320 100644
--- a/runtime/syntax/vim.vim
+++ b/runtime/syntax/vim.vim
@@ -165,7 +165,6 @@ syn keyword vimCommand contained in
syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=a\%[ppend]$" matchgroup=vimCommand end="^\.$""
syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=c\%[hange]$" matchgroup=vimCommand end="^\.$""
syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=i\%[nsert]$" matchgroup=vimCommand end="^\.$""
-syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=starti\%[nsert]$" matchgroup=vimCommand end="^\.$""
" Behave! {{{2
" =======
@@ -201,9 +200,9 @@ syn keyword vimAugroupKey contained aug[roup]
" Operators: {{{2
" =========
syn cluster vimOperGroup contains=vimEnvvar,vimFunc,vimFuncVar,vimOper,vimOperParen,vimNumber,vimString,vimType,vimRegister,vimContinue,vim9Comment
-syn match vimOper "\%#=1\(==\|!=\|>=\|<=\|=\~\|!\~\|>\|<\|=\)[?#]\{0,2}" skipwhite nextgroup=vimString,vimSpecFile
-syn match vimOper "\(\<is\|\<isnot\)[?#]\{0,2}\>" skipwhite nextgroup=vimString,vimSpecFile
syn match vimOper "||\|&&\|[-+.!]" skipwhite nextgroup=vimString,vimSpecFile
+syn match vimOper "\%#=1\(==\|!=\|>=\|<=\|=\~\|!\~\|>\|<\|=\|!\~#\)[?#]\{0,2}" skipwhite nextgroup=vimString,vimSpecFile
+syn match vimOper "\(\<is\|\<isnot\)[?#]\{0,2}\>" skipwhite nextgroup=vimString,vimSpecFile
syn region vimOperParen matchgroup=vimParenSep start="(" end=")" contains=vimoperStar,@vimOperGroup
syn region vimOperParen matchgroup=vimSep start="#\={" end="}" contains=@vimOperGroup nextgroup=vimVar,vimFuncVar
if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_noopererror")
@@ -368,7 +367,7 @@ syn match vimSetMod contained "&vim\=\|[!&?<]\|all&"
" Let: {{{2
" ===
syn keyword vimLet let unl[et] skipwhite nextgroup=vimVar,vimFuncVar,vimLetHereDoc
-VimFoldh syn region vimLetHereDoc matchgroup=vimLetHereDocStart start='=<<\s\+\%(trim\>\)\=\s*\z(\L\S*\)' matchgroup=vimLetHereDocStop end='^\s*\z1\s*$' contains=vimComment,vim9Comment
+VimFoldh syn region vimLetHereDoc matchgroup=vimLetHereDocStart start='=<<\s\+\%(trim\>\)\=\s*\z(\L\S*\)' matchgroup=vimLetHereDocStop end='^\s*\z1\s*$'
" Abbreviations: {{{2
" =============