├── LICENSE.txt ├── README.markdown ├── autoload └── clojurecomplete.vim ├── clj ├── .gitignore ├── bin │ └── syntime ├── dev-resources │ ├── test-basic-sexp-indent.txt │ ├── test-dispatch-macro-indent.in │ ├── test-dispatch-macro-indent.out │ ├── test-inherit-indent.in │ ├── test-inherit-indent.out │ ├── test-multibyte-indent.txt │ ├── test-reader-conditional-indent.in │ ├── test-reader-conditional-indent.out │ ├── test-side-effects-in-indentexpr.in │ └── test-side-effects-in-indentexpr.out ├── project.clj ├── src │ └── vim_clojure_static │ │ ├── generate.clj │ │ └── test.clj ├── test │ └── vim_clojure_static │ │ ├── indent_test.clj │ │ └── syntax_test.clj └── vim │ └── test-runtime.vim ├── doc └── clojure.txt ├── ftdetect └── clojure.vim ├── ftplugin └── clojure.vim ├── indent └── clojure.vim └── syntax └── clojure.vim /LICENSE.txt: -------------------------------------------------------------------------------- 1 | VimClojure License 2 | ================== 3 | 4 | Copyright 2008-2012 (c) Meikel Brandmeyer. 5 | All rights reserved. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | 25 | vim-clojure-static License 26 | ========================== 27 | 28 | Copyright 2013-2014 (c) Sung Pae. 29 | 30 | Relicensed under the Vim License (below) for distribution with Vim. 31 | 32 | VIM LICENSE 33 | 34 | I) There are no restrictions on distributing unmodified copies of Vim except 35 | that they must include this license text. You can also distribute 36 | unmodified parts of Vim, likewise unrestricted except that they must 37 | include this license text. You are also allowed to include executables 38 | that you made from the unmodified Vim sources, plus your own usage 39 | examples and Vim scripts. 40 | 41 | II) It is allowed to distribute a modified (or extended) version of Vim, 42 | including executables and/or source code, when the following four 43 | conditions are met: 44 | 1) This license text must be included unmodified. 45 | 2) The modified Vim must be distributed in one of the following five ways: 46 | a) If you make changes to Vim yourself, you must clearly describe in 47 | the distribution how to contact you. When the maintainer asks you 48 | (in any way) for a copy of the modified Vim you distributed, you 49 | must make your changes, including source code, available to the 50 | maintainer without fee. The maintainer reserves the right to 51 | include your changes in the official version of Vim. What the 52 | maintainer will do with your changes and under what license they 53 | will be distributed is negotiable. If there has been no negotiation 54 | then this license, or a later version, also applies to your changes. 55 | The current maintainer is Bram Moolenaar . If this 56 | changes it will be announced in appropriate places (most likely 57 | vim.sf.net, www.vim.org and/or comp.editors). When it is completely 58 | impossible to contact the maintainer, the obligation to send him 59 | your changes ceases. Once the maintainer has confirmed that he has 60 | received your changes they will not have to be sent again. 61 | b) If you have received a modified Vim that was distributed as 62 | mentioned under a) you are allowed to further distribute it 63 | unmodified, as mentioned at I). If you make additional changes the 64 | text under a) applies to those changes. 65 | c) Provide all the changes, including source code, with every copy of 66 | the modified Vim you distribute. This may be done in the form of a 67 | context diff. You can choose what license to use for new code you 68 | add. The changes and their license must not restrict others from 69 | making their own changes to the official version of Vim. 70 | d) When you have a modified Vim which includes changes as mentioned 71 | under c), you can distribute it without the source code for the 72 | changes if the following three conditions are met: 73 | - The license that applies to the changes permits you to distribute 74 | the changes to the Vim maintainer without fee or restriction, and 75 | permits the Vim maintainer to include the changes in the official 76 | version of Vim without fee or restriction. 77 | - You keep the changes for at least three years after last 78 | distributing the corresponding modified Vim. When the maintainer 79 | or someone who you distributed the modified Vim to asks you (in 80 | any way) for the changes within this period, you must make them 81 | available to him. 82 | - You clearly describe in the distribution how to contact you. This 83 | contact information must remain valid for at least three years 84 | after last distributing the corresponding modified Vim, or as long 85 | as possible. 86 | e) When the GNU General Public License (GPL) applies to the changes, 87 | you can distribute the modified Vim under the GNU GPL version 2 or 88 | any later version. 89 | 3) A message must be added, at least in the output of the ":version" 90 | command and in the intro screen, such that the user of the modified Vim 91 | is able to see that it was modified. When distributing as mentioned 92 | under 2)e) adding the message is only required for as far as this does 93 | not conflict with the license used for the changes. 94 | 4) The contact information as required under 2)a) and 2)d) must not be 95 | removed or changed, except that the person himself can make 96 | corrections. 97 | 98 | III) If you distribute a modified version of Vim, you are encouraged to use 99 | the Vim license for your changes and make them available to the 100 | maintainer, including the source code. The preferred way to do this is 101 | by e-mail or by uploading the files to a server and e-mailing the URL. 102 | If the number of changes is small (e.g., a modified Makefile) e-mailing a 103 | context diff will do. The e-mail address to be used is 104 | 105 | 106 | IV) It is not allowed to remove this license from the distribution of the Vim 107 | sources, parts of it or from a modified version. You may use this 108 | license for previous Vim releases instead of the license that they came 109 | with, at your option. 110 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | 2 | 3 | o8o 4 | '"' 5 | oooo ooooooo ooo. .oo. .oo. 6 | `88. .8' `888 `888P"Y88bP"Y88b 7 | `88..8' 888 888 888 888 8 | `888' 888 888 888 888 9 | `8' o888oo888o o888o o888o 10 | 11 | 12 | oooo o8o 13 | `888 '"' 14 | .ooooo. 888 .ooooo. oooooooo oooo oooo d8b .ooooo. 15 | d88' `"Y8 888 d88' `88b`888`888 `888 `888""8Pd88' `88b 16 | 888 888 888 888 888 888 888 888 888ooo888 17 | 888 .o8 888 888 888 888 888 888 888 888 .o 18 | `Y8bod8P'o888o`Y8bod8P' 888 `V88V"V8P'd888b `Y8bod8P' 19 | 888 20 | .o. 88P 21 | . `Y888P . o8o 22 | .o8 .o8 '"' 23 | .oooo.o.o888oo .oooo. .o888oooooo .ooooo. 24 | d88( "8 888 `P )88b 888 `888 d88' `"Y8 25 | `"Y88b. 888 .oP"888 888 888 888 26 | o. )88b 888 .d8( 888 888 . 888 888 .o8 27 | 8""888P' "888"`Y888""8o "888"o888o`Y8bod8P' 28 | 29 | 30 | 31 | Meikel Brandmeyer's excellent Clojure runtime files, extracted from the 32 | [VimClojure](http://www.vim.org/scripts/script.php?script_id=2501) project for 33 | use with alternate Clojure REPL plugins. 34 | 35 | These files ship with Vim versions 7.3.803 and later, and are periodically 36 | merged into the official Vim repository. 37 | 38 | Installation 39 | ============ 40 | 41 | If you are running an old version of Vim or if you would like to keep up with 42 | development, you can install this repository like a standard Vim plugin. 43 | 44 | If you are unfamiliar with this process, refer to 45 | the [Pathogen](https://github.com/tpope/vim-pathogen) project. 46 | 47 | Please make sure that the following options are set in your vimrc to enable 48 | all features: 49 | 50 | ```vim 51 | syntax on 52 | filetype plugin indent on 53 | ``` 54 | 55 | Features 56 | ======== 57 | 58 | * [Augmentable](#syntax-options) syntax highlighting for Clojure and 59 | ClojureScript buffers. 60 | 61 | * [Configurable](#indent-options) Clojure-specific indentation. 62 | 63 | * Basic insert mode completion for special forms and public vars in 64 | `clojure.core`. 65 | 66 | This is bound to both the `'omnifunc'` and `'completefunc'` options, which 67 | can be invoked with the insert mode mappings `` and `` 68 | respectively. 69 | 70 | If you install this project as a plugin, `*.edn` files are recognized as a 71 | Clojure filetype, overriding the built-in declaration as `edif`. 72 | 73 | Third Party Extensions 74 | ====================== 75 | 76 | * Rainbow Parentheses 77 | 78 | kien's [`rainbow_parentheses.vim`](https://github.com/kien/rainbow_parentheses.vim) 79 | is highly recommended. 80 | 81 | * Extended Syntax Highlighting 82 | 83 | [`vim-clojure-highlight`](https://github.com/guns/vim-clojure-highlight) is 84 | a fireplace.vim plugin that extends syntax highlighting to local, referred, 85 | and aliased vars via [`b:clojure_syntax_keywords`](#syntax-options). 86 | 87 | This is a reimplementation of the DynamicHighlighting feature from 88 | VimClojure. 89 | 90 | Clojure REPL Plugins 91 | ==================== 92 | 93 | If you would like to get more serious about programming in Clojure, consider 94 | using an interactive 95 | [Clojure REPL plugin](https://github.com/guns/vim-clojure-static/wiki/Clojure-REPL-Plugins). 96 | 97 | Syntax Options 98 | ============== 99 | 100 | Syntax highlighting for public vars from `clojure.core` is provided by 101 | default, but any symbol can be matched and highlighted by adding it to the 102 | `g:clojure_syntax_keywords` or `b:clojure_syntax_keywords` variables: 103 | 104 | ```vim 105 | let g:clojure_syntax_keywords = { 106 | \ 'clojureMacro': ["defproject", "defcustom"], 107 | \ 'clojureFunc': ["string/join", "string/replace"] 108 | \ } 109 | ``` 110 | 111 | See `s:clojure_syntax_keywords` in the [syntax script](syntax/clojure.vim) for 112 | a complete example. 113 | 114 | The global version of this variable is intended for users that always wish 115 | to have a certain set of symbols highlighted in a certain way, while the 116 | buffer-local version is intended for plugin authors who wish to highlight 117 | symbols dynamically. 118 | 119 | If the buffer flag `b:clojure_syntax_without_core_keywords` is set, vars from 120 | `clojure.core` are not highlighted by default. This is useful for highlighting 121 | namespaces that have set `(:refer-clojure :only [])`. 122 | 123 | [`vim-clojure-highlight`](https://github.com/guns/vim-clojure-highlight) uses 124 | these variables to highlight extra vars when connected to a REPL. 125 | 126 | Indent Options 127 | ============== 128 | 129 | Clojure indentation differs somewhat from traditional Lisps, due in part to 130 | the use of square and curly brackets, and otherwise by community convention. 131 | These conventions are not universally followed, so the Clojure indent script 132 | offers a few configurable options, listed below. 133 | 134 | If the current vim does not include searchpairpos(), the indent script falls 135 | back to normal `'lisp'` indenting, and the following options are ignored. 136 | 137 | ### `g:clojure_maxlines` 138 | 139 | Set maximum scan distance of searchpairpos(). Larger values trade performance 140 | for correctness when dealing with very long forms. A value of 0 will scan 141 | without limits. 142 | 143 | ```vim 144 | " Default 145 | let g:clojure_maxlines = 100 146 | ``` 147 | 148 | ### `g:clojure_fuzzy_indent`, `g:clojure_fuzzy_indent_patterns`, `g:clojure_fuzzy_indent_blacklist` 149 | 150 | The `'lispwords'` option is a list of comma-separated words that mark special 151 | forms whose subforms must be indented with two spaces. 152 | 153 | For example: 154 | 155 | ```clojure 156 | (defn bad [] 157 | "Incorrect indentation") 158 | 159 | (defn good [] 160 | "Correct indentation") 161 | ``` 162 | 163 | If you would like to specify `'lispwords'` with a pattern instead, you can use 164 | the fuzzy indent feature: 165 | 166 | ```vim 167 | " Default 168 | let g:clojure_fuzzy_indent = 1 169 | let g:clojure_fuzzy_indent_patterns = ['^with', '^def', '^let'] 170 | let g:clojure_fuzzy_indent_blacklist = ['-fn$', '\v^with-%(meta|out-str|loading-context)$'] 171 | 172 | " Legacy comma-delimited string version; the list format above is 173 | " recommended. Note that patterns are implicitly anchored with ^ and $. 174 | let g:clojure_fuzzy_indent_patterns = 'with.*,def.*,let.*' 175 | ``` 176 | 177 | `g:clojure_fuzzy_indent_patterns` and `g:clojure_fuzzy_indent_blacklist` are 178 | lists of patterns that will be matched against the unqualified symbol at the 179 | head of a list. This means that a pattern like `"^foo"` will match all these 180 | candidates: `foobar`, `my.ns/foobar`, and `#'foobar`. 181 | 182 | Each candidate word is tested for special treatment in this order: 183 | 184 | 1. Return true if word is literally in `'lispwords'` 185 | 2. Return false if word matches a pattern in `g:clojure_fuzzy_indent_blacklist` 186 | 3. Return true if word matches a pattern in `g:clojure_fuzzy_indent_patterns` 187 | 4. Return false and indent normally otherwise 188 | 189 | ### `g:clojure_special_indent_words` 190 | 191 | Some forms in Clojure are indented so that every subform is indented only 192 | two spaces, regardless of `'lispwords'`. If you have a custom construct that 193 | should be indented in this idiosyncratic fashion, you can add your symbols to 194 | the default list below. 195 | 196 | ```vim 197 | " Default 198 | let g:clojure_special_indent_words = 'deftype,defrecord,reify,proxy,extend-type,extend-protocol,letfn' 199 | ``` 200 | 201 | ### `g:clojure_align_multiline_strings` 202 | 203 | Align subsequent lines in multiline strings to the column after the opening 204 | quote, instead of the same column. 205 | 206 | For example: 207 | 208 | ```clojure 209 | (def default 210 | "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do 211 | eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut 212 | enim ad minim veniam, quis nostrud exercitation ullamco laboris 213 | nisi ut aliquip ex ea commodo consequat.") 214 | 215 | (def aligned 216 | "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do 217 | eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut 218 | enim ad minim veniam, quis nostrud exercitation ullamco laboris 219 | nisi ut aliquip ex ea commodo consequat.") 220 | ``` 221 | 222 | This option is off by default. 223 | 224 | ```vim 225 | " Default 226 | let g:clojure_align_multiline_strings = 0 227 | ``` 228 | 229 | ### `g:clojure_align_subforms` 230 | 231 | By default, parenthesized compound forms that look like function calls and 232 | whose head subform is on its own line have subsequent subforms indented by 233 | two spaces relative to the opening paren: 234 | 235 | ```clojure 236 | (foo 237 | bar 238 | baz) 239 | ``` 240 | 241 | Setting this option changes this behavior so that all subforms are aligned to 242 | the same column, emulating the default behavior of clojure-mode.el: 243 | 244 | ```clojure 245 | (foo 246 | bar 247 | baz) 248 | ``` 249 | 250 | This option is off by default. 251 | 252 | ```vim 253 | " Default 254 | let g:clojure_align_subforms = 0 255 | ``` 256 | 257 | Development 258 | =========== 259 | 260 | Pull requests and patches are strongly encouraged! 261 | 262 | A large portion of the syntax file is generated from Clojure code in 263 | `clj/src/`. Generation of vim code in this fashion is preferred over hand 264 | crafting of the same. 265 | 266 | There is an incomplete syntax test suite in `clj/test/`. Any additions and 267 | improvements to these tests are highly appreciated. 268 | 269 | License and Acknowledgements 270 | ============================ 271 | 272 | Many thanks to [Meikel Brandmeyer](http://kotka.de/) for his excellent work on 273 | making Vim a first class Clojure editor. 274 | 275 | Thanks to [Tim Pope](https://github.com/tpope/) for advice in #vim. 276 | 277 | `syntax/clojure.vim` 278 | 279 | * Copyright 2007-2008 (c) Toralf Wittner 280 | * Copyright 2008-2012 (c) Meikel Brandmeyer 281 | 282 | `ftdetect/clojure.vim`,
283 | `ftplugin/clojure.vim`,
284 | `indent/clojure.vim` 285 | 286 | * Copyright 2008-2012 (c) Meikel Brandmeyer 287 | 288 | Modified and relicensed under the Vim License for distribution with Vim: 289 | 290 | * Copyright 2013-2014 (c) Sung Pae 291 | 292 | See LICENSE.txt for more information. 293 | 294 | 297 | -------------------------------------------------------------------------------- /autoload/clojurecomplete.vim: -------------------------------------------------------------------------------- 1 | " Vim completion script 2 | " Language: Clojure 3 | " Maintainer: Sung Pae 4 | " URL: https://github.com/guns/vim-clojure-static 5 | " License: Same as Vim 6 | " Last Change: %%RELEASE_DATE%% 7 | 8 | " -*- COMPLETION WORDS -*- 9 | " Generated from https://github.com/guns/vim-clojure-static/blob/%%RELEASE_TAG%%/clj/src/vim_clojure_static/generate.clj 10 | " Clojure version 1.8.0 11 | 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-readably*","*read-eval*","*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","Throwable->map","accessor","aclone","add-classpath","add-watch","agent","agent-error","agent-errors","aget","alength","alias","all-ns","alter","alter-meta!","alter-var-root","amap","ancestors","and","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","booleans","bound-fn","bound-fn*","bound?","butlast","byte","byte-array","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","doubles","drop","drop-last","drop-while","eduction","empty","empty?","ensure","ensure-reduced","enumeration-seq","error-handler","error-mode","eval","even?","every-pred","every?","ex-data","ex-info","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","hash","hash-combine","hash-map","hash-ordered-coll","hash-set","hash-unordered-coll","identical?","identity","if","if-let","if-not","if-some","ifn?","import","in-ns","inc","inc'","init-proxy","instance?","int","int-array","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","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?","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","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-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-watch","repeat","repeatedly","replace","replicate","require","reset!","reset-meta!","resolve","rest","restart-agent","resultset-seq","reverse","reversible?","rseq","rsubseq","run!","satisfies?","second","select-keys","send","send-off","send-via","seq","seq?","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","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!","symbol","symbol?","sync","tagged-literal","tagged-literal?","take","take-last","take-nth","take-while","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","use","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"] 12 | 13 | " Simple word completion for special forms and public vars in clojure.core 14 | function! clojurecomplete#Complete(findstart, base) 15 | if a:findstart 16 | return searchpos('\<', 'bnW', line('.'))[1] - 1 17 | else 18 | return { 'words': filter(copy(s:words), 'v:val =~# "\\V\\^' . a:base . '"') } 19 | endif 20 | endfunction 21 | 22 | " vim:sts=8:sw=8:ts=8:noet 23 | -------------------------------------------------------------------------------- /clj/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /lib 3 | /classes 4 | /checkouts 5 | pom.xml 6 | pom.xml.asc 7 | *.jar 8 | *.class 9 | .lein-deps-sum 10 | .lein-failures 11 | .lein-plugins 12 | .lein-repl-history 13 | /tmp 14 | -------------------------------------------------------------------------------- /clj/bin/syntime: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright (c) 2017 Sung Pae 4 | # Distributed under the MIT license. 5 | # http://www.opensource.org/licenses/mit-license.php 6 | 7 | abort_with_help() { 8 | echo "usage: $(basename "$0") [-p PREFIX] file.clj" 9 | exit 1 10 | } 11 | 12 | PREFIX='report' 13 | 14 | while getopts :p: opt; do 15 | case "$opt" in 16 | p) PREFIX="$OPTARG";; 17 | h) abort_with_help;; 18 | esac 19 | done 20 | shift $((OPTIND-1)) 21 | 22 | (($# == 1)) || abort_with_help 23 | 24 | VIMRC=" 25 | set runtimepath^=$(dirname "$0")/../.. 26 | filetype plugin indent on 27 | syntax on 28 | syntime on 29 | " 30 | 31 | exec vim -N -u <(echo "$VIMRC") \ 32 | -c "execute 'redir > ' . strftime('${PREFIX}-$(date +%s.%N).log')" \ 33 | -c 'call feedkeys(repeat("j", line("$")-1) . ":silent syntime report | quit\")' \ 34 | "$1" 35 | -------------------------------------------------------------------------------- /clj/dev-resources/test-basic-sexp-indent.txt: -------------------------------------------------------------------------------- 1 | (ns test-basic-sexp-indent 2 | "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 3 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 4 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 5 | consequat.") 6 | 7 | ;; vim:ft=clojure: 8 | -------------------------------------------------------------------------------- /clj/dev-resources/test-dispatch-macro-indent.in: -------------------------------------------------------------------------------- 1 | (#(foo) 2 | bar) 3 | 4 | (#(foo 5 | bar)) 6 | 7 | (#(foo bar 8 | a)) 9 | 10 | (#(foo bar) 11 | a) 12 | 13 | (#{foo} 14 | bar) 15 | 16 | (#{foo 17 | bar}) 18 | 19 | (#{foo bar} 20 | a) 21 | 22 | (#_(foo) 23 | bar) 24 | 25 | (#_(foo 26 | bar)) 27 | 28 | (#_(foo bar) 29 | a) 30 | 31 | ;; vim:ft=clojure: 32 | -------------------------------------------------------------------------------- /clj/dev-resources/test-dispatch-macro-indent.out: -------------------------------------------------------------------------------- 1 | (#(foo) 2 | bar) 3 | 4 | (#(foo 5 | bar)) 6 | 7 | (#(foo bar 8 | a)) 9 | 10 | (#(foo bar) 11 | a) 12 | 13 | (#{foo} 14 | bar) 15 | 16 | (#{foo 17 | bar}) 18 | 19 | (#{foo bar} 20 | a) 21 | 22 | (#_(foo) 23 | bar) 24 | 25 | (#_(foo 26 | bar)) 27 | 28 | (#_(foo bar) 29 | a) 30 | 31 | ;; vim:ft=clojure: 32 | -------------------------------------------------------------------------------- /clj/dev-resources/test-inherit-indent.in: -------------------------------------------------------------------------------- 1 | (foo bar 2 | "This string has unpaired brackets [ 3 | and is indented weirdly." 4 | α 5 | [β]) 6 | 7 | ;; vim:ft=clojure: 8 | -------------------------------------------------------------------------------- /clj/dev-resources/test-inherit-indent.out: -------------------------------------------------------------------------------- 1 | (foo bar 2 | "This string has unpaired brackets [ 3 | and is indented weirdly." 4 | a 5 | 6 | [ 7 | 8 | b 9 | c 10 | 11 | d]) 12 | 13 | ;; vim:ft=clojure: 14 | -------------------------------------------------------------------------------- /clj/dev-resources/test-multibyte-indent.txt: -------------------------------------------------------------------------------- 1 | (let [Δt (if foo 2 | bar 3 | baz)]) 4 | 5 | ;; vim:ft=clojure: 6 | -------------------------------------------------------------------------------- /clj/dev-resources/test-reader-conditional-indent.in: -------------------------------------------------------------------------------- 1 | (def DateTime #?(:clj org.joda.time.DateTime, 2 | :cljs goog.date.UtcDateTime)) 3 | 4 | #?(:cljs 5 | (extend-protocol ToDateTime 6 | goog.date.Date 7 | (-to-date-time [x] 8 | (goog.date.UtcDateTime. (.getYear x) (.getMonth x) (.getDate x))))) 9 | 10 | ;; vim:ft=clojure: 11 | -------------------------------------------------------------------------------- /clj/dev-resources/test-reader-conditional-indent.out: -------------------------------------------------------------------------------- 1 | (def DateTime #?(:clj org.joda.time.DateTime, 2 | :cljs goog.date.UtcDateTime)) 3 | 4 | #?(:cljs 5 | (extend-protocol ToDateTime 6 | goog.date.Date 7 | (-to-date-time [x] 8 | (goog.date.UtcDateTime. (.getYear x) (.getMonth x) (.getDate x))))) 9 | 10 | ;; vim:ft=clojure: 11 | -------------------------------------------------------------------------------- /clj/dev-resources/test-side-effects-in-indentexpr.in: -------------------------------------------------------------------------------- 1 | (doseq [x (range 10) y (range 10)] 2 | (println α) 3 | (println β)) 4 | -------------------------------------------------------------------------------- /clj/dev-resources/test-side-effects-in-indentexpr.out: -------------------------------------------------------------------------------- 1 | (doseq [x (range 10) y (range 10)] 2 | (println x) 3 | (println y)) 4 | -------------------------------------------------------------------------------- /clj/project.clj: -------------------------------------------------------------------------------- 1 | (defproject vim-clojure-static "0.1.0" 2 | :description "Utilities and tests for Vim's Clojure runtime files." 3 | :url "https://github.com/guns/vim-clojure-static" 4 | :license {:name "Vim License" 5 | :url "http://vimdoc.sourceforge.net/htmldoc/uganda.html#license" 6 | :comments ":help license"} 7 | :dependencies [[org.clojure/clojure "1.8.0"] 8 | [frak "0.1.6"]]) 9 | -------------------------------------------------------------------------------- /clj/src/vim_clojure_static/generate.clj: -------------------------------------------------------------------------------- 1 | ;; Authors: Sung Pae 2 | ;; Joel Holdbrooks 3 | 4 | (ns vim-clojure-static.generate 5 | (:require [clojure.java.io :as io] 6 | [clojure.java.shell :refer [sh]] 7 | [clojure.set :as set] 8 | [clojure.string :as string] 9 | [frak :as f]) 10 | (:import (clojure.lang MultiFn) 11 | (java.lang Character$UnicodeBlock Character$UnicodeScript) 12 | (java.lang.reflect Field) 13 | (java.text SimpleDateFormat) 14 | (java.util Date) 15 | (java.util.regex Pattern Pattern$CharPropertyNames UnicodeProp))) 16 | 17 | ;; 18 | ;; Helpers 19 | ;; 20 | 21 | (defn- vim-frak-pattern 22 | "Create a non-capturing regular expression pattern compatible with Vim." 23 | [strs] 24 | (-> (f/string-pattern strs {:escape-chars :vim}) 25 | (string/replace #"\(\?:" "\\%\\("))) 26 | 27 | (defn- property-pattern 28 | "Vimscript very magic pattern for a character property class." 29 | ([s] (property-pattern s true)) 30 | ([s braces?] 31 | (if braces? 32 | (format "\\v\\\\[pP]\\{%s\\}" s) 33 | (format "\\v\\\\[pP]%s" s)))) 34 | 35 | (defn- syntax-match-properties 36 | "Vimscript literal `syntax match` for a character property class." 37 | ([group fmt props] (syntax-match-properties group fmt props true)) 38 | ([group fmt props braces?] 39 | (format "syntax match %s \"%s\" contained display\n" 40 | (name group) 41 | (property-pattern (format fmt (vim-frak-pattern props)) braces?)))) 42 | 43 | (defn- get-private-field 44 | "Violate encapsulation and get the value of a private field." 45 | [^Class cls fieldname] 46 | (let [^Field field (first (filter #(= fieldname (.getName ^Field %)) 47 | (.getDeclaredFields cls)))] 48 | (.setAccessible field true) 49 | (.get field field))) 50 | 51 | (defn- fn-var? [v] 52 | (let [f @v] 53 | (or (contains? (meta v) :arglists) 54 | (fn? f) 55 | (instance? MultiFn f)))) 56 | 57 | (defn- inner-class-name [^Class cls] 58 | (string/replace (.getName cls) #".*\$(.+)" "$1")) 59 | 60 | (defn- map-keyword-names [coll] 61 | (reduce 62 | (fn [v x] 63 | ;; Include fully qualified versions of core vars for matching vars in 64 | ;; macroexpanded forms 65 | (cond (symbol? x) (if-let [m (meta (resolve x))] 66 | (conj v 67 | (str (:name m)) 68 | (str (:ns m) \/ (:name m))) 69 | (conj v (str x))) 70 | (nil? x) (conj v "nil") 71 | :else (conj v (str x)))) 72 | [] coll)) 73 | 74 | (defn- vim-top-cluster 75 | "Generate a Vimscript literal `syntax cluster` statement for `groups` and 76 | all top-level syntax groups in the given syntax buffer." 77 | [groups syntax-buf] 78 | (->> syntax-buf 79 | (re-seq #"syntax\s+(?:keyword|match|region)\s+(\S+)(?!.*\bcontained\b)") 80 | (map peek) 81 | (concat groups) 82 | sort 83 | distinct 84 | (string/join \,) 85 | (format "syntax cluster clojureTop contains=@Spell,%s\n"))) 86 | 87 | ;; 88 | ;; Definitions 89 | ;; 90 | 91 | (def generation-comment 92 | "\" Generated from https://github.com/guns/vim-clojure-static/blob/%%RELEASE_TAG%%/clj/src/vim_clojure_static/generate.clj\n") 93 | 94 | (def clojure-version-comment 95 | (format "\" Clojure version %s\n" (clojure-version))) 96 | 97 | (def java-version-comment 98 | (format "\" Java version %s\n" (System/getProperty "java.version"))) 99 | 100 | (def special-forms 101 | "http://clojure.org/special_forms" 102 | '#{def if do let quote var fn loop recur throw try catch finally 103 | monitor-enter monitor-exit . new set!}) 104 | 105 | (def keyword-groups 106 | "Special forms, constants, and every public var in clojure.core keyed by 107 | syntax group name." 108 | (let [exceptions '#{throw try catch finally} 109 | builtins {"clojureConstant" '#{nil} 110 | "clojureBoolean" '#{true false} 111 | "clojureSpecial" (apply disj special-forms exceptions) 112 | "clojureException" exceptions 113 | "clojureCond" '#{case cond cond-> cond->> condp if-let 114 | if-not if-some when when-first when-let 115 | when-not when-some} 116 | ;; Imperative looping constructs (not sequence functions) 117 | "clojureRepeat" '#{doseq dotimes while}} 118 | coresyms (set/difference (set (keys (ns-publics 'clojure.core))) 119 | (set (mapcat peek builtins))) 120 | group-preds [["clojureDefine" #(re-seq #"\Adef(?!ault)" (str %))] 121 | ["clojureMacro" #(:macro (meta (ns-resolve 'clojure.core %)))] 122 | ["clojureFunc" #(fn-var? (ns-resolve 'clojure.core %))] 123 | ["clojureVariable" identity]]] 124 | (first 125 | (reduce 126 | (fn [[m syms] [group pred]] 127 | (let [group-syms (set (filterv pred syms))] 128 | [(assoc m group group-syms) 129 | (set/difference syms group-syms)])) 130 | [builtins coresyms] group-preds)))) 131 | 132 | (def character-properties 133 | "Character property names derived via reflection." 134 | (let [props (->> (get-private-field Pattern$CharPropertyNames "map") 135 | (mapv (fn [[prop field]] [(inner-class-name (class field)) prop])) 136 | (group-by first) 137 | (reduce-kv (fn [m k v] (assoc m k (mapv peek v))) {})) 138 | binary (concat (map #(.name ^UnicodeProp %) (get-private-field UnicodeProp "$VALUES")) 139 | (keys (get-private-field UnicodeProp "aliases"))) 140 | script (concat (map #(.name ^Character$UnicodeScript %) (Character$UnicodeScript/values)) 141 | (keys (get-private-field Character$UnicodeScript "aliases"))) 142 | block (keys (get-private-field Character$UnicodeBlock "map"))] 143 | ;; 144 | ;; * The keys "1"…"5" reflect the order of CharPropertyFactory 145 | ;; declarations in Pattern.java! 146 | ;; 147 | ;; * The "L1" (Latin-1) category is not defined by Unicode and exists 148 | ;; merely as an alias for the first 8 bits of code points. 149 | ;; 150 | ;; * The "all" category is the Unicode "Any" category by a different name, 151 | ;; and thus excluded. 152 | ;; 153 | {:posix (disj (set (mapcat (partial get props) ["2" "3"])) "L1") 154 | :java (set (get props "4")) 155 | :binary (set binary) 156 | :category (set (get props "1")) 157 | :script (set script) 158 | :block (set block)})) 159 | 160 | (def lispwords 161 | "Specially indented symbols in clojure.core and clojure.test. The following 162 | commit message (tag `lispwords-guidelines`) outlines a convention: 163 | 164 | commit c2920f43191ae48084cea2c641a42ca8d34381f5 165 | Author: guns 166 | Date: Sat Jan 26 06:53:14 2013 -0600 167 | 168 | Update lispwords 169 | 170 | Besides expanding the definitions into an easily maintainable style, we 171 | update the set of words for Clojure 1.5 using a simple rule: 172 | 173 | A function should only be indented specially if its first argument 174 | is special. 175 | 176 | This generally includes: 177 | 178 | * Definitions 179 | * Binding forms 180 | * Constructs that branch from a predicate 181 | 182 | What it does not include are functions/macros that accept a flat list of 183 | arguments (arglist: [& body]). Omissions include: 184 | 185 | clojure.core/dosync [& exprs] 186 | clojure.core/future [& body] 187 | clojure.core/gen-class [& options] 188 | clojure.core/gen-interface [& options] 189 | clojure.core/with-out-str [& body] 190 | 191 | Also added some symbols from clojure.test, since this namespace is 192 | present in many projects. 193 | 194 | Interestingly, clojure-mode.el includes \"assoc\" and \"struct-map\" in the 195 | special indent list, which makes a good deal of sense: 196 | 197 | (assoc my-map 198 | :foo \"foo\" 199 | :bar \"bar\") 200 | 201 | If we were to include this in lispwords, the following functions/macros 202 | should also be considered since they also take optional key value pairs 203 | at the end of the arglist: 204 | 205 | clojure.core/agent [state & options] 206 | clojure.core/assoc … [map key val & kvs] 207 | clojure.core/assoc! … [coll key val & kvs] 208 | clojure.core/atom … [x & options] 209 | clojure.core/ref [x] [x & options] 210 | clojure.core/refer [ns-sym & filters] 211 | clojure.core/restart-agent [a new-state & options] 212 | clojure.core/slurp [f & opts] 213 | clojure.core/sorted-map-by [comparator & keyvals] 214 | clojure.core/spit [f content & options] 215 | clojure.core/struct-map [s & inits]" 216 | (set/union 217 | ;; Definitions 218 | '#{bound-fn def definline definterface defmacro defmethod defmulti defn 219 | defn- defonce defprotocol defrecord defstruct deftest deftest- deftype 220 | extend extend-protocol extend-type fn ns proxy reify set-test} 221 | ;; Binding forms 222 | '#{as-> binding doseq dotimes doto for if-let if-some let letfn locking 223 | loop testing when-first when-let when-some with-bindings with-in-str 224 | with-local-vars with-open with-precision with-redefs with-redefs-fn 225 | with-test} 226 | ;; Conditional branching 227 | '#{case cond-> cond->> condp if if-not when when-not while} 228 | ;; Exception handling 229 | '#{catch})) 230 | 231 | ;; 232 | ;; Vimscript literals 233 | ;; 234 | 235 | (def vim-keywords 236 | "Vimscript literal dictionary of important identifiers." 237 | (->> keyword-groups 238 | sort 239 | (map (fn [[group keywords]] 240 | (->> keywords 241 | map-keyword-names 242 | sort 243 | (map pr-str) 244 | (string/join \,) 245 | (format "'%s': [%s]" group)))) 246 | (string/join "\n \\ , ") 247 | (format "let s:clojure_syntax_keywords = {\n \\ %s\n \\ }\n"))) 248 | 249 | (def vim-completion-words 250 | "Vimscript literal list of words for omnifunc completion." 251 | (->> 'clojure.core 252 | ns-publics 253 | keys 254 | (concat special-forms) 255 | (map (comp pr-str str)) 256 | sort 257 | (string/join \,) 258 | (format "let s:words = [%s]\n"))) 259 | 260 | (def vim-posix-char-classes 261 | "Vimscript literal `syntax match` for POSIX character classes." 262 | ;; `IsPosix` works, but is undefined. 263 | (syntax-match-properties 264 | :clojureRegexpPosixCharClass 265 | "%s" 266 | (:posix character-properties))) 267 | 268 | (def vim-java-char-classes 269 | "Vimscript literal `syntax match` for \\p{javaMethod} property classes." 270 | ;; `IsjavaMethod` works, but is undefined. 271 | (syntax-match-properties 272 | :clojureRegexpJavaCharClass 273 | "java%s" 274 | (map #(string/replace % #"\Ajava" "") (:java character-properties)))) 275 | 276 | (def vim-unicode-binary-char-classes 277 | "Vimscript literal `syntax match` for Unicode Binary properties." 278 | ;; Though the docs do not mention it, the property name is matched case 279 | ;; insensitively like the other Unicode properties. 280 | (syntax-match-properties 281 | :clojureRegexpUnicodeCharClass 282 | "\\cIs%s" 283 | (map string/lower-case (:binary character-properties)))) 284 | 285 | (def vim-unicode-category-char-classes 286 | "Vimscript literal `syntax match` for Unicode General Category classes." 287 | (let [cats (sort (:category character-properties)) 288 | chrs (->> (map seq cats) 289 | (group-by first) 290 | (keys) 291 | (map str) 292 | (sort))] 293 | ;; gc= and general_category= can be case insensitive, but this is behavior 294 | ;; is undefined. 295 | (str 296 | (syntax-match-properties 297 | :clojureRegexpUnicodeCharClass 298 | "%s" 299 | chrs 300 | false) 301 | (syntax-match-properties 302 | :clojureRegexpUnicodeCharClass 303 | "%s" 304 | cats) 305 | (syntax-match-properties 306 | :clojureRegexpUnicodeCharClass 307 | "%%(Is|gc\\=|general_category\\=)?%s" 308 | cats)))) 309 | 310 | (def vim-unicode-script-char-classes 311 | "Vimscript literal `syntax match` for Unicode Script properties." 312 | ;; Script names are matched case insensitively, but Is, sc=, and script= 313 | ;; should be matched exactly. In this case, only Is is matched exactly, but 314 | ;; this is an acceptable trade-off. 315 | ;; 316 | ;; InScriptName works, but is undefined. 317 | (syntax-match-properties 318 | :clojureRegexpUnicodeCharClass 319 | "\\c%%(Is|sc\\=|script\\=)%s" 320 | (map string/lower-case (:script character-properties)))) 321 | 322 | (def vim-unicode-block-char-classes 323 | "Vimscript literal `syntax match` for Unicode Block properties." 324 | ;; Block names work like Script names, except the In prefix is used in place 325 | ;; of Is. 326 | (syntax-match-properties 327 | :clojureRegexpUnicodeCharClass 328 | "\\c%%(In|blk\\=|block\\=)%s" 329 | (map string/lower-case (:block character-properties)))) 330 | 331 | (def vim-lispwords 332 | "Vimscript literal `setlocal lispwords=` statement." 333 | (str "setlocal lispwords=" (string/join \, (sort lispwords)) "\n")) 334 | 335 | (defn- comprehensive-clojure-character-property-regexps [] 336 | "A string representing a Clojure literal vector of regular expressions 337 | containing all possible property character classes. For testing Vimscript 338 | syntax matching optimizations." 339 | (let [fmt (fn [prefix prop-key] 340 | (let [props (map (partial format "\\p{%s%s}" prefix) 341 | (sort (get character-properties prop-key)))] 342 | (format "#\"%s\"" (string/join props))))] 343 | (string/join \newline [(fmt "" :posix) 344 | (fmt "" :java) 345 | (fmt "Is" :binary) 346 | (fmt "general_category=" :category) 347 | (fmt "script=" :script) 348 | (fmt "block=" :block)]))) 349 | 350 | ;; 351 | ;; Update functions 352 | ;; 353 | 354 | (def ^:private CLOJURE-SECTION 355 | #"(?ms)^CLOJURE.*?(?=^[\p{Lu} ]+\t*\*)") 356 | 357 | (defn- fjoin [& args] 358 | (string/join \/ args)) 359 | 360 | (defn- qstr [& xs] 361 | (string/replace (string/join xs) "\\" "\\\\")) 362 | 363 | (defn- update-doc! [first-line-pattern src-file dst-file] 364 | (let [sbuf (with-open [rdr (io/reader src-file)] 365 | (->> rdr 366 | line-seq 367 | (drop-while #(not (re-find first-line-pattern %))) 368 | (string/join \newline))) 369 | dbuf (slurp dst-file) 370 | dmatch (re-find CLOJURE-SECTION dbuf) 371 | hunk (re-find CLOJURE-SECTION sbuf)] 372 | (spit dst-file (string/replace-first dbuf dmatch hunk)))) 373 | 374 | (defn- copy-runtime-files! [src dst & opts] 375 | (let [{:keys [tag date paths]} (apply hash-map opts)] 376 | (doseq [path paths 377 | :let [buf (-> (fjoin src path) 378 | slurp 379 | (string/replace "%%RELEASE_TAG%%" tag) 380 | (string/replace "%%RELEASE_DATE%%" date))]] 381 | (spit (fjoin dst "runtime" path) buf)))) 382 | 383 | (defn- project-replacements [dir] 384 | {(fjoin dir "syntax/clojure.vim") 385 | {"-*- KEYWORDS -*-" 386 | (qstr generation-comment 387 | clojure-version-comment 388 | vim-keywords) 389 | "-*- CHARACTER PROPERTY CLASSES -*-" 390 | (qstr generation-comment 391 | java-version-comment 392 | vim-posix-char-classes 393 | vim-java-char-classes 394 | vim-unicode-binary-char-classes 395 | vim-unicode-category-char-classes 396 | vim-unicode-script-char-classes 397 | vim-unicode-block-char-classes) 398 | "-*- TOP CLUSTER -*-" 399 | (qstr generation-comment 400 | (vim-top-cluster (keys keyword-groups) 401 | (slurp (fjoin dir "syntax/clojure.vim"))))} 402 | 403 | (fjoin dir "ftplugin/clojure.vim") 404 | {"-*- LISPWORDS -*-" 405 | (qstr generation-comment 406 | vim-lispwords)} 407 | 408 | (fjoin dir "autoload/clojurecomplete.vim") 409 | {"-*- COMPLETION WORDS -*-" 410 | (qstr generation-comment 411 | clojure-version-comment 412 | vim-completion-words)}}) 413 | 414 | (defn- update-project! 415 | "Update project runtime files in the given directory." 416 | [dir] 417 | (doseq [[file replacements] (project-replacements dir)] 418 | (doseq [[magic-comment replacement] replacements] 419 | (let [buf (slurp file) 420 | pat (Pattern/compile (str "(?s)\\Q" magic-comment "\\E\\n.*?\\n\\n")) 421 | rep (str magic-comment "\n" replacement "\n") 422 | buf' (string/replace buf pat rep)] 423 | (if (= buf buf') 424 | (printf "No changes: %s\n" magic-comment) 425 | (do (printf "Updating %s\n" magic-comment) 426 | (spit file buf'))))))) 427 | 428 | (defn- update-vim! 429 | "Update Vim repository runtime files in dst/runtime" 430 | [src dst] 431 | (let [current-tag (string/trim-newline (:out (sh "git" "tag" "--points-at" "HEAD"))) 432 | current-date (.format (SimpleDateFormat. "dd MMMM YYYY") (Date.))] 433 | (assert (seq current-tag) "Git HEAD is not tagged!") 434 | (update-doc! #"CLOJURE\t*\*ft-clojure-indent\*" 435 | (fjoin src "doc/clojure.txt") 436 | (fjoin dst "runtime/doc/indent.txt")) 437 | (update-doc! #"CLOJURE\t*\*ft-clojure-syntax\*" 438 | (fjoin src "doc/clojure.txt") 439 | (fjoin dst "runtime/doc/syntax.txt")) 440 | (copy-runtime-files! src dst 441 | :tag current-tag 442 | :date current-date 443 | :paths ["autoload/clojurecomplete.vim" 444 | "ftplugin/clojure.vim" 445 | "indent/clojure.vim" 446 | "syntax/clojure.vim"]))) 447 | 448 | (comment 449 | ;; Run this to update the project files 450 | (update-project! "..") 451 | 452 | ;; Run this to update a vim repository 453 | (update-vim! ".." "../../vim") 454 | 455 | ;; Generate an example file with all possible character property literals. 456 | (spit "tmp/all-char-props.clj" 457 | (comprehensive-clojure-character-property-regexps)) 458 | 459 | ;; Performance test: `syntax keyword` vs `syntax match` 460 | (vim-clojure-static.test/benchmark 461 | 1000 "tmp/bench.clj" (str keyword-groups) 462 | ;; `syntax keyword` 463 | (->> keyword-groups 464 | (map (fn [[group keywords]] 465 | (format "syntax keyword clojure%s %s\n" 466 | group 467 | (string/join \space (sort (map-keyword-names keywords)))))) 468 | (map string/trim-newline) 469 | (string/join " | ")) 470 | ;; Naive `syntax match` 471 | (->> keyword-groups 472 | (map (fn [[group keywords]] 473 | (format "syntax match clojure%s \"\\V\\<%s\\>\"\n" 474 | group 475 | (string/join "\\|" (map-keyword-names keywords))))) 476 | (map string/trim-newline) 477 | (string/join " | ")) 478 | ;; Frak-optimized `syntax match` 479 | (->> keyword-groups 480 | (map (fn [[group keywords]] 481 | (format "syntax match clojure%s \"\\v<%s>\"\n" 482 | group 483 | (vim-frak-pattern (map-keyword-names keywords))))) 484 | (map string/trim-newline) 485 | (string/join " | "))) 486 | ) 487 | -------------------------------------------------------------------------------- /clj/src/vim_clojure_static/test.clj: -------------------------------------------------------------------------------- 1 | ;; Authors: Sung Pae 2 | 3 | (ns vim-clojure-static.test 4 | (:require [clojure.edn :as edn] 5 | [clojure.java.io :as io] 6 | [clojure.java.shell :as shell] 7 | [clojure.string :as string] 8 | [clojure.test :as test]) 9 | (:import (java.io File) 10 | (java.util List))) 11 | 12 | (defmacro with-tempfile 13 | {:requires [File]} 14 | [tmp-sym & body] 15 | `(let [~tmp-sym (File/createTempFile "vim-clojure-static" ".tmp")] 16 | (try 17 | ~@body 18 | (finally 19 | (.delete ~tmp-sym))))) 20 | 21 | (defn vim-exec 22 | "Spit buf into file, then execute vim-expr after Vim loads the file. The 23 | value of vim-expr is evaluated as EDN and returned." 24 | [file buf vim-expr & opts] 25 | (let [{:keys [pre]} (apply hash-map opts)] 26 | (with-tempfile tmp 27 | (io/make-parents file) 28 | (spit file buf) 29 | (spit tmp (str "let @x = " vim-expr)) 30 | (let [{:keys [exit err]} 31 | (shell/sh "vim" "-N" "-u" "vim/test-runtime.vim" 32 | "-c" (or pre "execute") 33 | "-c" (str "source " tmp) 34 | "-c" (str "call writefile([@x], " (pr-str (str tmp)) ")") 35 | "-c" "quitall!" 36 | file)] 37 | (when-not (zero? exit) 38 | (throw (RuntimeException. ^String err)))) 39 | (edn/read-string (slurp tmp))))) 40 | 41 | (defn syn-id-names 42 | "Map lines of clojure text to vim synID names at each column as keywords: 43 | 44 | (syn-id-names \"foo\" …) -> {\"foo\" [:clojureString :clojureString :clojureString] …} 45 | 46 | First parameter is the file that is used to communicate with Vim. The file 47 | is not deleted to allow manual inspection." 48 | [file & lines] 49 | (into {} (map (fn [l ids] [l (mapv keyword ids)]) 50 | lines 51 | (vim-exec file (string/join \newline lines) "ClojureSynIDNames()")))) 52 | 53 | (defn subfmt 54 | "Extract a subsequence of seq s corresponding to the character positions of 55 | %s in format spec fmt" 56 | [fmt s] 57 | (let [f (seq (format fmt \o001)) 58 | i (.indexOf ^List f \o001)] 59 | (->> s 60 | (drop i) 61 | (drop-last (- (count f) i 1))))) 62 | 63 | (defmacro defsyntaxtest 64 | "Create a new testing var with tests in the format: 65 | 66 | (defsyntaxtest example 67 | [format 68 | [test-string test-predicate 69 | …]] 70 | [\"#\\\"%s\\\"\" 71 | [\"123\" #(every? (partial = :clojureRegexp) %) 72 | …]] 73 | […]) 74 | 75 | At runtime the syn-id-names of the strings (which are placed in the format 76 | spec) are passed to their associated predicates. The format spec should 77 | contain a single `%s`." 78 | {:requires [#'test/deftest syn-id-names subfmt]} 79 | [name & body] 80 | (assert (every? (fn [[fmt tests]] (and (string? fmt) 81 | (coll? tests) 82 | (even? (count tests)))) 83 | body)) 84 | (let [[strings contexts] (reduce (fn [[strings contexts] [fmt tests]] 85 | (let [[ss λs] (apply map list (partition 2 tests)) 86 | ss (map #(format fmt %) ss)] 87 | [(concat strings ss) 88 | (conj contexts {:fmt fmt :ss ss :λs λs})])) 89 | [[] []] body) 90 | test-file (str "tmp/" name ".clj") 91 | syntable (gensym "syntable")] 92 | `(test/deftest ~name 93 | (spit ~test-file "") 94 | (let [~syntable (syn-id-names ~test-file ~@strings)] 95 | ~@(map (fn [{:keys [fmt ss λs]}] 96 | `(test/testing ~fmt 97 | ~@(map (fn [s λ] `(test/is (~λ (subfmt ~fmt (get ~syntable ~s))))) 98 | ss λs))) 99 | contexts))))) 100 | 101 | (defmacro defpredicates 102 | "Create two complementary predicate vars, `sym` and `!sym`, which test if 103 | all members of a passed collection are equal to `kw`" 104 | [sym kw] 105 | `(do 106 | (defn ~sym 107 | ~(str "Returns true if all elements of coll equal " kw) 108 | {:arglists '~'[coll]} 109 | [coll#] 110 | (every? (partial = ~kw) coll#)) 111 | (defn ~(symbol (str \! sym)) 112 | ~(str "Returns true if any elements of coll do not equal " kw) 113 | {:arglists '~'[coll]} 114 | [coll#] 115 | (boolean (some (partial not= ~kw) coll#))))) 116 | 117 | (defmacro with-transform-test 118 | "Copy contents of `in` to a tempfile, execute body with tempfile bound to 119 | tmp-sym, then finally compare the transformed contents of the tempfile with 120 | the contents of `out`. 121 | 122 | `in` and `out` are urls that will be passed to clojure.java.io/resource." 123 | {:requires [#'test/testing #'with-tempfile]} 124 | [string {:keys [in out]} [tmp-sym] & body] 125 | `(test/testing ~string 126 | (with-tempfile ~tmp-sym 127 | (try 128 | (spit ~tmp-sym (slurp (~io/resource ~in))) 129 | ~@body 130 | (catch Throwable e# 131 | (spit ~tmp-sym e#)) 132 | (finally 133 | (test/is (= (slurp ~tmp-sym) 134 | (slurp (~io/resource ~out))))))))) 135 | 136 | (defmacro test-indent 137 | {:requires [#'with-transform-test]} 138 | [string & opts] 139 | (let [{:keys [in out pre keys]} (apply hash-map opts) 140 | test-file (str "tmp/test-indent-" (string/replace string #"[^\w-]" "-") ".clj") 141 | vim-expr (if keys 142 | (format "TypeKeys(%s)" (string/replace (pr-str keys) "\\\\" "\\")) 143 | "IndentFile()")] 144 | `(with-transform-test ~string 145 | {:in ~in :out ~out} 146 | [tmp#] 147 | ;; FIXME: Too much file IO 148 | (~io/make-parents ~test-file) 149 | (spit ~test-file "") 150 | (~vim-exec ~test-file (slurp tmp#) ~vim-expr ~@(when pre [:pre pre])) 151 | (spit tmp# (slurp ~test-file))))) 152 | 153 | (defn benchmark [n file buf & exprs] 154 | (vim-exec file buf (format "Benchmark(%d, %s)" 155 | n 156 | (string/join \, (map pr-str exprs))))) 157 | -------------------------------------------------------------------------------- /clj/test/vim_clojure_static/indent_test.clj: -------------------------------------------------------------------------------- 1 | (ns vim-clojure-static.indent-test 2 | (:require [clojure.test :refer [deftest]] 3 | [vim-clojure-static.test :refer [test-indent]])) 4 | 5 | (deftest test-basic-sexp-indent 6 | (test-indent "works as expected with basic S-expressions" 7 | :in "test-basic-sexp-indent.txt" 8 | :out "test-basic-sexp-indent.txt")) 9 | 10 | (deftest test-multibyte-indent 11 | (test-indent "with multibyte characters" 12 | :in "test-multibyte-indent.txt" 13 | :out "test-multibyte-indent.txt")) 14 | 15 | (deftest test-inherit-indent 16 | (test-indent "is inherited from previous element" 17 | :in "test-inherit-indent.in" 18 | :out "test-inherit-indent.out" 19 | :keys "/α\\s\\Oa\\/β\\s\\\\\\\\\\\\\\\\\\b\\c\\\\d\\")) 20 | 21 | (deftest test-side-effects-in-indentexpr 22 | (test-indent "GetClojureIndent does not move cursor" 23 | :in "test-side-effects-in-indentexpr.in" 24 | :out "test-side-effects-in-indentexpr.out" 25 | :keys "/α\\:call GetClojureIndent()\\rxj:call GetClojureIndent()\\ry")) 26 | 27 | (deftest test-reader-conditional-indent 28 | (test-indent "reader conditionals are indented like maps" 29 | :in "test-reader-conditional-indent.in" 30 | :out "test-reader-conditional-indent.out")) 31 | 32 | (deftest test-dispatch-macro-indent 33 | (test-indent "dispatch macro indentation is handled correctly" 34 | :in "test-dispatch-macro-indent.in" 35 | :out "test-dispatch-macro-indent.out")) 36 | -------------------------------------------------------------------------------- /clj/test/vim_clojure_static/syntax_test.clj: -------------------------------------------------------------------------------- 1 | ;; Authors: Sung Pae 2 | ;; Joel Holdbrooks 3 | 4 | (ns vim-clojure-static.syntax-test 5 | (:require [vim-clojure-static.test :refer [defpredicates defsyntaxtest]])) 6 | 7 | (defpredicates number :clojureNumber) 8 | (defpredicates kw :clojureKeyword) 9 | (defpredicates regexp :clojureRegexp) 10 | (defpredicates regexp-escape :clojureRegexpEscape) 11 | (defpredicates regexp-char-class :clojureRegexpCharClass) 12 | (defpredicates regexp-predefined-char-class :clojureRegexpPredefinedCharClass) 13 | (defpredicates regexp-posix-char-class :clojureRegexpPosixCharClass) 14 | (defpredicates regexp-java-char-class :clojureRegexpJavaCharClass) 15 | (defpredicates regexp-unicode-char-class :clojureRegexpUnicodeCharClass) 16 | (defpredicates regexp-boundary :clojureRegexpBoundary) 17 | (defpredicates regexp-quantifier :clojureRegexpQuantifier) 18 | (defpredicates regexp-back-ref :clojureRegexpBackRef) 19 | (defpredicates regexp-or :clojureRegexpOr) 20 | (defpredicates regexp-group :clojureRegexpGroup) 21 | (defn regexp-mod [xs] (= (second xs) :clojureRegexpMod)) 22 | (def !regexp-mod (complement regexp-mod)) 23 | 24 | (defsyntaxtest test-number-literals 25 | ["%s" 26 | ["1234567890" number "+1" number "-1" number ; Integer 27 | "0" number "+0" number "-0" number ; Integer zero 28 | "0.12" number "+0.12" number "-0.12" number ; Float 29 | "1." number "+1." number "-1." number ; Float 30 | "0.0" number "+0.0" number "-0.0" number ; Float zero 31 | "01234567" number "+07" number "-07" number ; Octal 32 | "00" number "+00" number "-00" number ; Octal zero 33 | "0x09abcdef" number "+0xf" number "-0xf" number ; Hexadecimal 34 | "0x0" number "+0x0" number "-0x0" number ; Hexadecimal zero 35 | "3/2" number "+3/2" number "-3/2" number ; Rational 36 | "0/0" number "+0/0" number "-0/0" number ; Rational (not a syntax error) 37 | "2r1" number "+2r1" number "-2r1" number ; Radix 38 | "36R1" number "+36R1" number "-36R1" number ; Radix 39 | 40 | ;; Illegal literals (some are accepted by the reader, but are bad style) 41 | 42 | ".1" !number 43 | "01.2" !number 44 | "089" !number 45 | "0xfg" !number 46 | "1.0/1" !number 47 | "01/2" !number 48 | "1/02" !number 49 | "2r2" !number 50 | "1r0" !number 51 | "37r36" !number 52 | 53 | ;; BigInt 54 | 55 | "0N" number 56 | "+0.1N" !number 57 | "-07N" number 58 | "08N" !number 59 | "+0x0fN" number 60 | "1/2N" !number 61 | 62 | ;; BigDecimal 63 | 64 | "0M" number 65 | "+0.1M" number 66 | "08M" !number 67 | "08.9M" !number 68 | "0x1fM" !number 69 | "3/4M" !number 70 | "2r1M" !number 71 | 72 | ;; Exponential notation 73 | 74 | "0e0" number 75 | "+0.1e-1" number 76 | "-1e-1" number 77 | "08e1" !number 78 | "07e1" !number 79 | "0xfe-1" !number 80 | "2r1e-1" !number]]) 81 | 82 | (comment (test #'test-number-literals)) 83 | 84 | ;; TODO: Finish me! (this was in an old git stash) 85 | ;; (defsyntaxtest keywords-test 86 | ;; (with-format "%s" 87 | ;; ":1" kw 88 | ;; ":A" kw 89 | ;; ":a" kw 90 | ;; ":αβγ" kw 91 | ;; "::a" kw 92 | ;; ":a/b" kw 93 | ;; ":a:b" kw 94 | ;; ":a:b/:c:b" kw 95 | ;; ":a/b/c/d" kw 96 | ;; "::a/b" !kw 97 | ;; "::" !kw 98 | ;; ":a:" !kw 99 | ;; ":a/" !kw 100 | ;; ":/" !kw 101 | ;; ":" !kw 102 | ;; )) 103 | ;; 104 | ;; (comment (test #'keywords-test)) 105 | 106 | (defsyntaxtest test-java-regexp-literals 107 | ["#\"%s\"" 108 | [;; http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html 109 | ;; 110 | ;; Characters 111 | ;; x The character x 112 | " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" regexp 113 | "λ❤" regexp 114 | ;; \\ The backslash character 115 | "\\\\" regexp-escape 116 | ;; \0n The character with octal value 0n (0 <= n <= 7) 117 | "\\07" regexp-escape 118 | "\\08" !regexp-escape 119 | ;; \0nn The character with octal value 0nn (0 <= n <= 7) 120 | "\\077" regexp-escape 121 | "\\078" !regexp-escape 122 | ;; \0mnn The character with octal value 0mnn (0 <= m <= 3, 0 <= n <= 7) 123 | "\\0377" regexp-escape 124 | "\\0378" !regexp-escape 125 | "\\0400" !regexp-escape 126 | ;; \xhh The character with hexadecimal value 0xhh 127 | "\\xff" regexp-escape 128 | "\\xfg" !regexp-escape 129 | "\\xfff" !regexp-escape 130 | ;; \uhhhh The character with hexadecimal value 0xhhhh 131 | "\\uffff" regexp-escape 132 | "\\ufff" !regexp-escape 133 | "\\ufffff" !regexp-escape 134 | ;; \x{h...h} The character with hexadecimal value 0xh...h (Character.MIN_CODE_POINT <= 0xh...h <= Character.MAX_CODE_POINT) 135 | ;; \t The tab character ('\u0009') 136 | "\\t" regexp-escape 137 | "\\T" !regexp-escape 138 | ;; \n The newline (line feed) character ('\u000A') 139 | "\\n" regexp-escape 140 | "\\N" !regexp-escape 141 | ;; \r The carriage-return character ('\u000D') 142 | "\\r" regexp-escape 143 | "\\R" !regexp-escape 144 | ;; \f The form-feed character ('\u000C') 145 | "\\f" regexp-escape 146 | "\\F" !regexp-escape 147 | ;; \a The alert (bell) character ('\u0007') 148 | "\\a" regexp-escape 149 | "\\A" !regexp-escape 150 | ;; \e The escape character ('\u001B') 151 | "\\e" regexp-escape 152 | "\\E" !regexp-escape 153 | ;; \cx The control character corresponding to x 154 | "\\cA" regexp-escape 155 | "\\c1" !regexp-escape 156 | "\\c" !regexp-escape 157 | ;; Special character escapes 158 | "\\(\\)\\[\\]\\{\\}\\^\\$\\*\\?\\+\\." regexp-escape 159 | 160 | ;;;; Character classes 161 | 162 | ;; [abc] a, b, or c (simple class) 163 | "[abc]" regexp-char-class 164 | ;; [^abc] Any character except a, b, or c (negation) 165 | "[^abc]" regexp-char-class 166 | ;; [a-zA-Z] a through z or A through Z, inclusive (range) 167 | ;; [a-d[m-p]] a through d, or m through p: [a-dm-p] (union) 168 | ;; [a-z&&[def]] d, e, or f (intersection) 169 | ;; [a-z&&[^bc]] a through z, except for b and c: [ad-z] (subtraction) 170 | ;; [a-z&&[^m-p]] a through z, and not m through p: [a-lq-z](subtraction) 171 | 172 | ;;;; Predefined character classes 173 | 174 | ;; . Any character (may or may not match line terminators) 175 | "." regexp-predefined-char-class 176 | ;; \d A digit: [0-9] 177 | "\\d" regexp-predefined-char-class 178 | ;; \D A non-digit: [^0-9] 179 | "\\D" regexp-predefined-char-class 180 | ;; \s A whitespace character: [ \t\n\x0B\f\r] 181 | "\\s" regexp-predefined-char-class 182 | ;; \S A non-whitespace character: [^\s] 183 | "\\S" regexp-predefined-char-class 184 | ;; \w A word character: [a-zA-Z_0-9] 185 | "\\w" regexp-predefined-char-class 186 | ;; \W A non-word character: [^\w] 187 | "\\W" regexp-predefined-char-class 188 | 189 | ;;;; POSIX character classes (US-ASCII only) 190 | 191 | ;; \p{Lower} A lower-case alphabetic character: [a-z] 192 | "\\p{Lower}" regexp-posix-char-class 193 | ;; \p{Upper} An upper-case alphabetic character:[A-Z] 194 | "\\p{Upper}" regexp-posix-char-class 195 | ;; \p{ASCII} All ASCII:[\x00-\x7F] 196 | "\\p{ASCII}" regexp-posix-char-class 197 | ;; \p{Alpha} An alphabetic character:[\p{Lower}\p{Upper}] 198 | "\\p{Alpha}" regexp-posix-char-class 199 | ;; \p{Digit} A decimal digit: [0-9] 200 | "\\p{Digit}" regexp-posix-char-class 201 | ;; \p{Alnum} An alphanumeric character:[\p{Alpha}\p{Digit}] 202 | "\\p{Alnum}" regexp-posix-char-class 203 | ;; \p{Punct} Punctuation: One of !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ 204 | "\\p{Punct}" regexp-posix-char-class 205 | ;; \p{Graph} A visible character: [\p{Alnum}\p{Punct}] 206 | "\\p{Graph}" regexp-posix-char-class 207 | ;; \p{Print} A printable character: [\p{Graph}\x20] 208 | "\\p{Print}" regexp-posix-char-class 209 | ;; \p{Blank} A space or a tab: [ \t] 210 | "\\p{Blank}" regexp-posix-char-class 211 | ;; \p{Cntrl} A control character: [\x00-\x1F\x7F] 212 | "\\p{Cntrl}" regexp-posix-char-class 213 | ;; \p{XDigit} A hexadecimal digit: [0-9a-fA-F] 214 | "\\p{XDigit}" regexp-posix-char-class 215 | ;; \p{Space} A whitespace character: [ \t\n\x0B\f\r] 216 | "\\p{Space}" regexp-posix-char-class 217 | 218 | ;;;; java.lang.Character classes (simple java character type) 219 | 220 | ;; \p{javaLowerCase} Equivalent to java.lang.Character.isLowerCase() 221 | "\\p{javaLowerCase}" regexp-java-char-class 222 | ;; \p{javaUpperCase} Equivalent to java.lang.Character.isUpperCase() 223 | "\\p{javaUpperCase}" regexp-java-char-class 224 | ;; \p{javaWhitespace} Equivalent to java.lang.Character.isWhitespace() 225 | "\\p{javaWhitespace}" regexp-java-char-class 226 | ;; \p{javaMirrored} Equivalent to java.lang.Character.isMirrored() 227 | "\\p{javaMirrored}" regexp-java-char-class 228 | 229 | ;;;; Classes for Unicode scripts, blocks, categories and binary properties 230 | 231 | ;; \p{IsLatin} A Latin script character (script) 232 | "\\p{IsLatin}" regexp-unicode-char-class 233 | ;; \p{InGreek} A character in the Greek block (block) 234 | "\\p{InGreek}" regexp-unicode-char-class 235 | ;; \p{IsAlphabetic} An alphabetic character (binary property) 236 | "\\p{IsAlphabetic}" regexp-unicode-char-class 237 | ;; \p{Sc} A currency symbol 238 | "\\p{Sc}" regexp-unicode-char-class 239 | ;; \P{InGreek} Any character except one in the Greek block (negation) 240 | "\\P{InGreek}" regexp-unicode-char-class 241 | ;; [\p{L}&&[^\p{Lu}]] Any letter except an uppercase letter (subtraction) 242 | 243 | ;; Abbreviated categories 244 | "\\pL" regexp-unicode-char-class 245 | "\\p{L}" regexp-unicode-char-class 246 | "\\p{Lu}" regexp-unicode-char-class 247 | "\\p{gc=L}" regexp-unicode-char-class 248 | "\\p{IsLu}" regexp-unicode-char-class 249 | 250 | ;;;; Invalid classes 251 | 252 | "\\P{Xzibit}" !regexp-posix-char-class 253 | "\\p{YoDawg}" !regexp-posix-char-class 254 | 255 | ;;;; Boundary matchers 256 | 257 | ;; ^ The beginning of a line 258 | "^" regexp-boundary 259 | ;; $ The end of a line 260 | "$" regexp-boundary 261 | ;; \b A word boundary 262 | "\\b" regexp-boundary 263 | ;; \B A non-word boundary 264 | "\\B" regexp-boundary 265 | ;; \A The beginning of the input 266 | "\\A" regexp-boundary 267 | ;; \G The end of the previous match 268 | "\\G" regexp-boundary 269 | ;; \Z The end of the input but for the final terminator, if any 270 | "\\Z" regexp-boundary 271 | ;; \z The end of the input 272 | "\\z" regexp-boundary 273 | 274 | ;;;; Greedy quantifiers 275 | 276 | ;; X? X, once or not at all 277 | "?" regexp-quantifier 278 | ;; X* X, zero or more times 279 | "*" regexp-quantifier 280 | ;; X+ X, one or more times 281 | "+" regexp-quantifier 282 | ;; X{n} X, exactly n times 283 | "{0}" regexp-quantifier 284 | ;; X{n,} X, at least n times 285 | "{0,}" regexp-quantifier 286 | ;; X{n,m} X, at least n but not more than m times 287 | "{0,1}" regexp-quantifier 288 | 289 | ;;;; Reluctant quantifiers 290 | 291 | ;; X?? X, once or not at all 292 | "??" regexp-quantifier 293 | ;; X*? X, zero or more times 294 | "*?" regexp-quantifier 295 | ;; X+? X, one or more times 296 | "+?" regexp-quantifier 297 | ;; X{n}? X, exactly n times 298 | "{0}?" regexp-quantifier 299 | ;; X{n,}? X, at least n times 300 | "{0,}?" regexp-quantifier 301 | ;; X{n,m}? X, at least n but not more than m times 302 | "{0,1}?" regexp-quantifier 303 | 304 | ;;;; Possessive quantifiers 305 | 306 | ;; X?+ X, once or not at all 307 | "?+" regexp-quantifier 308 | ;; X*+ X, zero or more times 309 | "*+" regexp-quantifier 310 | ;; X++ X, one or more times 311 | "++" regexp-quantifier 312 | ;; X{n}+ X, exactly n times 313 | "{0}+" regexp-quantifier 314 | ;; X{n,}+ X, at least n times 315 | "{0,}+" regexp-quantifier 316 | ;; X{n,m}+ X, at least n but not more than m times 317 | "{0,1}+" regexp-quantifier 318 | 319 | "{-1}" !regexp-quantifier 320 | "{-1,}" !regexp-quantifier 321 | "{-1,-2}" !regexp-quantifier 322 | "{-1}?" !regexp-quantifier 323 | "{-1,}?" !regexp-quantifier 324 | "{-1,-2}?" !regexp-quantifier 325 | "{-1}?" !regexp-quantifier 326 | "{-1,}?" !regexp-quantifier 327 | "{-1,-2}?" !regexp-quantifier 328 | 329 | ;;;; Logical operators 330 | ;; XY X followed by Y 331 | ;; XXX: Tested above (regexp) 332 | 333 | ;; X|Y Either X or Y 334 | "|" regexp-or 335 | 336 | ;; (X) X, as a capturing group 337 | "(X)" regexp-group 338 | 339 | ;;;; Back references 340 | 341 | ;; \n Whatever the nth capturing group matched 342 | "\\1" regexp-back-ref 343 | ;; \k Whatever the named-capturing group "name" matched 344 | "\\k" regexp-back-ref 345 | 346 | ;;;; Quotation 347 | 348 | ;; \ Nothing, but quotes the following character 349 | ;; XXX: Tested above 350 | 351 | ;; \Q Nothing, but quotes all characters until \E 352 | ;; \E Nothing, but ends quoting started by \Q 353 | "\\Qa\\E" (partial = [:clojureRegexpQuote :clojureRegexpQuote :clojureRegexpQuoted :clojureRegexpQuote :clojureRegexpQuote]) 354 | "\\Qa\\\"" (partial = [:clojureRegexpQuote :clojureRegexpQuote :clojureRegexpQuoted :clojureRegexpQuoted :clojureRegexpQuoted]) 355 | "\\qa\\E" (partial not-any? #{:clojureRegexpQuote :clojureRegexpQuoted}) 356 | 357 | ;;;; Special constructs (named-capturing and non-capturing) 358 | ;; (?X) X, as a named-capturing group 359 | "(?X)" regexp-mod 360 | ;; (?:X) X, as a non-capturing group 361 | "(?:X)" regexp-mod 362 | ;; (?idmsuxU-idmsuxU) Nothing, but turns match flags i d m s u x U on - off 363 | "(?idmsuxU-idmsuxU)" regexp-mod 364 | "(?idmsuxU)" regexp-mod 365 | "(?-idmsuxU)" regexp-mod 366 | ;; (?idmsux-idmsux:X) X, as a non-capturing group with the given flags i d m s u x on - off 367 | "(?idmsuxU-idmsuxU:X)" regexp-mod 368 | "(?idmsuxU:)" regexp-mod 369 | "(?-idmsuxU:)" regexp-mod 370 | ;; (?=X) X, via zero-width positive lookahead 371 | "(?=X)" regexp-mod 372 | ;; (?!X) X, via zero-width negative lookahead 373 | "(?!X)" regexp-mod 374 | ;; (?<=X) X, via zero-width positive lookbehind 375 | "(?<=X)" regexp-mod 376 | ;; (?X) X, as an independent, non-capturing group 379 | "(?>X)" regexp-mod 380 | 381 | "(?X)" !regexp-mod 382 | ]] 383 | ["#%s" 384 | [;; Backslashes with character classes 385 | "\"[\\\\]\"" (partial = [:clojureRegexp :clojureRegexpCharClass :clojureRegexpCharClass :clojureRegexpCharClass :clojureRegexpCharClass :clojureRegexp]) 386 | "\"\\[]\"" (partial = [:clojureRegexp :clojureRegexpEscape :clojureRegexpEscape :clojureRegexp :clojureRegexp]) 387 | "\"\\\\[]\"" (partial = [:clojureRegexp :clojureRegexpEscape :clojureRegexpEscape :clojureRegexpCharClass :clojureRegexpCharClass :clojureRegexp])]]) 388 | 389 | (comment (test #'test-java-regexp-literals)) 390 | -------------------------------------------------------------------------------- /clj/vim/test-runtime.vim: -------------------------------------------------------------------------------- 1 | " Authors: Sung Pae 2 | 3 | execute 'set rtp=' . expand('%:p:h:h:h') . ',$VIMRUNTIME' 4 | filetype plugin indent on 5 | syntax on 6 | set synmaxcol=0 backspace=2 7 | setfiletype clojure 8 | 9 | function! EDN(value) 10 | " Changing the quotes may make this valid EDN 11 | return tr(string(a:value), "'", '"') 12 | endfunction 13 | 14 | function! ClojureSynIDNames() 15 | let names = [] 16 | for lnum in range(1, line('$')) 17 | let f = 'synIDattr(synID(' . lnum . ', v:val, 0), "name")' 18 | call add(names, map(range(1, virtcol([lnum, '$']) - 1), f)) 19 | endfor 20 | return EDN(names) 21 | endfunction 22 | 23 | function! TypeKeys(keys) 24 | execute 'normal! ' . a:keys 25 | write 26 | endfunction 27 | 28 | function! IndentFile() 29 | normal! gg=G 30 | write 31 | endfunction 32 | 33 | function! Time(n, expr) 34 | let start = reltime() 35 | let i = 0 36 | while i < a:n 37 | execute a:expr 38 | let i += 1 39 | endwhile 40 | return eval(reltimestr(reltime(start))) 41 | endfunction 42 | 43 | function! Benchmark(n, ...) 44 | let times = [] 45 | for expr in a:000 46 | call add(times, Time(a:n, expr)) 47 | endfor 48 | return EDN(times) 49 | endfunction 50 | 51 | " vim:sts=8:sw=8:ts=8:noet 52 | -------------------------------------------------------------------------------- /doc/clojure.txt: -------------------------------------------------------------------------------- 1 | *clojure.txt* Clojure runtime files 2 | 3 | INTRODUCTION *clojure-introduction* 4 | 5 | Meikel Brandmeyer's excellent Clojure runtime files. Includes syntax, indent, 6 | ftdetect, and ftplugin scripts. 7 | 8 | CLOJURE *ft-clojure-indent* *clojure-indent* 9 | 10 | Clojure indentation differs somewhat from traditional Lisps, due in part to 11 | the use of square and curly brackets, and otherwise by community convention. 12 | These conventions are not universally followed, so the Clojure indent script 13 | offers a few configurable options, listed below. 14 | 15 | If the current vim does not include searchpairpos(), the indent script falls 16 | back to normal 'lisp' indenting, and the following options are ignored. 17 | 18 | *g:clojure_maxlines* 19 | 20 | Set maximum scan distance of searchpairpos(). Larger values trade performance 21 | for correctness when dealing with very long forms. A value of 0 will scan 22 | without limits. 23 | > 24 | " Default 25 | let g:clojure_maxlines = 100 26 | < 27 | *g:clojure_fuzzy_indent* 28 | *g:clojure_fuzzy_indent_patterns* 29 | *g:clojure_fuzzy_indent_blacklist* 30 | 31 | The 'lispwords' option is a list of comma-separated words that mark special 32 | forms whose subforms must be indented with two spaces. 33 | 34 | For example: 35 | > 36 | (defn bad [] 37 | "Incorrect indentation") 38 | 39 | (defn good [] 40 | "Correct indentation") 41 | < 42 | If you would like to specify 'lispwords' with a |pattern| instead, you can use 43 | the fuzzy indent feature: 44 | > 45 | " Default 46 | let g:clojure_fuzzy_indent = 1 47 | let g:clojure_fuzzy_indent_patterns = ['^with', '^def', '^let'] 48 | let g:clojure_fuzzy_indent_blacklist = 49 | \ ['-fn$', '\v^with-%(meta|out-str|loading-context)$'] 50 | 51 | " Legacy comma-delimited string version; the list format above is 52 | " recommended. Note that patterns are implicitly anchored with ^ and $ 53 | let g:clojure_fuzzy_indent_patterns = 'with.*,def.*,let.*' 54 | < 55 | |g:clojure_fuzzy_indent_patterns| and |g:clojure_fuzzy_indent_blacklist| are 56 | |Lists| of patterns that will be matched against the unquoted, unqualified 57 | symbol at the head of a list. This means that a pattern like "^foo" will match 58 | all these candidates: "foobar", "my.ns/foobar", and "#'foobar". 59 | 60 | Each candidate word is tested for special treatment in this order: 61 | 62 | 1. Return true if word is literally in 'lispwords' 63 | 2. Return false if word matches a pattern in 64 | |g:clojure_fuzzy_indent_blacklist| 65 | 3. Return true if word matches a pattern in 66 | |g:clojure_fuzzy_indent_patterns| 67 | 4. Return false and indent normally otherwise 68 | 69 | *g:clojure_special_indent_words* 70 | 71 | Some forms in Clojure are indented so that every subform is indented only two 72 | spaces, regardless of 'lispwords'. If you have a custom construct that should 73 | be indented in this idiosyncratic fashion, you can add your symbols to the 74 | default list below. 75 | > 76 | " Default 77 | let g:clojure_special_indent_words = 78 | \ 'deftype,defrecord,reify,proxy,extend-type,extend-protocol,letfn' 79 | < 80 | *g:clojure_align_multiline_strings* 81 | 82 | Align subsequent lines in multiline strings to the column after the opening 83 | quote, instead of the same column. 84 | 85 | For example: 86 | > 87 | (def default 88 | "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do 89 | eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut 90 | enim ad minim veniam, quis nostrud exercitation ullamco laboris 91 | nisi ut aliquip ex ea commodo consequat.") 92 | 93 | (def aligned 94 | "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do 95 | eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut 96 | enim ad minim veniam, quis nostrud exercitation ullamco laboris 97 | nisi ut aliquip ex ea commodo consequat.") 98 | < 99 | This option is off by default. 100 | > 101 | " Default 102 | let g:clojure_align_multiline_strings = 0 103 | < 104 | *g:clojure_align_subforms* 105 | 106 | By default, parenthesized compound forms that look like function calls and 107 | whose head subform is on its own line have subsequent subforms indented by 108 | two spaces relative to the opening paren: 109 | > 110 | (foo 111 | bar 112 | baz) 113 | < 114 | Setting this option changes this behavior so that all subforms are aligned to 115 | the same column, emulating the default behavior of clojure-mode.el: 116 | > 117 | (foo 118 | bar 119 | baz) 120 | < 121 | This option is off by default. 122 | > 123 | " Default 124 | let g:clojure_align_subforms = 0 125 | < 126 | 127 | CLOJURE *ft-clojure-syntax* 128 | 129 | The default syntax groups can be augmented through the 130 | *g:clojure_syntax_keywords* and *b:clojure_syntax_keywords* variables. The 131 | value should be a |Dictionary| of syntax group names to a |List| of custom 132 | identifiers: 133 | > 134 | let g:clojure_syntax_keywords = { 135 | \ 'clojureMacro': ["defproject", "defcustom"], 136 | \ 'clojureFunc': ["string/join", "string/replace"] 137 | \ } 138 | < 139 | Refer to the Clojure syntax script for valid syntax group names. 140 | 141 | If the |buffer-variable| *b:clojure_syntax_without_core_keywords* is set, only 142 | language constants and special forms are matched. 143 | 144 | Setting *g:clojure_fold* enables folding Clojure code via the syntax engine. 145 | Any list, vector, or map that extends over more than one line can be folded 146 | using the standard Vim |fold-commands|. 147 | 148 | Please note that this option does not work with scripts that redefine the 149 | bracket syntax regions, such as rainbow-parentheses plugins. 150 | 151 | This option is off by default. 152 | > 153 | " Default 154 | let g:clojure_fold = 0 155 | < 156 | 157 | ABOUT *clojure-about* 158 | 159 | This document and associated runtime files are maintained at: 160 | https://github.com/guns/vim-clojure-static 161 | 162 | Distributed under the Vim license. See |license|. 163 | 164 | syntax/clojure.vim 165 | 166 | Copyright 2007-2008 (c) Toralf Wittner 167 | Copyright 2008-2012 (c) Meikel Brandmeyer 168 | 169 | ftdetect/clojure.vim, 170 | ftplugin/clojure.vim, 171 | indent/clojure.vim 172 | 173 | Copyright 2008-2012 (c) Meikel Brandmeyer 174 | 175 | Modified and relicensed under the Vim License for distribution with Vim: 176 | 177 | Copyright 2013-2014 (c) Sung Pae 178 | 179 | Last Change: %%RELEASE_DATE%% 180 | 181 | vim:tw=78:noet:sw=8:sts=8:ts=8:ft=help:norl: 182 | -------------------------------------------------------------------------------- /ftdetect/clojure.vim: -------------------------------------------------------------------------------- 1 | autocmd BufNewFile,BufRead *.clj,*.cljs,*.edn,*.cljx,*.cljc,{build,profile}.boot setlocal filetype=clojure 2 | -------------------------------------------------------------------------------- /ftplugin/clojure.vim: -------------------------------------------------------------------------------- 1 | " Vim filetype plugin file 2 | " Language: Clojure 3 | " Author: Meikel Brandmeyer 4 | " 5 | " Maintainer: Sung Pae 6 | " URL: https://github.com/guns/vim-clojure-static 7 | " License: Same as Vim 8 | " Last Change: %%RELEASE_DATE%% 9 | 10 | if exists("b:did_ftplugin") 11 | finish 12 | endif 13 | let b:did_ftplugin = 1 14 | 15 | let s:cpo_save = &cpo 16 | set cpo&vim 17 | 18 | let b:undo_ftplugin = 'setlocal iskeyword< define< formatoptions< comments< commentstring< lispwords<' 19 | 20 | setlocal iskeyword+=?,-,*,!,+,/,=,<,>,.,:,$ 21 | 22 | " There will be false positives, but this is better than missing the whole set 23 | " of user-defined def* definitions. 24 | setlocal define=\\v[(/]def(ault)@!\\S* 25 | 26 | " Remove 't' from 'formatoptions' to avoid auto-wrapping code. 27 | setlocal formatoptions-=t 28 | 29 | " Lisp comments are routinely nested (e.g. ;;; SECTION HEADING) 30 | setlocal comments=n:; 31 | setlocal commentstring=;\ %s 32 | 33 | " Specially indented symbols from clojure.core and clojure.test. 34 | " 35 | " Clojure symbols are indented in the defn style when they: 36 | " 37 | " * Define vars and anonymous functions 38 | " * Create new lexical scopes or scopes with altered environments 39 | " * Create conditional branches from a predicate function or value 40 | " 41 | " The arglists for these functions are generally in the form of [x & body]; 42 | " Functions that accept a flat list of forms do not treat the first argument 43 | " specially and hence are not indented specially. 44 | " 45 | " -*- LISPWORDS -*- 46 | " Generated from https://github.com/guns/vim-clojure-static/blob/%%RELEASE_TAG%%/clj/src/vim_clojure_static/generate.clj 47 | 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 48 | 49 | " Provide insert mode completions for special forms and clojure.core. As 50 | " 'omnifunc' is set by popular Clojure REPL client plugins, we also set 51 | " 'completefunc' so that the user has some form of completion available when 52 | " 'omnifunc' is set and no REPL connection exists. 53 | for s:setting in ['omnifunc', 'completefunc'] 54 | if exists('&' . s:setting) && empty(eval('&' . s:setting)) 55 | execute 'setlocal ' . s:setting . '=clojurecomplete#Complete' 56 | let b:undo_ftplugin .= ' | setlocal ' . s:setting . '<' 57 | endif 58 | endfor 59 | 60 | " Take all directories of the CLOJURE_SOURCE_DIRS environment variable 61 | " and add them to the path option. 62 | " 63 | " This is a legacy option for VimClojure users. 64 | if exists('$CLOJURE_SOURCE_DIRS') 65 | for s:dir in split($CLOJURE_SOURCE_DIRS, (has("win32") || has("win64")) ? ';' : ':') 66 | let s:dir = fnameescape(s:dir) 67 | " Whitespace escaping for Windows 68 | let s:dir = substitute(s:dir, '\', '\\\\', 'g') 69 | let s:dir = substitute(s:dir, '\ ', '\\ ', 'g') 70 | execute "setlocal path+=" . s:dir . "/**" 71 | endfor 72 | let b:undo_ftplugin .= ' | setlocal path<' 73 | endif 74 | 75 | " Skip brackets in ignored syntax regions when using the % command 76 | if exists('loaded_matchit') 77 | let b:match_words = &matchpairs 78 | let b:match_skip = 's:comment\|string\|regex\|character' 79 | let b:undo_ftplugin .= ' | unlet! b:match_words b:match_skip' 80 | endif 81 | 82 | " Win32 can filter files in the browse dialog 83 | if has("gui_win32") && !exists("b:browsefilter") 84 | let b:browsefilter = "Clojure Source Files (*.clj)\t*.clj\n" . 85 | \ "ClojureScript Source Files (*.cljs)\t*.cljs\n" . 86 | \ "Java Source Files (*.java)\t*.java\n" . 87 | \ "All Files (*.*)\t*.*\n" 88 | let b:undo_ftplugin .= ' | unlet! b:browsefilter' 89 | endif 90 | 91 | let &cpo = s:cpo_save 92 | 93 | unlet! s:cpo_save s:setting s:dir 94 | 95 | " vim:sts=8:sw=8:ts=8:noet 96 | -------------------------------------------------------------------------------- /indent/clojure.vim: -------------------------------------------------------------------------------- 1 | " Vim indent file 2 | " Language: Clojure 3 | " Author: Meikel Brandmeyer 4 | " URL: http://kotka.de/projects/clojure/vimclojure.html 5 | " 6 | " Maintainer: Sung Pae 7 | " URL: https://github.com/guns/vim-clojure-static 8 | " License: Same as Vim 9 | " Last Change: %%RELEASE_DATE%% 10 | 11 | if exists("b:did_indent") 12 | finish 13 | endif 14 | let b:did_indent = 1 15 | 16 | let s:save_cpo = &cpo 17 | set cpo&vim 18 | 19 | let b:undo_indent = 'setlocal autoindent< smartindent< expandtab< softtabstop< shiftwidth< indentexpr< indentkeys<' 20 | 21 | setlocal noautoindent nosmartindent 22 | setlocal softtabstop=2 shiftwidth=2 expandtab 23 | setlocal indentkeys=!,o,O 24 | 25 | if exists("*searchpairpos") 26 | 27 | if !exists('g:clojure_maxlines') 28 | let g:clojure_maxlines = 100 29 | endif 30 | 31 | if !exists('g:clojure_fuzzy_indent') 32 | let g:clojure_fuzzy_indent = 1 33 | endif 34 | 35 | if !exists('g:clojure_fuzzy_indent_patterns') 36 | let g:clojure_fuzzy_indent_patterns = ['^with', '^def', '^let'] 37 | endif 38 | 39 | if !exists('g:clojure_fuzzy_indent_blacklist') 40 | let g:clojure_fuzzy_indent_blacklist = ['-fn$', '\v^with-%(meta|out-str|loading-context)$'] 41 | endif 42 | 43 | if !exists('g:clojure_special_indent_words') 44 | let g:clojure_special_indent_words = 'deftype,defrecord,reify,proxy,extend-type,extend-protocol,letfn' 45 | endif 46 | 47 | if !exists('g:clojure_align_multiline_strings') 48 | let g:clojure_align_multiline_strings = 0 49 | endif 50 | 51 | if !exists('g:clojure_align_subforms') 52 | let g:clojure_align_subforms = 0 53 | endif 54 | 55 | function! s:syn_id_name() 56 | return synIDattr(synID(line("."), col("."), 0), "name") 57 | endfunction 58 | 59 | function! s:ignored_region() 60 | return s:syn_id_name() =~? '\vstring|regex|comment|character' 61 | endfunction 62 | 63 | function! s:current_char() 64 | return getline('.')[col('.')-1] 65 | endfunction 66 | 67 | function! s:current_word() 68 | return getline('.')[col('.')-1 : searchpos('\v>', 'n', line('.'))[1]-2] 69 | endfunction 70 | 71 | function! s:is_paren() 72 | return s:current_char() =~# '\v[\(\)\[\]\{\}]' && !s:ignored_region() 73 | endfunction 74 | 75 | " Returns 1 if string matches a pattern in 'patterns', which may be a 76 | " list of patterns, or a comma-delimited string of implicitly anchored 77 | " patterns. 78 | function! s:match_one(patterns, string) 79 | let list = type(a:patterns) == type([]) 80 | \ ? a:patterns 81 | \ : map(split(a:patterns, ','), '"^" . v:val . "$"') 82 | for pat in list 83 | if a:string =~# pat | return 1 | endif 84 | endfor 85 | endfunction 86 | 87 | function! s:match_pairs(open, close, stopat) 88 | " Stop only on vector and map [ resp. {. Ignore the ones in strings and 89 | " comments. 90 | if a:stopat == 0 && g:clojure_maxlines > 0 91 | let stopat = max([line(".") - g:clojure_maxlines, 0]) 92 | else 93 | let stopat = a:stopat 94 | endif 95 | 96 | let pos = searchpairpos(a:open, '', a:close, 'bWn', "!s:is_paren()", stopat) 97 | return [pos[0], col(pos)] 98 | endfunction 99 | 100 | function! s:clojure_check_for_string_worker() 101 | " Check whether there is the last character of the previous line is 102 | " highlighted as a string. If so, we check whether it's a ". In this 103 | " case we have to check also the previous character. The " might be the 104 | " closing one. In case the we are still in the string, we search for the 105 | " opening ". If this is not found we take the indent of the line. 106 | let nb = prevnonblank(v:lnum - 1) 107 | 108 | if nb == 0 109 | return -1 110 | endif 111 | 112 | call cursor(nb, 0) 113 | call cursor(0, col("$") - 1) 114 | if s:syn_id_name() !~? "string" 115 | return -1 116 | endif 117 | 118 | " This will not work for a " in the first column... 119 | if s:current_char() == '"' 120 | call cursor(0, col("$") - 2) 121 | if s:syn_id_name() !~? "string" 122 | return -1 123 | endif 124 | if s:current_char() != '\' 125 | return -1 126 | endif 127 | call cursor(0, col("$") - 1) 128 | endif 129 | 130 | let p = searchpos('\(^\|[^\\]\)\zs"', 'bW') 131 | 132 | if p != [0, 0] 133 | return p[1] - 1 134 | endif 135 | 136 | return indent(".") 137 | endfunction 138 | 139 | function! s:check_for_string() 140 | let pos = getpos('.') 141 | try 142 | let val = s:clojure_check_for_string_worker() 143 | finally 144 | call setpos('.', pos) 145 | endtry 146 | return val 147 | endfunction 148 | 149 | function! s:strip_namespace_and_macro_chars(word) 150 | return substitute(a:word, "\\v%(.*/|[#'`~@^,]*)(.*)", '\1', '') 151 | endfunction 152 | 153 | function! s:clojure_is_method_special_case_worker(position) 154 | " Find the next enclosing form. 155 | call search('\S', 'Wb') 156 | 157 | " Special case: we are at a '(('. 158 | if s:current_char() == '(' 159 | return 0 160 | endif 161 | call cursor(a:position) 162 | 163 | let next_paren = s:match_pairs('(', ')', 0) 164 | 165 | " Special case: we are now at toplevel. 166 | if next_paren == [0, 0] 167 | return 0 168 | endif 169 | call cursor(next_paren) 170 | 171 | call search('\S', 'W') 172 | let w = s:strip_namespace_and_macro_chars(s:current_word()) 173 | if g:clojure_special_indent_words =~# '\V\<' . w . '\>' 174 | return 1 175 | endif 176 | 177 | return 0 178 | endfunction 179 | 180 | function! s:is_method_special_case(position) 181 | let pos = getpos('.') 182 | try 183 | let val = s:clojure_is_method_special_case_worker(a:position) 184 | finally 185 | call setpos('.', pos) 186 | endtry 187 | return val 188 | endfunction 189 | 190 | " Check if form is a reader conditional, that is, it is prefixed by #? 191 | " or @#? 192 | function! s:is_reader_conditional_special_case(position) 193 | return getline(a:position[0])[a:position[1] - 3 : a:position[1] - 2] == "#?" 194 | endfunction 195 | 196 | " Returns 1 for opening brackets, -1 for _anything else_. 197 | function! s:bracket_type(char) 198 | return stridx('([{', a:char) > -1 ? 1 : -1 199 | endfunction 200 | 201 | " Returns: [opening-bracket-lnum, indent] 202 | function! s:clojure_indent_pos() 203 | " Get rid of special case. 204 | if line(".") == 1 205 | return [0, 0] 206 | endif 207 | 208 | " We have to apply some heuristics here to figure out, whether to use 209 | " normal lisp indenting or not. 210 | let i = s:check_for_string() 211 | if i > -1 212 | return [0, i + !!g:clojure_align_multiline_strings] 213 | endif 214 | 215 | call cursor(0, 1) 216 | 217 | " Find the next enclosing [ or {. We can limit the second search 218 | " to the line, where the [ was found. If no [ was there this is 219 | " zero and we search for an enclosing {. 220 | let paren = s:match_pairs('(', ')', 0) 221 | let bracket = s:match_pairs('\[', '\]', paren[0]) 222 | let curly = s:match_pairs('{', '}', bracket[0]) 223 | 224 | " In case the curly brace is on a line later then the [ or - in 225 | " case they are on the same line - in a higher column, we take the 226 | " curly indent. 227 | if curly[0] > bracket[0] || curly[1] > bracket[1] 228 | if curly[0] > paren[0] || curly[1] > paren[1] 229 | return curly 230 | endif 231 | endif 232 | 233 | " If the curly was not chosen, we take the bracket indent - if 234 | " there was one. 235 | if bracket[0] > paren[0] || bracket[1] > paren[1] 236 | return bracket 237 | endif 238 | 239 | " There are neither { nor [ nor (, ie. we are at the toplevel. 240 | if paren == [0, 0] 241 | return paren 242 | endif 243 | 244 | " Now we have to reimplement lispindent. This is surprisingly easy, as 245 | " soon as one has access to syntax items. 246 | " 247 | " - Check whether we are in a special position after a word in 248 | " g:clojure_special_indent_words. These are special cases. 249 | " - Get the next keyword after the (. 250 | " - If its first character is also a (, we have another sexp and align 251 | " one column to the right of the unmatched (. 252 | " - In case it is in lispwords, we indent the next line to the column of 253 | " the ( + sw. 254 | " - If not, we check whether it is last word in the line. In that case 255 | " we again use ( + sw for indent. 256 | " - In any other case we use the column of the end of the word + 2. 257 | call cursor(paren) 258 | 259 | if s:is_method_special_case(paren) 260 | return [paren[0], paren[1] + &shiftwidth - 1] 261 | endif 262 | 263 | if s:is_reader_conditional_special_case(paren) 264 | return paren 265 | endif 266 | 267 | " In case we are at the last character, we use the paren position. 268 | if col("$") - 1 == paren[1] 269 | return paren 270 | endif 271 | 272 | " In case after the paren is a whitespace, we search for the next word. 273 | call cursor(0, col('.') + 1) 274 | if s:current_char() == ' ' 275 | call search('\v\S', 'W') 276 | endif 277 | 278 | " If we moved to another line, there is no word after the (. We 279 | " use the ( position for indent. 280 | if line(".") > paren[0] 281 | return paren 282 | endif 283 | 284 | " We still have to check, whether the keyword starts with a (, [ or {. 285 | " In that case we use the ( position for indent. 286 | let w = s:current_word() 287 | if s:bracket_type(w[0]) == 1 288 | return paren 289 | endif 290 | 291 | " If the keyword begins with #, check if it is an anonymous 292 | " function or set, in which case we indent by the shiftwidth 293 | " (minus one if g:clojure_align_subforms = 1), or if it is 294 | " ignored, in which case we use the ( position for indent. 295 | if w[0] == "#" 296 | " TODO: Handle #=() and other rare reader invocations? 297 | if w[1] == '(' || w[1] == '{' 298 | return [paren[0], paren[1] + (g:clojure_align_subforms ? 0 : &shiftwidth - 1)] 299 | elseif w[1] == '_' 300 | return paren 301 | endif 302 | endif 303 | 304 | " Test words without namespace qualifiers and leading reader macro 305 | " metacharacters. 306 | " 307 | " e.g. clojure.core/defn and #'defn should both indent like defn. 308 | let ww = s:strip_namespace_and_macro_chars(w) 309 | 310 | if &lispwords =~# '\V\<' . ww . '\>' 311 | return [paren[0], paren[1] + &shiftwidth - 1] 312 | endif 313 | 314 | if g:clojure_fuzzy_indent 315 | \ && !s:match_one(g:clojure_fuzzy_indent_blacklist, ww) 316 | \ && s:match_one(g:clojure_fuzzy_indent_patterns, ww) 317 | return [paren[0], paren[1] + &shiftwidth - 1] 318 | endif 319 | 320 | call search('\v\_s', 'cW') 321 | call search('\v\S', 'W') 322 | if paren[0] < line(".") 323 | return [paren[0], paren[1] + (g:clojure_align_subforms ? 0 : &shiftwidth - 1)] 324 | endif 325 | 326 | call search('\v\S', 'bW') 327 | return [line('.'), col('.') + 1] 328 | endfunction 329 | 330 | function! GetClojureIndent() 331 | let lnum = line('.') 332 | let orig_lnum = lnum 333 | let orig_col = col('.') 334 | let [opening_lnum, indent] = s:clojure_indent_pos() 335 | 336 | " Account for multibyte characters 337 | if opening_lnum > 0 338 | let indent -= indent - virtcol([opening_lnum, indent]) 339 | endif 340 | 341 | " Return if there are no previous lines to inherit from 342 | if opening_lnum < 1 || opening_lnum >= lnum - 1 343 | call cursor(orig_lnum, orig_col) 344 | return indent 345 | endif 346 | 347 | let bracket_count = 0 348 | 349 | " Take the indent of the first previous non-white line that is 350 | " at the same sexp level. cf. src/misc1.c:get_lisp_indent() 351 | while 1 352 | let lnum = prevnonblank(lnum - 1) 353 | let col = 1 354 | 355 | if lnum <= opening_lnum 356 | break 357 | endif 358 | 359 | call cursor(lnum, col) 360 | 361 | " Handle bracket counting edge case 362 | if s:is_paren() 363 | let bracket_count += s:bracket_type(s:current_char()) 364 | endif 365 | 366 | while 1 367 | if search('\v[(\[{}\])]', '', lnum) < 1 368 | break 369 | elseif !s:ignored_region() 370 | let bracket_count += s:bracket_type(s:current_char()) 371 | endif 372 | endwhile 373 | 374 | if bracket_count == 0 375 | " Check if this is part of a multiline string 376 | call cursor(lnum, 1) 377 | if s:syn_id_name() !~? '\vstring|regex' 378 | call cursor(orig_lnum, orig_col) 379 | return indent(lnum) 380 | endif 381 | endif 382 | endwhile 383 | 384 | call cursor(orig_lnum, orig_col) 385 | return indent 386 | endfunction 387 | 388 | setlocal indentexpr=GetClojureIndent() 389 | 390 | else 391 | 392 | " In case we have searchpairpos not available we fall back to 393 | " normal lisp indenting. 394 | setlocal indentexpr= 395 | setlocal lisp 396 | let b:undo_indent .= '| setlocal lisp<' 397 | 398 | endif 399 | 400 | let &cpo = s:save_cpo 401 | unlet! s:save_cpo 402 | 403 | " vim:sts=8:sw=8:ts=8:noet 404 | -------------------------------------------------------------------------------- /syntax/clojure.vim: -------------------------------------------------------------------------------- 1 | " Vim syntax file 2 | " Language: Clojure 3 | " Authors: Toralf Wittner 4 | " modified by Meikel Brandmeyer 5 | " URL: http://kotka.de/projects/clojure/vimclojure.html 6 | " 7 | " Contributors: Joel Holdbrooks (Regexp support, bug fixes) 8 | " 9 | " Maintainer: Sung Pae 10 | " URL: https://github.com/guns/vim-clojure-static 11 | " License: Same as Vim 12 | " Last Change: %%RELEASE_DATE%% 13 | 14 | if exists("b:current_syntax") 15 | finish 16 | endif 17 | 18 | let s:cpo_sav = &cpo 19 | set cpo&vim 20 | 21 | if has("folding") && exists("g:clojure_fold") && g:clojure_fold > 0 22 | setlocal foldmethod=syntax 23 | endif 24 | 25 | " -*- KEYWORDS -*- 26 | " Generated from https://github.com/guns/vim-clojure-static/blob/%%RELEASE_TAG%%/clj/src/vim_clojure_static/generate.clj 27 | " Clojure version 1.8.0 28 | let s:clojure_syntax_keywords = { 29 | \ 'clojureBoolean': ["false","true"] 30 | \ , '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"] 31 | \ , 'clojureConstant': ["nil"] 32 | \ , '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"] 33 | \ , 'clojureException': ["catch","finally","throw","try"] 34 | \ , 'clojureFunc': ["*","*'","+","+'","-","-'","->ArrayChunk","->Eduction","->Vec","->VecNode","->VecSeq","-cache-protocol-fn","-reset-methods","/","<","<=","=","==",">",">=","Throwable->map","accessor","aclone","add-classpath","add-watch","agent","agent-error","agent-errors","aget","alength","alias","all-ns","alter","alter-meta!","alter-var-root","ancestors","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","booleans","bound-fn*","bound?","butlast","byte","byte-array","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/Throwable->map","clojure.core/accessor","clojure.core/aclone","clojure.core/add-classpath","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/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/booleans","clojure.core/bound-fn*","clojure.core/bound?","clojure.core/butlast","clojure.core/byte","clojure.core/byte-array","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/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-data","clojure.core/ex-info","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/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/identical?","clojure.core/identity","clojure.core/ifn?","clojure.core/in-ns","clojure.core/inc","clojure.core/inc'","clojure.core/init-proxy","clojure.core/instance?","clojure.core/int","clojure.core/int-array","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/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?","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/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-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-watch","clojure.core/repeat","clojure.core/repeatedly","clojure.core/replace","clojure.core/replicate","clojure.core/require","clojure.core/reset!","clojure.core/reset-meta!","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/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/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/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/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/use","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","doubles","drop","drop-last","drop-while","eduction","empty","empty?","ensure","ensure-reduced","enumeration-seq","error-handler","error-mode","eval","even?","every-pred","every?","ex-data","ex-info","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","hash","hash-combine","hash-map","hash-ordered-coll","hash-set","hash-unordered-coll","identical?","identity","ifn?","in-ns","inc","inc'","init-proxy","instance?","int","int-array","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","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?","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","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-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-watch","repeat","repeatedly","replace","replicate","require","reset!","reset-meta!","resolve","rest","restart-agent","resultset-seq","reverse","reversible?","rseq","rsubseq","run!","satisfies?","second","select-keys","send","send-off","send-via","seq","seq?","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","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!","symbol","symbol?","tagged-literal","tagged-literal?","take","take-last","take-nth","take-while","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","use","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"] 35 | \ , '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"] 36 | \ , 'clojureRepeat': ["clojure.core/doseq","clojure.core/dotimes","clojure.core/while","doseq","dotimes","while"] 37 | \ , '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"] 38 | \ , 'clojureVariable': ["*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-readably*","*read-eval*","*source-path*","*suppress-read*","*unchecked-math*","*use-context-classloader*","*verbose-defrecords*","*warn-on-reflection*","EMPTY-NODE","char-escape-string","char-name-string","clojure.core/*1","clojure.core/*2","clojure.core/*3","clojure.core/*agent*","clojure.core/*allow-unresolved-vars*","clojure.core/*assert*","clojure.core/*clojure-version*","clojure.core/*command-line-args*","clojure.core/*compile-files*","clojure.core/*compile-path*","clojure.core/*compiler-options*","clojure.core/*data-readers*","clojure.core/*default-data-reader-fn*","clojure.core/*e","clojure.core/*err*","clojure.core/*file*","clojure.core/*flush-on-newline*","clojure.core/*fn-loader*","clojure.core/*in*","clojure.core/*math-context*","clojure.core/*ns*","clojure.core/*out*","clojure.core/*print-dup*","clojure.core/*print-length*","clojure.core/*print-level*","clojure.core/*print-meta*","clojure.core/*print-readably*","clojure.core/*read-eval*","clojure.core/*source-path*","clojure.core/*suppress-read*","clojure.core/*unchecked-math*","clojure.core/*use-context-classloader*","clojure.core/*verbose-defrecords*","clojure.core/*warn-on-reflection*","clojure.core/EMPTY-NODE","clojure.core/char-escape-string","clojure.core/char-name-string","clojure.core/default-data-readers","clojure.core/primitives-classnames","clojure.core/unquote","clojure.core/unquote-splicing","default-data-readers","primitives-classnames","unquote","unquote-splicing"] 39 | \ } 40 | 41 | function! s:syntax_keyword(dict) 42 | for key in keys(a:dict) 43 | execute 'syntax keyword' key join(a:dict[key], ' ') 44 | endfor 45 | endfunction 46 | 47 | if exists('b:clojure_syntax_without_core_keywords') && b:clojure_syntax_without_core_keywords 48 | " Only match language specials and primitives 49 | for s:key in ['clojureBoolean', 'clojureConstant', 'clojureException', 'clojureSpecial'] 50 | execute 'syntax keyword' s:key join(s:clojure_syntax_keywords[s:key], ' ') 51 | endfor 52 | else 53 | call s:syntax_keyword(s:clojure_syntax_keywords) 54 | endif 55 | 56 | if exists('g:clojure_syntax_keywords') 57 | call s:syntax_keyword(g:clojure_syntax_keywords) 58 | endif 59 | 60 | if exists('b:clojure_syntax_keywords') 61 | call s:syntax_keyword(b:clojure_syntax_keywords) 62 | endif 63 | 64 | unlet! s:key 65 | delfunction s:syntax_keyword 66 | 67 | " Keywords are symbols: 68 | " static Pattern symbolPat = Pattern.compile("[:]?([\\D&&[^/]].*/)?([\\D&&[^/]][^/]*)"); 69 | " But they: 70 | " * Must not end in a : or / 71 | " * Must not have two adjacent colons except at the beginning 72 | " * Must not contain any reader metacharacters except for ' and # 73 | syntax match clojureKeyword "\v<:{1,2}%([^ \n\r\t()\[\]{}";@^`~\\%/]+/)*[^ \n\r\t()\[\]{}";@^`~\\%/]+:@" 74 | 75 | syntax match clojureStringEscape "\v\\%([\\btnfr"]|u\x{4}|[0-3]\o{2}|\o{1,2})" contained 76 | 77 | syntax region clojureString matchgroup=clojureStringDelimiter start=/"/ skip=/\\\\\|\\"/ end=/"/ contains=clojureStringEscape,@Spell 78 | 79 | syntax match clojureCharacter "\\." 80 | syntax match clojureCharacter "\\o\%([0-3]\o\{2\}\|\o\{1,2\}\)" 81 | syntax match clojureCharacter "\\u\x\{4\}" 82 | syntax match clojureCharacter "\\space" 83 | syntax match clojureCharacter "\\tab" 84 | syntax match clojureCharacter "\\newline" 85 | syntax match clojureCharacter "\\return" 86 | syntax match clojureCharacter "\\backspace" 87 | syntax match clojureCharacter "\\formfeed" 88 | 89 | syntax match clojureSymbol "\v%([a-zA-Z!$&*_+=|<.>?-]|[^\x00-\x7F])+%(:?%([a-zA-Z0-9!#$%&*_+=|'<.>/?-]|[^\x00-\x7F]))*[#:]@"' 94 | endfor 95 | unlet! s:radix_chars s:radix 96 | 97 | syntax match clojureNumber "\v<[-+]?%(0\o*|0x\x+|[1-9]\d*)N?>" 98 | syntax match clojureNumber "\v<[-+]?%(0|[1-9]\d*|%(0|[1-9]\d*)\.\d*)%(M|[eE][-+]?\d+)?>" 99 | syntax match clojureNumber "\v<[-+]?%(0|[1-9]\d*)/%(0|[1-9]\d*)>" 100 | 101 | syntax match clojureVarArg "&" 102 | 103 | syntax match clojureQuote "'" 104 | syntax match clojureQuote "`" 105 | syntax match clojureUnquote "\~" 106 | syntax match clojureUnquote "\~@" 107 | syntax match clojureMeta "\^" 108 | syntax match clojureDeref "@" 109 | syntax match clojureDispatch "\v#[\^'=<_]?" 110 | 111 | " Clojure permits no more than 20 anonymous params. 112 | syntax match clojureAnonArg "%\(20\|1\d\|[1-9]\|&\)\?" 113 | 114 | syntax match clojureRegexpEscape "\v\\%([\\tnrfae.()\[\]{}^$*?+]|c\u|0[0-3]?\o{1,2}|x%(\x{2}|\{\x{1,6}\})|u\x{4})" contained display 115 | syntax region clojureRegexpQuoted start=/\\Q/ms=e+1 skip=/\\\\\|\\"/ end=/\\E/me=s-1 end=/"/me=s-1 contained 116 | syntax region clojureRegexpQuote start=/\\Q/ skip=/\\\\\|\\"/ end=/\\E/ end=/"/me=s-1 contains=clojureRegexpQuoted keepend contained 117 | 118 | " -*- CHARACTER PROPERTY CLASSES -*- 119 | " Generated from https://github.com/guns/vim-clojure-static/blob/%%RELEASE_TAG%%/clj/src/vim_clojure_static/generate.clj 120 | " Java version 1.8.0_92 121 | syntax match clojureRegexpPosixCharClass "\v\\[pP]\{%(Cntrl|A%(l%(pha|num)|SCII)|Space|Graph|Upper|P%(rint|unct)|Blank|XDigit|Digit|Lower)\}" contained display 122 | 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 123 | 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 124 | syntax match clojureRegexpUnicodeCharClass "\v\\[pP][NSCMZPL]" contained display 125 | syntax match clojureRegexpUnicodeCharClass "\v\\[pP]\{%(N[dlo]?|P[dcifeos]?|C[ncfos]?|M[nce]?|Z[lsp]?|S[mcko]?|L[muCDlto]?)\}" contained display 126 | syntax match clojureRegexpUnicodeCharClass "\v\\[pP]\{%(Is|gc\=|general_category\=)?%(N[dlo]?|P[dcifeos]?|C[ncfos]?|M[nce]?|Z[lsp]?|S[mcko]?|L[muCDlto]?)\}" contained display 127 | syntax match clojureRegexpUnicodeCharClass "\v\\[pP]\{\c%(Is|sc\=|script\=)%(l%(epc%(ha)?|y%([dc]i%(an)?)|a%(t%(n|in)|na|oo?)|i%(n%(b|ear_b)|mbu?|su))|p%(rti|lrd|h%(oenician|li|ag%(s_pa)?|nx))|vaii?|d%(srt|e%(seret|va%(nagari)?))|g%(lag%(olitic)?|eor%(gian)?|oth%(ic)?|re%(k|ek)|u%(j%(arati|r)|r%(u|mukhi)))|u%(gar%(itic)?|nknown)|a%(r%(ab%(ic)?|m%([ni]|enian))|v%(st|estan))|e%(thi%(opic)?|gyp%(tian_hieroglyphs)?)|z%(inh|yyy|zzz)|r%(un%(ic|r)|ejang|jng)|s%(inh%(ala)?|h%(rd|a%(vian|rada|w))|a%(ur%(ashtra)?|m%(r|aritan)|rb)|y%(r%(c|iac)|lo%(ti_nagri)?)|und%(anese)?|ora%(_sompeng)?)|i%(n%(scriptional_pa%(rthian|hlavi)|herited)|mperial_aramaic|tal)|b%(eng%(ali)?|a%(t%(ak|k)|li%(nese)?|mum?)|ra%(i%(lle)?|h%(mi)?)|opo%(mofo)?|u%(gi%(nese)?|h%(d|id)))|o%(g%(am|ham)|r%(iya|kh|ya)|sma%(nya)?|l%(d_%(south_arabian|persian|italic|turkic)|ck|_chiki))|k%(h%(m%(r|er)|ar%(oshthi)?)|nda|a%(li|n%(a|nada)|takana|yah_li|ithi)|thi)|m%(a%(nd%(aic)?|layalam)|lym|y%(anmar|mr)|tei|e%(r%(c|o%(itic_%(hieroglyphs|cursive))?)|etei_mayek)|ong%(olian)?|iao)|yi%(ii)?|x%(peo|sux)|n%(ew_tai_lue|koo?)|h%(ira%(gana)?|an%([io]|unoo|g%(ul)?)?|ebr%(ew)?)|c%(y%(priot|r%(l|illic))|a%(km|n%(adian_aboriginal|s)|ri%(an)?)|prt|h%(er%(okee)?|a%(m|kma))|uneiform|o%(pt%(ic)?|mmon))|t%(elu%(gu)?|i%(finagh|b%(t|etan))|ha%(i|a%(na)?)|a%(i_%(le|tham|viet)|g%(alog|b%(anwa)?)|vt|kri?|l[ue]|m%(il|l))|fng|glg)|java%(nese)?)\}" contained display 128 | syntax match clojureRegexpUnicodeCharClass "\v\\[pP]\{\c%(In|blk\=|block\=)%(javanese|h%(a%(lfwidth%( and fullwidth forms|andfullwidthforms|_and_fullwidth_forms)|n%(unoo|gul%(compatibilityjamo|syllables|jamo%(extended\-[ab])?|_%(syllables|jamo%(_extended_[ab])?|compatibility_jamo)| %(syllables|compatibility jamo|jamo%( extended\-[ab])?))))|i%(ragana|gh%( %(private use surrogates|surrogates)|_%(private_use_surrogates|surrogates)|surrogates|privateusesurrogates))|ebrew)|i%(pa%([ _]extensions|extensions)|deographic%( description characters|_description_characters|descriptioncharacters)|nscriptional%(%([ _]pa%(rthian|hlavi))|pa%(rthian|hlavi))|mperial%(aramaic|[_ ]aramaic))|l%(e%(tterlike%([_ ]symbols|symbols)|pcha)|ow%([_ ]surrogates|surrogates)|i%(mbu|near%(_b_%(ideograms|syllabary)|b%(ideograms|syllabary)| b %(ideograms|syllabary))|su)|a%(tin%(extended%(additional|\-[dacb])| extended%( additional|\-[dacb])|\-1%(supplement| supplement)|_%(extended_%([dcb]|a%(dditional)?)|1_supplement))|o)|y[cd]ian)|b%(u%(ginese|hid)|ra%(hmi|ille%(patterns|[_ ]patterns))|o%(x%([ _]drawing|drawing)|pomofo%([ _]extended|extended)?)|lock%([ _]elements|elements)|yzantine%( musical symbols|musicalsymbols|_musical_symbols)|engali|a%(linese|mum%(supplement|[ _]supplement)?|tak|sic%([ _]latin|latin)))|e%(gyptian%([ _]hieroglyphs|hieroglyphs)|moticons|nclosed%( %(cjk letters and months|ideographic supplement|alphanumeric%( supplement|s))|cjklettersandmonths|_%(ideographic_supplement|alphanumeric%(_supplement|s)|cjk_letters_and_months)|alphanumerics%(upplement)?|ideographicsupplement)|thiopic%(supplement|_%(supplement|extended%(_a)?)| %(supplement|extended%(\-a)?)|extended%(\-a)?)?)|k%(h%(aroshthi|mer%([_ ]symbols|symbols)?)|a%(takana%(_phonetic_extensions|phoneticextensions| phonetic extensions)?|n%(gxi%([_ ]radicals|radicals)|a%(supplement|[ _]supplement)|bun|nada)|ithi|yah%([ _]li|li)))|m%(i%(ao|scellaneous%(technical|symbols%(and%(pictographs|arrows))?|mathematicalsymbols\-[ab]| %(technical|mathematical symbols\-[ab]|symbols%( and %(pictographs|arrows))?)|_%(technical|symbols%(_and_%(pictographs|arrows))?|mathematical_symbols_[ab])))|usical%([_ ]symbols|symbols)|e%(etei%(mayek%(extensions)?|_mayek%(_extensions)?| mayek%( extensions)?)|roitic%(hieroglyphs|%([_ ]%(hieroglyphs|cursive))|cursive))|a%(ndaic|hjong%([ _]tiles|tiles)|layalam|thematical%(alphanumericsymbols| %(alphanumeric symbols|operators)|_%(alphanumeric_symbols|operators)|operators))|yanmar%(extended\-a|_extended_a| extended\-a)?|o%(difier%(_tone_letters| tone letters|toneletters)|ngolian))|r%(u%(nic|mi%(numeralsymbols| numeral symbols|_numeral_symbols))|ejang)|n%(umber%(forms|[ _]forms)|ko|ew%(_tai_lue|tailue| tai lue))|c%(o%(ntrol%(pictures|[ _]pictures)|m%(bining%(diacriticalmarks%(supplement|forsymbols)?|halfmarks| %(diacritical marks%( %(supplement|for symbols))?|half marks|marks for symbols)|marksforsymbols|_%(marks_for_symbols|half_marks|diacritical_marks%(_supplement)?))|mon%(_indic_number_forms|indicnumberforms| indic number forms))|ptic|unting%( rod numerals|_rod_numerals|rodnumerals))|y%(rillic%(extended\-[ab]|_%(extended_[ab]|supplementary)|supplement%(ary)?| %(extended\-[ab]|supplement%(ary)?))?|priot%(syllabary|[ _]syllabary))|u%(rrency%([_ ]symbols|symbols)|neiform%(_numbers_and_punctuation|numbersandpunctuation| numbers and punctuation)?)|h%(a%(m|kma)|erokee)|arian|jk%(s%(ymbolsandpunctuation|trokes)|compatibility%(forms|ideographs%(supplement)?)?|radicalssupplement| %(compatibility%( %(ideographs%( supplement)?|forms))?|radicals supplement|unified ideographs%( extension [dacb])?|s%(ymbols and punctuation|trokes))|_%(s%(trokes|ymbols_and_punctuation)|radicals_supplement|compatibility%(_%(forms|ideographs%(_supplement)?))?|unified_ideographs%(_extension_[dacb])?)|unifiedideographs%(extension[dacb])?))|d%(e%(seret|vanagari%([ _]extended|extended)?)|ingbats|omino%([ _]tiles|tiles))|yi%(syllables|%([_ ]%(syllables|radicals))|radicals|jing%(hexagramsymbols| hexagram symbols|_hexagram_symbols))|s%(mall%( form variants|formvariants|_form_variants)|p%(acing%(_modifier_letters| modifier letters|modifierletters)|ecials)|ora%(sompeng|[ _]sompeng)|ha%(vian|rada)|a%(maritan|urashtra)|inhala|y%(riac|loti%([_ ]nagri|nagri))|u%(ndanese%(supplement|[ _]supplement)?|p%(erscripts%(_and_subscripts|andsubscripts| and subscripts)|plementa%(ry%(_private_use_area_[ab]|privateusearea\-[ab]| private use area\-[ab])|l%(_%(arrows_[ab]|mathematical_operators|punctuation)| %(mathematical operators|punctuation|arrows\-[ab])|mathematicaloperators|punctuation|arrows\-[ab])))|rrogates_area))|p%(h%(o%(enician|netic%( extensions%( supplement)?|extensions%(supplement)?|_extensions%(_supplement)?))|a%(istos%([ _]disc|disc)|gs[_\-]pa))|laying%(cards|[_ ]cards)|rivate%(usearea| use area|_use_area))|o%(smanya|l%([ _]chiki|d%( %(south arabian|persian|italic|turkic)|southarabian|_%(south_arabian|persian|italic|turkic)|persian|italic|turkic)|chiki)|riya|ptical%( character recognition|_character_recognition|characterrecognition)|gham)|g%(u%(jarati|rmukhi)|othic|lagolitic|e%(o%(rgian%(supplement|[ _]supplement)?|metric%(shapes|[ _]shapes))|neral%([_ ]punctuation|punctuation))|reek%( %(and coptic|extended)|andcoptic|_extended|extended)?)|t%(i%(betan|finagh)|elugu|ransport%( and map symbols|_and_map_symbols|andmapsymbols)|a%(mil|kri|i%(xuanjingsymbols|_%(le|xuan_jing_symbols|tham|viet)|le| %(xuan jing symbols|le|tham|viet)|tham|viet)|g%(alog|s|banwa))|ha%(i|ana))|a%(l%(chemical%([_ ]symbols|symbols)|phabetic%( presentation forms|_presentation_forms|presentationforms))|r%(menian|abic%(extended\-a|mathematicalalphabeticsymbols|supplement|_%(presentation_forms_[ab]|supplement|extended_a|mathematical_alphabetic_symbols)| %(extended\-a|mathematical alphabetic symbols|supplement|presentation forms\-[ab])|presentationforms\-[ab])?|rows)|ncient%(_%(greek_%(musical_notation|numbers)|symbols)|greek%(numbers|musicalnotation)| %(greek %(numbers|musical notation)|symbols)|symbols)|egean%(numbers|[ _]numbers)|vestan)|u%(garitic|nified%(canadianaboriginalsyllabics%(extended)?|_canadian_aboriginal_syllabics%(_extended)?| canadian aboriginal syllabics%( extended)?))|v%(a%(i|riation%( selectors%( supplement)?|selectors%(supplement)?|_selectors%(_supplement)?))|e%(rtical%(forms|[ _]forms)|dic%([ _]extensions|extensions))))\}" contained display 129 | 130 | syntax match clojureRegexpPredefinedCharClass "\v%(\\[dDsSwW]|\.)" contained display 131 | syntax cluster clojureRegexpCharPropertyClasses contains=clojureRegexpPosixCharClass,clojureRegexpJavaCharClass,clojureRegexpUnicodeCharClass 132 | syntax cluster clojureRegexpCharClasses contains=clojureRegexpPredefinedCharClass,clojureRegexpCharClass,@clojureRegexpCharPropertyClasses 133 | syntax region clojureRegexpCharClass start="\[" skip=/\\\\\|\\]/ end="]" contained contains=clojureRegexpPredefinedCharClass,@clojureRegexpCharPropertyClasses 134 | syntax match clojureRegexpBoundary "\\[bBAGZz]" contained display 135 | syntax match clojureRegexpBoundary "[$^]" contained display 136 | syntax match clojureRegexpQuantifier "[?*+][?+]\=" contained display 137 | syntax match clojureRegexpQuantifier "\v\{\d+%(,|,\d+)?}\??" contained display 138 | syntax match clojureRegexpOr "|" contained display 139 | syntax match clojureRegexpBackRef "\v\\%([1-9]\d*|k\<[a-zA-z]+\>)" contained display 140 | 141 | " Mode modifiers, mode-modified spans, lookaround, regular and atomic 142 | " grouping, and named-capturing. 143 | syntax match clojureRegexpMod "\v\(@<=\?:" contained display 144 | syntax match clojureRegexpMod "\v\(@<=\?[xdsmiuU]*-?[xdsmiuU]+:?" contained display 145 | syntax match clojureRegexpMod "\v\(@<=\?%(\)" contained display 146 | syntax match clojureRegexpMod "\v\(@<=\?\<[a-zA-Z]+\>" contained display 147 | 148 | syntax region clojureRegexpGroup start="(" skip=/\\\\\|\\)/ end=")" matchgroup=clojureRegexpGroup contained contains=clojureRegexpMod,clojureRegexpQuantifier,clojureRegexpBoundary,clojureRegexpEscape,@clojureRegexpCharClasses 149 | syntax region clojureRegexp start=/\#"/ skip=/\\\\\|\\"/ end=/"/ contains=@clojureRegexpCharClasses,clojureRegexpEscape,clojureRegexpQuote,clojureRegexpBoundary,clojureRegexpQuantifier,clojureRegexpOr,clojureRegexpBackRef,clojureRegexpGroup keepend 150 | 151 | syntax keyword clojureCommentTodo contained FIXME XXX TODO FIXME: XXX: TODO: 152 | 153 | syntax match clojureComment ";.*$" contains=clojureCommentTodo,@Spell 154 | syntax match clojureComment "#!.*$" 155 | 156 | " -*- TOP CLUSTER -*- 157 | " Generated from https://github.com/guns/vim-clojure-static/blob/%%RELEASE_TAG%%/clj/src/vim_clojure_static/generate.clj 158 | 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 159 | 160 | syntax region clojureSexp matchgroup=clojureParen start="(" end=")" contains=@clojureTop fold 161 | syntax region clojureVector matchgroup=clojureParen start="\[" end="]" contains=@clojureTop fold 162 | syntax region clojureMap matchgroup=clojureParen start="{" end="}" contains=@clojureTop fold 163 | 164 | " Highlight superfluous closing parens, brackets and braces. 165 | syntax match clojureError "]\|}\|)" 166 | 167 | syntax sync fromstart 168 | 169 | highlight default link clojureConstant Constant 170 | highlight default link clojureBoolean Boolean 171 | highlight default link clojureCharacter Character 172 | highlight default link clojureKeyword Keyword 173 | highlight default link clojureNumber Number 174 | highlight default link clojureString String 175 | highlight default link clojureStringDelimiter String 176 | highlight default link clojureStringEscape Character 177 | 178 | highlight default link clojureRegexp Constant 179 | highlight default link clojureRegexpEscape Character 180 | highlight default link clojureRegexpCharClass SpecialChar 181 | highlight default link clojureRegexpPosixCharClass clojureRegexpCharClass 182 | highlight default link clojureRegexpJavaCharClass clojureRegexpCharClass 183 | highlight default link clojureRegexpUnicodeCharClass clojureRegexpCharClass 184 | highlight default link clojureRegexpPredefinedCharClass clojureRegexpCharClass 185 | highlight default link clojureRegexpBoundary SpecialChar 186 | highlight default link clojureRegexpQuantifier SpecialChar 187 | highlight default link clojureRegexpMod SpecialChar 188 | highlight default link clojureRegexpOr SpecialChar 189 | highlight default link clojureRegexpBackRef SpecialChar 190 | highlight default link clojureRegexpGroup clojureRegexp 191 | highlight default link clojureRegexpQuoted clojureString 192 | highlight default link clojureRegexpQuote clojureRegexpBoundary 193 | 194 | highlight default link clojureVariable Identifier 195 | highlight default link clojureCond Conditional 196 | highlight default link clojureDefine Define 197 | highlight default link clojureException Exception 198 | highlight default link clojureFunc Function 199 | highlight default link clojureMacro Macro 200 | highlight default link clojureRepeat Repeat 201 | 202 | highlight default link clojureSpecial Special 203 | highlight default link clojureVarArg Special 204 | highlight default link clojureQuote SpecialChar 205 | highlight default link clojureUnquote SpecialChar 206 | highlight default link clojureMeta SpecialChar 207 | highlight default link clojureDeref SpecialChar 208 | highlight default link clojureAnonArg SpecialChar 209 | highlight default link clojureDispatch SpecialChar 210 | 211 | highlight default link clojureComment Comment 212 | highlight default link clojureCommentTodo Todo 213 | 214 | highlight default link clojureError Error 215 | 216 | highlight default link clojureParen Delimiter 217 | 218 | let b:current_syntax = "clojure" 219 | 220 | let &cpo = s:cpo_sav 221 | unlet! s:cpo_sav 222 | 223 | " vim:sts=8:sw=8:ts=8:noet 224 | --------------------------------------------------------------------------------