From 9acb6d29a01b546cdc3b28e1b8727f2d039fdb55 Mon Sep 17 00:00:00 2001 From: Daniel Leong Date: Sun, 11 Nov 2018 21:46:17 -0500 Subject: [PATCH 1/5] Add some rough, preliminary support for clojurescript Highlights public functions and vars, but does not handle aliased refers or macros or... probably several others. It's a start, though! --- autoload/vim_clojure_highlight.cljs | 99 +++++++++++++++++++++++++++++ autoload/vim_clojure_highlight.vim | 50 +++++++++++++-- plugin/vim_clojure_highlight.vim | 1 + 3 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 autoload/vim_clojure_highlight.cljs diff --git a/autoload/vim_clojure_highlight.cljs b/autoload/vim_clojure_highlight.cljs new file mode 100644 index 0000000..5f6bb14 --- /dev/null +++ b/autoload/vim_clojure_highlight.cljs @@ -0,0 +1,99 @@ +(ns vim-clojure-highlight) + +;;;;;;;;;;;;;;;;;;;; Copied from vim-clojure-static.generate ;;;;;;;;;;;;;;;;;;; + +(defn- fn-var? [v] + (let [f @v] + (or (when (seq (:arglists (meta v))) + ; in clojurescript, all vars have :arglists, but it may be empty + true) + (fn? f) + #_(instance? MultiFn f)))) + +(def special-forms + "http://clojure.org/special_forms" + '#{def if do let quote var fn loop recur throw try catch finally + monitor-enter monitor-exit . new set!}) + +#_(def keyword-groups + "Special forms, constants, and every public var in clojure.core keyed by + syntax group name." + (let [exceptions '#{throw try catch finally} + builtins {"clojureConstant" '#{nil} + "clojureBoolean" '#{true false} + "clojureSpecial" (apply disj special-forms exceptions) + "clojureException" exceptions + "clojureCond" '#{case cond cond-> cond->> condp if-let + if-not if-some when when-first when-let + when-not when-some} + ;; Imperative looping constructs (not sequence functions) + "clojureRepeat" '#{doseq dotimes while}} + coresyms (clojure.set/difference (set (keys (ns-publics 'cljs.core))) + (set (mapcat peek builtins))) + group-preds [["clojureDefine" #(re-seq #"\Adef(?!ault)" (str %))] + ["clojureMacro" #(:macro (meta (ns-resolve 'clojure.core %)))] + ["clojureFunc" #(fn-var? (ns-resolve 'clojure.core %))] + ["clojureVariable" identity]]] + (first + (reduce + (fn [[m syms] [group pred]] + (let [group-syms (set (filterv pred syms))] + [(assoc m group group-syms) + (clojure.set/difference syms group-syms)])) + [builtins coresyms] group-preds)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +#_(def core-symbol->syntax-group + "A map of symbols from clojure.core mapped to syntax group name." + (reduce + (fn [m [group syms]] + (reduce + (fn [m sym] + (assoc m sym group)) + m syms)) + {} keyword-groups)) + +(defn clojure-core? + "Is this var from clojure.core?" + [var] + (= "cljs.core" (-> var meta :ns str))) + +(defn aliased-refers [ns] + [] + #_(mapcat + (fn [[alias alias-ns]] + (mapv #(vector (symbol (str alias \/ (first %))) (peek %)) + (ns-publics alias-ns))) + (ns-aliases ns))) + +(defn var-type [v] + (let [f @v + m (meta v)] + (cond ; (clojure-core? v) (core-symbol->syntax-group (:name m)) + (:macro m) "clojureMacro" + (fn-var? v) "clojureFunc" + :else "clojureVariable"))) + +(defn syntax-keyword-dictionary [ns-refs] + (->> ns-refs + (group-by (comp var-type peek)) + (mapv (fn [[type sym->var]] + (->> sym->var + (mapv (comp pr-str str first)) + (clojure.string/join \,) + ((fn [values] + (str "'" type "': [" values "]")))))) + (clojure.string/join \,))) + +(defn ns-syntax-command [ns publics & opts] + ; NOTE: (ns-publics) is a macro in clojurescript! + (let [{:keys [local-vars] :or {local-vars true}} (apply hash-map opts) + dict (syntax-keyword-dictionary + publics + #_(concat (ns-refers ns) + (aliased-refers ns) + #_(when local-vars (ns-publics ns))))] + ; NOTE: don't disable core keywords just yet + (str "let b:clojure_syntax_keywords = {" dict "}"))) + diff --git a/autoload/vim_clojure_highlight.vim b/autoload/vim_clojure_highlight.vim index 95df568..d4acac0 100644 --- a/autoload/vim_clojure_highlight.vim +++ b/autoload/vim_clojure_highlight.vim @@ -1,14 +1,51 @@ " vim-clojure-highlight +function! s:is_cljs() + return expand('%:e') == 'cljs' +endfunction + function! s:session_exists() return exists('g:fireplace_nrepl_sessions') && len(g:fireplace_nrepl_sessions) endfunction -function! s:require() - if fireplace#evalparse("(find-ns 'vim-clojure-highlight)") ==# '' - let buf = join(readfile(globpath(&runtimepath, 'autoload/vim_clojure_highlight.clj')), "\n") +function! s:evalparse(cmd) + if !s:is_cljs() + return fireplace#evalparse(a:cmd) + endif + + " NOTE: evalparse doesn't seem to work in cljs + " due to the {'session': 0} opts (weird). + let cmd = printf(g:fireplace#reader, a:cmd) + let resp = fireplace#session_eval(cmd) + if !empty(resp) + return eval(resp) + else + return '' + endif +endfunction + +function! s:require(force) + if !a:force && s:evalparse("(nil? (find-ns 'vim-clojure-highlight))") == 0 + return 0 + endif + + let ext = expand('%:e') + if ext != 'cljs' && ext != 'clj' + let ext = 'clj' + endif + let file = globpath(&runtimepath, 'autoload/vim_clojure_highlight.' . ext) + let buf = join(readfile(file), "\n") + if s:is_cljs() + call fireplace#session_eval('(ns vim-clojure-highlight) (do ' . buf . ')') + else call fireplace#session_eval('(do ' . buf . ')') endif + return 1 +endfunction + +" temporary, to force-reload the vim-clojure-highlight ns +function! vim_clojure_highlight#require() + return s:require(1) endfunction " Pass zero explicitly to prevent highlighting local vars @@ -16,12 +53,15 @@ function! vim_clojure_highlight#syntax_match_references(...) if !s:session_exists() | return | endif try - call s:require() + call s:require(0) let ns = "'" . fireplace#ns() let opts = (a:0 > 0 && !a:1) ? ' :local-vars false' : '' + if is_cljs() + let ns = ns . ' (ns-publics ' . ns . ')' + endif + execute s:evalparse("(vim-clojure-highlight/ns-syntax-command " . ns . opts . ")") - execute fireplace#evalparse("(vim-clojure-highlight/ns-syntax-command " . ns . opts . ")") let &syntax = &syntax catch /./ endtry diff --git a/plugin/vim_clojure_highlight.vim b/plugin/vim_clojure_highlight.vim index 589ba99..78480e4 100644 --- a/plugin/vim_clojure_highlight.vim +++ b/plugin/vim_clojure_highlight.vim @@ -28,6 +28,7 @@ endfunction augroup vim_clojure_highlight autocmd! autocmd BufRead *.clj ClojureHighlightReferences + " autocmd BufRead *.cljs silent! ClojureHighlightReferences augroup END command! -bar ToggleClojureHighlightReferences call s:toggle_clojure_highlight_references() From cc87aa35d51b28784b1d30e248fdeacc611de8e7 Mon Sep 17 00:00:00 2001 From: Daniel Leong Date: Mon, 12 Nov 2018 08:15:28 -0500 Subject: [PATCH 2/5] Fix typo --- autoload/vim_clojure_highlight.vim | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/autoload/vim_clojure_highlight.vim b/autoload/vim_clojure_highlight.vim index d4acac0..8e6069b 100644 --- a/autoload/vim_clojure_highlight.vim +++ b/autoload/vim_clojure_highlight.vim @@ -26,9 +26,11 @@ endfunction function! s:require(force) if !a:force && s:evalparse("(nil? (find-ns 'vim-clojure-highlight))") == 0 + echom "Loaded!" return 0 endif + echom "Loading vim-clojure-highlight" let ext = expand('%:e') if ext != 'cljs' && ext != 'clj' let ext = 'clj' @@ -53,13 +55,15 @@ function! vim_clojure_highlight#syntax_match_references(...) if !s:session_exists() | return | endif try + echom "require(0)" call s:require(0) let ns = "'" . fireplace#ns() let opts = (a:0 > 0 && !a:1) ? ' :local-vars false' : '' - if is_cljs() + if s:is_cljs() let ns = ns . ' (ns-publics ' . ns . ')' endif + echom "run highlight" execute s:evalparse("(vim-clojure-highlight/ns-syntax-command " . ns . opts . ")") let &syntax = &syntax From bfc3029e615bec7dde2284a84bd9272d4da49b2a Mon Sep 17 00:00:00 2001 From: Daniel Leong Date: Mon, 12 Nov 2018 08:24:26 -0500 Subject: [PATCH 3/5] Restore MultiFn support; clean up unusable bits from cljs util --- autoload/vim_clojure_highlight.cljs | 62 +++-------------------------- autoload/vim_clojure_highlight.vim | 4 -- 2 files changed, 5 insertions(+), 61 deletions(-) diff --git a/autoload/vim_clojure_highlight.cljs b/autoload/vim_clojure_highlight.cljs index 5f6bb14..99afb03 100644 --- a/autoload/vim_clojure_highlight.cljs +++ b/autoload/vim_clojure_highlight.cljs @@ -8,70 +8,19 @@ ; in clojurescript, all vars have :arglists, but it may be empty true) (fn? f) - #_(instance? MultiFn f)))) - -(def special-forms - "http://clojure.org/special_forms" - '#{def if do let quote var fn loop recur throw try catch finally - monitor-enter monitor-exit . new set!}) - -#_(def keyword-groups - "Special forms, constants, and every public var in clojure.core keyed by - syntax group name." - (let [exceptions '#{throw try catch finally} - builtins {"clojureConstant" '#{nil} - "clojureBoolean" '#{true false} - "clojureSpecial" (apply disj special-forms exceptions) - "clojureException" exceptions - "clojureCond" '#{case cond cond-> cond->> condp if-let - if-not if-some when when-first when-let - when-not when-some} - ;; Imperative looping constructs (not sequence functions) - "clojureRepeat" '#{doseq dotimes while}} - coresyms (clojure.set/difference (set (keys (ns-publics 'cljs.core))) - (set (mapcat peek builtins))) - group-preds [["clojureDefine" #(re-seq #"\Adef(?!ault)" (str %))] - ["clojureMacro" #(:macro (meta (ns-resolve 'clojure.core %)))] - ["clojureFunc" #(fn-var? (ns-resolve 'clojure.core %))] - ["clojureVariable" identity]]] - (first - (reduce - (fn [[m syms] [group pred]] - (let [group-syms (set (filterv pred syms))] - [(assoc m group group-syms) - (clojure.set/difference syms group-syms)])) - [builtins coresyms] group-preds)))) + (instance? MultiFn f)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -#_(def core-symbol->syntax-group - "A map of symbols from clojure.core mapped to syntax group name." - (reduce - (fn [m [group syms]] - (reduce - (fn [m sym] - (assoc m sym group)) - m syms)) - {} keyword-groups)) - (defn clojure-core? "Is this var from clojure.core?" [var] (= "cljs.core" (-> var meta :ns str))) -(defn aliased-refers [ns] - [] - #_(mapcat - (fn [[alias alias-ns]] - (mapv #(vector (symbol (str alias \/ (first %))) (peek %)) - (ns-publics alias-ns))) - (ns-aliases ns))) - (defn var-type [v] (let [f @v m (meta v)] - (cond ; (clojure-core? v) (core-symbol->syntax-group (:name m)) - (:macro m) "clojureMacro" + (cond (:macro m) "clojureMacro" ;; NOTE: this doesn't actually work, sadly (fn-var? v) "clojureFunc" :else "clojureVariable"))) @@ -90,10 +39,9 @@ ; NOTE: (ns-publics) is a macro in clojurescript! (let [{:keys [local-vars] :or {local-vars true}} (apply hash-map opts) dict (syntax-keyword-dictionary - publics - #_(concat (ns-refers ns) - (aliased-refers ns) - #_(when local-vars (ns-publics ns))))] + ; NOTE: ns-refers and ns-aliases don't exist in clojurescript + (when local-vars + publics))] ; NOTE: don't disable core keywords just yet (str "let b:clojure_syntax_keywords = {" dict "}"))) diff --git a/autoload/vim_clojure_highlight.vim b/autoload/vim_clojure_highlight.vim index 8e6069b..6e64ce6 100644 --- a/autoload/vim_clojure_highlight.vim +++ b/autoload/vim_clojure_highlight.vim @@ -26,11 +26,9 @@ endfunction function! s:require(force) if !a:force && s:evalparse("(nil? (find-ns 'vim-clojure-highlight))") == 0 - echom "Loaded!" return 0 endif - echom "Loading vim-clojure-highlight" let ext = expand('%:e') if ext != 'cljs' && ext != 'clj' let ext = 'clj' @@ -55,7 +53,6 @@ function! vim_clojure_highlight#syntax_match_references(...) if !s:session_exists() | return | endif try - echom "require(0)" call s:require(0) let ns = "'" . fireplace#ns() @@ -63,7 +60,6 @@ function! vim_clojure_highlight#syntax_match_references(...) if s:is_cljs() let ns = ns . ' (ns-publics ' . ns . ')' endif - echom "run highlight" execute s:evalparse("(vim-clojure-highlight/ns-syntax-command " . ns . opts . ")") let &syntax = &syntax From 4c8f6ac2c86027c6c71ff294123385482182fa8c Mon Sep 17 00:00:00 2001 From: Daniel Leong Date: Sat, 9 Feb 2019 17:47:11 -0500 Subject: [PATCH 4/5] Fix errors not being completely suppressed --- autoload/vim_clojure_highlight.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/vim_clojure_highlight.vim b/autoload/vim_clojure_highlight.vim index 6e64ce6..bc0bdd6 100644 --- a/autoload/vim_clojure_highlight.vim +++ b/autoload/vim_clojure_highlight.vim @@ -63,7 +63,7 @@ function! vim_clojure_highlight#syntax_match_references(...) execute s:evalparse("(vim-clojure-highlight/ns-syntax-command " . ns . opts . ")") let &syntax = &syntax - catch /./ + catch /.*/ endtry endfunction From 5d6724c391a979d3823f592a712feef8be49330e Mon Sep 17 00:00:00 2001 From: Daniel Leong Date: Wed, 12 Jun 2019 10:34:40 -0400 Subject: [PATCH 5/5] Fix cljs highlighting disabled --- plugin/vim_clojure_highlight.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/vim_clojure_highlight.vim b/plugin/vim_clojure_highlight.vim index 78480e4..7baa5f6 100644 --- a/plugin/vim_clojure_highlight.vim +++ b/plugin/vim_clojure_highlight.vim @@ -28,7 +28,7 @@ endfunction augroup vim_clojure_highlight autocmd! autocmd BufRead *.clj ClojureHighlightReferences - " autocmd BufRead *.cljs silent! ClojureHighlightReferences + autocmd BufRead *.cljs silent! ClojureHighlightReferences augroup END command! -bar ToggleClojureHighlightReferences call s:toggle_clojure_highlight_references()