diff options
author | thing1 <thing1@seacrossedlovers.xyz> | 2025-01-28 09:14:32 +0000 |
---|---|---|
committer | thing1 <thing1@seacrossedlovers.xyz> | 2025-01-28 09:14:32 +0000 |
commit | 904cec3c4a329cf89fc3219d359239910d61f3f6 (patch) | |
tree | 8d113899921dfbaca0e77c49ab5fc827362d1091 /autoload/filetype |
Diffstat (limited to 'autoload/filetype')
111 files changed, 12025 insertions, 0 deletions
diff --git a/autoload/filetype/apl.kak b/autoload/filetype/apl.kak new file mode 100644 index 0000000..ff3f2f0 --- /dev/null +++ b/autoload/filetype/apl.kak @@ -0,0 +1,86 @@ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*\.(apl|aplf|aplo|apln|aplc|apli|dyalog) %{ + set-option buffer filetype apl + + set-option buffer matching_pairs ( ) { } [ ] +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=apl %| + require-module apl + + hook window InsertChar \n -group apl-insert apl-insert-on-new-line + hook window InsertChar \n -group apl-indent apl-indent-on-new-line + hook window InsertChar [}⟩\]] -group apl-indent apl-indent-on-closing + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window apl-.+ } +| + +hook -group apl-highlight global WinSetOption filetype=apl %{ + add-highlighter window/apl ref apl + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/apl } +} + +provide-module apl %¹ + +# Highlighters & Completion +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/apl regions +add-highlighter shared/apl/code default-region group +add-highlighter shared/apl/comment region "⍝" "$" fill comment +add-highlighter shared/apl/string region "'" "'" fill string + +add-highlighter shared/apl/code/ regex "[{}]" 0:meta +add-highlighter shared/apl/code/ regex "⋄" 0:meta +add-highlighter shared/apl/code/ regex "[\[\]]" 0:magenta +add-highlighter shared/apl/code/ regex "[()]" 0:bright-black +add-highlighter shared/apl/code/ regex "[:;?]" 0:bright-black +add-highlighter shared/apl/code/ regex "[←→]" 0:normal +# Number +add-highlighter shared/apl/code/ regex "¯?[0-9][¯0-9A-Za-z]*(?:\.[¯0-9Ee][¯0-9A-Za-z]*)*|¯?\.[0-9Ee][¯0-9A-Za-z]*" 0:value +add-highlighter shared/apl/code/ regex "\." 0:normal +add-highlighter shared/apl/code/ regex "[⍺⍶⍵⍹χ∇]" 0:blue # arguments +# function +add-highlighter shared/apl/code/ regex "[+\-×÷⌈⌊∣|⍳?*⍟○!⌹<≤=>≥≠≡≢∊⍷∪∩~∨∧⍱⍲⍴,⍪⌽⊖⍉↑↓⊂⊃⌷⍋⍒⊤⊥⍕⍎⊣⊢⍁⍂≈⌸⍯↗⊆⊇⍸√⌾…⍮]" 0:green # function +# operator +add-highlighter shared/apl/code/ regex "[\.\\/⌿⍀¨⍣⍨⍠⍤∘⌸&⌶@⌺⍥⍛⍢]" 0:magenta +# system +add-highlighter shared/apl/code/ regex "⎕[A-Z_a-zÀ-ÖØ-Ýßà-öø-üþ∆⍙Ⓐ-Ⓩ][A-Z_a-zÀ-ÖØ-Ýßà-öø-üþ∆⍙Ⓐ-Ⓩ¯0-9]*" 0:yellow +add-highlighter shared/apl/code/ regex "\n^\s*\n(\n\t[A-Z_a-zÀ-ÖØ-Ýßà-öø-üþ∆⍙Ⓐ-Ⓩ]\n\t[A-Z_a-zÀ-ÖØ-Ýßà-öø-üþ∆⍙Ⓐ-Ⓩ¯0-9]*\n)\n(:)" 0:meta + +declare-user-mode apl +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden apl-insert-on-new-line %{ + evaluate-commands -draft -itersel %[ + # copy # comments prefix + try %{ execute-keys -draft <semicolon><c-s>k<a-x> s ^\h*\K#+\h* <ret> y<c-o>P<esc> } + ] +} + +define-command -hidden apl-indent-on-new-line %` + evaluate-commands -draft -itersel %_ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # indent after lines ending with { [ + try %( execute-keys -draft k<a-x> <a-k> [{\[]\h*$ <ret> j<a-gt> ) + # cleanup trailing white spaces on the previous line + try %{ execute-keys -draft k<a-x> s \h+$ <ret>d } + _ +` + +define-command -hidden apl-indent-on-closing %` + evaluate-commands -draft -itersel %_ + # align to opening bracket + try %( execute-keys -draft <a-h> <a-k> ^\h*[}\]]$ <ret> h m <a-S> 1<a-&> ) + _ +` + +¹ diff --git a/autoload/filetype/arch-linux.kak b/autoload/filetype/arch-linux.kak new file mode 100644 index 0000000..08135a7 --- /dev/null +++ b/autoload/filetype/arch-linux.kak @@ -0,0 +1,4 @@ +# package build description file +hook global BufCreate (.*/)?PKGBUILD %{ + set-option buffer filetype sh +} diff --git a/autoload/filetype/asciidoc.kak b/autoload/filetype/asciidoc.kak new file mode 100644 index 0000000..453ffd4 --- /dev/null +++ b/autoload/filetype/asciidoc.kak @@ -0,0 +1,90 @@ +# http://asciidoc.org/ +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .+\.(a(scii)?doc|asc) %{ + set-option buffer filetype asciidoc +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook -group asciidoc-highlight global WinSetOption filetype=asciidoc %{ + require-module asciidoc + + add-highlighter window/asciidoc ref asciidoc + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/asciidoc } +} + +provide-module asciidoc %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/asciidoc group + +# Titles and headers (multi-line style) +add-highlighter shared/asciidoc/ regex (\A|\n\n)[^\n]+\n={2,}\h*$ 0:title +add-highlighter shared/asciidoc/ regex (\A|\n\n)[^\n]+\n-{2,}\h*$ 0:header +add-highlighter shared/asciidoc/ regex (\A|\n\n)[^\n]+\n~{2,}\h*$ 0:header +add-highlighter shared/asciidoc/ regex (\A|\n\n)[^\n]+\n\^{2,}\h*$ 0:header + +# Titles and headerss (one-line style) +add-highlighter shared/asciidoc/ regex (\A|\n\n)=\h+[^\n]+$ 0:title +add-highlighter shared/asciidoc/ regex (\A|\n\n)={2,}\h+[^\n]+$ 0:header + +# Comments +add-highlighter shared/asciidoc/ regex ^//(?:[^\n/][^\n]*|)$ 0:comment +add-highlighter shared/asciidoc/ regex ^(/{4,}).*?\n(/{4,})$ 0:comment + +# List titles +add-highlighter shared/asciidoc/ regex ^\.[^\h\W][^\n]*$ 0:title + +# Bulleted lists +add-highlighter shared/asciidoc/ regex ^\h*(?<bullet>[-\*])\h+[^\n]+$ 0:list bullet:bullet +add-highlighter shared/asciidoc/ regex ^\h*(?<bullet>[-\*]+)\h+[^\n]+(\n\h+[^-\*\n]*)?$ 0:list bullet:bullet + +# Delimited blocks +# https://docs.asciidoctor.org/asciidoc/latest/blocks/delimited/ +add-highlighter shared/asciidoc/ regex ^(-{4,})\n[^\n\h].*?\n(-{4,})$ 0:block +add-highlighter shared/asciidoc/ regex ^(={4,})\n[^\n\h].*?\n(={4,})$ 0:block +add-highlighter shared/asciidoc/ regex ^(~{4,})\n[^\n\h].*?\n(~{4,})$ 0:block +add-highlighter shared/asciidoc/ regex ^(\*{4,})\n[^\n\h].*?\n(\*{4,})$ 0:block + +# Monospaced text +add-highlighter shared/asciidoc/ regex \B(?:\+[^\n]+?\+|`[^\n]+?`)\B 0:mono + +# Bolded text +add-highlighter shared/asciidoc/ regex \s\*[^\n\*]+\*\B 0:+b +add-highlighter shared/asciidoc/ regex \h\*[^\n\*]+\*\B 0:+b +add-highlighter shared/asciidoc/ regex \*{2}(?!\h)[^\n\*]+\*{2} 0:+b +add-highlighter shared/asciidoc/ regex \h\*{2}[^\n\*]+\*{2} 0:+b + +# Italicized text +# (these are simpler since they aren't able to _also_ be bullet characters.) +add-highlighter shared/asciidoc/ regex \b_[^\n]+?_\b 0:+i +add-highlighter shared/asciidoc/ regex __[^\n]+?__ 0:+i + +# Attributes +add-highlighter shared/asciidoc/ regex ^:(?:(?<neg>!?)[-\w]+|[-\w]+(?<neg>!?)): 0:meta neg:operator +add-highlighter shared/asciidoc/ regex [^\\](\{[-\w]+\})[^\\]? 1:meta + +# Options +add-highlighter shared/asciidoc/ regex ^\[[^\n]+\]$ 0:operator + +# Admonition pargraphs +add-highlighter shared/asciidoc/ regex ^(NOTE|TIP|IMPORTANT|CAUTION|WARNING): 0:block +add-highlighter shared/asciidoc/ regex ^\[(NOTE|TIP|IMPORTANT|CAUTION|WARNING)\]$ 0:block + +# Links, inline macros +add-highlighter shared/asciidoc/ regex \b((?:https?|ftp|irc://)[^\h\[]+)\[([^\n]*)?\] 1:link 2:+i +add-highlighter shared/asciidoc/ regex (link|mailto):([^\n]+)(?:\[([^\n]*)\]) 1:keyword 2:link 3:+i +add-highlighter shared/asciidoc/ regex (xref):([^\n]+)(?:\[([^\n]*)\]) 1:keyword 2:meta 3:+i +add-highlighter shared/asciidoc/ regex (<<([^\n><]+)>>) 1:link 2:meta + +# Commands +# ‾‾‾‾‾‾‾‾ + +} diff --git a/autoload/filetype/awk.kak b/autoload/filetype/awk.kak new file mode 100644 index 0000000..536e352 --- /dev/null +++ b/autoload/filetype/awk.kak @@ -0,0 +1,88 @@ +# Detection +# --------- + +hook global BufCreate .*\.awk %{ + set-option buffer filetype awk +} + +# Initialization +# -------------- + +hook global WinSetOption filetype=awk %{ + require-module awk + + hook window InsertChar \n -group awk-indent awk-indent-on-new-line + hook window ModeChange pop:insert:.* -group awk-trim-indent awk-trim-indent + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window awk-.+ } +} + +hook -group awk-highlight global WinSetOption filetype=awk %{ + add-highlighter window/awk ref awk + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/awk } +} + +provide-module awk %@ + +# Highlighters +# ------------ + +add-highlighter shared/awk regions +add-highlighter shared/awk/code default-region group +add-highlighter shared/awk/comment region '#' '$' fill comment +add-highlighter shared/awk/string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/awk/regex region (\A|[^\s\w)\]+-]|\bcase)\s*\K/ (?<!\\)(\\\\)*/ fill attribute + +add-highlighter shared/awk/code/ regex (\.\d+|\b\d+\.?\d*)([eE][+-]?\d+)?\b 0:value # Decimal/octal/scientific +add-highlighter shared/awk/code/ regex \b0[xX][\da-fA-F]+\b 0:value # Hexadecimal +add-highlighter shared/awk/code/ regex \$|\+|-|\*|/|%|\^|=|&&|\||!|<|>|\?|~ 0:operator + +evaluate-commands %sh{ + # Grammar + patterns="BEGIN END BEGINFILE ENDFILE" + variables="BINMODE CONVFMT FIELDWIDTHS FPAT FS IGNORECASE LINT OFMT OFS + ORS PREC ROUNDMODE RS SUBSEP TEXTDOMAIN ARGC ARGV ARGIND ENVIRON + ERRNO FILENAME FNR NF FUNCTAB NR PROCINFO RLENGTH RSTART RT SYMTAB" + keywords="break continue delete exit function getline next print printf + return switch nextfile func if else while for do" + functions="atan2 cos exp int intdiv log rand sin sqrt srand asort asort1 + gensub gsub index length match patsplit split sprintf strtonum sub + substr tolower toupper close fflush system mktime strftime systime + and compl lshift or rshift xor isarray typeof bindtextdomain dcgettext + dcngetext" + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # Add the language's grammar to the static completion list + printf %s\\n "hook global WinSetOption filetype=awk %{ + set-option window static_words $(join "${patterns} ${variables} ${keywords} ${functions}" ' ') + }" + + # Highlight keywords + printf %s\\n "add-highlighter shared/awk/code/ regex \b($(join "${patterns}" '|'))\b 0:type" + printf %s\\n "add-highlighter shared/awk/code/ regex \b($(join "${variables}" '|'))\b 0:meta" + printf %s\\n "add-highlighter shared/awk/code/ regex \b($(join "${keywords}" '|'))\b 0:keyword" + printf %s\\n "add-highlighter shared/awk/code/ regex \b($(join "${functions}" '|'))\b 0:function" +} + +# Commands +# -------- + +define-command -hidden awk-indent-on-new-line %[ + evaluate-commands -draft -itersel %[ + # preserve previous line indent + try %[ execute-keys -draft <semicolon> K <a-&> ] + # cleanup trailing whitespaces from previous line + try %[ execute-keys -draft k x s \h+$ <ret> d ] + # indent after line ending in opening curly brace + try %[ execute-keys -draft kx <a-k>\{\h*(#.*)?$<ret> j<a-gt> ] + # deindent closing brace when after cursor + try %[ execute-keys -draft x <a-k> ^\h*\} <ret> gh / \} <ret> m <a-S> 1<a-&> ] + ] +] + +define-command -hidden awk-trim-indent %{ + try %{ execute-keys -draft <semicolon> x s ^\h+$ <ret> d } +} + +@ diff --git a/autoload/filetype/c-family.kak b/autoload/filetype/c-family.kak new file mode 100644 index 0000000..0677b11 --- /dev/null +++ b/autoload/filetype/c-family.kak @@ -0,0 +1,476 @@ +# Detection +hook global BufCreate .*\.(cc|cpp|cxx|C|hh|hpp|hxx|H)$ %{ + set-option buffer filetype cpp +} + +hook global BufSetOption filetype=c\+\+ %{ + hook -once buffer NormalIdle '' "set-option buffer filetype cpp" +} + +hook global BufCreate .*\.c$ %{ + set-option buffer filetype c +} + +hook global BufCreate .*\.h$ %{ + try %{ + execute-keys -draft %{%s\b::\b|\btemplate\h*<lt>|\bclass\h+\w+|\b(typename|namespace)\b|\b(public|private|protected)\h*:<ret>} + set-option buffer filetype cpp + } catch %{ + set-option buffer filetype c + } +} + +hook global BufCreate .*\.m %{ + set-option buffer filetype objc +} + +hook global WinSetOption filetype=(c|cpp|objc) %[ + require-module c-family + + evaluate-commands "set-option window static_words %%opt{%val{hook_param_capture_1}_static_words}" + + hook -group "%val{hook_param_capture_1}-trim-indent" window ModeChange pop:insert:.* c-family-trim-indent + hook -group "%val{hook_param_capture_1}-insert" window InsertChar \n c-family-insert-on-newline + hook -group "%val{hook_param_capture_1}-indent" window InsertChar \n c-family-indent-on-newline + hook -group "%val{hook_param_capture_1}-indent" window InsertChar \{ c-family-indent-on-opening-curly-brace + hook -group "%val{hook_param_capture_1}-indent" window InsertChar \} c-family-indent-on-closing-curly-brace + hook -group "%val{hook_param_capture_1}-insert" window InsertChar \} c-family-insert-on-closing-curly-brace + + alias window alt "%val{hook_param_capture_1}-alternative-file" + + hook -once -always window WinSetOption filetype=.* " + remove-hooks window %val{hook_param_capture_1}-.+ + unalias window alt %val{hook_param_capture_1}-alternative-file + " +] + +hook -group c-highlight global WinSetOption filetype=c %{ + add-highlighter window/c ref c + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/c } +} + +hook -group cpp-highlight global WinSetOption filetype=cpp %{ + add-highlighter window/cpp ref cpp + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/cpp } +} + +hook -group objc-highlight global WinSetOption filetype=objc %{ + add-highlighter window/objc ref objc + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/objc } +} + + +provide-module c-family %§ + +define-command -hidden c-family-trim-indent %{ + # remove the line if it's empty when leaving the insert mode + try %{ execute-keys -draft x 1s^(\h+)$<ret> d } +} + +define-command -hidden c-family-indent-on-newline %< evaluate-commands -draft -itersel %< + execute-keys <semicolon> + try %< + # if previous line is part of a comment, do nothing + execute-keys -draft <a-?>/\*<ret> <a-K>^\h*[^/*\h]<ret> + > catch %< + # else if previous line closed a paren (possibly followed by words and a comment), + # copy indent of the opening paren line + execute-keys -draft kx 1s(\))(\h+\w+)*\h*(\;\h*)?(?://[^\n]+)?\n\z<ret> m<a-semicolon>J <a-S> 1<a-&> + > catch %< + # else indent new lines with the same level as the previous one + execute-keys -draft K <a-&> + > + # remove previous empty lines resulting from the automatic indent + try %< execute-keys -draft k x <a-k>^\h+$<ret> Hd > + # indent after an opening brace or parenthesis at end of line + try %< execute-keys -draft k x <a-k>[{(]\h*$<ret> j <a-gt> > + # indent after a label + try %< execute-keys -draft k x s[a-zA-Z0-9_-]+:\h*$<ret> j <a-gt> > + # indent after a statement not followed by an opening brace + try %< execute-keys -draft k x s\)\h*(?://[^\n]+)?\n\z<ret> \ + <a-semicolon>mB <a-k>\A\b(if|for|while)\b<ret> <a-semicolon>j <a-gt> > + try %< execute-keys -draft k x s \belse\b\h*(?://[^\n]+)?\n\z<ret> \ + j <a-gt> > + # deindent after a single line statement end + try %< execute-keys -draft K x <a-k>\;\h*(//[^\n]+)?$<ret> \ + K x s\)(\h+\w+)*\h*(//[^\n]+)?\n([^\n]*\n){2}\z<ret> \ + MB <a-k>\A\b(if|for|while)\b<ret> <a-S>1<a-&> > + try %< execute-keys -draft K x <a-k>\;\h*(//[^\n]+)?$<ret> \ + K x s \belse\b\h*(?://[^\n]+)?\n([^\n]*\n){2}\z<ret> \ + <a-S>1<a-&> > + # deindent closing brace(s) when after cursor + try %< execute-keys -draft x <a-k> ^\h*[})] <ret> gh / [})] <esc> m <a-S> 1<a-&> > + # align to the opening parenthesis or opening brace (whichever is first) + # on a previous line if its followed by text on the same line + try %< evaluate-commands -draft %< + # Go to opening parenthesis and opening brace, then select the most nested one + try %< execute-keys [c [({],[)}] <ret> > + # Validate selection and get first and last char + execute-keys <a-k>\A[{(](\h*\S+)+\n<ret> <a-K>"(([^"]*"){2})*<ret> <a-K>'(([^']*'){2})*<ret> <a-:><a-semicolon>L <a-S> + # Remove possibly incorrect indent from new line which was copied from previous line + try %< execute-keys -draft , <a-h> s\h+<ret> d > + # Now indent and align that new line with the opening parenthesis/brace + execute-keys 1<a-&> & + > > +> > + +define-command -hidden c-family-indent-on-opening-curly-brace %[ + # align indent with opening paren when { is entered on a new line after the closing paren + try %[ execute-keys -draft -itersel h<a-F>)M <a-k> \A\(.*\)\h*\n\h*\{\z <ret> <a-S> 1<a-&> ] + # align indent with opening paren when { is entered on a new line after the else + try %[ execute-keys -draft -itersel hK x s \belse\b\h*(?://[^\n]+)?\n\h*\{<ret> <a-S> 1<a-&> ] +] + +define-command -hidden c-family-indent-on-closing-curly-brace %[ + evaluate-commands -draft -itersel -verbatim try %[ + # check if alone on the line and select to opening curly brace + execute-keys <a-h><a-:><a-k>^\h+\}$<ret>hm + try %[ + # in case open curly brace follows a closing paren possibly with qualifiers, extend to opening paren + execute-keys -draft <a-f>) <a-k> \A\)(\h+\w+)*\h*\{\z <ret> + execute-keys <a-F>)M + ] + # align to selection start + execute-keys <a-S>1<a-&> + ] +] + +define-command -hidden c-family-insert-on-closing-curly-brace %[ + # add a semicolon after a closing brace if part of a class, union or struct definition + evaluate-commands -itersel -draft -verbatim try %[ + execute-keys -draft hmh <a-?>\b(class|struct|union|enum)\b<ret> <a-K>\{<ret> <a-K>\)(\s+\w+)*\s*\z<ret> + execute-keys -draft ';i;<esc>' + ] +] + +define-command -hidden c-family-insert-on-newline %[ evaluate-commands -itersel -draft %[ + execute-keys <semicolon> + try %[ + evaluate-commands -draft -save-regs '/"' %[ + # copy the commenting prefix + execute-keys -save-regs '' k x1s^\h*(//+\h*)<ret> y + try %[ + # if the previous comment isn't empty, create a new one + execute-keys x<a-K>^\h*//+\h*$<ret> jxs^\h*<ret>P + ] catch %[ + # if there is no text in the previous comment, remove it completely + execute-keys d + ] + ] + + # trim trailing whitespace on the previous line + try %[ execute-keys -draft k x s\h+$<ret> d ] + ] + try %[ + # if the previous line isn't within a comment scope, break + execute-keys -draft kx <a-k>^(\h*/\*|\h+\*(?!/))<ret> + + # find comment opening, validate it was not closed, and check its using star prefixes + execute-keys -draft <a-?>/\*<ret><a-H> <a-K>\*/<ret> <a-k>\A\h*/\*([^\n]*\n\h*\*)*[^\n]*\n\h*.\z<ret> + + try %[ + # if the previous line is opening the comment, insert star preceeded by space + execute-keys -draft kx<a-k>^\h*/\*<ret> + execute-keys -draft i*<space><esc> + ] catch %[ + try %[ + # if the next line is a comment line insert a star + execute-keys -draft jx<a-k>^\h+\*<ret> + execute-keys -draft i*<space><esc> + ] catch %[ + try %[ + # if the previous line is an empty comment line, close the comment scope + execute-keys -draft kx<a-k>^\h+\*\h+$<ret> x1s\*(\h*)<ret>c/<esc> + ] catch %[ + # if the previous line is a non-empty comment line, add a star + execute-keys -draft i*<space><esc> + ] + ] + ] + + # trim trailing whitespace on the previous line + try %[ execute-keys -draft k x s\h+$<ret> d ] + # align the new star with the previous one + execute-keys Kx1s^[^*]*(\*)<ret>& + ] +] ] + +# Regions definition are the same between c++ and objective-c +evaluate-commands %sh{ + for ft in c cpp objc; do + if [ "${ft}" = "objc" ]; then + maybe_at='@?' + else + maybe_at='' + fi + + cat <<-EOF + add-highlighter shared/$ft regions + add-highlighter shared/$ft/code default-region group + add-highlighter shared/$ft/string region %{$maybe_at(?<!')(?<!'\\\\)"} %{(?<!\\\\)(?:\\\\\\\\)*"} fill string + add-highlighter shared/$ft/documentation_comment region /\*(\*[^/]|!) \*/ fill documentation + add-highlighter shared/$ft/line_documentation_comment region //[/!] $ fill documentation + add-highlighter shared/$ft/comment region /\\* \\*/ fill comment + add-highlighter shared/$ft/line_comment region // (?<!\\\\)(?=\\n) fill comment + add-highlighter shared/$ft/disabled region -recurse "#\\h*if(?:def)?" ^\\h*?#\\h*if\\h+(?:0|FALSE)\\b "#\\h*(?:else|elif|endif)" fill comment + add-highlighter shared/$ft/ifdef region %{^\\h*\\K#\\h*(?:define|elif|if)(?=\\h)} %{(?<!\\\\)(?=\\s)|(?=//)} fill meta + add-highlighter shared/$ft/macro region %{^\\h*#} %{(?<!\\\\)(?=\\n)|(?=//)} group + add-highlighter shared/$ft/macro/ regex ^\\h*(#\\h*\\S*) 1:meta + add-highlighter shared/$ft/macro/ regex ^\\h*#\\h*include\\h+(<[^>]*>|"(?:[^"\\\\]|\\\\.)*") 1:module + add-highlighter shared/$ft/macro/ regex /\\*.*?\\*/ 0:comment + EOF + done +} + +# c specific +add-highlighter shared/c/code/numbers regex %{\b-?(0[xX][0-9a-fA-F]+|\d+)([uU][lL]{0,2}|[lL]{1,2}[uU]?|[fFdDiI]|([eE][-+]?\d+))?|'((\\.)?|[^'\\])'} 0:value +evaluate-commands %sh{ + # Grammar + keywords='asm break case continue default do else for goto if return + sizeof switch while offsetof alignas alignof' + attributes='auto atomic const enum extern inline register restrict static + struct typedef union volatile thread_local' + types='char double float int long short signed unsigned void + complex imaginary + fenv_t fexcept_t + imaxdiv_t + lconv + float_t double_t + jmp_buf + sig_atomic_t + va_list + memory_order atomic_flag atomic_bool atomic_char atomic_schar atomic_uchar atomic_wchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_llong atomic_ulong atomic_ullong atomic_char16_t atomic_char32_t atomic_intptr_t atomic_intmax_t atomic_int8_t atomic_int16_t atomic_int32_t atomic_int64_t atomic_int_least8_t atomic_int_least16_t atomic_int_least32_t atomic_int_least64_t atomic_int_fast8_t atomic_int_fast16_t atomic_int_fast32_t atomic_int_fast64_t atomic_uintptr_t atomic_uintmax_t atomic_uint8_t atomic_uint16_t atomic_uint32_t atomic_uint64_t atomic_uint_least8_t atomic_uint_least16_t atomic_uint_least32_t atomic_uint_least64_t atomic_uint_fast8_t atomic_uint_fast16_t atomic_uint_fast32_t atomic_uint_fast64_t atomic_size_t atomic_ptrdiff_t + bool + ptrdiff_t size_t max_align_t wchar_t + intptr_t intmax_t int8_t int16_t int32_t int64_t int_least8_t int_least16_t int_least32_t int_least64_t int_fast8_t int_fast16_t int_fast32_t int_fast64_t uintptr_t uintmax_t uint8_t uint16_t uint32_t uint64_t uint_least8_t uint_least16_t uint_least32_t uint_least64_t uint_fast8_t uint_fast16_t uint_fast32_t uint_fast64_t + FILE fpos_t + div_t ldiv_t lldiv_t + cnd_t thrd_t thrd_start_t tss_t tss_dtor_t mtx_t once_flag + clock_t time_t timespec tm + mbstate_t wint_t + wctrans_t wctype_t + char16_t char32_t + ssize_t gid_t uid_t off_t off64_t useconds_t pid_t socklen_t' + + macros='assert static_assert NDEBUG + I + EDOM EILSEQ ERANGE errno + FE_DIVBYZERO FE_INEXACT FE_INVALID FE_OVERFLOW FE_UNDERFLOW FE_ALL_EXCEPT FE_DOWNWARD FE_TONEAREST FE_TOWARDZERO FE_UPWARD FE_DFL_ENV + DECIMAL_DIG FLT_ROUNDS FLT_EVAL_METHOD FLT_RADIX FLT_DIG FLT_MANT_DIG FLT_DECIMAL_DIG FLT_MIN_EXP FLT_MIN_10_EXP FLT_MAX_EXP FLT_MAX FLT_EPSILON FLT_TRUE_MIN FLT_HAS_SUBNORM DBL_DIG DBL_MANT_DIG DBL_DECIMAL_DIG DBL_MIN_EXP DBL_MIN_10_EXP DBL_MAX_EXP DBL_MAX DBL_EPSILON DBL_TRUE_MIN DBL_HAS_SUBNORM LDBL_DIG LDBL_MANT_DIG LDBL_DECIMAL_DIG LDBL_MIN_EXP LDBL_MIN_10_EXP LDBL_MAX_EXP LDBL_MAX LDBL_EPSILON LDBL_TRUE_MIN LDBL_HAS_SUBNORM + PRIdMAX PRIdPTR PRId8 PRId16 PRId32 PRId64 PRIdLEAST8 PRIdLEAST16 PRIdLEAST32 PRIdLEAST64 PRIdFAST8 PRIdFAST16 PRIdFAST32 PRIdFAST64 PRIiMAX PRIiPTR PRIi8 PRIi16 PRIi32 PRIi64 PRIiLEAST8 PRIiLEAST16 PRIiLEAST32 PRIiLEAST64 PRIiFAST8 PRIiFAST16 PRIiFAST32 PRIiFAST64 PRIoMAX PRIoPTR PRIo8 PRIo16 PRIo32 PRIo64 PRIoLEAST8 PRIoLEAST16 PRIoLEAST32 PRIoLEAST64 PRIoFAST8 PRIoFAST16 PRIoFAST32 PRIoFAST64 PRIuMAX PRIuPTR PRIu8 PRIu16 PRIu32 PRIu64 PRIuLEAST8 PRIuLEAST16 PRIuLEAST32 PRIuLEAST64 PRIuFAST8 PRIuFAST16 PRIuFAST32 PRIuFAST64 PRIxMAX PRIxPTR PRIx8 PRIx16 PRIx32 PRIx64 PRIxLEAST8 PRIxLEAST16 PRIxLEAST32 PRIxLEAST64 PRIxFAST8 PRIxFAST16 PRIxFAST32 PRIxFAST64 PRIXMAX PRIXPTR PRIX8 PRIX16 PRIX32 PRIX64 PRIXLEAST8 PRIXLEAST16 PRIXLEAST32 PRIXLEAST64 PRIXFAST8 PRIXFAST16 PRIXFAST32 PRIXFAST64 SCNdMAX SCNdPTR SCNd8 SCNd16 SCNd32 SCNd64 SCNdLEAST8 SCNdLEAST16 SCNdLEAST32 SCNdLEAST64 SCNdFAST8 SCNdFAST16 SCNdFAST32 SCNdFAST64 SCNiMAX SCNiPTR SCNi8 SCNi16 SCNi32 SCNi64 SCNiLEAST8 SCNiLEAST16 SCNiLEAST32 SCNiLEAST64 SCNiFAST8 SCNiFAST16 SCNiFAST32 SCNiFAST64 SCNoMAX SCNoPTR SCNo8 SCNo16 SCNo32 SCNo64 SCNoLEAST8 SCNoLEAST16 SCNoLEAST32 SCNoLEAST64 SCNoFAST8 SCNoFAST16 SCNoFAST32 SCNoFAST64 SCNuMAX SCNuPTR SCNu8 SCNu16 SCNu32 SCNu64 SCNuLEAST8 SCNuLEAST16 SCNuLEAST32 SCNuLEAST64 SCNuFAST8 SCNuFAST16 SCNuFAST32 SCNuFAST64 SCNxMAX SCNxPTR SCNx8 SCNx16 SCNx32 SCNx64 SCNxLEAST8 SCNxLEAST16 SCNxLEAST32 SCNxLEAST64 SCNxFAST8 SCNxFAST16 SCNxFAST32 SCNxFAST64 + and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq + CHAR_MIN CHAR_MAX SCHAR_MIN SCHAR_MAX WCHAR_MIN WCHAR_MAX SHRT_MIN SHRT_MAX INT_MIN INT_MAX LONG_MIN LONG_MAX LLONG_MIN LLONG_MAX MB_LEN_MAX UCHAR_MAX USHRT_MAX UINT_MAX ULONG_MAX ULLONG_MAX CHAR_BIT + LC_ALL LC_COLLATE LC_CTYPE LC_MONETARY LC_NUMERIC LC_TIME + HUGE_VAL HUGE_VALF HUGE_VALL INFINITY NAN FP_INFINITE FP_NAN FP_NORMAL FP_SUBNORMAL FP_ZERO FP_FAST_FMA FP_FAST_FMAF FP_FAST_FMAL FP_ILOGB0 FP_ILOGBNAN MATH_ERRNO MATH_ERREXCEPT math_errhandling isgreater isgreaterequal isless islessequal islessgreater isunordered + setjmp + SIG_DFL SIG_ERR SIG_IGN SIGABRT SIGFPE SIGILL SIGINT SIGSEGV SIGTERM + va_start va_arg va_end va_copy + ATOMIC_BOOL_LOCK_FREE ATOMIC_CHAR_LOCK_FREE ATOMIC_CHAR16_T_LOCK_FREE ATOMIC_CHAR32_T_LOCK_FREE ATOMIC_WCHAR_T_LOCK_FREE ATOMIC_SHORT_LOCK_FREE ATOMIC_INT_LOCK_FREE ATOMIC_LONG_LOCK_FREE ATOMIC_LLONG_LOCK_FREE ATOMIC_POINTER_LOCK_FREE ATOMIC_FLAG_INIT ATOMIC_VAR_INIT memory_order_relaxed memory_order_consume memory_order_acquire memory_order_release memory_order_acq_rel memory_order_seq_cst kill_dependency + true false + NULL + _IOFBF _IOLBF _IONBF BUFSIZ EOF FOPEN_MAX FILENAME_MAX TMP_MAX L_tmpnam SEEK_CUR SEEK_END SEEK_SET stderr stdin stdout + EXIT_FAILURE EXIT_SUCCESS MB_CUR_MAX RAND_MAX + PTRDIFF_MIN PTRDIFF_MAX SIG_ATOMIC_MIN SIG_ATOMIC_MAX WINT_MIN WINT_MAX INTMAX_MIN INTMAX_MAX INTPTR_MIN INTPTR_MAX INT8_MIN INT8_MAX INT16_MIN INT16_MAX INT32_MIN INT32_MAX INT64_MIN INT64_MAX INT_LEAST8_MIN INT_LEAST8_MAX INT_LEAST16_MIN INT_LEAST16_MAX INT_LEAST32_MIN INT_LEAST32_MAX INT_LEAST64_MIN INT_LEAST64_MAX INT_FAST8_MIN INT_FAST8_MAX INT_FAST16_MIN INT_FAST16_MAX INT_FAST32_MIN INT_FAST32_MAX INT_FAST64_MIN INT_FAST64_MAX UINTMAX_MAX UINTPTR_MAX UINT8_MAX UINT16_MAX UINT32_MAX UINT64_MAX UINT_LEAST8_MAX UINT_LEAST16_MAX UINT_LEAST32_MAX UINT_LEAST64_MAX UINT_FAST8_MAX UINT_FAST16_MAX UINT_FAST32_MAX UINT_FAST64_MAX INTMAX_C INT8_C INT16_C INT32_C INT64_C UINTMAX_C UINT8_C UINT16_C UINT32_C UINT64_C + mtx_plain mtx_recursive mtx_timed thrd_timedout thrd_success thrd_busy thrd_error thrd_nomem ONCE_FLAG_INIT TSS_DTOR_ITERATION + CLOCKS_PER_SEC TIME_UTC + WEOF + noreturn + R_OK W_OK X_OK F_OK F_LOCK F_ULOCK F_TLOCK F_TEST' + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list c_static_words $(join "${keywords} ${attributes} ${types} ${macros}" ' ')" + + # Highlight keywords + printf %s " + add-highlighter shared/c/code/keywords regex \b($(join "${keywords}" '|'))\b 0:keyword + add-highlighter shared/c/code/attributes regex \b($(join "${attributes}" '|'))\b 0:attribute + add-highlighter shared/c/code/types regex \b($(join "${types}" '|'))\b 0:type + add-highlighter shared/c/code/values regex \b($(join "${macros}" '|'))\b 0:value + " +} + +# c++ specific + +# raw strings +add-highlighter shared/cpp/raw_string region -match-capture %{R"([^(]*)\(} %{\)([^")]*)"} fill string + +# integer literals +add-highlighter shared/cpp/code/ regex %{(?i)(?<!\.)\b[1-9]('?\d+)*(ul?l?|ll?u?)?\b(?!\.)} 0:value +add-highlighter shared/cpp/code/ regex %{(?i)(?<!\.)\b0b[01]('?[01]+)*(ul?l?|ll?u?)?\b(?!\.)} 0:value +add-highlighter shared/cpp/code/ regex %{(?i)(?<!\.)\b0('?[0-7]+)*(ul?l?|ll?u?)?\b(?!\.)} 0:value +add-highlighter shared/cpp/code/ regex %{(?i)(?<!\.)\b0x[\da-f]('?[\da-f]+)*(ul?l?|ll?u?)?\b(?!\.)} 0:value + +# floating point literals +add-highlighter shared/cpp/code/ regex %{(?i)(?<!\.)\b\d('?\d+)*\.([fl]\b|\B)(?!\.)} 0:value +add-highlighter shared/cpp/code/ regex %{(?i)(?<!\.)\b\d('?\d+)*\.?e[+-]?\d('?\d+)*[fl]?\b(?!\.)} 0:value +add-highlighter shared/cpp/code/ regex %{(?i)(?<!\.)(\b(\d('?\d+)*)|\B)\.\d('?[\d]+)*(e[+-]?\d('?\d+)*)?[fl]?\b(?!\.)} 0:value +add-highlighter shared/cpp/code/ regex %{(?i)(?<!\.)\b0x[\da-f]('?[\da-f]+)*\.([fl]\b|\B)(?!\.)} 0:value +add-highlighter shared/cpp/code/ regex %{(?i)(?<!\.)\b0x[\da-f]('?[\da-f]+)*\.?p[+-]?\d('?\d+)*)?[fl]?\b(?!\.)} 0:value +add-highlighter shared/cpp/code/ regex %{(?i)(?<!\.)\b0x([\da-f]('?[\da-f]+)*)?\.\d('?[\d]+)*(p[+-]?\d('?\d+)*)?[fl]?\b(?!\.)} 0:value + +# character literals (no multi-character literals) +add-highlighter shared/cpp/code/char regex %{(\b(u8|u|U|L)|\B)'((\\.)|[^'\\])'\B} 0:value + +evaluate-commands %sh{ + # Grammar + keywords='alignas alignof and and_eq asm bitand bitor break case catch + compl const_cast continue decltype delete do dynamic_cast + else export for goto if new not not_eq operator or or_eq + reinterpret_cast return sizeof static_assert static_cast switch + throw try typedef typeid using while xor xor_eq' + attributes='audit auto axiom const consteval constexpr default explicit + extern final friend inline mutable noexcept override private + protected public register requires static thread_local typename + virtual volatile' + entities='class concept enum namespace struct template union' + types='bool byte char char8_t char16_t char32_t double float int long + max_align_t nullptr_t ptrdiff_t short signed size_t unsigned void + wchar_t' + values='NULL false nullptr this true' + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list cpp_static_words $(join "${keywords} ${attributes} ${entities} ${types} ${values}" ' ')" + + # Highlight keywords + printf %s " + add-highlighter shared/cpp/code/keywords regex \b($(join "${keywords}" '|'))\b 0:keyword + add-highlighter shared/cpp/code/attributes regex \b($(join "${attributes} ${entities}" '|'))\b 0:attribute + add-highlighter shared/cpp/code/types regex \b($(join "${types}" '|'))\b 0:type + add-highlighter shared/cpp/code/values regex \b($(join "${values}" '|'))\b 0:value + " +} + +# c and c++ compiler macros +evaluate-commands %sh{ + builtin_macros="__cplusplus|__STDC_HOSTED__|__FILE__|__LINE__|__DATE__|__TIME__|__STDCPP_DEFAULT_NEW_ALIGNMENT__" + + printf %s " + add-highlighter shared/c/code/macros regex \b(${builtin_macros})\b 0:builtin + add-highlighter shared/cpp/code/macros regex \b(${builtin_macros})\b 0:builtin + " +} + +# objective-c specific +add-highlighter shared/objc/code/number regex %{\b-?\d+[fdiu]?|'((\\.)?|[^'\\])'} 0:value + +evaluate-commands %sh{ + # Grammar + keywords='break case continue default do else for goto if return switch + while' + attributes='IBAction IBOutlet __block assign auto const copy enum extern + inline nonatomic readonly retain static strong struct typedef + union volatile weak' + types='BOOL CGFloat NSInteger NSString NSUInteger bool char float + instancetype int long short signed size_t unsigned void' + values='FALSE NO NULL TRUE YES id nil self super' + decorators='autoreleasepool catch class end implementation interface + property protocol selector synchronized synthesize try' + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list objc_static_words $(join "${keywords} ${attributes} ${types} ${values} ${decorators}" ' ')" + + # Highlight keywords + printf %s " + add-highlighter shared/objc/code/keywords regex \b($(join "${keywords}" '|'))\b 0:keyword + add-highlighter shared/objc/code/attributes regex \b($(join "${attributes}" '|'))\b 0:attribute + add-highlighter shared/objc/code/types regex \b($(join "${types}" '|'))\b 0:type + add-highlighter shared/objc/code/values regex \b($(join "${values}" '|'))\b 0:value + add-highlighter shared/objc/code/decorators regex @($(join "${decorators}" '|'))\b 0:attribute + " +} + +declare-option -docstring %{ + control the type of include guard to be inserted in empty headers + Can be one of the following: + ifdef: old style ifndef/define guard + pragma: newer type of guard using "pragma once" +} str c_include_guard_style "ifdef" + +define-command -hidden c-family-insert-include-guards %{ + evaluate-commands %sh{ + case "${kak_opt_c_include_guard_style}" in + ifdef) + echo 'execute-keys gg"%PI/<esc>xs^.*/<ret>dxs\.<ret>r_A_INCLUDED<esc>xyPPI#ifndef<space><esc>jI#define<space><esc>jI#endif<space>//<space><esc>O<esc>' + ;; + pragma) + echo 'execute-keys ggi#pragma<space>once<esc>' + ;; + *);; + esac + } +} + +hook -group c-family-insert global BufNewFile .*\.(h|hh|hpp|hxx|H) c-family-insert-include-guards + +declare-option -docstring "colon separated list of path in which header files will be looked for" \ + str-list alt_dirs '.' '..' + +define-command -hidden c-family-alternative-file %{ + evaluate-commands %sh{ + file="${kak_buffile##*/}" + file_noext="${file%.*}" + dir=$(dirname "${kak_buffile}") + + # Set $@ to alt_dirs + eval "set -- ${kak_quoted_opt_alt_dirs}" + + case ${file} in + *.c|*.cc|*.cpp|*.cxx|*.C|*.inl|*.m) + for alt_dir in "$@"; do + for ext in h hh hpp hxx H; do + case "$alt_dir" in + /*) altname="${alt_dir}/${file_noext}.${ext}" ;; + *) altname="${dir}/${alt_dir}/${file_noext}.${ext}" ;; + esac + if [ -f "${altname}" ]; then + printf 'edit %%{%s}\n' "${altname}" + exit + fi + done + done + ;; + *.h|*.hh|*.hpp|*.hxx|*.H) + for alt_dir in "$@"; do + for ext in c cc cpp cxx C m; do + case "$alt_dir" in + /*) altname="${alt_dir}/${file_noext}.${ext}" ;; + *) altname="${dir}/${alt_dir}/${file_noext}.${ext}" ;; + esac + if [ -f "${altname}" ]; then + printf 'edit %%{%s}\n' "${altname}" + exit + fi + done + done + ;; + *) + echo "fail 'extension not recognized'" + exit + ;; + esac + echo "fail 'alternative file not found'" + } +} + +define-command c-alternative-file -docstring "Jump to the alternate c file (header/implementation)" %{ + c-family-alternative-file +} +define-command cpp-alternative-file -docstring "Jump to the alternate cpp file (header/implementation)" %{ + c-family-alternative-file +} +define-command objc-alternative-file -docstring "Jump to the alternate objc file (header/implementation)" %{ + c-family-alternative-file +} + +§ + +# Module aliases +provide-module c %{ require-module c-family } +provide-module cpp %{ require-module c-family } +provide-module objc %{ require-module c-family } diff --git a/autoload/filetype/cabal.kak b/autoload/filetype/cabal.kak new file mode 100644 index 0000000..a1f4526 --- /dev/null +++ b/autoload/filetype/cabal.kak @@ -0,0 +1,88 @@ +# http://haskell.org/cabal +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](cabal) %{ + set-option buffer filetype cabal +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=cabal %[ + require-module cabal + + hook window ModeChange pop:insert:.* -group cabal-trim-indent cabal-trim-indent + hook window InsertChar \n -group cabal-insert cabal-insert-on-new-line + hook window InsertChar \n -group cabal-indent cabal-indent-on-new-line + hook window InsertChar \{ -group cabal-indent cabal-indent-on-opening-curly-brace + hook window InsertChar \} -group cabal-indent cabal-indent-on-closing-curly-brace + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window cabal-.+ } +] + +hook -group cabal-highlight global WinSetOption filetype=cabal %{ + add-highlighter window/cabal ref cabal + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/cabal } +} + + +provide-module cabal %[ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/cabal regions +add-highlighter shared/cabal/code default-region group +add-highlighter shared/cabal/line_comment region (--) $ fill comment +add-highlighter shared/cabal/comment region -recurse \{- \{- -\} fill comment + +add-highlighter shared/cabal/code/ regex \b(true|false)\b|(([<>]?=?)?\d+(\.\d+)+) 0:value +add-highlighter shared/cabal/code/ regex \b(if|else)\b 0:keyword +add-highlighter shared/cabal/code/ regex ^\h*([A-Za-z][A-Za-z0-9_-]*)\h*: 1:variable + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden cabal-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden cabal-insert-on-new-line %[ + evaluate-commands -draft -itersel %[ + # copy '--' comment prefix and following white spaces + try %[ execute-keys -draft k x s ^\h*\K--\h* <ret> y gh j P ] + ] +] + +define-command -hidden cabal-indent-on-new-line %[ + evaluate-commands -draft -itersel %[ + # preserve previous line indent + try %[ execute-keys -draft <semicolon> K <a-&> ] + # filter previous line + try %[ execute-keys -draft k : cabal-trim-indent <ret> ] + # indent after lines ending with { or : + try %[ execute-keys -draft , k x <a-k> [:{]$ <ret> j <a-gt> ] + # deindent closing brace when after cursor + try %[ execute-keys -draft x <a-k> \h*\} <ret> gh / \} <ret> m <a-S> 1<a-&> ] + ] +] + +define-command -hidden cabal-indent-on-opening-curly-brace %[ + evaluate-commands -draft -itersel %[ + # align indent with opening paren when { is entered on a new line after the closing paren + try %[ execute-keys -draft h <a-F> ) M <a-k> \A\(.*\)\h*\n\h*\{\z <ret> s \A|.\z <ret> 1<a-&> ] + ] +] + +define-command -hidden cabal-indent-on-closing-curly-brace %[ + evaluate-commands -draft -itersel %[ + # align to opening curly brace when alone on a line + try %[ execute-keys -draft <a-h> <a-k> ^\h+\}$ <ret> h m s \A|.\z<ret> 1<a-&> ] + ] +] + +] diff --git a/autoload/filetype/clojure.kak b/autoload/filetype/clojure.kak new file mode 100644 index 0000000..d876262 --- /dev/null +++ b/autoload/filetype/clojure.kak @@ -0,0 +1,237 @@ +# http://clojure.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](clj|cljc|cljs|cljx|edn) %{ + set-option buffer filetype clojure +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +hook global WinSetOption filetype=clojure %{ + require-module clojure + clojure-configure-window +} + +hook -group clojure-highlight global WinSetOption filetype=clojure %{ + add-highlighter window/clojure ref clojure + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/clojure } +} + +hook -group clojure-insert global BufNewFile .*[.](clj|cljc|cljs|cljx) %{ + require-module clojure + clojure-insert-ns +} + +provide-module clojure %{ + +require-module lisp + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/clojure regions +add-highlighter shared/clojure/code default-region group +add-highlighter shared/clojure/comment region '(?<!\\)(?:\\\\)*\K;' '$' fill comment +add-highlighter shared/clojure/shebang region '(?<!\\)(?:\\\\)*\K#!' '$' fill comment +add-highlighter shared/clojure/string region '(?<!\\)(?:\\\\)*\K"' '(?<!\\)(?:\\\\)*"' fill string + +add-highlighter shared/clojure/code/ regex \b(nil|true|false)\b 0:value +add-highlighter shared/clojure/code/ regex \ + \\(?:space|tab|newline|return|backspace|formfeed|u[0-9a-fA-F]{4}|o[0-3]?[0-7]{1,2}|.)\b 0:string + +evaluate-commands %sh{ + exec awk -f - <<'EOF' + BEGIN{ + symbol_char="[^\\s()\\[\\]{}\"\\;@^`~\\\\%/]"; + in_core="(clojure\\.core/|(?<!/))"; + split( \ + "case cond condp cond-> cond->> def definline definterface defmacro defmethod "\ + "defmulti defn defn- defonce defprotocol defrecord defstruct deftype fn if "\ + "if-let if-not if-some let letfn new ns when when-first when-let when-not "\ + "when-some . ..", keywords); + + split( \ + "* *' + +' - -' -> ->> ->ArrayChunk ->Eduction ->Vec ->VecNode ->VecSeq / < "\ + "<= = == > >= StackTraceElement->vec 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 any? apply "\ + "areduce array-map as-> aset aset-boolean aset-byte aset-char aset-double "\ + "aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in "\ + "associative? atom await await-for bases bean bigdec bigint biginteger "\ + "binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set "\ + "bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array "\ + "boolean? booleans bound-fn bound-fn* bound? bounded-count butlast byte "\ + "byte-array bytes bytes? cast cat catch char char-array char-escape-string "\ + "char-name-string char? chars class class? clear-agent-errors "\ + "clojure-version coll? comment 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? declare dedupe default-data-readers "\ + "delay delay? deliver denominator deref derive descendants disj disj! "\ + "dissoc dissoc! distinct distinct? do doall dorun doseq dosync dotimes doto "\ + "double double-array double? doubles drop drop-last drop-while eduction "\ + "empty empty? ensure ensure-reduced enumeration-seq error-handler "\ + "error-mode eval even? every-pred every? ex-data ex-info extend "\ + "extend-protocol extend-type extenders extends? false? ffirst file-seq "\ + "filter filterv finally find find-keyword find-ns find-var first flatten "\ + "float float-array float? floats flush fn? fnext fnil for force format "\ + "frequencies future future-call future-cancel future-cancelled? "\ + "future-done? future? gen-class gen-interface gensym get get-in get-method "\ + "get-proxy-class get-thread-bindings get-validator group-by halt-when hash "\ + "hash-map hash-ordered-coll hash-set hash-unordered-coll ident? identical? "\ + "identity ifn? import in-ns inc inc' indexed? init-proxy inst-ms inst? "\ + "instance? int int-array int? integer? interleave intern interpose into "\ + "into-array ints io! isa? iterate iterator-seq juxt keep keep-indexed key "\ + "keys keyword keyword? last lazy-cat lazy-seq line-seq list list* list? "\ + "load load-file load-reader load-string loaded-libs locking long long-array "\ + "longs 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 methods min min-key mix-collection-hash mod monitor-enter "\ + "monitor-exit name namespace namespace-munge nat-int? neg-int? neg? newline "\ + "next nfirst nil? nnext not not-any? not-empty not-every? not= ns-aliases "\ + "ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve "\ + "ns-unalias ns-unmap nth nthnext nthrest num number? numerator object-array "\ + "odd? or parents partial partition partition-all partition-by pcalls peek "\ + "persistent! pmap pop pop! pop-thread-bindings pos-int? pos? pr pr-str "\ + "prefer-method prefers print print-str printf println println-str prn "\ + "prn-str promise proxy proxy-mappings proxy-super push-thread-bindings "\ + "pvalues qualified-ident? qualified-keyword? qualified-symbol? quot quote "\ + "rand rand-int rand-nth random-sample range ratio? rational? rationalize "\ + "re-find re-groups re-matcher re-matches re-pattern re-seq read read-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! reset-vals! resolve rest restart-agent resultset-seq reverse "\ + "reversible? rseq rsubseq run! satisfies? second select-keys send send-off "\ + "send-via seq seq? seqable? seque sequence sequential? set set! "\ + "set-agent-send-executor! set-agent-send-off-executor! set-error-handler! "\ + "set-error-mode! set-validator! set? short short-array shorts shuffle "\ + "shutdown-agents simple-ident? simple-keyword? simple-symbol? slurp some "\ + "some-> some->> some-fn some? sort sort-by sorted-map sorted-map-by "\ + "sorted-set sorted-set-by sorted? special-symbol? spit split-at split-with "\ + "str string? struct struct-map subs subseq subvec supers swap! swap-vals! "\ + "symbol symbol? sync tagged-literal tagged-literal? take take-last take-nth "\ + "take-while 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 unreduced "\ + "unsigned-bit-shift-right update update-in update-proxy uri? use uuid? val "\ + "vals var var-get var-set var? vary-meta vec vector vector-of vector? "\ + "volatile! volatile? vreset! vswap! while with-bindings with-bindings* "\ + "with-in-str with-local-vars with-meta with-open with-out-str "\ + "with-precision with-redefs with-redefs-fn xml-seq zero? zipmap", core_fns); + + split( \ + "*1 *2 *3 *agent* *clojure-version* *command-line-args* *compile-files* "\ + "*compile-path* *compiler-options* *data-readers* *default-data-reader-fn* "\ + "*e *err* *file* *flush-on-newline* *in* *ns* *out* *print-dup* "\ + "*print-length* *print-level* *print-meta* *print-namespace-maps* "\ + "*print-readably* *read-eval* *unchecked-math* *warn-on-reflection*", core_vars); + } + function print_word_highlighter(words, face, first) { + printf("add-highlighter shared/clojure/code/ regex (?<!%s)%s(", \ + symbol_char, in_core); + first = 1; + for (i in words) { + if (!first) { printf("|"); } + printf("\\Q%s\\E", words[i]); + first = 0; + } + printf(")(?!%s) 0:%s\n", symbol_char, face); + } + function print_static_words(words) { + for (i in words) { + printf("%s clojure.core/%s ", words[i], words[i]); + } + } + BEGIN{ + # Keywords + printf("add-highlighter shared/clojure/code/ regex ::?(%s+/)?%s+ 0:value\n", symbol_char, symbol_char); + + # Numbers + printf("add-highlighter shared/clojure/code/ regex (?<!%s)[-+]?(?:0(?:[xX][0-9a-fA-F]+|[0-7]*)|[1-9]\\d*)N? 0:value\n", symbol_char); + printf("add-highlighter shared/clojure/code/ regex (?<!%s)[-+]?(?:0|[1-9]\\d*)(?:\\.\\d*)(?:M|[eE][-+]?\\d+)? 0:value\n", symbol_char); + printf("add-highlighter shared/clojure/code/ regex (?<!%s)[-+]?(?:0|[1-9]\\d*)/(?:0|[1-9]\\d*) 0:value\n", symbol_char); + + print_word_highlighter(keywords, "keyword"); + print_word_highlighter(core_fns, "function"); + print_word_highlighter(core_vars, "variable"); + + printf("declare-option str-list clojure_static_words ") + print_static_words(keywords); + print_static_words(core_fns); + print_static_words(core_vars); + printf("\n"); + } +EOF +} + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden clojure-configure-window %{ + set-option window static_words %opt{clojure_static_words} + + hook window ModeChange pop:insert:.* -group clojure-trim-indent clojure-trim-indent + hook window InsertChar \n -group clojure-indent clojure-indent-on-new-line + + set-option buffer extra_word_chars '_' . / * ? + - < > ! : "'" + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window clojure-.+ } +} + +define-command -hidden clojure-trim-indent lisp-trim-indent + +declare-option \ + -docstring 'regex matching the head of forms which have options *and* indented bodies' \ + regex clojure_special_indent_forms \ + '(?:def.*|doseq|for|fn\*?|if(-.*|)|let.*|loop|ns|testing|with-.*|when(-.*|))' + +define-command -hidden clojure-indent-on-new-line %{ + # registers: i = best align point so far; w = start of first word of form + evaluate-commands -draft -save-regs '/"|^@iw' -itersel %{ + execute-keys -draft 'gk"iZ' + try %{ + execute-keys -draft '[bl"i<a-Z><gt>"wZ' + + try %{ + # If a special form, indent another (indentwidth - 1) spaces + execute-keys -draft '"wze<a-K>[\s()\[\]\{\}]<ret><a-k>\A' %opt{clojure_special_indent_forms} '\z<ret>' + execute-keys -draft '"wze<a-L>s.{' %sh{printf $(( kak_opt_indentwidth - 1 ))} '}\K.*<ret><a-;>;"i<a-Z><gt>' + } catch %{ + # If not special and parameter appears on line 1, indent to parameter + execute-keys -draft '"wz<a-K>[()[\]{}]<ret>e<a-K>[\s()\[\]\{\}]<ret><a-l>s\h\K[^\s].*<ret><a-;>;"i<a-Z><gt>' + } + } + try %{ execute-keys -draft '[rl"i<a-Z><gt>' } + try %{ execute-keys -draft '[Bl"i<a-Z><gt>' } + execute-keys -draft ';"i<a-z>a&,' + } +} + +declare-option -docstring %{ + top-level directories which can contain clojure files + e.g. '(src|test|dev)' +} regex clojure_source_directories '(src|test|dev)' + +define-command -docstring %{clojure-insert-ns: Insert namespace directive at top of Clojure source file} \ + clojure-insert-ns %{ + evaluate-commands -draft %{ + execute-keys -save-regs '' 'gk\O' "%val{bufname}" '<esc>giZ' + try %{ execute-keys 'z<a-l>s\.clj[csx]?$<ret><a-d>' } + try %{ execute-keys 'z<a-l>s^' "%opt{clojure_source_directories}" '/<ret><a-d>' } + try %{ execute-keys 'z<a-l>s/<ret>r.' } + try %{ execute-keys 'z<a-l>s_<ret>r-' } + execute-keys 'z<a-l>\c(ns <c-r>")<ret><esc>' + } +} + +} diff --git a/autoload/filetype/cmake.kak b/autoload/filetype/cmake.kak new file mode 100644 index 0000000..86fda25 --- /dev/null +++ b/autoload/filetype/cmake.kak @@ -0,0 +1,36 @@ +hook global BufCreate .+\.cmake|.*/CMakeLists.txt %{ + set-option buffer filetype cmake +} + +hook global BufCreate .*/CMakeCache.txt %{ + set-option buffer filetype ini +} + +hook global WinSetOption filetype=cmake %{ + require-module cmake +} + +hook -group cmake-highlight global WinSetOption filetype=cmake %{ + add-highlighter window/cmake ref cmake + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/cmake } +} + +provide-module cmake %{ + +add-highlighter shared/cmake regions +add-highlighter shared/cmake/code default-region group +add-highlighter shared/cmake/comment region '#' '$' fill comment +add-highlighter shared/cmake/argument region -recurse '\(' '\w+\h*\(\K' '(?=\))' regions + +add-highlighter shared/cmake/code/ regex '\w+\h*(?=\()' 0:meta + +add-highlighter shared/cmake/argument/args default-region regex '\$\{\w+\}' 0:variable +add-highlighter shared/cmake/argument/comment region '#' '$' fill comment +add-highlighter shared/cmake/argument/quoted region '"' '(?<!\\)(\\\\)*"' group +add-highlighter shared/cmake/argument/raw-quoted region -match-capture '\[(=*)\[' '\](=*)\]' ref cmake/argument/quoted + +add-highlighter shared/cmake/argument/quoted/ fill string +add-highlighter shared/cmake/argument/quoted/ regex '\$\{\w+\}' 0:variable +add-highlighter shared/cmake/argument/quoted/ regex '\w+\h*(?=\()' 0:function + +} diff --git a/autoload/filetype/coffee.kak b/autoload/filetype/coffee.kak new file mode 100644 index 0000000..c9ee330 --- /dev/null +++ b/autoload/filetype/coffee.kak @@ -0,0 +1,92 @@ +# http://coffeescript.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](coffee) %{ + set-option buffer filetype coffee +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=coffee %{ + require-module coffee + + hook window ModeChange pop:insert:.* -group coffee-trim-indent coffee-trim-indent + hook window InsertChar \n -group coffee-insert coffee-insert-on-new-line + hook window InsertChar \n -group coffee-indent coffee-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window coffee-.+ } +} + +hook -group coffee-highlight global WinSetOption filetype=coffee %{ + add-highlighter window/coffee ref coffee + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/coffee } +} + + +provide-module coffee %[ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/coffee regions +add-highlighter shared/coffee/code default-region group +add-highlighter shared/coffee/single_string region "'" "'" fill string +add-highlighter shared/coffee/single_string_alt region "'''" "'''" fill string +add-highlighter shared/coffee/double_string region '"' (?<!\\)(\\\\)*" regions +add-highlighter shared/coffee/double_string_alt region '"""' '"""' ref shared/coffee/double_string +add-highlighter shared/coffee/regex region '/' (?<!\\)(\\\\)*/[gimy]* regions +add-highlighter shared/coffee/regex_alt region '///' ///[gimy]* ref shared/coffee/regex +add-highlighter shared/coffee/comment1 region '#' '$' fill comment +add-highlighter shared/coffee/comment2 region '###' '###' fill comment + +# Regular expression flags are: g → global match, i → ignore case, m → multi-lines, y → sticky +# https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp + +add-highlighter shared/coffee/double_string/base default-region fill string +add-highlighter shared/coffee/double_string/interpolation region -recurse \{ \Q#{ \} fill meta +add-highlighter shared/coffee/regex/base default-region fill meta +add-highlighter shared/coffee/regex/interpolation region -recurse \{ \Q#{ \} fill meta + +# Keywords are collected at +# https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords +# http://coffeescript.org/documentation/docs/lexer.html#section-63 +add-highlighter shared/coffee/code/ regex [$@]\w* 0:variable +add-highlighter shared/coffee/code/ regex \b(Array|Boolean|Date|Function|Number|Object|RegExp|String)\b 0:type +add-highlighter shared/coffee/code/ regex \b(document|false|no|null|off|on|parent|self|this|true|undefined|window|yes)\b 0:value +add-highlighter shared/coffee/code/ regex \b(and|is|isnt|not|or)\b 0:operator +add-highlighter shared/coffee/code/ regex \b(break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|function|if|implements|import|in|instanceof|interface|let|native|new|package|private|protected|public|return|static|super|switch|throw|try|typeof|var|void|while|with|yield)\b 0:keyword + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden coffee-trim-indent %{ + evaluate-commands -draft -itersel %{ + execute-keys x + # remove trailing white spaces + try %{ execute-keys -draft s \h + $ <ret> d } + } +} + +define-command -hidden coffee-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy '#' comment prefix and following white spaces + try %{ execute-keys -draft k x s '^\h*\K#\h*' <ret> y gh j P } + } +} + +define-command -hidden coffee-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : coffee-trim-indent <ret> } + # indent after start structure + try %{ execute-keys -draft k x <a-k> ^ \h * (case|catch|class|else|finally|for|function|if|switch|try|while|with) \b | (=|->) $ <ret> j <a-gt> } + } +} + +] diff --git a/autoload/filetype/conf.kak b/autoload/filetype/conf.kak new file mode 100644 index 0000000..9b71589 --- /dev/null +++ b/autoload/filetype/conf.kak @@ -0,0 +1,30 @@ +hook global BufCreate .+\.(repo|cfg|properties|desktop) %{ + set-option buffer filetype conf +} + +hook global WinCreate .+\.ini %{ + try %{ + execute-keys /^\h*#<ret> + set-option buffer filetype conf + } +} + +hook global WinSetOption filetype=conf %{ + require-module conf +} + +hook -group conf-highlight global WinSetOption filetype=conf %{ + add-highlighter window/conf ref conf + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/conf } +} + +provide-module conf %{ + +add-highlighter shared/conf regions +add-highlighter shared/conf/code default-region group +add-highlighter shared/conf/comment region '(^|\h)\K#' $ fill comment + +add-highlighter shared/conf/code/ regex "(?S)^\h*(\[.+?\])\h*$" 1:title +add-highlighter shared/conf/code/ regex "^\h*([^\[][^=\n]*)=([^\n]*)" 1:variable 2:value + +} diff --git a/autoload/filetype/coq.kak b/autoload/filetype/coq.kak new file mode 100644 index 0000000..cab1abf --- /dev/null +++ b/autoload/filetype/coq.kak @@ -0,0 +1,127 @@ + +# Detection +# -------- + +hook global BufCreate .*\.v %{ + set-option buffer filetype coq +} + +# Initialization +# -------------- + +hook global WinSetOption filetype=coq %{ + require-module coq + hook window ModeChange pop:insert:.* -group coq-trim-indent coq-trim-indent + hook window InsertChar \n -group coq-indent coq-copy-indent-on-newline + + set-option window static_words %opt{coq_static_words} + add-highlighter window/coq ref coq + + hook -once -always window WinSetOption filetype=.* %{ + remove-highlighter window/coq + remove-hooks window coq-indent + } +} + +provide-module coq %{ + +# Syntax +# ------ + +# This is a `looks sensible' keyword syntax highlighting, far from being correct. +# Note that only the core language and the proof language is supported, +# the Ltac language is not (for now). + +add-highlighter shared/coq regions + +add-highlighter shared/coq/comment region -recurse \Q(* \Q(* \Q*) fill comment +add-highlighter shared/coq/string region (?<!")" (?<!")("")*" fill string + +add-highlighter shared/coq/command default-region group + +# This is not any lexical convention of coq, simply highlighting used to make +# proofs look better, based on how people usually use notations +add-highlighter shared/coq/command/ regex [`!@#$%^&*-=+\\:\;|<>/]+ 0:operator +add-highlighter shared/coq/command/ regex \(dfs\)|\(bfs\) 0:operator +add-highlighter shared/coq/command/ regex [()\[\]{}] 0:operator + +# numeral literals +add-highlighter shared/coq/command/ regex [-]?[0-9][0-9_]*(\.[0-9_]+)?([eE][+-][0-9_]+)? 0:value + +evaluate-commands %sh{ + # These are builtin keywords of the Gallina language (without tactics) + keywords="_ IF Prop SProp Set Type as at by cofix discriminated else end exists exists2 fix for" + keywords="${keywords} forall fun if in lazymatch let match multimatch return then using where with" + keywords="${keywords} inside outside" + + # These are (part of) coq top level commands + commands="Abort About Add Admitted All Arguments Axiom Back BackTo" + commands="${commands} Canonical Cd Check Coercion CoFixpoint Collection Compute Conjecture Context Contextual Corollary" + commands="${commands} Declare Defined Definition Delimit Drop End Eval Example Existential Export" + commands="${commands} Fact Fail File Fixpoint Focus From Function Generalizable Global Goal Grab" + commands="${commands} Hint Hypotheses Hypothesis Immediate Implicit Import Include Inductive" + commands="${commands} Lemma Let Library Load LoadPath Local Locate Module No Notation Opaque" + commands="${commands} Parameter Parameters Primitive Print Proof Property Proposition Pwd Qed Quit" + commands="${commands} Rec Record Redirect Register Remark Remove Require Reset" + commands="${commands} Section Search SearchAbout SearchHead SearchPattern SearchRewrite Show Strategy" + commands="${commands} Test Theorem Time Timeout Transparent Types Universes Undo Unfocus Unfocused Unset Variable Variables" + + # These are (part of) coq's builtin tactics + tactics="abstract absurd admit all apply assert assert_fails" + tactics="${tactics} assert_succeeds assumption auto autoapply" + tactics="${tactics} autorewrite autounfold btauto by case cbn" + tactics="${tactics} cbv change clear clearbody cofix compare" + tactics="${tactics} compute congr congruence constructor contradict" + tactics="${tactics} cut cutrewrite cycle decide decompose dependent" + tactics="${tactics} destruct discriminate do done double" + tactics="${tactics} eapply eassert eauto eexact elim elimtype exact exfalso" + tactics="${tactics} fail field first firstorder fix fold functional" + tactics="${tactics} generalize guard have hnf idtac induction injection" + tactics="${tactics} instantiate intro intros intuition inversion" + tactics="${tactics} inversion_clear lapply lazy last move omega" + tactics="${tactics} pattern pose progress red refine reflexivity" + tactics="${tactics} remember rename repeat replace rewrite right ring" + tactics="${tactics} set setoid_reflexivity setoid_replace setoid_rewrite" + tactics="${tactics} setoid_symmetry setoid_transitivity simpl simple" + tactics="${tactics} simplify_eq solve specialize split start stop" + tactics="${tactics} subst symmetry tauto transitivity trivial try" + tactics="${tactics} under unfold unify unlock" + + echo declare-option str-list coq_static_words ${keywords} ${commands} ${tactics} + + keywords_regex=$(echo ${keywords} | tr ' ' '|') + printf %s " + add-highlighter shared/coq/command/ regex \b(${keywords_regex})\b 0:keyword + " + commands_regex=$(echo ${commands} | tr ' ' '|') + printf %s " + add-highlighter shared/coq/command/ regex ^[\h\n]*(${commands_regex})\b 0:variable + " + + tactics_regex=$(echo ${tactics} | tr ' ' '|') + printf %s " + add-highlighter shared/coq/command/ regex \b(${tactics_regex})\b 0:keyword + " +} + +# Indentation +# ----------- +# Coq's syntax is based heavily on keywords and program structure, +# not based on explicit, unique delimiters, like braces in C-family. +# So it is difficult to properly indent using only regex... +# Hence here only a simple mechanism of copying indent is done. +define-command -hidden coq-copy-indent-on-newline %{ + evaluate-commands -draft -itersel %{ + try %{ execute-keys -draft k x s ^\h+ <ret> y gh j P } + } +} + +define-command -hidden coq-trim-indent %{ + evaluate-commands -no-hooks -draft -itersel %{ + execute-keys x + # remove trailing white spaces + try %{ execute-keys -draft s \h + $ <ret> d } + } +} + +} diff --git a/autoload/filetype/crystal.kak b/autoload/filetype/crystal.kak new file mode 100644 index 0000000..e354067 --- /dev/null +++ b/autoload/filetype/crystal.kak @@ -0,0 +1,258 @@ +# Crystal +# https://crystal-lang.org + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate '.*\.cr' %{ + set-option buffer filetype crystal +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=crystal %{ + require-module crystal + + add-highlighter window/crystal ref crystal + evaluate-commands set-option window static_words %opt{crystal_keywords} %opt{crystal_attributes} %opt{crystal_objects} + + hook window ModeChange pop:insert:.* -group crystal-trim-indent crystal-trim-indent + hook window InsertChar .* -group crystal-indent crystal-indent-on-char + hook window InsertChar '\n' -group crystal-indent crystal-indent-on-new-line + hook window InsertChar '\n' -group crystal-insert crystal-insert-on-new-line + + hook -always -once window WinSetOption filetype=.* %{ + remove-highlighter window/crystal + remove-hooks window crystal-.+ + } +} + +provide-module crystal %§ + +declare-option -hidden str-list crystal_keywords 'abstract' 'alias' 'annotation' 'as' 'asm' 'begin' 'break' 'case' 'class' 'def' 'do' 'else' 'elsif' 'end' 'ensure' 'enum' 'extend' 'false' 'for' 'fun' 'if' 'include' 'instance_sizeof' 'is_a?' 'lib' 'macro' 'module' 'next' 'nil' 'nil?' 'of' 'offsetof' 'out' 'pointerof' 'private' 'protected' 'require' 'rescue' 'responds_to?' 'return' 'select' 'self' 'sizeof' 'struct' 'super' 'then' 'true' 'type' 'typeof' 'uninitialized' 'union' 'unless' 'until' 'verbatim' 'when' 'while' 'with' 'yield' +# https://crystal-lang.org/reference/syntax_and_semantics/methods_and_instance_variables.html#getters-and-setters +declare-option -hidden str-list crystal_attributes 'getter' 'setter' 'property' +declare-option -hidden str-list crystal_operators '+' '-' '*' '/' '//' '%' '|' '&' '^' '~' '**' '<<' '<' '<=' '==' '!=' '=~' '!~' '>>' '>' '>=' '<=>' '===' '[]' '[]=' '[]?' '[' '&+' '&-' '&*' '&**' +declare-option -hidden str-list crystal_objects 'Adler32' 'ArgumentError' 'Array' 'Atomic' 'Base64' 'Benchmark' 'BigDecimal' 'BigFloat' 'BigInt' 'BigRational' 'BitArray' 'Bool' 'Box' 'Bytes' 'Channel' 'Char' 'Class' 'Colorize' 'Comparable' 'Complex' 'Concurrent' 'ConcurrentExecutionException' 'CRC32' 'Crypto' 'Crystal' 'CSV' 'Debug' 'Deprecated' 'Deque' 'Digest' 'Dir' 'DivisionByZeroError' 'DL' 'ECR' 'Enum' 'Enumerable' 'ENV' 'Errno' 'Exception' 'Fiber' 'File' 'FileUtils' 'Flags' 'Flate' 'Float' 'Float32' 'Float64' 'GC' 'Gzip' 'Hash' 'HTML' 'HTTP' 'Indexable' 'IndexError' 'INI' 'Int' 'Int128' 'Int16' 'Int32' 'Int64' 'Int8' 'InvalidBigDecimalException' 'InvalidByteSequenceError' 'IO' 'IPSocket' 'Iterable' 'Iterator' 'JSON' 'KeyError' 'Levenshtein' 'Link' 'LLVM' 'Logger' 'Markdown' 'Math' 'MIME' 'Mutex' 'NamedTuple' 'Nil' 'NilAssertionError' 'NotImplementedError' 'Number' 'OAuth' 'OAuth2' 'Object' 'OpenSSL' 'OptionParser' 'OverflowError' 'PartialComparable' 'Path' 'Pointer' 'PrettyPrint' 'Proc' 'Process' 'Random' 'Range' 'Readline' 'Reference' 'Reflect' 'Regex' 'SemanticVersion' 'Set' 'Signal' 'Slice' 'Socket' 'Spec' 'StaticArray' 'String' 'StringPool' 'StringScanner' 'Struct' 'Symbol' 'System' 'TCPServer' 'TCPSocket' 'Termios' 'Time' 'Tuple' 'TypeCastError' 'UDPSocket' 'UInt128' 'UInt16' 'UInt32' 'UInt64' 'UInt8' 'Unicode' 'Union' 'UNIXServer' 'UNIXSocket' 'URI' 'UUID' 'VaList' 'Value' 'WeakRef' 'XML' 'YAML' 'Zip' 'Zlib' + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/crystal regions +add-highlighter shared/crystal/code default-region group + +# Comments +# https://crystal-lang.org/reference/syntax_and_semantics/comments.html +# Avoid string literals with interpolation +add-highlighter shared/crystal/comment region '#(?!\{)' '$' fill comment + +# String +# https://crystal-lang.org/reference/syntax_and_semantics/literals/string.html +add-highlighter shared/crystal/string region '"' '(?<!\\)(\\\\)*"' regions + +# Percent string literals +# https://crystal-lang.org/reference/syntax_and_semantics/literals/string.html#percent-string-literals +add-highlighter shared/crystal/parenthesis-string region -recurse '\(' '%Q?\(' '\)' regions +add-highlighter shared/crystal/bracket-string region -recurse '\[' '%Q?\[' '\]' regions +add-highlighter shared/crystal/brace-string region -recurse '\{' '%Q?\{' '\}' regions +add-highlighter shared/crystal/angle-string region -recurse '<' '%Q?<' '>' regions +add-highlighter shared/crystal/pipe-string region '%Q?\|' '\|' regions + +# Raw +# https://crystal-lang.org/reference/syntax_and_semantics/literals/string.html#percent-string-literals +# https://crystal-lang.org/reference/syntax_and_semantics/literals/string.html#percent-string-array-literal +# https://crystal-lang.org/reference/syntax_and_semantics/literals/symbol.html#percent-symbol-array-literal +add-highlighter shared/crystal/raw-parenthesis-string region -recurse '\(' '%[qwi]\(' '\)' fill string +add-highlighter shared/crystal/raw-bracket-string region -recurse '\[' '%[qwi]\[' '\]' fill string +add-highlighter shared/crystal/raw-brace-string region -recurse '\{' '%[qwi]\{' '\}' fill string +add-highlighter shared/crystal/raw-angle-string region -recurse '<' '%[qwi]<' '>' fill string +add-highlighter shared/crystal/raw-pipe-string region '%[qwi]\|' '\|' fill string + +# Here document +# https://crystal-lang.org/reference/syntax_and_semantics/literals/string.html#heredoc +add-highlighter shared/crystal/heredoc region -match-capture '<<-(\w+)' '^\h*(\w+)$' regions +# Raw +add-highlighter shared/crystal/raw-heredoc region -match-capture "<<-'(\w+)'" '^\h*(\w+)$' regions +add-highlighter shared/crystal/raw-heredoc/fill default-region fill string +add-highlighter shared/crystal/raw-heredoc/interpolation region -recurse '\{' '#\{' '\}' fill meta + +# Symbol +# https://crystal-lang.org/reference/syntax_and_semantics/literals/symbol.html +add-highlighter shared/crystal/quoted-symbol region ':"' '(?<!\\)(\\\\)*"' fill value + +# Regular expressions +# https://crystal-lang.org/reference/syntax_and_semantics/literals/regex.html +# https://crystal-lang.org/reference/syntax_and_semantics/literals/regex.html#modifiers +add-highlighter shared/crystal/regex region '/' '(?<!\\)(\\\\)*/[imx]*' regions +# Avoid unterminated regular expression +add-highlighter shared/crystal/division region ' / ' '.\K' group + +# Percent regex literals +# https://crystal-lang.org/reference/syntax_and_semantics/literals/regex.html#percent-regex-literals +add-highlighter shared/crystal/parenthesis-regex region -recurse '\(' '%r?\(' '\)[imx]*' regions +add-highlighter shared/crystal/bracket-regex region -recurse '\[' '%r?\[' '\][imx]*' regions +add-highlighter shared/crystal/brace-regex region -recurse '\{' '%r?\{' '\}[imx]*' regions +add-highlighter shared/crystal/angle-regex region -recurse '<' '%r?<' '>[imx]*' regions +add-highlighter shared/crystal/pipe-regex region '%r?\|' '\|[imx]*' regions + +# Command +# https://crystal-lang.org/reference/syntax_and_semantics/literals/command.html +add-highlighter shared/crystal/command region '`' '(?<!\\)(\\\\)*`' regions + +# Percent command literals +add-highlighter shared/crystal/parenthesis-command region -recurse '\(' '%x?\(' '\)' regions +add-highlighter shared/crystal/bracket-command region -recurse '\[' '%x?\[' '\]' regions +add-highlighter shared/crystal/brace-command region -recurse '\{' '%x?\{' '\}' regions +add-highlighter shared/crystal/angle-command region -recurse '<' '%x?<' '>' regions +add-highlighter shared/crystal/pipe-command region '%x?\|' '\|' regions + +evaluate-commands %sh[ + # Keywords + eval "set -- $kak_quoted_opt_crystal_keywords" + regex="\\b(?:\\Q$1\\E" + shift + for keyword do + regex="$regex|\\Q$keyword\\E" + done + regex="$regex)\\b" + printf 'add-highlighter shared/crystal/code/keywords regex %s 0:keyword\n' "$regex" + + # Attributes + eval "set -- $kak_quoted_opt_crystal_attributes" + regex="\\b(?:\\Q$1\\E" + shift + for attribute do + regex="$regex|\\Q$attribute\\E" + done + regex="$regex)\\b" + printf 'add-highlighter shared/crystal/code/attributes regex %s 0:attribute\n' "$regex" + + # Symbols + eval "set -- $kak_quoted_opt_crystal_operators" + # Avoid to match modules + regex="(?<!:):(?:\\w+[?!]?" + for operator do + regex="$regex|\\Q$operator\\E" + done + regex="$regex)" + printf 'add-highlighter shared/crystal/code/symbols regex %%(%s) 0:value\n' "$regex" + + # Objects + eval "set -- $kak_quoted_opt_crystal_objects" + regex="\\b(?:\\Q$1\\E" + shift + for object do + regex="$regex|\\Q$object\\E" + done + regex="$regex)\\b" + printf 'add-highlighter shared/crystal/code/objects regex %s 0:builtin\n' "$regex" + + # Interpolation + # String + # https://crystal-lang.org/reference/syntax_and_semantics/literals/string.html#interpolation + for id in string parenthesis-string bracket-string brace-string angle-string pipe-string heredoc; do + printf " + add-highlighter shared/crystal/$id/fill default-region fill string + add-highlighter shared/crystal/$id/interpolation region -recurse '\\{' '#\\{' '\\}' ref crystal + " + done + + # Regular expressions + # https://crystal-lang.org/reference/syntax_and_semantics/literals/regex.html#interpolation + for id in regex parenthesis-regex bracket-regex brace-regex angle-regex pipe-regex; do + printf " + add-highlighter shared/crystal/$id/fill default-region fill meta + add-highlighter shared/crystal/$id/interpolation region -recurse '\\{' '#\\{' '\\}' ref crystal + " + done + + # Command + for id in command parenthesis-command bracket-command brace-command angle-command pipe-command; do + printf " + add-highlighter shared/crystal/$id/fill default-region fill meta + add-highlighter shared/crystal/$id/interpolation region -recurse '\\{' '#\\{' '\\}' ref crystal + " + done +] + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden crystal-trim-indent %{ + evaluate-commands -no-hooks -draft -itersel %{ + execute-keys x + # remove trailing white spaces + try %{ execute-keys -draft s \h+$ <ret> d } + } +} + +define-command -hidden crystal-indent-on-char %{ + evaluate-commands -no-hooks -draft -itersel %{ + # align 'else' to 'if/case' + try %{ execute-keys -draft x <a-k> ^\h*else$ <ret> <a-a>i <a-semicolon> <a-?> ^\h*(?:if|case) <ret> <a-S> 1<a-&> } + # align 'elsif' to 'if' + try %{ execute-keys -draft x <a-k> ^\h*elsif$ <ret> <a-a>i <a-semicolon> <a-?> ^\h*(?:if) <ret> <a-S> 1<a-&> } + # align 'when' to 'case' + try %{ execute-keys -draft x <a-k> ^\h*when$ <ret> <a-a>i <a-semicolon> <a-?> ^\h*(?:case) <ret> <a-S> 1<a-&> } + # align 'rescue' to 'begin/def' + try %{ execute-keys -draft x <a-k> ^\h*rescue$ <ret> <a-a>i <a-semicolon> <a-?> ^\h*(?:begin|def) <ret> <a-S> 1<a-&> } + # align 'end' to opening structure + try %{ execute-keys -draft x <a-k> ^\h*end$ <ret> <a-a>i <a-semicolon> <a-?> ^\h*(?:begin|case|class|def|for|if|module|unless|until|while) <ret> <a-S> 1<a-&> } + } +} + +define-command -hidden crystal-indent-on-new-line %{ + evaluate-commands -no-hooks -draft -itersel %{ + # Copy previous line indent + try %{ execute-keys -draft K <a-&> } + # Remove previous line's trailing spaces + try %{ execute-keys -draft k :crystal-trim-indent <ret> } + # Indent after start structure/opening statement + try %{ execute-keys -draft k x <a-k> ^\h*(?:begin|case|class|def|else|elsif|ensure|for|if|module|rescue|unless|until|when|while|.+\bdo$|.+\bdo\h\|.+(?=\|))[^0-9A-Za-z_!?] <ret> j <a-gt> } + } +} + +define-command -hidden crystal-insert-on-new-line %[ + evaluate-commands -no-hooks -draft -itersel %[ + # copy _#_ comment prefix and following white spaces + try %{ execute-keys -draft k x s '^\h*\K#\h*' <ret> y j x<semicolon> P } + # wisely add end structure + evaluate-commands -save-regs x %[ + try %{ execute-keys -draft k x s ^ \h + <ret> \" x y } catch %{ reg x '' } + try %[ + evaluate-commands -draft %[ + # Check if previous line opens a block + execute-keys -draft kx <a-k>^<c-r>x(?:begin|case|class|def|for|if|module|unless|until|while|.+\bdo$|.+\bdo\h\|.+(?=\|))[^0-9A-Za-z_!?]<ret> + # Check that we do not already have an end for this indent level which is first set via `crystal-indent-on-new-line` hook + execute-keys -draft }i J x <a-K> ^<c-r>x(?:end|else|elsif|rescue|when)[^0-9A-Za-z_!?]<ret> + ] + execute-keys -draft o<c-r>xend<esc> # insert a new line with containing end + ] + ] + ] +] + +define-command -hidden crystal-fetch-keywords %{ + set-register dquote %sh{ + curl --location https://github.com/crystal-lang/crystal/raw/master/src/compiler/crystal/syntax/lexer.cr | + kak -f '%1scheck_ident_or_keyword\(:(\w+\??), \w+\)<ret>y%<a-R>a<ret><esc><a-_>a<del><esc>|sort<ret>' + } +} + +define-command -hidden crystal-fetch-operators %{ + set-register dquote %sh{ + curl --location https://github.com/crystal-lang/crystal/raw/master/src/compiler/crystal/syntax/parser.cr | + kak -f '/AtomicWithMethodCheck =<ret>x1s:"([^"]+)"<ret>y%<a-R>i''<esc>a''<ret><esc><a-_>a<del><esc>' + } +} + +define-command -hidden crystal-fetch-objects %{ + set-register dquote %sh{ + curl --location https://crystal-lang.org/api/ | + # Remove Top Level Namespace + kak -f '%1sdata-id="github.com/crystal-lang/crystal/(\w+)"<ret>)<a-,>y%<a-R>a<ret><esc><a-_>a<del><esc>' + } +} + +§ diff --git a/autoload/filetype/css.kak b/autoload/filetype/css.kak new file mode 100644 index 0000000..b498a43 --- /dev/null +++ b/autoload/filetype/css.kak @@ -0,0 +1,186 @@ +# http://w3.org/Style/CSS +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](css) %{ + set-option buffer filetype css +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=css %[ + require-module css + + hook window ModeChange pop:insert:.* -group css-trim-indent css-trim-indent + hook window InsertChar \n -group css-insert css-insert-on-new-line + hook window InsertChar \n -group css-indent css-indent-on-new-line + hook window InsertChar \} -group css-indent css-indent-on-closing-curly-brace + set-option buffer extra_word_chars '_' '-' + set-face global cssLogicalOperator +i@keyword + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window css-.+ } +] + +hook -group css-highlight global WinSetOption filetype=css %{ + add-highlighter window/css ref css + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/css } +} + + +provide-module css %[ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ +add-highlighter shared/css regions +add-highlighter shared/css/code default-region group +add-highlighter shared/css/attr_selector region \[ \] regions +add-highlighter shared/css/double_string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/css/single_string region "'" (?<!\\)(\\\\)*' fill string +add-highlighter shared/css/comment region /\* \*/ fill comment + +evaluate-commands %sh{ + # html tags + # generated from the URL & <code> below + # includes elements that cannot be styled, which is fine. + # + # https://developer.mozilla.org/en-US/docs/Web/HTML/Element + html_tags='html body address article aside footer header h1 h2 h3 h4 h5 h6 main nav section blockquote dd div dl dt figcaption figure hr li ol p pre ul a abbr b bdi bdo br cite code data dfn em i kbd mark q rp rt ruby s samp small span strong sub sup time u var wbr area audio img map track video embed iframe object param picture portal source canvas noscript script del ins caption col colgroup table tbody td tfoot th thead tr button datalist fieldset form input label legend meter optgroup option output progress select textarea details dialog menu summary slot template acronym applet basefont bgsound big blink center content dir font frame frameset hgroup image keygen marquee menuitem nobr noembed noframes plaintext rb rtc shadow spacer strike tt xmp' + + # Units + # ‾‾‾‾‾ + # generated from the URL & <code> below + # includes #rgb, #rrggbb, #rrggbbaa as color values {3,8} + # + # https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Values_and_Units + units='% cap ch cm deg dpcm dpi dppx em ex grad Hz ic in kHz lh mm ms pc pt px Q rad rem rlh s turn vb vh vi vmax vmin vw x' + + logical_ops='and not only from to' + keywords='!important auto inherit initial unset none' + media_types='all print screen speech' + + # easing_re='linear|ease(-(in-out|in|out))?|step-(start|end)' + + # combinators='+ > ~ ||' + # attribute_op='= ~= |= ^= $= *=' + + join() { eval set -- $1; IFS="|"; echo "$*"; } + + # Selectors + # ‾‾‾‾‾‾‾‾‾ + # universal: *, ns|*, *|*, |* + # class/id: .class, #id + # type: element + # attr: [attr=val] + + # order below matters + printf %s " + add-highlighter shared/css/code/tag_selectors regex \b($(join "${html_tags}"))((:[a-z:])|[\h.#,]) 1:keyword + + add-highlighter shared/css/code/functional_notation regex ([a-zA-Z0-9-_]+[a-zA-Z0-9])\( 1:keyword + + add-highlighter shared/css/code/logical_operators regex (\b($(join "${logical_ops}"))\b|$(join "${keywords}")) 1:cssLogicalOperator + + add-highlighter shared/css/code/media_types regex \b($(join "${media_types}"))\b 1:+i + + # (after functional notation as they may contain paranthesis) + add-highlighter shared/css/code/pseudo regex (:{1,2})([a-z-]+) 0:attribute + + add-highlighter shared/css/code/at_rules regex @[a-z-]+ 0:function + + add-highlighter shared/css/code/css_property regex ([A-Za-z][A-Za-z0-9_-]*)\h*:\h 1:operator 1:+a + + add-highlighter shared/css/code/selectors regex (\*|[*]?[.][A-Za-z][A-Za-z0-9_-]+) 0:type + add-highlighter shared/css/code/selectors_id regex (\*|[*]?[#][A-Za-z][A-Za-z0-9_-]+) 0:type 0:+i + + add-highlighter shared/css/code/hex_values regex (#[0-9A-Fa-f]{3,8})\b 0:value 0:+a + add-highlighter shared/css/code/units regex \b(\d*\.)?\d+($(join "${units}"))?\b 0:value 0:+a + " +} + +# Attribute Selectors +add-highlighter shared/css/attr_selector/base default-region group +add-highlighter shared/css/attr_selector/base/ regex ([a-zA-Z0-9-]+) 1:attribute +add-highlighter shared/css/attr_selector/base/ regex \h(i|s) 1:type +add-highlighter shared/css/attr_selector/double_string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/css/attr_selector/single_string region "'" (?<!\\)(\\\\)*' fill string + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden css-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden css-indent-on-new-line %[ + evaluate-commands -draft -itersel %[ + execute-keys <semicolon> + try %< + # if previous line is part of a comment, do nothing + execute-keys -draft <a-?>/\*<ret> <a-K>^\h*[^/*\h]<ret> + > catch %< + # else if previous line closed a paren (possibly followed by words and a comment), + # copy indent of the opening paren line + execute-keys -draft kx 1s(\))(\h+\w+)*\h*(\;\h*)?(?://[^\n]+)?\n\z<ret> m<a-semicolon>J <a-S> 1<a-&> + > catch %< + # else indent new lines with the same level as the previous one + execute-keys -draft K <a-&> + > + # filter previous line + try %< execute-keys -draft k x <a-k>^\h+$<ret> Hd > + # indent after lines ending with with { + try %[ execute-keys -draft k x <a-k> \{$ <ret> j <a-gt> ] + # deindent closing brace when after cursor + try %[ execute-keys -draft x <a-k> ^\h*\} <ret> gh / \} <ret> m <a-S> 1<a-&> ] + ] +] + +define-command -hidden css-insert-on-new-line %[ + evaluate-commands -draft -itersel %< + execute-keys <semicolon> + try %[ + # if the previous line isn't within a comment scope, break + execute-keys -draft kx <a-k>^(\h*/\*|\h+\*(?!/))<ret> + + # find comment opening, validate it was not closed, and check its using star prefixes + execute-keys -draft <a-?>/\*<ret><a-H> <a-K>\*/<ret> <a-k>\A\h*/\*([^\n]*\n\h*\*)*[^\n]*\n\h*.\z<ret> + + try %[ + # if the previous line is opening the comment, insert star preceeded by space + execute-keys -draft kx<a-k>^\h*/\*<ret> + execute-keys -draft i*<space><esc> + ] catch %[ + try %[ + # if the next line is a comment line insert a star + execute-keys -draft jx<a-k>^\h+\*<ret> + execute-keys -draft i*<space><esc> + ] catch %[ + try %[ + # if the previous line is an empty comment line, close the comment scope + execute-keys -draft kx<a-k>^\h+\*\h+$<ret> x1s\*(\h*)<ret>c/<esc> + ] catch %[ + # if the previous line is a non-empty comment line, add a star + execute-keys -draft i*<space><esc> + ] + ] + ] + + # trim trailing whitespace on the previous line + try %[ execute-keys -draft s\h+$<ret> d ] + # align the new star with the previous one + execute-keys Kx1s^[^*]*(\*)<ret>& + ] + > +] + +define-command -hidden css-indent-on-closing-curly-brace %[ + evaluate-commands -draft -itersel %[ + # align to opening curly brace when alone on a line + try %[ execute-keys -draft <a-h> <a-k> ^\h+\}$ <ret> m s \A|.\z <ret> 1<a-&> ] + ] +] + +] diff --git a/autoload/filetype/cucumber.kak b/autoload/filetype/cucumber.kak new file mode 100644 index 0000000..f8f5415 --- /dev/null +++ b/autoload/filetype/cucumber.kak @@ -0,0 +1,102 @@ +# http://cukes.info +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](feature|story) %{ + set-option buffer filetype cucumber +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=cucumber %{ + require-module cucumber + + hook window ModeChange pop:insert:.* -group cucumber-trim-indent cucumber-trim-indent + hook window InsertChar \n -group cucumber-insert cucumber-insert-on-new-line + hook window InsertChar \n -group cucumber-indent cucumber-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window cucumber-.+ } +} + +hook -group cucumber-highlight global WinSetOption filetype=cucumber %{ + add-highlighter window/cucumber ref cucumber + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/cucumber } +} + + +provide-module cucumber %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/cucumber regions +add-highlighter shared/cucumber/code default-region group +add-highlighter shared/cucumber/language region ^\h*#\h*language: $ group +add-highlighter shared/cucumber/comment region ^\h*# $ fill comment + +add-highlighter shared/cucumber/language/ fill meta +add-highlighter shared/cucumber/language/ regex \S+$ 0:value + +# Spoken languages +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +# https://github.com/cucumber/cucumber/wiki/Spoken-languages +# +# curl --location https://github.com/cucumber/gherkin/raw/master/lib/gherkin/i18n.json +# +# { +# "en": { +# "name": "English", +# "native": "English", +# "feature": "Feature|Business Need|Ability", +# "background": "Background", +# "scenario": "Scenario", +# "scenario_outline": "Scenario Outline|Scenario Template", +# "examples": "Examples|Scenarios", +# "given": "*|Given", +# "when": "*|When", +# "then": "*|Then", +# "and": "*|And", +# "but": "*|But" +# }, +# … +# } +# +# jq 'with_entries({ key: .key, value: .value | del(.name) | del(.native) | join("|") })' +# +# { +# "en": "Feature|Business Need|Ability|Background|Scenario|Scenario Outline|Scenario Template|Examples|Scenarios|*|Given|*|When|*|Then|*|And|*|But", +# … +# } + +add-highlighter shared/cucumber/code/ regex \b(Feature|Business\h+Need|Ability|Background|Scenario|Scenario\h+Outline|Scenario\h+Template|Examples|Scenarios|Given|When|Then|And|But)\b 0:keyword + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden cucumber-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden cucumber-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy '#' comment prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K#\h* <ret> y gh j P } + } +} + +define-command -hidden cucumber-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : cucumber-trim-indent <ret> } + # indent after lines containing : + try %{ execute-keys -draft , k x <a-k> : <ret> j <a-gt> } + } +} + +} diff --git a/autoload/filetype/cue.kak b/autoload/filetype/cue.kak new file mode 100644 index 0000000..f400837 --- /dev/null +++ b/autoload/filetype/cue.kak @@ -0,0 +1,168 @@ +# https://cuelang.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](cue) %{ + set-option buffer filetype cue +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=cue %[ + require-module cue + + # cleanup trailing whitespaces when exiting insert mode + hook window ModeChange pop:insert:.* -group cue-trim-indent cue-trim-indent + hook window InsertChar \n -group cue-insert cue-insert-on-new-line + hook window InsertChar \n -group cue-indent cue-indent-on-new-line + hook window InsertChar \{ -group cue-indent cue-indent-on-opening-curly-brace + hook window InsertChar [)}] -group cue-indent cue-indent-on-closing + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window cue-.+ } +] + +hook -group cue-highlight global WinSetOption filetype=cue %{ + add-highlighter window/cue ref cue + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/cue } +} + +provide-module cue %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +# https://cuelang.org/docs/references/spec/ + +add-highlighter shared/cue regions +add-highlighter shared/cue/code default-region group +add-highlighter shared/cue/simple_string region '"' (?<!\\)(\\\\)*" regions +add-highlighter shared/cue/simple_bytes region "'" (?<!\\)(\\\\)*' fill string +add-highlighter shared/cue/multiline_string region '"""' '"""' ref shared/cue/simple_string +add-highlighter shared/cue/multiline_bytes region "'''" "'''" ref shared/cue/simple_bytes +add-highlighter shared/cue/line_comment region "//" "$" fill comment + +add-highlighter shared/cue/simple_string/base default-region fill string +add-highlighter shared/cue/simple_string/interpolation region -recurse \( \\\( \) fill meta + +evaluate-commands %sh{ + # Grammar + binary_digit="[01]" + decimal_digit="[0-9]" + hex_digit="[0-9a-fA-F]" + octal_digit="[0-7]" + + decimal_lit="[1-9](_?${decimal_digit})*" + binary_lit="0b${binary_digit}(_?${binary_digit})*" + hex_lit="0[xX]${hex_digit}(_?${hex_digit})*" + octal_lit="0o${octal_digit}(_?${octal_digit})*" + + decimals="${decimal_digit}(_?${decimal_digit})*" + multiplier="([KMGTP]i?)?" + exponent="([eE][+-]?${decimals})" + si_lit="(${decimals}(\.${decimals})?${multiplier}|\.${decimals}${multiplier})" + + int_lit="\b(${decimal_lit}|${si_lit}|${octal_lit}|${binary_lit}|${hex_lit})\b" + float_lit="\b${decimals}\.(${decimals})?${exponent}?|\b${decimals}${exponent}\b|\.${decimals}${exponent}?\b" + + operator_chars="(\+|-|\*|/|&|&&|\||\|\||=|==|=~|!|!=|!~|<|>|<=|>=)" + punctuation="(_\|_|:|::|,|\.|\.\.\.|\(|\{|\[|\)|\}|\])" + + function_calls="\w+(?=\()" + identifier="(?!\d)[\w_$]+" + reserved="\b__${identifier}" + + preamble="^(package|import)\b" + + functions="len close and or" + keywords="for in if let" + operators="div mod quo rem" + types=" + bool string bytes rune number + uint uint8 uint16 uint32 uint64 uint128 + int int8 int16 int32 int64 int128 + float float32 float64 + " + values="null true false" + + join() { sep=$2; set -- $1; IFS="$sep"; echo "$*"; } + + static_words="$(join "package import ${functions} ${keywords} ${operators} ${types} ${values}" ' ')" + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list cue_static_words ${static_words}" + + functions="$(join "${functions}" '|')" + keywords="$(join "${keywords}" '|')" + operators="$(join "${operators}" '|')" + types="$(join "${types}" '|')" + values="$(join "${values}" '|')" + + # Highlight keywords + printf %s " + add-highlighter shared/cue/code/ regex ${float_lit} 0:value + add-highlighter shared/cue/code/ regex ${function_calls} 0:function + add-highlighter shared/cue/code/ regex ${int_lit} 0:value + add-highlighter shared/cue/code/ regex ${operator_chars} 0:operator + add-highlighter shared/cue/code/ regex ${preamble} 0:keyword + add-highlighter shared/cue/code/ regex ${punctuation} 0:operator + add-highlighter shared/cue/code/ regex ${reserved} 0:keyword + add-highlighter shared/cue/code/ regex \b(${functions})\b 0:builtin + add-highlighter shared/cue/code/ regex \b(${keywords})\b 0:keyword + add-highlighter shared/cue/code/ regex \b(${operators})\b 0:operator + add-highlighter shared/cue/code/ regex \b(${types})\b 0:type + add-highlighter shared/cue/code/ regex \b(${values})\b 0:value + " +} + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden cue-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden cue-insert-on-new-line %~ + evaluate-commands -draft -itersel %< + # copy // comments prefix and following white spaces + try %{ execute-keys -draft <semicolon><c-s>kx s ^\h*\K//[!/]?\h* <ret> y<c-o>P<esc> } + > +~ + +define-command -hidden cue-indent-on-new-line %~ + evaluate-commands -draft -itersel %< + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + try %< + # only if we didn't copy a comment + execute-keys -draft x <a-K> ^\h*// <ret> + # indent after lines ending with { or ( + try %[ execute-keys -draft k x <a-k> [{(]\h*$ <ret> j <a-gt> ] + # indent after lines ending with [{(].+ and move first parameter to own line + try %< execute-keys -draft [c[({],[)}] <ret> <a-k> \A[({][^\n]+\n[^\n]*\n?\z <ret> L i<ret><esc> <gt> <a-S> <a-&> > + # deindent closing brace(s) when after cursor + try %< execute-keys -draft x <a-k> ^\h*[})] <ret> gh / [})] <ret> m <a-S> 1<a-&> > + > + # filter previous line + try %{ execute-keys -draft k : cue-trim-indent <ret> } + > +~ + +define-command -hidden cue-indent-on-opening-curly-brace %[ + evaluate-commands -draft -itersel %_ + # align indent with opening paren when { is entered on a new line after the closing paren + try %[ execute-keys -draft h <a-F> ) M <a-k> \A\(.*\)\h*\n\h*\{\z <ret> s \A|.\z <ret> 1<a-&> ] + _ +] + +define-command -hidden cue-indent-on-closing %[ + evaluate-commands -draft -itersel %_ + # align to opening curly brace or paren when alone on a line + try %< execute-keys -draft <a-h> <a-k> ^\h*[)}]$ <ret> h m <a-S> 1<a-&> > + _ +] + +§ diff --git a/autoload/filetype/d.kak b/autoload/filetype/d.kak new file mode 100644 index 0000000..359c1ca --- /dev/null +++ b/autoload/filetype/d.kak @@ -0,0 +1,145 @@ +# http://dlang.org/ +# + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*\.di? %{ + set-option buffer filetype d +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=d %{ + require-module d + + set-option window static_words %opt{d_static_words} + + # cleanup trailing whitespaces when exiting insert mode + hook window ModeChange pop:insert:.* -group d-trim-indent %{ try %{ execute-keys -draft xs^\h+$<ret>d } } + hook window InsertChar \n -group d-insert d-insert-on-new-line + hook window InsertChar \n -group d-indent d-indent-on-new-line + hook window InsertChar \{ -group d-indent d-indent-on-opening-curly-brace + hook window InsertChar \} -group d-indent d-indent-on-closing-curly-brace + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window d-.+ } +} + +hook -group d-highlight global WinSetOption filetype=d %{ + add-highlighter window/d ref d + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/d } +} + +provide-module d %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/d regions +add-highlighter shared/d/code default-region group +add-highlighter shared/d/string region %{(?<!')(?<!'\\)"} %{(?<!\\)(?:\\\\)*"} group +add-highlighter shared/d/verbatim_string region %{(?<!')(?<!'\\)`} %{(?<!\\)(?:\\\\)*`} fill meta +add-highlighter shared/d/verbatim_string_prefixed region %{r`([^(]*)\(} %{\)([^)]*)`} fill meta +add-highlighter shared/d/docstring1 region -recurse '/\+' '/\+\+' '\+/' fill documentation +add-highlighter shared/d/docstring2 region '/\*\*' '\*/' fill documentation +add-highlighter shared/d/docstring3 region /// $ fill documentation +add-highlighter shared/d/disabled region -recurse '/\+' '/\+[^+]?' '\+/' fill comment +add-highlighter shared/d/comment1 region '/\*[^*]?' '\*/' fill comment +add-highlighter shared/d/comment2 region '//[^/]?' $ fill comment + +add-highlighter shared/d/string/ fill string +add-highlighter shared/d/string/ regex %{\\(x[0-9a-fA-F]{2}|[0-7]{1,3}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})\b} 0:value +add-highlighter shared/d/code/ regex %{'((\\.)?|[^'\\])'} 0:value +add-highlighter shared/d/code/ regex "-?([0-9_]*\.(?!0[xXbB]))?\b([0-9_]+|0[xX][0-9a-fA-F_]*\.?[0-9a-fA-F_]+|0[bb][01_]+)([ep]-?[0-9_]+)?[fFlLuUi]*\b" 0:value +add-highlighter shared/d/code/ regex "\b(this)\b\s*[^(]" 1:value +add-highlighter shared/d/code/ regex "((?:~|\b)this)\b\s*\(" 1:function +add-highlighter shared/d/code/ regex '(#line)\h+(\d+)(\h+"[^"\n]*")?' 1:meta 2:value 3:string + +evaluate-commands %sh{ + # Grammar + + keywords="abstract|alias|align|asm|assert|auto|body|break|case|cast" + keywords="${keywords}|catch|cent|class|const|continue|debug" + keywords="${keywords}|default|delegate|delete|deprecated|do|else|enum|export|extern" + keywords="${keywords}|final|finally|for|foreach|foreach_reverse|function|goto" + keywords="${keywords}|if|immutable|import|in|inout|interface|invariant" + keywords="${keywords}|is|lazy|macro|mixin|module|new|nothrow|out|override" + keywords="${keywords}|package|pragma|private|protected|public|pure|ref|return|scope" + keywords="${keywords}|shared|static|struct|super|switch|synchronized|template" + keywords="${keywords}|throw|try|typedef|typeid|typeof|union" + keywords="${keywords}|unittest|version|volatile|while|with" + attributes="abstract|align|auto|const|debug|deprecated|export|extern|final" + attributes="${attributes}|immutable|inout|nothrow|package|private|protected" + attributes="${attributes}|public|pure|ref|override|scope|shared|static|synchronized|version" + attributes="${attributes}|__gshared|__traits|__vector|__parameters" + types="bool|byte|cdouble|cent|cfloat|char|creal|dchar|double|dstring|float" + types="${types}|idouble|ifloat|int|ireal|long|ptrdiff_t|real|size_t|short" + types="${types}|string|ubyte|ucent|uint|ulong|ushort|void|wchar|wstring" + values="true|false|null" + tokens="__FILE__|__MODULE__|__LINE__|__FUNCTION__" + tokens="${tokens}|__PRETTY_FUNCTION__|__DATE__|__EOF__|__TIME__" + tokens="${tokens}|__TIMESTAMP__|__VENDOR__|__VERSION__|#line" + properties="this|init|sizeof|alignof|mangleof|stringof|infinity|nan|dig|epsilon|mant_dig" + properties="${properties}|max_10_exp|min_exp|max|min_normal|re|im|classinfo" + properties="${properties}|length|dup|keys|values|rehash|clear" + decorators="disable|property|nogc|safe|trusted|system" + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list d_static_words ${keywords} ${attributes} ${types} ${values} ${decorators} ${properties}" | tr '|' ' ' + + # Highlight keywords + printf %s " + add-highlighter shared/d/code/ regex \b(${keywords})\b 0:keyword + add-highlighter shared/d/code/ regex \b(${attributes})\b 0:attribute + add-highlighter shared/d/code/ regex \b(${types})\b 0:type + add-highlighter shared/d/code/ regex \b(${values})\b 0:value + add-highlighter shared/d/code/ regex @(${decorators})\b 0:attribute + add-highlighter shared/d/code/ regex \b(${tokens})\b 0:builtin + add-highlighter shared/d/code/ regex \.(${properties})\b 1:builtin + " +} + +add-highlighter shared/d/code/ regex "\bimport\s+([\w._-]+)(?:\s*=\s*([\w._-]+))?" 1:module 2:module +add-highlighter shared/d/code/ regex "\bmodule\s+([\w_-]+)\b" 1:module + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden d-insert-on-new-line %~ + evaluate-commands -draft -itersel %= + # copy // comments prefix and following white spaces + try %{ execute-keys -draft <semicolon><c-s>kx s ^\h*\K/{2,}\h* <ret> y<c-o>P<esc> } + = +~ + +define-command -hidden d-indent-on-new-line %~ + evaluate-commands -draft -itersel %= + # preserve previous line indent + try %{ execute-keys -draft <semicolon>K<a-&> } + # indent after lines ending with { or ( + try %[ execute-keys -draft kx <a-k> [{(]\h*$ <ret> j<a-gt> ] + # cleanup trailing white spaces on the previous line + try %{ execute-keys -draft kx s \h+$ <ret>d } + # align to opening paren of previous line + try %{ execute-keys -draft [( <a-k> \A\([^\n]+\n[^\n]*\n?\z <ret> s \A\(\h*.|.\z <ret> '<a-;>' & } + # indent after a switch's case/default statements + try %[ execute-keys -draft kx <a-k> ^\h*(case|default).*:$ <ret> j<a-gt> ] + # indent after if|else|while|for + try %[ execute-keys -draft <semicolon><a-F>)MB <a-k> \A(if|else|while|for)\h*\(.*\)\h*\n\h*\n?\z <ret> s \A|.\z <ret> 1<a-&>1<a-,><a-gt> ] + # deindent closing brace(s) when after cursor + try %[ execute-keys -draft x <a-k> ^\h*[})] <ret> gh / [})] <ret> m <a-S> 1<a-&> ] + = +~ + +define-command -hidden d-indent-on-opening-curly-brace %[ + # align indent with opening paren when { is entered on a new line after the closing paren + try %[ execute-keys -draft -itersel h<a-F>)M <a-k> \A\(.*\)\h*\n\h*\{\z <ret> s \A|.\z <ret> 1<a-&> ] +] + +define-command -hidden d-indent-on-closing-curly-brace %[ + # align to opening curly brace when alone on a line + try %[ execute-keys -itersel -draft <a-h><a-k>^\h+\}$<ret>hms\A|.\z<ret>1<a-&> ] +] + +§ diff --git a/autoload/filetype/dart.kak b/autoload/filetype/dart.kak new file mode 100644 index 0000000..d662359 --- /dev/null +++ b/autoload/filetype/dart.kak @@ -0,0 +1,126 @@ +# https://dartlang.org/ +# + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*\.dart %{ + set-option buffer filetype dart +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=dart %{ + require-module dart + + set-option window static_words %opt{dart_static_words} + + # cleanup trailing whitespaces when exiting insert mode + hook window ModeChange pop:insert:.* -group dart-trim-indent %{ try %{ execute-keys -draft xs^\h+$<ret>d } } + hook window InsertChar \n -group dart-insert dart-insert-on-new-line + hook window InsertChar \n -group dart-indent dart-indent-on-new-line + hook window InsertChar \{ -group dart-indent dart-indent-on-opening-curly-brace + hook window InsertChar \} -group dart-indent dart-indent-on-closing-curly-brace + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window dart-.+ } +} + +hook -group dart-highlight global WinSetOption filetype=dart %{ + add-highlighter window/dart ref dart + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/dart } +} + + +provide-module dart %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/dart regions +add-highlighter shared/dart/code default-region group +add-highlighter shared/dart/double_string region '"' (?<!\\)(\\\\)*" group +add-highlighter shared/dart/single_string region "'" (?<!\\)(\\\\)*' group +add-highlighter shared/dart/comment region /\* \*/ fill comment +add-highlighter shared/dart/comment_line region '//' $ fill comment + +add-highlighter shared/dart/code/ regex %{-?([0-9]*\.(?!0[xX]))?\b([0-9]+|0[xX][0-9a-fA-F]+)\.?([eE][+-]?[0-9]+)?i?\b} 0:value + +# String interpolation +add-highlighter shared/dart/double_string/ fill string +add-highlighter shared/dart/double_string/ regex \$\{.*?\} 0:value +add-highlighter shared/dart/single_string/ fill string +add-highlighter shared/dart/single_string/ regex \$\{.*?\} 0:value + +evaluate-commands %sh{ + # Grammar + keywords="abstract|do|import|super|as|in|switch|assert|else|interface|async" + keywords="${keywords}|enum|is|this|export|library|throw|await|external|mixin|break|extends" + keywords="${keywords}|new|try|case|factory|typedef|catch|operator|class|final|part|extension" + keywords="${keywords}|const|finally|rethrow|while|continue|for|return|with|covariant" + keywords="${keywords}|get|set|yield|default|if|static|deferred|implements" + generator_keywords="async\*|sync\*|yield\*" + + types="void|bool|num|int|double|dynamic|var" + values="false|true|null" + + annotations="@[a-zA-Z]+" + functions="(_?[a-z][a-zA-Z0-9]*)(\(|\w+=>)" + classes="_?[A-Z][a-zA-Z0-9]*" + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list dart_static_words ${keywords} ${attributes} ${types} ${values}" | tr '|' ' ' + + # Highlight keywords + printf %s " + add-highlighter shared/dart/code/ regex \b(${keywords})\b 0:keyword + add-highlighter shared/dart/code/ regex \b(${generator_keywords}) 0:keyword + add-highlighter shared/dart/code/ regex \b(${attributes})\b 0:attribute + add-highlighter shared/dart/code/ regex \b(${types})\b 0:type + add-highlighter shared/dart/code/ regex \b(${values})\b 0:value + add-highlighter shared/dart/code/ regex \b(${functions}) 2:function + add-highlighter shared/dart/code/ regex (${annotations})\b 0:meta + add-highlighter shared/dart/code/ regex \b(${classes})\b 0:module + " +} + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden dart-insert-on-new-line %~ + evaluate-commands -draft -itersel %= + # copy // comments prefix and following white spaces + try %{ execute-keys -draft <semicolon><c-s>kx s ^\h*\K/{2,}\h* <ret> y<c-o>P<esc> } + = +~ + +define-command -hidden dart-indent-on-new-line %~ + evaluate-commands -draft -itersel %= + # preserve previous line indent + try %{ execute-keys -draft <semicolon>K<a-&> } + # indent after lines ending with { or ( + try %[ execute-keys -draft kx <a-k> [{(]\h*$ <ret> j<a-gt> ] + # cleanup trailing white spaces on the previous line + try %{ execute-keys -draft kx s \h+$ <ret>d } + # align to opening paren of previous line + try %{ execute-keys -draft [( <a-k> \A\([^\n]+\n[^\n]*\n?\z <ret> s \A\(\h*.|.\z <ret> '<a-;>' & } + # indent after a switch's case/default statements + try %[ execute-keys -draft kx <a-k> ^\h*(case|default).*:$ <ret> j<a-gt> ] + # indent after if|else|while|for + try %[ execute-keys -draft <semicolon><a-F>)MB <a-k> \A(if|else|while|for)\h*\(.*\)\h*\n\h*\n?\z <ret> s \A|.\z <ret> 1<a-&>1<a-,><a-gt> ] + # deindent closing brace when after cursor + try %[ execute-keys -draft x <a-k> ^\h*\} <ret> gh / \} <ret> m <a-S> 1<a-&> ] + = +~ + +define-command -hidden dart-indent-on-opening-curly-brace %[ + # align indent with opening paren when { is entered on a new line after the closing paren + try %[ execute-keys -draft -itersel h<a-F>)M <a-k> \A\(.*\)\h*\n\h*\{\z <ret> s \A|.\z <ret> 1<a-&> ] +] + +define-command -hidden dart-indent-on-closing-curly-brace %[ + # align to opening curly brace when alone on a line + try %[ execute-keys -itersel -draft <a-h><a-k>^\h+\}$<ret>hms\A|.\z<ret>1<a-&> ] +] + +§ diff --git a/autoload/filetype/dhall.kak b/autoload/filetype/dhall.kak new file mode 100644 index 0000000..94b69d6 --- /dev/null +++ b/autoload/filetype/dhall.kak @@ -0,0 +1,101 @@ +# https://dhall-lang.org +# + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](dhall) %{ + set-option buffer filetype dhall +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=dhall %{ + require-module dhall + + hook window ModeChange pop:insert:.* -group dhall-trim-indent dhall-trim-indent + hook window InsertChar \n -group dhall-insert dhall-insert-on-new-line + hook window InsertChar \n -group dhall-indent dhall-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window dhall-.+ } +} + +hook -group dhall-highlight global WinSetOption filetype=dhall %{ + add-highlighter window/dhall ref dhall + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/dhall } +} + + +provide-module dhall %[ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/dhall regions +add-highlighter shared/dhall/code default-region group +add-highlighter shared/dhall/string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/dhall/comment region -recurse \{- \{- -\} fill comment +add-highlighter shared/dhall/line_comment region -- $ fill comment + +# Matches multi-line string literals +add-highlighter shared/dhall/multiline_string region \Q''\E$ [^']''[^'] fill string + +# Matches quoted labels +add-highlighter shared/dhall/quoted_label region ` ` fill normal + +# Matches built-in types +add-highlighter shared/dhall/code/ regex \b(Location|Sort|Kind|Type|Text|Bool|Natural|Integer|Double|List|Optional|\{\})\b 0:type + +# Matches built-in keywords +add-highlighter shared/dhall/code/ regex \b(if|then|else|let|in|using|missing|as|merge|toMap)\b 0:keyword + +# Matches bulit-in values +add-highlighter shared/dhall/code/ regex \b(True|False|Some|None|-?Infinity|\{=\}|NaN)\b 0:value + +# Matches built-in operators +add-highlighter shared/dhall/code/ regex (,|:|\|\||&&|==|!=|=|\+|\*|\+\+|#|⩓|//\\\\|→|->|\?|λ|\\|\^|⫽|//|\[|\]|\{|\}) 0:operator + +# Matches built-in functions +add-highlighter shared/dhall/code/ regex \b(Natural-fold|Natural-build|Natural-isZero|Natural-even|Natural-odd|Natural-toInteger|Natural-show|Integer-toDouble|Integer-show|Natural-subtract|Double-show|List-build|List-fold|List-length|List-head|List-last|List-indexed|List-reverse|Optional-fold|Optional-build|Text-show)\b 0:keyword + +# Matches http[s] imports +add-highlighter shared/dhall/code/ regex \b(http[s]://\S+)\b(\s+sha256:[a-f0-9]{64}\b)? 0:meta + +# Matches local imports +add-highlighter shared/dhall/code/ regex (~|\.|\.\.|/)\S+ 0:meta + +# Matches number (natural, integer, double) literals +add-highlighter shared/dhall/code/ regex \b(\+|-)?\d+(\.\d+)?(e(\+|-)?\d+)?\b 0:value + +# Matches union syntax +add-highlighter shared/dhall/union region -recurse < < > group +add-highlighter shared/dhall/union/sep regex (<|\|)\s*((?:_|[A-Z])(?:[a-zA-Z0-9-/_]*))\s*(?:(:)([^|>]*))? 1:operator 2:attribute 3:operator 4:type +add-highlighter shared/dhall/union/end regex > 0:operator + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden dhall-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden dhall-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy -- comments prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K--\h* <ret> y gh j P } + } +} +define-command -hidden dhall-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft \; K <a-&> } + # filter previous line + try %{ execute-keys -draft k : dhall-trim-indent <ret> } + # indent after lines ending with let, : or = + try %{ execute-keys -draft \; k x <a-k> (\blet|:|=)$ <ret> j <a-gt> } + } +} + +] diff --git a/autoload/filetype/diff-parse.pl b/autoload/filetype/diff-parse.pl new file mode 100644 index 0000000..203e9b1 --- /dev/null +++ b/autoload/filetype/diff-parse.pl @@ -0,0 +1,143 @@ +#!/usr/bin/env perl + +use warnings; + +sub quote { + my $token = shift; + $token =~ s/'/''/g; + return "'$token'"; +} +sub fail { + my $reason = shift; + print "set-register e fail " . quote("diff-parse.pl: $reason"); + exit; +} + +my $begin; +my $end; + +while (defined $ARGV[0]) { + if ($ARGV[0] eq "--") { + shift; + last; + } + if ($ARGV[0] =~ m{^(BEGIN|END)$}) { + if (not defined $ARGV[1]) { + fail "missing argument to $ARGV[0]"; + } + if ($ARGV[0] eq "BEGIN") { + $begin = $ARGV[1]; + } else { + $end = $ARGV[1]; + } + shift, shift; + next; + } + fail "unknown argument: $ARGV[0]"; +} + +# Inputs +our $directory = $ENV{PWD}; +our $strip; +our $in_file; +our $in_file_line; +our $version = "+"; + +eval $begin if defined $begin; + +$in_file = "$directory/$in_file" if defined $in_file; + +# Outputs +our $diff_line = 0; +our $commit; +our $file; +our $file_line; +our $diff_line_text; + +my $other_version; +if ($version eq "+") { + $other_version = "-"; +} else { + $other_version = "+"; +} +my $is_recursive_diff = 0; +my $state = "header"; +my $fallback_file; +my $other_file; +my $other_file_line; + +sub strip { + my $is_recursive_diff = shift; + my $f = shift; + + my $effective_strip; + if (defined $strip) { + $effective_strip = $strip; + } else { + # A "diff -r" or "git diff" adds "diff" lines to + # the output. If no such line is present, we have + # a plain diff between files (not directories), so + # there should be no need to strip the directory. + $effective_strip = $is_recursive_diff ? 1 : 0; + } + + if ($f !~ m{^/}) { + $f =~ s,^([^/]+/+){$effective_strip},, or fail "directory prefix underflow"; + $f = "$directory/$f"; + } + return $f; +} + +while (<STDIN>) { + $diff_line++; + s/^(> )*//g; + $diff_line_text = $_; + if (m{^commit (\w+)}) { + $commit = $1; + next; + } + if (m{^diff\b}) { + $state = "header"; + $is_recursive_diff = 1; + if (m{^diff -\S* (\S+) (\S+)$}) { + $fallback_file = strip $is_recursive_diff, ($version eq "+" ? $2 : $1); + } + next; + } + if ($state eq "header") { + if (m{^[$version]{3} ([^\t\n]+)}) { + $file = strip $is_recursive_diff, $1; + next; + } + if (m{^[$other_version]{3} ([^\t\n]+)}) { + $other_file = strip $is_recursive_diff, $1; + next; + } + } + if (m{^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@}) { + $state = "contents"; + $file_line = ($version eq "+" ? $2 : $1) - 1; + $other_file_line = ($version eq "+" ? $1 : $2) - 1; + } else { + my $iscontext = m{^[ ]}; + if (m{^[ $version]}) { + $file_line++ if defined $file_line; + } + if (m{^[ $other_version]}) { + $other_file_line++ if defined $other_file_line; + } + } + if (defined $in_file and defined $file and $file eq $in_file) { + if (defined $in_file_line and defined $file_line and $file_line >= $in_file_line) { + last; + } + } +} +if (not defined $file) { + $file = ($fallback_file or $other_file); +} +if (not defined $file) { + fail "missing diff header"; +} + +eval $end if defined $end; diff --git a/autoload/filetype/diff.kak b/autoload/filetype/diff.kak new file mode 100644 index 0000000..baa6599 --- /dev/null +++ b/autoload/filetype/diff.kak @@ -0,0 +1,141 @@ +hook global BufCreate .*\.(diff|patch) %{ + set-option buffer filetype diff +} + +hook global WinSetOption filetype=diff %{ + require-module diff + map buffer normal <ret> :diff-jump<ret> +} + +hook -group diff-highlight global WinSetOption filetype=diff %{ + add-highlighter window/diff ref diff + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/diff } +} + +provide-module diff %§ + +add-highlighter shared/diff group +add-highlighter shared/diff/ regex "^\+[^\n]*\n" 0:green,default +add-highlighter shared/diff/ regex "^-[^\n]*\n" 0:red,default +add-highlighter shared/diff/ regex "^@@[^\n]*@@" 0:cyan,default +# If any trailing whitespace was introduced in diff, show it with red background +add-highlighter shared/diff/ regex "^\+[^\n]*?(\h+)\n" 1:default,red + +define-command diff-jump -params .. -docstring %{ + diff-jump [<switches>] [<directory>]: edit the diff's source file at the cursor position. + Paths are resolved relative to <directory>, or the current working directory if unspecified. + + Switches: + - jump to the old file instead of the new file + -<num> strip <num> leading directory components, like -p<num> in patch(1). Defaults to 1 if there is a 'diff' line (as printed by 'diff -r'), or 0 otherwise. + } %{ + evaluate-commands -draft -save-regs c %{ + # Save the column because we will move the cursor. + set-register c %val{cursor_column} + # If there is a "diff" line, we don't need to look further back. + try %{ + execute-keys %{<a-l><semicolon><a-?>^(?:> )*diff\b<ret>x} + } catch %{ + # A single file diff won't have a diff line. Start parsing from + # the buffer start, so we can tell if +++/--- lines are headers + # or content. + execute-keys Gk + } + diff-parse BEGIN %{ + my $seen_ddash = 0; + foreach (@ARGV) { + if ($seen_ddash or !m{^-}) { + $directory = $_; + } elsif ($_ eq "-") { + $version = "-", $other_version = "+"; + } elsif (m{^-(\d+)$}) { + $strip = $1; + } elsif ($_ eq "--") { + $seen_ddash = 1; + } else { + fail "unknown option: $_"; + } + } + } END %exp{ + my $file_column; + if (not defined $file_line) { + $file_line = ""; + $file_column = ""; + } else { + my $diff_column = %reg{c}; + $file_column = $diff_column - 1; # Account for [ +-] diff prefix. + # If the cursor was on a hunk header, go to the section header if possible. + if ($diff_line_text =~ m{^(@@ -\d+(?:,\d+)? \+\d+(?:,\d+) @@ )([^\n]*)}) { + my $hunk_header_prefix = $1; + my $hunk_header_from_userdiff = $2; + open FILE, "<", $file or fail "failed to open file: $!: $file"; + my @lines = <FILE>; + for (my $i = $file_line - 1; $i >= 0 and $i < scalar @lines; $i--) { + if ($lines[$i] !~ m{\Q$hunk_header_from_userdiff}) { + next; + } + $file_line = $i + 1; + # Re-add 1 because the @@ line does not have a [ +-] diff prefix. + $file_column = $diff_column + 1 - length $hunk_header_prefix; + last; + } + } + } + printf "set-register c %%s $file_line $file_column\n", quote($file); + } -- %arg{@} + evaluate-commands -client %val{client} %{ + evaluate-commands -try-client %opt{jumpclient} %{ + edit -existing -- %reg{c} + } + } + } +} +complete-command diff-jump file + +define-command -hidden diff-parse -params 2.. %{ + evaluate-commands -save-regs ae| %{ + set-register a %arg{@} + set-register e nop + set-register | %{ + eval set -- "$kak_quoted_reg_a" + perl "${kak_runtime}/rc/filetype/diff-parse.pl" "$@" >"$kak_command_fifo" + } + execute-keys <a-|><ret> + %reg{e} + } +} + +§ + +define-command \ + -docstring %{diff-select-file: Select surrounding patch file} \ + -params 0 \ + diff-select-file %{ + evaluate-commands -itersel -save-regs 'ose/' %{ + try %{ + execute-keys '"oZgl<a-?>^diff <ret>;"sZ' 'Ge"eZ' + try %{ execute-keys '"sz?\n(?=diff )<ret>"e<a-Z><lt>' } + execute-keys '"ez' + } catch %{ + execute-keys '"oz' + fail 'Not in a diff file' + } + } +} + +define-command \ + -docstring %{diff-select-hunk: Select surrounding patch hunk} \ + -params 0 \ + diff-select-hunk %{ + evaluate-commands -itersel -save-regs 'ose/' %{ + try %{ + execute-keys '"oZgl<a-?>^@@ <ret>;"sZ' 'Ge"eZ' + try %{ execute-keys '"sz?\n(?=diff )<ret>"e<a-Z><lt>' } + try %{ execute-keys '"sz?\n(?=@@ )<ret>"e<a-Z><lt>' } + execute-keys '"ez' + } catch %{ + execute-keys '"oz' + fail 'Not in a diff hunk' + } + } +} diff --git a/autoload/filetype/dockerfile.kak b/autoload/filetype/dockerfile.kak new file mode 100644 index 0000000..a9000d8 --- /dev/null +++ b/autoload/filetype/dockerfile.kak @@ -0,0 +1,55 @@ +# http://docker.com +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# See https://docs.docker.com/reference/builder + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*/?Dockerfile(\..+)?$ %{ + set-option buffer filetype dockerfile +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=dockerfile %{ + require-module dockerfile + set-option window static_words %opt{dockerfile_static_words} +} + +hook -group dockerfile-highlight global WinSetOption filetype=dockerfile %{ + add-highlighter window/dockerfile ref dockerfile + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/dockerfile } +} + +provide-module dockerfile %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/dockerfile regions +add-highlighter shared/dockerfile/code default-region group +add-highlighter shared/dockerfile/double_string region '"' '(?<!\\)(\\\\)*"' fill string +add-highlighter shared/dockerfile/single_string region "'" "'" fill string +add-highlighter shared/dockerfile/comment region '#' $ fill comment + +evaluate-commands %sh{ + # Grammar + keywords="ADD|ARG|CMD|COPY|ENTRYPOINT|ENV|EXPOSE|FROM|HEALTHCHECK|LABEL" + keywords="${keywords}|MAINTAINER|RUN|SHELL|STOPSIGNAL|USER|VOLUME|WORKDIR" + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list dockerfile_static_words ONBUILD|${keywords}" | tr '|' ' ' + + # Highlight keywords + printf %s " + add-highlighter shared/dockerfile/code/ regex '^(?i)(ONBUILD\h+)?(${keywords})\b' 2:keyword + add-highlighter shared/dockerfile/code/ regex '^(?i)(ONBUILD)\h+' 1:keyword + " +} + +add-highlighter shared/dockerfile/code/ regex (?<!\\)(?:\\\\)*\K\$\{[\w_]+\} 0:value +add-highlighter shared/dockerfile/code/ regex (?<!\\)(?:\\\\)*\K\$[\w_]+ 0:value + +} diff --git a/autoload/filetype/elixir.kak b/autoload/filetype/elixir.kak new file mode 100644 index 0000000..9c06052 --- /dev/null +++ b/autoload/filetype/elixir.kak @@ -0,0 +1,128 @@ +# http://elixir-lang.org +# ---------------------- + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](ex|exs) %{ + set-option buffer filetype elixir +} + +hook global BufCreate .*[.]html[.]l?eex %{ + set-option buffer filetype eex +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=elixir %{ + require-module elixir + + hook window ModeChange pop:insert:.* -group elixir-trim-indent elixir-trim-indent + hook window InsertChar \n -group elixir-indent elixir-indent-on-new-line + hook window InsertChar \n -group elixir-insert elixir-insert-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window elixir-.+ } +} + +hook -group elixir-highlight global WinSetOption filetype=elixir %{ + add-highlighter window/elixir ref elixir + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/elixir } +} + +hook global WinSetOption filetype=eex %{ + require-module eex + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window eex-.+ } +} + +hook -group eex-highlight global WinSetOption filetype=eex %{ + add-highlighter window/eex ref eex + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/eex } +} + +provide-module eex %{ +require-module html +require-module elixir + +add-highlighter shared/eex regions +add-highlighter shared/eex/html default-region ref html +add-highlighter shared/eex/comment region '<%#' '%>' fill comment +add-highlighter shared/eex/quote region '<%%' '%>' ref html +add-highlighter shared/eex/code region '<%=?' '%>' ref elixir +} + +provide-module elixir %[ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/elixir regions +add-highlighter shared/elixir/code default-region group +add-highlighter shared/elixir/double_string region -match-capture ("""|") (?<!\\)(?:\\\\)*("""|") regions +add-highlighter shared/elixir/single_string region "'" "(?<!\\)(?:\\\\)*'" fill string +add-highlighter shared/elixir/comment region '#' '$' fill comment + +add-highlighter shared/elixir/leex region -match-capture '~L("""|")' '(?<!\\)(?:\\\\)*("""|")' ref eex + +add-highlighter shared/elixir/double_string/base default-region fill string +add-highlighter shared/elixir/double_string/interpolation region -recurse \{ \Q#{ \} fill builtin + +add-highlighter shared/elixir/code/ regex ':[\w_]+\b' 0:type +add-highlighter shared/elixir/code/ regex '[\w_]+:' 0:type +add-highlighter shared/elixir/code/ regex '[A-Z][\w_]+\b' 0:module +add-highlighter shared/elixir/code/ regex '(:[\w_]+)(\.)' 1:module +add-highlighter shared/elixir/code/ regex '\b_\b' 0:default +add-highlighter shared/elixir/code/ regex '\b_[\w_]+\b' 0:default +add-highlighter shared/elixir/code/ regex '~[a-zA-Z]\(.*?[^\\]\)' 0:string +add-highlighter shared/elixir/code/ regex \b(true|false|nil)\b 0:value +add-highlighter shared/elixir/code/ regex (->|<-|<<|>>|=>) 0:builtin +add-highlighter shared/elixir/code/ regex \b(require|alias|use|import)\b 0:keyword +add-highlighter shared/elixir/code/ regex \b(__MODULE__|__DIR__|__ENV__|__CALLER__)\b 0:value +add-highlighter shared/elixir/code/ regex \b(def|defp|defmacro|defmacrop|defstruct|defmodule|defimpl|defprotocol|defoverridable)\b 0:keyword +add-highlighter shared/elixir/code/ regex \b(fn|do|end|when|case|if|else|unless|var!|for|cond|quote|unquote|receive|with|raise|reraise|try|catch)\b 0:keyword +add-highlighter shared/elixir/code/ regex '@[\w_]+\b' 0:attribute +add-highlighter shared/elixir/code/ regex '\b\d+[\d_]*\b' 0:value + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden elixir-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden elixir-insert-on-new-line %[ + evaluate-commands -no-hooks -draft -itersel %[ + # copy '#' comment prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K#\h* <ret> y jgi P } + # wisely add end structure + evaluate-commands -save-regs x %[ + try %{ execute-keys -draft k x s ^ \h + <ret> \" x y } catch %{ reg x '' } + try %[ + evaluate-commands -draft %[ + # Check if previous line opens a block + execute-keys -draft kx <a-k>^<c-r>x(.+\bdo$)<ret> + # Check that we do not already have an end for this indent level which is first set via `elixir-indent-on-new-line` hook + execute-keys -draft }i J x <a-K> ^<c-r>x(end|else)[^0-9A-Za-z_!?]<ret> + ] + execute-keys -draft o<c-r>xend<esc> # insert a new line with containing end + ] + ] + ] +] + +define-command -hidden elixir-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # indent after line ending with: + # try %{ execute-keys -draft k x <a-k> (\bdo|\belse|->)$ <ret> & } + # filter previous line + try %{ execute-keys -draft k : elixir-trim-indent <ret> } + # indent after lines ending with do or -> + try %{ execute-keys -draft <semicolon> k x <a-k> ^.+(\bdo|->)$ <ret> j <a-gt> } + } +} + +] diff --git a/autoload/filetype/elm.kak b/autoload/filetype/elm.kak new file mode 100644 index 0000000..0bd5196 --- /dev/null +++ b/autoload/filetype/elm.kak @@ -0,0 +1,85 @@ +# http://elm-lang.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](elm) %{ + set-option buffer filetype elm +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=elm %{ + require-module elm + + hook window ModeChange pop:insert:.* -group elm-trim-indent elm-trim-indent + hook window InsertChar \n -group elm-insert elm-insert-on-new-line + hook window InsertChar \n -group elm-indent elm-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window elm-.+ } +} + +hook -group elm-highlight global WinSetOption filetype=elm %{ + add-highlighter window/elm ref elm + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/elm } +} + + +provide-module elm %[ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/elm regions +add-highlighter shared/elm/code default-region group +add-highlighter shared/elm/multiline_string region '"""' '"""' fill string +add-highlighter shared/elm/string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/elm/line_comment region (--) $ fill comment +add-highlighter shared/elm/comment region -recurse \{- \{- -\} fill comment + +add-highlighter shared/elm/code/ regex \b[A-Z]\w*\b 0:type +add-highlighter shared/elm/code/ regex \b[a-z]\w*\b 0:variable +add-highlighter shared/elm/code/ regex ^[a-z]\w*\b 0:function +add-highlighter shared/elm/code/ regex "-?\b[0-9]*\.?[0-9]+" 0:value +add-highlighter shared/elm/code/ regex \B[-+<>!@#$%^&*=:/\\|]+\B 0:operator +add-highlighter shared/elm/code/ regex \b(import|exposing|as|module|port)\b 0:meta +add-highlighter shared/elm/code/ regex \b(type|alias|if|then|else|case|of|let|in|infix|_)\b) 0:keyword +add-highlighter shared/elm/code/ regex (?<![-+<>!@#$%^&*=:/\\|])(->|:|=|\|)(?![-+<>!@#$%^&*=:/\\|]) 0:keyword + +# Commands +# ‾‾‾‾‾‾‾‾ + +# http://elm-lang.org/docs/style-guide + +define-command -hidden elm-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden elm-indent-after " + execute-keys -draft <semicolon> k x <a-k> ^\\h*if|[=(]$|\\b(case\\h+[\\w']+\\h+of|let|in)$|(\\{\\h+\\w+|\\w+\\h+->)$ <ret> j <a-gt> +" + +define-command -hidden elm-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy -- comments prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K--\h* <ret> y gh j P } + } +} + +define-command -hidden elm-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # align to first clause + try %{ execute-keys -draft <semicolon> k x X s ^\h*(if|then|else)?\h*(([\w']+\h+)+=)?\h*(case\h+[\w']+\h+of|let)\h+\K.* <ret> s \A|.\z <ret> & } + # filter previous line + try %{ execute-keys -draft k : elm-trim-indent <ret> } + # indent after lines beginning with condition or ending with expression or =( + try %{ elm-indent-after } + } +} + +] diff --git a/autoload/filetype/elvish.kak b/autoload/filetype/elvish.kak new file mode 100644 index 0000000..5377862 --- /dev/null +++ b/autoload/filetype/elvish.kak @@ -0,0 +1,67 @@ +# Syntax highlighting and indentation for Elvish (https://elv.sh) + +hook global BufCreate .*\.elv %{ + set-option buffer filetype elvish +} + +hook global WinSetOption filetype=elvish %< + require-module elvish + + hook window ModeChange pop:insert:.* -group elvish-trim-indent elvish-trim-indent + hook window InsertChar \n -group elvish-insert elvish-indent + hook window InsertChar [\]})] -group elvish-insert elvish-deindent + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window elvish-.+ } +> + +hook -group elvish-highlight global WinSetOption filetype=elvish %{ + add-highlighter window/elvish ref elvish + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/elvish } +} + +provide-module elvish %§ + +add-highlighter shared/elvish regions +add-highlighter shared/elvish/code default-region group +add-highlighter shared/elvish/double_string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/elvish/single_string region "'" ('')*' fill string +add-highlighter shared/elvish/comment region '#' $ fill comment + +add-highlighter shared/elvish/code/variable regex \$[\w\d-_:~]+ 0:variable +add-highlighter shared/elvish/code/variable_in_assignment regex (?:^|\{\s|\(|\||\;)\h*(?:var|set|tmp|del)((?:\h+[\w\d-_:~]+)*) 1:variable +add-highlighter shared/elvish/code/variable_in_for regex (?:^|\{\s|\(|\||\;)\h*for\h+([\w\d-_:~]*) 1:variable +add-highlighter shared/elvish/code/variable_in_catch regex \}\h+(?:catch|except)\h+([\w\d-_:~]*) 1:variable + +add-highlighter shared/elvish/code/builtin regex (?:^|\{\s|\(|\||\;)\h*(!=|!=s|%|\*|\+|-gc|-ifaddrs|-log|-override-wcwidth|-stack|-|/|<|<=|<=s|<s|==|==s|>|>=|>=s|>s|all|assoc|base|bool|break|call|cd|compare|constantly|continue|count|defer|deprecate|dissoc|drop|each|eawk|echo|eq|eval|exact-num|exec|exit|external|fail|fg|float64|from-json|from-lines|from-terminated|get-env|has-env|has-external|has-key|has-value|is|keys|kind-of|make-map|multi-error|nop|not-eq|not|ns|num|one|only-bytes|only-values|order|peach|pprint|print|printf|put|rand|randint|range|read-line|read-upto|repeat|repr|resolve|return|run-parallel|search-external|set-env|show|sleep|slurp|src|styled|styled-segment|take|tilde-abbr|time|to-json|to-lines|to-string|to-terminated|unset-env|use-mod|wcswidth)(?![-:])\b 1:builtin +add-highlighter shared/elvish/code/keyword regex (?:^|\{\s|\(|\||\;)\h*(use|var|set|tmp|del|and|or|coalesce|pragma|while|for|try|fn|if)(?![-:])\b 1:keyword +add-highlighter shared/elvish/code/keyword_block regex \}\h+(catch|elif|else|except|finally)(?![-:])\b 1:keyword + +add-highlighter shared/elvish/code/metachar regex [*?|&\;<>()[\]{}] 0:operator + +define-command -hidden elvish-trim-indent %{ + evaluate-commands -no-hooks -draft -itersel %{ + execute-keys x + # remove trailing white spaces + try %{ execute-keys -draft s \h + $ <ret> d } + } +} + +define-command -hidden elvish-indent %< evaluate-commands -draft -itersel %< + execute-keys <semicolon> + try %< + # if the previous line is a comment, copy indent, # and whitespace + execute-keys -draft k x s^\h*#\h*<ret> yjP + > catch %< + # copy indent + execute-keys -draft K <a-&> + # indent after { [ ( | + try %< execute-keys -draft k x <a-k>[[{(|]\h*$<ret> j <a-gt> > + > +>> + +define-command -hidden elvish-deindent %< evaluate-commands -draft -itersel %< + try %< + # Deindent only when there is a lone closing character + execute-keys -draft x <a-k>^\h*[^\h]$<ret> <a-lt> + > +>> +§ diff --git a/autoload/filetype/erlang.kak b/autoload/filetype/erlang.kak new file mode 100644 index 0000000..35b60cf --- /dev/null +++ b/autoload/filetype/erlang.kak @@ -0,0 +1,68 @@ +# Erlang/OTP +# https://erlang.org +# ---------------------- + +# Detection and Initialization sections were adapted from rc/filetype/elixir.kak + +# Detection +# ‾‾‾‾‾‾‾‾‾ +hook global BufCreate .*[.](erl|hrl) %{ + set-option buffer filetype erlang +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +hook global WinSetOption filetype=erlang %{ + require-module erlang + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window erlang-.+ } +} + +hook -group erlang-highlight global WinSetOption filetype=erlang %{ + add-highlighter window/erlang ref erlang + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/erlang } +} + +provide-module erlang %[ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/erlang regions +add-highlighter shared/erlang/default default-region group + +add-highlighter shared/erlang/comment region '(?<!\$)%' '$' fill comment +add-highlighter shared/erlang/attribute_atom_single_quoted region %{-'} %{(?<!\\)(?:\\\\)*'(?=[\( \.])} fill builtin +add-highlighter shared/erlang/attribute region '\b-[a-z][\w@]*(?=[\( \.])' '\K' fill builtin +add-highlighter shared/erlang/atom_single_quoted region %{'} %{(?<!\\)(?:\\\\)*'} fill type +add-highlighter shared/erlang/char_list region %{"} %{(?<!\\)(?:\\\\)*"} fill string +add-highlighter shared/erlang/dollar_double_quote region %{\$\\?"} '\K' fill value +add-highlighter shared/erlang/dollar_single_quote region %{\$\\?'} '\K' fill value + +# default-region regex highlighters +add-highlighter shared/erlang/default/atom regex '\b[a-z][\w@]*\b' 0:type +add-highlighter shared/erlang/default/funtion_call regex '\b[a-z][\w@]*(?=\()' 0:function +add-highlighter shared/erlang/default/keywords regex '\b(after|begin|case|try|catch|end|fun|if|of|receive|when|andalso|orelse|bnot|not|div|rem|band|and|bor|bxor|bsl|bsr|or|xor)\b' 0:keyword +add-highlighter shared/erlang/default/variable_name regex '\b(?<!\?)[A-Z_][\w@]*\b' 0:variable +add-highlighter shared/erlang/default/module_prefix regex '\b([a-z][\w_@]+)(?=:)' 1:value +# e.g. #Ref<0.1380825548.292038421.197518> +add-highlighter shared/erlang/default/ref regex '#Ref<\d+\.\d+\.\d+\.\d+>' 0:value +# e.g. #Port<0.1> +add-highlighter shared/erlang/default/port regex '#Port<\d+\.\d+>' 0:value +# e.g. <0.401.0> +add-highlighter shared/erlang/default/pid regex '<\d+\.\d+\.\d+>' 0:value +add-highlighter shared/erlang/default/base_number regex '\b(\d[_\d]*(?<!_)#[a-zA-Z0-9][a-z_A-Z0-9]*(?<!_)(?!\{))\b' 1:value +add-highlighter shared/erlang/default/float regex '\b(?<![\.])(\d[\d_]*(?<!_)\.\d[\d_]*(?<!_)(?:e[+-]?\d[\d_]*(?<!_))?)\b' 1:value +add-highlighter shared/erlang/default/integer regex '\b(?<!/)(\d[\d_]*)(?<!_)\b' 1:value +# e.g $\xff +add-highlighter shared/erlang/default/dollar_hex regex '\$\\x[0-9a-f][0-9a-f]' 0:value +# e.g. $\^a $\^C +add-highlighter shared/erlang/default/dollar_ctrl_char regex '\$\\\^[a-zA-Z]' 0:value +# e.g. $\101, $\70 +add-highlighter shared/erlang/default/dollar_octal regex '\$\\[0-7][0-7][0-7]?' 0:value +# e.g. $\↕ $\7 +add-highlighter shared/erlang/default/dollar_esc_char regex '\$\\[^x]' 0:value +# e.g. $↕ $a +add-highlighter shared/erlang/default/dollar_char regex '\$.' 0:value + +] diff --git a/autoload/filetype/eruby.kak b/autoload/filetype/eruby.kak new file mode 100644 index 0000000..273fa07 --- /dev/null +++ b/autoload/filetype/eruby.kak @@ -0,0 +1,26 @@ +# eRuby +# http://www2a.biglobe.ne.jp/~seki/ruby/erb.html + +hook global BufCreate '.*\.erb' %{ + set-option buffer filetype eruby +} + +hook global WinSetOption filetype=eruby %{ + require-module eruby + add-highlighter window/eruby ref eruby + hook -group eruby-indent window InsertChar '\n' html-indent-on-new-line + hook -always -once window WinSetOption filetype=.* %{ + remove-highlighter window/eruby + remove-hooks window eruby-.+ + } +} + +provide-module eruby %{ + require-module ruby + require-module html + add-highlighter shared/eruby regions + add-highlighter shared/eruby/html default-region ref html + add-highlighter shared/eruby/simple-expression-tag region '<%=' '%>' ref ruby + add-highlighter shared/eruby/simple-execution-tag region '<%' '%>' ref ruby + add-highlighter shared/eruby/simple-comment-tag region '<%#' '%>' fill comment +} diff --git a/autoload/filetype/etc.kak b/autoload/filetype/etc.kak new file mode 100644 index 0000000..b04b7b4 --- /dev/null +++ b/autoload/filetype/etc.kak @@ -0,0 +1,95 @@ +# Highlighting for common files in /etc +hook global BufCreate .*/etc/(hosts|networks|services) %{ set-option buffer filetype etc-hosts } +hook global BufCreate .*/etc/resolv.conf %{ set-option buffer filetype etc-resolv-conf } +hook global BufCreate .*/etc/shadow %{ set-option buffer filetype etc-shadow } +hook global BufCreate .*/etc/passwd %{ set-option buffer filetype etc-passwd } +hook global BufCreate .*/etc/gshadow %{ set-option buffer filetype etc-gshadow } +hook global BufCreate .*/etc/group %{ set-option buffer filetype etc-group } +hook global BufCreate .*/etc/(fs|m)tab %{ set-option buffer filetype etc-fstab } +hook global BufCreate .*/etc/environment %{ set-option buffer filetype sh } +hook global BufCreate .*/etc/env.d/.* %{ set-option buffer filetype sh } +hook global BufCreate .*/etc/profile(\.(csh|env))? %{ set-option buffer filetype sh } +hook global BufCreate .*/etc/profile\.d/.* %{ set-option buffer filetype sh } + + +hook global WinSetOption filetype=etc-(hosts|resolv-conf|shadow|passwd|gshadow|group|fstab) %{ + require-module "etc-%val{hook_param_capture_1}" +} + + +hook -group etc-resolv-conf-highlight global WinSetOption filetype=etc-resolv-conf %{ + add-highlighter window/etc-resolv-conf ref etc-resolv-conf + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/etc-resolv-conf } +} +hook -group etc-hosts-highlight global WinSetOption filetype=etc-hosts %{ + add-highlighter window/etc-hosts ref etc-hosts + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/etc-hosts } +} +hook -group etc-fstab-highlight global WinSetOption filetype=etc-fstab %{ + add-highlighter window/etc-fstab ref etc-fstab + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/etc-fstab } +} +hook -group etc-group-highlight global WinSetOption filetype=etc-group %{ + add-highlighter window/etc-group ref etc-group + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/etc-group } +} +hook -group etc-gshadow-highlight global WinSetOption filetype=etc-gshadow %{ + add-highlighter window/etc-gshadow ref etc-gshadow + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/etc-gshadow } +} +hook -group etc-shadow-highlight global WinSetOption filetype=etc-shadow %{ + add-highlighter window/etc-shadow ref etc-shadow + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/etc-shadow } +} +hook -group etc-passwd-highlight global WinSetOption filetype=etc-passwd %{ + add-highlighter window/etc-passwd ref etc-passwd + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/etc-passwd } +} + + +# Highlighters + +provide-module etc-resolv-conf %{ +## /etc/resolv.conf +add-highlighter shared/etc-resolv-conf group +add-highlighter shared/etc-resolv-conf/ regex ^#.*?$ 0:comment +add-highlighter shared/etc-resolv-conf/ regex ^(nameserver|server|domain|sortlist|options)[\s\t]+(.*?)$ 1:type 2:attribute +} + +provide-module etc-hosts %{ +## /etc/hosts +add-highlighter shared/etc-hosts group +add-highlighter shared/etc-hosts/ regex ^(.+?)[\s\t]+?(.*?)$ 1:type 2:attribute +add-highlighter shared/etc-hosts/ regex '#.*?$' 0:comment +} + +provide-module etc-fstab %{ +## /etc/fstab +add-highlighter shared/etc-fstab group +add-highlighter shared/etc-fstab/ regex ^(\S{1,})\s+?(\S{1,})\s+?(\S{1,})\s+?(\S{1,})\s+?(\S{1,})\s+?(\S{1,})(?:\s+)?$ 1:keyword 2:value 3:type 4:string 5:attribute 6:attribute +add-highlighter shared/etc-fstab/ regex '#.*?$' 0:comment +} + +provide-module etc-group %{ +## /etc/group +add-highlighter shared/etc-group group +add-highlighter shared/etc-group/ regex ^(\S+?):(\S+?)?:(\S+?)?:(\S+?)?$ 1:keyword 2:type 3:value 4:string +} + +provide-module etc-gshadow %{ +## /etc/gshadow +add-highlighter shared/etc-gshadow group +add-highlighter shared/etc-gshadow/ regex ^(\S+?):(\S+?)?:(\S+?)?:(\S+?)?$ 1:keyword 2:type 3:value 4:string +} + +provide-module etc-shadow %{ +## /etc/shadow +add-highlighter shared/etc-shadow group +add-highlighter shared/etc-shadow/ regex ^(\S+?):(\S+?):([0-9]+?):([0-9]+?)?:([0-9]+?)?:([0-9]+?)?:([0-9]+?)?:([0-9]+?)?:(.*?)?$ 1:keyword 2:type 3:value 4:value 5:value 6:value 7:value 8:value +} + +provide-module etc-passwd %{ +## /etc/passwd +add-highlighter shared/etc-passwd group +add-highlighter shared/etc-passwd/ regex ^(\S+?):(\S+?):([0-9]+?):([0-9]+?):(.*?)?:(.+?):(.+?)$ 1:keyword 2:type 3:value 4:value 5:string 6:attribute 7:attribute +} diff --git a/autoload/filetype/exherbo.kak b/autoload/filetype/exherbo.kak new file mode 100644 index 0000000..7271425 --- /dev/null +++ b/autoload/filetype/exherbo.kak @@ -0,0 +1,138 @@ +## Repository metadata files +hook global BufCreate .*/metadata/mirrors\.conf %{ set-option buffer filetype paludis-mirrors-conf } +hook global BufCreate .*/metadata/licence_groups.conf %{ set-option buffer filetype exheres-0-licence-groups } +hook global BufCreate .*/metadata/options/descriptions/.*\.conf %{ set-option buffer filetype exheres-0-licence-groups } +hook global BufCreate .*/metadata/.*\.conf %{ set-option buffer filetype exheres-0-metadata } + +## News items +hook global BufCreate .*/metadata/news/.*/.*\.txt %{ set-option buffer filetype glep42 } + +## exheres-0, exlib +hook global BufCreate .*\.(exheres-0|exlib) %{ set-option buffer filetype sh } + +# Paludis configurations +hook global BufCreate .*/etc/paludis(-.*)?/bashrc %{ set-option buffer filetype sh } +hook global BufCreate .*/etc/paludis(-.*)?/general(\.conf.d/.*.conf|\.conf) %{ set-option buffer filetype paludis-key-value-conf } +hook global BufCreate .*/etc/paludis(-.*)?/licences(\.conf.d/.*.conf|\.conf) %{ set-option buffer filetype paludis-options-conf } +hook global BufCreate .*/etc/paludis(-.*)?/mirrors(\.conf.d/.*.conf|\.conf) %{ set-option buffer filetype paludis-mirrors-conf } +hook global BufCreate .*/etc/paludis(-.*)?/options(\.conf.d/.*.conf|\.conf) %{ set-option buffer filetype paludis-options-conf } +hook global BufCreate .*/etc/paludis(-.*)?/output(\.conf.d/.*.conf|\.conf) %{ set-option buffer filetype paludis-key-value-conf } +hook global BufCreate .*/etc/paludis(-.*)?/package_(unmask|mask)(\.conf.d/.*.conf|\.conf) %{ set-option buffer filetype paludis-specs-conf } +hook global BufCreate .*/etc/paludis(-.*)?/platforms(\.conf.d/.*.conf|\.conf) %{ set-option buffer filetype paludis-specs-conf } +hook global BufCreate .*/etc/paludis(-.*)?/repositories/.*\.conf %{ set-option buffer filetype paludis-key-value-conf } +hook global BufCreate .*/etc/paludis(-.*)?/repository\.template %{ set-option buffer filetype paludis-key-value-conf } +hook global BufCreate .*/etc/paludis(-.*)?/repository_defaults\.conf %{ set-option buffer filetype paludis-key-value-conf } +hook global BufCreate .*/etc/paludis(-.*)?/specpath\.conf %{ set-option buffer filetype paludis-key-value-conf } +hook global BufCreate .*/etc/paludis(-.*)?/suggestions(\.conf.d/.*.conf|\.conf) %{ set-option buffer filetype paludis-specs-conf } + +hook global WinSetOption filetype=exheres-0-(metadata|options-descriptions|licence-groups) %{ + require-module exheres +} + +hook -group exheres-0-metadata-highlight global WinSetOption filetype=exheres-0-metadata %{ + add-highlighter window/exheres-0-metadata ref exheres-0-metadata + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/exheres-0-metadata } +} + +hook -group exheres-0-options-descriptions-highlight global WinSetOption filetype=exheres-0-options-descriptions %{ + add-highlighter window/exheres-0-options-descriptions ref exheres-0-options-descriptions + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/exheres-0-options-descriptions } +} + +hook -group exheres-0-licence-groups-highlight global WinSetOption filetype=exheres-0-licence-groups %{ + add-highlighter window/exheres-0-licence-groups ref exheres-0-licence-groups + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/exheres-0-licence-groups } +} + +provide-module exheres %{ +# Highlighters +## exheres-0 Repository metadata files +add-highlighter shared/exheres-0-metadata group +add-highlighter shared/exheres-0-metadata/ regex ^#.*?$ 0:comment +add-highlighter shared/exheres-0-metadata/ regex ^(?:[\s\t]+)?(\*)?(\S+)(?:[\s\t]+)?=(?:[\s\t]+)?(.+?)?$ 1:type 2:attribute 3:string +add-highlighter shared/exheres-0-metadata/ regex ^(?:[\s\t]+)?[\S]+[\s\t]+=[\s\t]+\[.+?[\s\t]+\] 0:string +add-highlighter shared/exheres-0-metadata/ regex ^(?:[\s\t]+)?(\S+)\s\[\[$ 0:type +add-highlighter shared/exheres-0-metadata/ regex ^(?:[\s\t]+)?\]\]$ 0:type + +## exheres-0 options descriptions +add-highlighter shared/exheres-0-options-descriptions group +add-highlighter shared/exheres-0-options-descriptions/ regex ^#.*?$ 0:comment +add-highlighter shared/exheres-0-options-descriptions/ regex ^(?:[\s\t]+)?[\S]+[\s\t]+-[\s\t]+\[.+?[\s\t]+\] 0:string +add-highlighter shared/exheres-0-options-descriptions/ regex ^(?:[\s\t]+)?(\S+)\s\[\[$ 0:type +add-highlighter shared/exheres-0-options-descriptions/ regex ^(?:[\s\t]+)?\]\]$ 0:type + +## metadata/licence_groups.conf +add-highlighter shared/exheres-0-licence-groups group +add-highlighter shared/exheres-0-licence-groups/ regex [\s\t]+(\S+(?:[\s\t]+))*$ 0:attribute +add-highlighter shared/exheres-0-licence-groups/ regex ^(\S+) 0:type +add-highlighter shared/exheres-0-licence-groups/ regex ^#.*?$ 0:comment +} + +hook global WinSetOption filetype=paludis-(key-value|options|mirrors|specs)-conf %{ + require-module paludis +} + +hook -group paludis-options-conf-highlight global WinSetOption filetype=paludis-options-conf %{ + add-highlighter window/paludis-options-conf ref paludis-options-conf + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/paludis-options-conf } +} + +hook -group paludis-key-value-conf-highlight global WinSetOption filetype=paludis-key-value-conf %{ + add-highlighter window/paludis-key-value-conf ref paludis-key-value-conf + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/paludis-key-value-conf } +} + +hook -group paludis-mirrors-conf-highlight global WinSetOption filetype=paludis-mirrors-conf %{ + add-highlighter window/paludis-mirrors-conf ref paludis-mirrors-conf + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/paludis-mirrors-conf } +} + +hook -group paludis-specs-conf-highlight global WinSetOption filetype=paludis-specs-conf %{ + add-highlighter window/paludis-specs-conf ref paludis-specs-conf + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/paludis-specs-conf } +} +provide-module paludis %{ +## Paludis configurations +### options.conf +add-highlighter shared/paludis-options-conf group +add-highlighter shared/paludis-options-conf/ regex [\s\t]+(\S+(?:[\s\t]+))*$ 0:attribute +add-highlighter shared/paludis-options-conf/ regex (?::)(?:[\s\t]+)(.*?$) 1:attribute +add-highlighter shared/paludis-options-conf/ regex [\s\t]+(\S+=)(\S+) 1:attribute 2:value +add-highlighter shared/paludis-options-conf/ regex [\s\t](\S+:) 0:keyword +add-highlighter shared/paludis-options-conf/ regex [\s\t](-\S+)(.*?) 1:red +add-highlighter shared/paludis-options-conf/ regex ^(\S+/\S+) 0:type +add-highlighter shared/paludis-options-conf/ regex ^#.*?$ 0:comment + +## general.conf, repository.template +add-highlighter shared/paludis-key-value-conf group +add-highlighter shared/paludis-key-value-conf/ regex ^[\s\t]?(\S+)[\s\t+]=[\s\t+](.*?)$ 1:attribute 2:value +add-highlighter shared/paludis-key-value-conf/ regex ^#.*?$ 0:comment + +## mirrors.conf +add-highlighter shared/paludis-mirrors-conf group +add-highlighter shared/paludis-mirrors-conf/ regex ^[\s\t+]?(\S+)[\s\t+](.*?)$ 1:type 2:value +add-highlighter shared/paludis-mirrors-conf/ regex ^#.*?$ 0:comment + +## package_(unmask|mask).conf, platforms.conf +add-highlighter shared/paludis-specs-conf group +add-highlighter shared/paludis-specs-conf/ regex [\s\t]+(\S+(?:[\s\t]+))*$ 0:attribute +add-highlighter shared/paludis-specs-conf/ regex ^(\S+/\S+) 0:type +add-highlighter shared/paludis-specs-conf/ regex ^#.*?$ 0:comment +} + +hook global WinSetOption filetype=glep42 %{ + require-module glep42 +} + +hook -group glep42-highlight global WinSetOption filetype=glep42 %{ + add-highlighter window/glep42 ref glep42 + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/glep42 } +} + +provide-module glep42 %{ +## News items (GLEP42) +add-highlighter shared/glep42 group +add-highlighter shared/glep42/ regex ^(Title|Author|Translator|Content-Type|Posted|Revision|News-Item-Format|Display-If-Installed|Display-If-Keyword|Display-If-Profile):([^\n]*(?:\n\h+[^\n]+)*)$ 1:keyword 2:attribute +add-highlighter shared/glep42/ regex <[^@>]+@.*?> 0:string +add-highlighter shared/glep42/ regex ^>.*?$ 0:comment +} diff --git a/autoload/filetype/fennel.kak b/autoload/filetype/fennel.kak new file mode 100644 index 0000000..7b82a8e --- /dev/null +++ b/autoload/filetype/fennel.kak @@ -0,0 +1,109 @@ +# http://fennel-lang.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.]fnl %{ + set-option buffer filetype fennel +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +hook global WinSetOption filetype=fennel %{ + require-module fennel + fennel-configure-window +} + +hook -group fennel-highlight global WinSetOption filetype=fennel %{ + add-highlighter window/fennel ref fennel + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/fennel } +} + +provide-module fennel %{ + +require-module lisp + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/fennel regions +add-highlighter shared/fennel/code default-region group +add-highlighter shared/fennel/comment region '(?<!\\)(?:\\\\)*\K;' '$' fill comment +add-highlighter shared/fennel/shebang region '(?<!\\)(?:\\\\)*\K#!' '$' fill comment +add-highlighter shared/fennel/string region '(?<!\\)(?:\\\\)*\K"' '(?<!\\)(?:\\\\)*"' fill string +add-highlighter shared/fennel/colon-string region '\W\K:[-\w?\\^_!$%&*+./@|<=>]' '(?![-\w?\\^_!$%&*+./@|<=>])' fill keyword +add-highlighter shared/fennel/code/ regex \\(?:space|tab|newline|return|backspace|formfeed|u[0-9a-fA-F]{4}|o[0-3]?[0-7]{1,2}|.)\b 0:string + +evaluate-commands %sh{ + # Grammar + keywords="require-macros eval-compiler doc lua hashfn macro macros import-macros pick-args pick-values macroexpand macrodebug + do values if when each for fn lambda λ partial while set global var local let tset set-forcibly! doto match or and + not not= collect icollect accumulate rshift lshift bor band bnot bxor with-open" + re_keywords='\\$ \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9 \\$\\.\\.\\.' + builtins="_G _VERSION arg assert bit32 collectgarbage coroutine debug + dofile error getfenv getmetatable io ipairs length load + loadfile loadstring math next os package pairs pcall + print rawequal rawget rawlen rawset require select setfenv + setmetatable string table tonumber tostring type unpack xpcall" + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + +# Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list fennel_static_words $(join "${keywords} ${builtins} false nil true" ' ')" + + # Highlight keywords + printf %s " + add-highlighter shared/fennel/code/keywords regex \b($(join "${keywords} ${re_keywords}" '|'))\b 0:keyword + add-highlighter shared/fennel/code/builtins regex \b($(join "${builtins}" '|'))\b 0:builtin + " +} + +add-highlighter shared/fennel/code/operator regex (\.|\?\.|\+|\.\.|\^|-|\*|%|/|>|<|>=|<=|=|\.\.\.|:|->|->>|-\?>|-\?>>) 0:operator +add-highlighter shared/fennel/code/value regex \b(false|nil|true|[0-9]+(:?\.[0-9])?(:?[eE]-?[0-9]+)?|0x[0-9a-fA-F])\b 0:value +add-highlighter shared/fennel/code/function_declaration regex \((?:fn|lambda|λ)\s+([\S]+) 1:function +add-highlighter shared/fennel/code/method_call regex (?:\w+|\$[0-9]{0,1}):(\S+)\b 1:function + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden fennel-configure-window %{ + set-option window static_words %opt{fennel_static_words} + + hook window ModeChange pop:insert:.* -group fennel-trim-indent fennel-trim-indent + hook window InsertChar \n -group fennel-indent fennel-indent-on-new-line + + set-option buffer extra_word_chars '_' . / * ? + - < > ! : "'" + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window fennel-.+ } +} + +define-command -hidden fennel-trim-indent lisp-trim-indent + +declare-option \ + -docstring 'regex matching the head of forms which have options *and* indented bodies' \ + regex fennel_special_indent_forms \ + '(?:if|when|each|for|fn|lambda|λ|partial|while|local|var|doto|let)' + +define-command -hidden fennel-indent-on-new-line %{ + # registers: i = best align point so far; w = start of first word of form + evaluate-commands -draft -save-regs '/"|^@iw' -itersel %{ + execute-keys -draft 'gk"iZ' + try %{ + execute-keys -draft '[bl"i<a-Z><gt>"wZ' + + try %{ + # If a special form, indent another (indentwidth - 1) spaces + execute-keys -draft '"wze<a-K>[\s()\[\]\{\}]<ret><a-k>\A' %opt{fennel_special_indent_forms} '\z<ret>' + execute-keys -draft '"wze<a-L>s.{' %sh{printf $(( kak_opt_indentwidth - 1 ))} '}\K.*<ret><a-;>;"i<a-Z><gt>' + } catch %{ + # If not special and parameter appears on line 1, indent to parameter + execute-keys -draft '"wz<a-K>[()[\]{}]<ret>e<a-K>[\s()\[\]\{\}]<ret><a-l>s\h\K[^\s].*<ret><a-;>;"i<a-Z><gt>' + } + } + try %{ execute-keys -draft '[rl"i<a-Z><gt>' } + try %{ execute-keys -draft '[Bl"i<a-Z><gt>' } + execute-keys -draft ';"i<a-z>a&,' + } +} + +} diff --git a/autoload/filetype/fidl.kak b/autoload/filetype/fidl.kak new file mode 100644 index 0000000..351eeb4 --- /dev/null +++ b/autoload/filetype/fidl.kak @@ -0,0 +1,79 @@ +# Detection +hook global BufCreate .*\.fidl %{ + set-option buffer filetype fidl +} + +hook global WinSetOption filetype=fidl %< + require-module fidl + hook window ModeChange pop:insert:.* -group fidl-trim-indent fidl-trim-indent + hook window InsertChar \n -group fidl-indent fidl-indent-on-new-line + hook window InsertChar [)}] -group fidl-indent fidl-indent-on-closing + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window fidl-.+ } +> + +hook -group fidl-highlight global WinSetOption filetype=fidl %{ + add-highlighter window/fidl ref fidl + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/fidl } +} + +provide-module fidl %§ + +# Highlighters + +add-highlighter shared/fidl regions +add-highlighter shared/fidl/code default-region group + +add-highlighter shared/fidl/string region \" (?<!\\)(\\\\)*" fill string + +add-highlighter shared/fidl/line_doc region ///(?!/) $ fill documentation +add-highlighter shared/fidl/line_comment region // $ group +add-highlighter shared/fidl/line_comment/comment fill comment +add-highlighter shared/fidl/line_comment/todo regex TODO|FIXME: 0:meta + +add-highlighter shared/fidl/attributes region @[a-zA-Z] \b fill meta + +add-highlighter shared/fidl/code/keywords regex \b(as|bits|compose|const|enum|error|flexible|optional|library|protocol|resource|service|strict|struct|table|type|union|using)\b 0:keyword +add-highlighter shared/fidl/code/types regex \b(array|bool|bytes?|client_end|float(32|64)|server_end|string|u?int(8|16|32|64)|vector)\b 0:type + +add-highlighter shared/fidl/code/literals group +add-highlighter shared/fidl/code/literals/bool regex \b(true|false)\b 0:value +add-highlighter shared/fidl/code/literals/decimal regex \b([0-9]+(\.[0-9]+)?)\b 0:value +add-highlighter shared/fidl/code/literals/hexadecimal regex \b(0x[0-9a-fA-F])\b 0:value +add-highlighter shared/fidl/code/literals/binary regex \b(0b[01])\b 0:value + +# Commands + +define-command -hidden fidl-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden fidl-indent-on-new-line %~ + evaluate-commands -draft -itersel %@ + try %{ # line comment + # copy the commenting prefix + execute-keys -draft k x s ^\h*/{2,}\h* <ret> yjghP + } catch %` + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # align to opening ( or { if possible + try %+ + execute-keys -draft <a-k> [)}] <ret> m <a-S> 1<a-&> + + catch %+ + # indent after lines ending with ( or { + try %! execute-keys -draft k x <a-k> [({]$ <ret> j <a-gt> ! + + + ` + # remove trailing white spaces + try %{ execute-keys -draft k : fidl-trim-indent <ret> } + @ +~ + +define-command -hidden fidl-indent-on-closing %~ + evaluate-commands -draft -itersel %@ + # align to opening ( or { when alone on a line + try %< execute-keys -draft <a-h> <a-k> ^\h*[)}]$ <ret> m <a-S> 1<a-&> > + @ +~ + +§ diff --git a/autoload/filetype/fish.kak b/autoload/filetype/fish.kak new file mode 100644 index 0000000..0bfcc4f --- /dev/null +++ b/autoload/filetype/fish.kak @@ -0,0 +1,87 @@ +# http://fishshell.com +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](fish) %{ + set-option buffer filetype fish +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=fish %{ + require-module fish + + hook window ModeChange pop:insert:.* -group fish-trim-indent fish-trim-indent + hook window InsertChar .* -group fish-indent fish-indent-on-char + hook window InsertChar \n -group fish-insert fish-insert-on-new-line + hook window InsertChar \n -group fish-indent fish-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window fish-.+ } +} + +hook -group fish-highlight global WinSetOption filetype=fish %{ + add-highlighter window/fish ref fish + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/fish } +} + + +provide-module fish %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/fish regions +add-highlighter shared/fish/code default-region group +add-highlighter shared/fish/double_string region (?<!\\)(?:\\\\)*\K" (?<!\\)(\\\\)*" group +add-highlighter shared/fish/single_string region (?<!\\)(?:\\\\)*\K' (?<!\\)(\\\\)*' fill string +add-highlighter shared/fish/comment region (?<!\\)(?:\\\\)*(?:^|\h)\K# '$' fill comment + +add-highlighter shared/fish/double_string/ fill string +add-highlighter shared/fish/double_string/ regex ((?<!\\)(?:\\\\)*\K\$\w+)|(\{\$\w+\}) 0:variable + +add-highlighter shared/fish/code/ regex (?<!\\)(?:\\\\)*\K(\$\w+)|(\{\$\w+\}) 0:variable + +# Command names are collected using `builtin --names`. +add-highlighter shared/fish/code/ regex \b(?<![$-])(and|argparse|begin|bg|bind|block|break|breakpoint|builtin|case|cd|command|commandline|complete|contains|continue|count|disown|echo|else|emit|end|eval|exec|exit|false|fg|for|function|functions|history|if|jobs|math|not|or|printf|pwd|random|read|realpath|return|set|set_color|source|status|string|switch|test|time|true|ulimit|wait|while)\b(?!-) 0:keyword + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden fish-trim-indent %{ + evaluate-commands -no-hooks -draft -itersel %{ + # remove trailing white spaces + try %{ execute-keys -draft x 1s^(\h+)$<ret> d } + } +} + +define-command -hidden fish-indent-on-char %{ + evaluate-commands -no-hooks -draft -itersel %{ + # align middle and end structures to start and indent when necessary + try %{ execute-keys -draft x<a-k>^\h*(else)$<ret><a-semicolon><a-?>^\h*(if)<ret>s\A|.\z<ret>1<a-&> } + try %{ execute-keys -draft x<a-k>^\h*(end)$<ret><a-semicolon><a-?>^\h*(begin|for|function|if|switch|while)<ret>s\A|.\z<ret>1<a-&> } + try %{ execute-keys -draft x<a-k>^\h*(case)$<ret><a-semicolon><a-?>^\h*(switch)<ret>s\A|.\z<ret>1<a-&> } + } +} + +define-command -hidden fish-insert-on-new-line %{ + evaluate-commands -no-hooks -draft -itersel %{ + # copy '#' comment prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*#\h* <ret> y jgh P } + } +} + +define-command -hidden fish-indent-on-new-line %{ + evaluate-commands -no-hooks -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # cleanup trailing whitespaces from previous line + try %{ execute-keys -draft k x s \h+$ <ret> d } + # indent after start structure + try %{ execute-keys -draft kx<a-k>^\h*(begin|case|else|for|function|if|while)\b<ret>j<a-gt> } + } +} + +} diff --git a/autoload/filetype/fsharp.kak b/autoload/filetype/fsharp.kak new file mode 100644 index 0000000..64d6b2c --- /dev/null +++ b/autoload/filetype/fsharp.kak @@ -0,0 +1,157 @@ +# https://fsharp.org/ +# + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](fs|fsx|fsi) %{ + set-option buffer filetype fsharp +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=fsharp %{ + require-module fsharp + + # indent on newline + hook window ModeChange pop:insert:.* -group fsharp-trim-indent fsharp-trim-indent + hook window InsertChar \n -group fsharp-insert fsharp-insert-on-new-line + hook window InsertChar \n -group fsharp-indent fsharp-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window fsharp-.+ } +} + +hook -group fsharp-highlight global WinSetOption filetype=fsharp %{ + add-highlighter window/fsharp ref fsharp + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/fsharp } +} + +provide-module fsharp %§ + +# Highlighters & Completion +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/fsharp regions +add-highlighter shared/fsharp/code default-region group +add-highlighter shared/fsharp/docstring region \(\*(?!\)) (\*\)) regions +add-highlighter shared/fsharp/double_string region @?(?<!')" (?<!\\)(\\\\)*"B? fill string +add-highlighter shared/fsharp/comment region '//' '$' fill comment +# https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/attributes +add-highlighter shared/fsharp/attributes region "\[<" ">\]" fill meta + +add-highlighter shared/fsharp/docstring/ default-region fill comment +# ability to write highlighted code inside docstring: +add-highlighter shared/fsharp/docstring/ region '>>> \K' '\z' ref fsharp +add-highlighter shared/fsharp/docstring/ region '\.\.\. \K' '\z' ref fsharp + +evaluate-commands %sh{ + # Grammar + meta="open" + + # exceptions taken from fsharp.vim colors (https://github.com/fsharp/vim-fsharp) + exceptions="try|failwith|failwithf|finally|invalid_arg|raise|rethrow" + + # keywords taken from fsharp.vim colors (https://github.com/fsharp/vim-fsharp) + keywords="abstract|as|assert|base|begin|class|default|delegate" + keywords="${keywords}|do|done|downcast|downto|elif|else|end|exception" + keywords="${keywords}|extern|for|fun|function|global|if|in|inherit|inline" + keywords="${keywords}|interface|lazy|let|match|member|module|mutable" + keywords="${keywords}|namespace|new|of|override|rec|static|struct|then" + keywords="${keywords}|to|type|upcast|use|val|void|when|while|with" + keywords="${keywords}|async|atomic|break|checked|component|const|constraint" + keywords="${keywords}|constructor|continue|decimal|eager|event|external" + keywords="${keywords}|fixed|functor|include|method|mixin|object|parallel" + keywords="${keywords}|process|pure|return|seq|tailcall|trait|yield" + # additional operator keywords (Microsoft.FSharp.Core.Operators) + keywords="${keywords}|box|hash|sizeof|nameof|typeof|typedefof|unbox|ref|fst|snd" + keywords="${keywords}|stdin|stdout|stderr" + # math operators (Microsoft.FSharp.Core.Operators) + keywords="${keywords}|abs|acos|asin|atan|atan2|ceil|cos|cosh|exp|floor|log" + keywords="${keywords}|log10|pown|round|sign|sin|sinh|sqrt|tan|tanh" + + + types="array|bool|byte|char|decimal|double|enum|exn|float" + types="${types}|float32|int|int16|int32|int64|lazy_t|list|nativeint" + types="${types}|obj|option|sbyte|single|string|uint|uint32|uint64" + types="${types}|uint16|unativeint|unit" + + fsharpCoreMethod="printf|printfn|sprintf|eprintf|eprintfn|fprintf|fprintfn" + + # Add the language's grammar to the static completion list + printf '%s\n' "hook global WinSetOption filetype=fsharp %{ + set-option window static_words ${values} ${meta} ${exceptions} ${keywords} ${types} + }" | tr '|' ' ' + + # Highlight keywords + printf '%s\n' " + add-highlighter shared/fsharp/code/ regex '\b(${meta})\b' 0:meta + add-highlighter shared/fsharp/code/ regex '\b(${exceptions})\b' 0:function + add-highlighter shared/fsharp/code/ regex '\b(${fsharpCoreMethod})\b' 0:function + add-highlighter shared/fsharp/code/ regex '\b(${keywords})\b' 0:keyword + " +} + +# computation expression keywords prefixed with ! +add-highlighter shared/fsharp/code/ regex "\w+!" 0:keyword +# brackets +add-highlighter shared/fsharp/code/ regex "[\[\]\(\){}]" 0:bracket +# accomodate typically overloaded operators +add-highlighter shared/fsharp/code/ regex "\B(<<>>|<\|\|>)\B" 0:operator +# fsharp operators +add-highlighter shared/fsharp/code/ regex "\B(->|<-|<=|>=)\B" 0:operator +add-highlighter shared/fsharp/code/ regex "(\b(not)\b|\b(and)\b)" 0:operator +add-highlighter shared/fsharp/code/ regex (?<=[\w\s\d'"_])((\?)([><+-/*%=]{1,2})(\??)|(\??)([><+-/*%=]{1,2})(\?)) 0:operator +add-highlighter shared/fsharp/code/ regex (?<=[\w\s\d'"_])((\|)+>|<(\|)+|<@|@>|<@@|@@>|:>|:\?|:=|(!|#)(?=\w)|:\?>|\?|~([-+]|(~){0,2})) 0:operator +add-highlighter shared/fsharp/code/ regex (?<=[\w\s\d'"_])(<>|::|\h\|\h|(\|\|)+|@|\.\.|<=|>=|(<)+|(>)+|!=|==|\|\|\||(\^)+|(&)+|\+|-|(\*)+|//|/|%+|=) 0:operator +add-highlighter shared/fsharp/code/ regex (?<=[\w\s\d'"_])((?<![=<>!])=(?![=])|[+*-]=) 0:builtin +# integer literals +add-highlighter shared/fsharp/code/ regex %{(?<!\.)\b[1-9]('?\d+)*(u?(l|L|y|s|n)?|[IMm])\b(?!\.)} 0:value +add-highlighter shared/fsharp/code/ regex %{(?<!\.)\b0b[01]('?[01]+)*(u?(l|L|y|s|n)?|[IMm])\b(?!\.)} 0:value +add-highlighter shared/fsharp/code/ regex %{(?<!\.)\b0('?[0-7]+)*(u?(l|L|y|s|n)?|[IMm])\b(?!\.)} 0:value +add-highlighter shared/fsharp/code/ regex %{(?<!\.)\b0x[\da-fA-F]('?[\da-fA-F]+)*(u?(l|L|y|s|n)?)?\b(?!\.)} 0:value +# floating point literals +add-highlighter shared/fsharp/code/ regex %{(?i)(?<!\.)\b\d('?\d+)*\.((lf|[fm])\b|\B)(?!\.)} 0:value +add-highlighter shared/fsharp/code/ regex %{(?i)(?<!\.)\b\d('?\d+)*\.?e[+-]?\d('?\d+)*(lf|[fm])?\b(?!\.)} 0:value +add-highlighter shared/fsharp/code/ regex %{(?i)(?<!\.)(\b(\d('?\d+)*)|\B)\.\d('?[\d]+)*(e[+-]?\d('?\d+)*)?(lf|[fm])?\b(?!\.)} 0:value +add-highlighter shared/fsharp/code/ regex %{(?i)(?<!\.)\b0x[\da-f]('?[\da-f]+)*((lf|[fm])\b|\B)(?!\.)} 0:value +add-highlighter shared/fsharp/code/ regex %{(?i)(?<!\.)\b0x[\da-f]('?[\da-f]+)*\.?p[+-]?\d('?\d+)*)?(lf|[fm])?\b(?!\.)} 0:value +add-highlighter shared/fsharp/code/ regex %{(?i)(?<!\.)\b0x([\da-f]('?[\da-f]+)*)?\.\d('?[\d]+)*(p[+-]?\d('?\d+)*)?(lf|[fm])?\b(?!\.)} 0:value +# character literals +add-highlighter shared/fsharp/code/char regex %{\B'((\\.)|[^'\\])'(\b(B)|\B)} 0:value +# other literals +add-highlighter shared/fsharp/code/ regex "\b(true|false)\b" 0:value +add-highlighter shared/fsharp/code/ regex "\B(\(\))\B" 0:value + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden fsharp-trim-indent %{ + evaluate-commands -no-hooks -draft -itersel %{ + execute-keys x + # remove trailing white spaces + try %{ execute-keys -draft s \h + $ <ret> d } + } +} + +define-command -hidden fsharp-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy // comments prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*//\h* <ret> y jgh P } + } +} + +define-command -hidden fsharp-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft \; K <a-&> } + # cleanup trailing whitespaces from previous line + try %{ execute-keys -draft k x s \h+$ <ret> d } + # indent after line ending with = + try %{ execute-keys -draft , k x <a-k> =$ <ret> j <a-gt> } + # indent after line ending with "do" + try %{ execute-keys -draft , k x <a-k> \bdo$ <ret> j <a-gt> } + } +} + +§ diff --git a/autoload/filetype/gas.kak b/autoload/filetype/gas.kak new file mode 100644 index 0000000..73f8db7 --- /dev/null +++ b/autoload/filetype/gas.kak @@ -0,0 +1,99 @@ +# Detection +# --------- +hook global BufCreate .*\.(s|S|asm)$ %{ + set-option buffer filetype gas +} + +hook global WinSetOption filetype=gas %{ + require-module gas + + hook window ModeChange pop:insert:.* -group gas-trim-indent gas-trim-indent + hook window InsertChar \n -group gas-indent gas-indent-on-new-line + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window gas-.+ } +} + +hook -group gas-highlight global WinSetOption filetype=gas %{ + add-highlighter window/gas ref gas + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/gas } +} + + +provide-module gas %{ + +add-highlighter shared/gas regions +add-highlighter shared/gas/code default-region group +add-highlighter shared/gas/string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/gas/commentMulti region /\* \*/ fill comment +add-highlighter shared/gas/commentSingle1 region '#' '$' fill comment +add-highlighter shared/gas/commentSingle2 region ';' '$' fill comment + +# Constant +add-highlighter shared/gas/code/ regex (0[xX][0-9a-fA-F]+|\b[0-9]+)\b 0:value + +# Labels +add-highlighter shared/gas/code/ regex ^\h*([A-Za-z0-9_.-]+): 0:operator + +# ARM Directives +add-highlighter shared/gas/code/ regex ((^|\s+)\.([248]byte|align|arch(_extension)?|arm|bsscantunwind|code|[cf]pu|[dq]n|eabi_attribute|even|extend|ldouble|fnend|fnstart|force_thumb|handlerdata|inst(\.[nw])?|ltorg|movsp|object_arch|packed|pad|personality(index)?|pool|req|save|setfp|screl32|syntax|thumb(_func|_set)?|tlsdescseq|unreq|unwind_raw|vsave)(\h+|$)) 0:type + +# Assembler Directives +add-highlighter shared/gas/code/ regex ((^|\s+)\.(abort|ABORT|align|app-file|ascii|asciz|balign[wl]|byte|comm|data|def|desc|dim|double|eject|else|endif|equ|extern|file|fill|float|global|globl|hword|ident|if|include|int|irp|irpc|lcomm|iflags|line|linkonce|ln|mri|list|loc|local|long|macro|nolist|octa|org|print|purgem|p2align[wl]?|psize|quad|rept|sbttl|section|set|short|single|size|skip|space|stab[dns]|string|struct|tag|text|title|type|title|uleb128|val|vtable_entry|weak|word|rodata|zero)(\h+|$)) 0:type + +# Registers +add-highlighter shared/gas/code/ regex \%(([re](ax|bx|cx|dx|si|di|bp|sp))|(al|bl|cl|dl|sil|dil|bpl|spl)|(r[8-9][dwb])|(r1[0-5][dwb])|(cs|ds|es|fs|gs|ss|ip|eflags)|([xy]mm[0-9]|[xy]mm1[0-5]))\b 0:variable + +# General Instructions +add-highlighter shared/gas/code/ regex \ +^\h*(mov|lea|call|test|cmp)([bwlq])?\b|\ +^\h*(bswap[lq]|cmpxchg[bwlq]|cmpxchg8b|cwt[ld]|movabs([bwlq])?|popa([lw])?|pusha([wl])?)\b|\ +^\h*(and|or|not|xor|sar|sal|shr|shl|sub|add|(i)?mul|(i)?div|inc|dec|adc|sbb)([bwlq])?\b|\ +^\h*(rcl|rcr|rol|ror|shld|shrd)([bwlq])?\b|\ +^\h*(bsf|bsr|bt|btc|btr|bts)([wlq])?\b|\ +^\h*(cmps|lods|movs)([sxbwdq])?\b|\ +^\h*(ret([bwlq])?|[il]ret([dq])?|leave|movzb[wlq]|movzw[lq]|movsb[wlq]|movsw[lq]|movslq|cwt[dl]|clt[sdq]|cqt[od])\b|\ +^\h*set(([bagl])?e|(n)?[zlesgabop]|(n)?(ae|le|ge|be))\b|\ +^\h*(cmovn[eszlgba]|cmov[glab]e|cmov[esglabz]|cmovn[lgba]e)\b|\ +^\h*(jmp|j[esglabzcop]|jn[esglabzcop]|j[glasbp]e|jn[glab]e|j(e)?cxz|jpo)\b|\ +^\h*(aa[adms]|da[as]|xadd[bwlq]|xchg[lwq])\b|\ +^\h*(rep|repnz|repz|scas([qlwb])?|stos([qlwb])?)\b|\ +^\h*(cl[cdi]|cmc|lahf|popf([lwq])?|pushf([lwq])?|sahf|st[cdi])\b|\ +^\h*(l[defgs]s([wl])?|cpuid|nop|ud2|xlat(b)?)\b|\ +^\h*(lea|call|push|pop)([wlq])?\b|\ +^\h*(in|ins([lwb])?|out|outs([lwb])?)\b|\ +^\h*(cb(t)?w|cwde|cdqe|cwd|cdq|cqo|sahf|lahf|por|pxor|movap[ds])\b|\ +^\h*(bound([wl])?|enter|int(o)?|lcall|loop(n)?[ez]|pause)\b 0:keyword + +#Floating Point Instructions +add-highlighter shared/gas/code/ regex \ +^\h*f(add|sub|mul|com|comp|sub|subr|div|divr|ld|xch|st|nop|stp|ldenv|chs|abs)\b|\ +^\h*f(tst|xam|ldcw|ld1|ld2[te]|ldpi|ld[gn]2|ldz|(n)?stenv|2xm1|yl2x|p(a)?tan)\b|\ +^\h*f(xtract|prem(1)?|(dec|inc)stp|(n)?stcw|yl2xp1|sqrt|sincos|rndint|scale|sin|cos|iadd)\b|\ +^\h*f(cmov[bn]e|cmove|cmovn[beu]|cmovnbe|cmovu|imul|icom|icomp|isub|isubr|icomp)\b|\ +^\h*(div|add|sub|mul|div)[ps]s\b|\ +^\h*(div|add|sub|mul|div)[ps]d\b|\ +^\h*(vmovs[ds]|vmovap[sd])\b|\ +^\h*(vcvtts[ds]2si(q)?|vcvtsi2s[d](q)?|vunpcklps|vcvtps2pd|vmovddup|vcvtpd2psx)\b|\ +^\h*(cvtss2s[di]|cvtsi2s[ds]|cvtsd2s[is]|cvtdq2p[ds]|cvtpd2(dq|pi|ps)|cvtpi2p[ds]|cvtps2p[id])\b|\ +^\h*(cvttp[ds]2dq|cvttp[ds]2pi|cvtts[ds]2si)\b|\ +^\h*(vxorp[sd]|vandp[sd]|ucomis[sd])\b 0:keyword + +define-command -hidden gas-trim-indent %{ + evaluate-commands -draft -itersel %{ + execute-keys x + # remove trailing white spaces + try %{ execute-keys -draft s \h+$ <ret> d } + } +} + +define-command -hidden gas-indent-on-new-line %~ + evaluate-commands -draft -itersel %< + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : gas-trim-indent <ret> } + # indent after label + try %[ execute-keys -draft k x <a-k> :$ <ret> j <a-gt> ] + > +~ + +} diff --git a/autoload/filetype/gdscript.kak b/autoload/filetype/gdscript.kak new file mode 100644 index 0000000..842a51e --- /dev/null +++ b/autoload/filetype/gdscript.kak @@ -0,0 +1,126 @@ +# http://godotengine.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](gd) %{ + set-option buffer filetype gdscript +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=gdscript %{ + require-module gdscript + + set-option window static_words %opt{gdscript_static_words} + + hook window InsertChar \n -group gdscript-insert gdscript-insert-on-new-line + hook window InsertChar \n -group gdscript-indent gdscript-indent-on-new-line + # cleanup trailing whitespaces on current line insert end + hook window ModeChange pop:insert:.* -group gdscript-trim-indent %{ try %{ execute-keys -draft <semicolon> x s ^\h+$ <ret> d } } + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window gdscript-.+ } +} + +hook -group gdscript-highlight global WinSetOption filetype=gdscript %{ + add-highlighter window/gdscript ref gdscript + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/gdscript } +} + +provide-module gdscript %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/gdscript regions +add-highlighter shared/gdscript/code default-region group + +add-highlighter shared/gdscript/string region -match-capture ("|'|"""|''') (?<!\\)(?:\\\\)*("|'|"""|''') group +add-highlighter shared/gdscript/string/ fill string +add-highlighter shared/gdscript/string/ regex \\[abfnrtv\n\\] 0:meta +add-highlighter shared/gdscript/string/ regex '%%' 0:meta +add-highlighter shared/gdscript/string/ regex '%[cs]' 0:value +add-highlighter shared/gdscript/string/ regex '%0?[+-]?([\d]*|\*?)\.?([\d]*|\*?)[dfoxX]' 0:value +add-highlighter shared/gdscript/string/ regex '%0?([\d]*|\*?)\.?([\d]*|\*?)[+-]?[dfoxX]' 0:value + +add-highlighter shared/gdscript/comment region '#' $ fill comment + +# integers +add-highlighter shared/gdscript/code/ regex (?i)\b0b[01]+l?\b 0:value +add-highlighter shared/gdscript/code/ regex (?i)\b0x[\da-f]+l?\b 0:value +add-highlighter shared/gdscript/code/ regex (?i)\b0o?[0-7]+l?\b 0:value +add-highlighter shared/gdscript/code/ regex (?i)\b([1-9]\d*|0)l?\b 0:value +# floats +add-highlighter shared/gdscript/code/ regex \b\d+[eE][+-]?\d+\b 0:value +add-highlighter shared/gdscript/code/ regex (\b\d+)?\.\d+\b 0:value +add-highlighter shared/gdscript/code/ regex \b\d+\. 0:value +# functions +add-highlighter shared/gdscript/code/ regex _?[a-zA-Z]\w*\s*(?=\() 0:function +add-highlighter shared/gdscript/code/ regex (?:func\h+)(_?\w+)(?:<[^>]+?>)?\( 1:function +# operators +add-highlighter shared/gdscript/code/ regex \+|-|\*|/|%|=|<|>|&|\||\^|~|:= 0:operator +# constants & enums +add-highlighter shared/gdscript/code/ regex \b[A-Z_][A-Z0-9_]*\b 0:variable +# annotations +add-highlighter shared/gdscript/code/ regex @\w+ 0:attribute +# special case of get =, set = +add-highlighter shared/gdscript/code/ regex \b(get)\h*=\h*(\w+) 1:keyword 2:function +add-highlighter shared/gdscript/code/ regex \b(set)\h*=\h*(\w+) 1:keyword 2:function +# keywords and built-ins +evaluate-commands %sh{ + keywords="as await break breakpoint class class_name const continue elif else enum extends for func if in is match pass return self signal static super var void while" + + values="false true null" + + # Built in `nushell` with `ls doc/classes | each {open $in.name | get attributes.name} | str join " "`, the rest are built similarly + builtin_classes="AABB AESContext AStar2D AStar3D AStarGrid2D AcceptDialog AnimatableBody2D AnimatableBody3D AnimatedSprite2D AnimatedSprite3D AnimatedTexture Animation AnimationLibrary AnimationNode AnimationNodeAdd2 AnimationNodeAdd3 AnimationNodeAnimation AnimationNodeBlend2 AnimationNodeBlend3 AnimationNodeBlendSpace1D AnimationNodeBlendSpace2D AnimationNodeBlendTree AnimationNodeOneShot AnimationNodeOutput AnimationNodeStateMachine AnimationNodeStateMachinePlayback AnimationNodeStateMachineTransition AnimationNodeSync AnimationNodeTimeScale AnimationNodeTimeSeek AnimationNodeTransition AnimationPlayer AnimationRootNode AnimationTrackEditPlugin AnimationTree Area2D Area3D Array ArrayMesh ArrayOccluder3D AspectRatioContainer AtlasTexture AudioBusLayout AudioEffect AudioEffectAmplify AudioEffectBandLimitFilter AudioEffectBandPassFilter AudioEffectCapture AudioEffectChorus AudioEffectCompressor AudioEffectDelay AudioEffectDistortion AudioEffectEQ AudioEffectEQ10 AudioEffectEQ21 AudioEffectEQ6 AudioEffectFilter AudioEffectHighPassFilter AudioEffectHighShelfFilter AudioEffectInstance AudioEffectLimiter AudioEffectLowPassFilter AudioEffectLowShelfFilter AudioEffectNotchFilter AudioEffectPanner AudioEffectPhaser AudioEffectPitchShift AudioEffectRecord AudioEffectReverb AudioEffectSpectrumAnalyzer AudioEffectSpectrumAnalyzerInstance AudioEffectStereoEnhance AudioListener2D AudioListener3D AudioServer AudioStream AudioStreamGenerator AudioStreamGeneratorPlayback AudioStreamMicrophone AudioStreamPlayback AudioStreamPlaybackPolyphonic AudioStreamPlaybackResampled AudioStreamPlayer AudioStreamPlayer2D AudioStreamPlayer3D AudioStreamPolyphonic AudioStreamRandomizer AudioStreamWAV BackBufferCopy BaseButton BaseMaterial3D Basis BitMap Bone2D BoneAttachment3D BoneMap BoxContainer BoxMesh BoxOccluder3D BoxShape3D Button ButtonGroup CPUParticles2D CPUParticles3D Callable CallbackTweener Camera2D Camera3D CameraAttributes CameraAttributesPhysical CameraAttributesPractical CameraFeed CameraServer CameraTexture CanvasGroup CanvasItem CanvasItemMaterial CanvasLayer CanvasModulate CanvasTexture CapsuleMesh CapsuleShape2D CapsuleShape3D CenterContainer CharFXTransform CharacterBody2D CharacterBody3D CheckBox CheckButton CircleShape2D ClassDB CodeEdit CodeHighlighter CollisionObject2D CollisionObject3D CollisionPolygon2D CollisionPolygon3D CollisionShape2D CollisionShape3D Color ColorPicker ColorPickerButton ColorRect CompressedCubemap CompressedCubemapArray CompressedTexture2D CompressedTexture2DArray CompressedTexture3D CompressedTextureLayered ConcavePolygonShape2D ConcavePolygonShape3D ConeTwistJoint3D ConfigFile ConfirmationDialog Container Control ConvexPolygonShape2D ConvexPolygonShape3D Crypto CryptoKey Cubemap CubemapArray Curve Curve2D Curve3D CurveTexture CurveXYZTexture CylinderMesh CylinderShape3D DTLSServer DampedSpringJoint2D Decal Dictionary DirAccess DirectionalLight2D DirectionalLight3D DisplayServer EditorCommandPalette EditorDebuggerPlugin EditorDebuggerSession EditorExportPlatform EditorExportPlugin EditorFeatureProfile EditorFileDialog EditorFileSystem EditorFileSystemDirectory EditorFileSystemImportFormatSupportQuery EditorImportPlugin EditorInspector EditorInspectorPlugin EditorInterface EditorNode3DGizmo EditorNode3DGizmoPlugin EditorPaths EditorPlugin EditorProperty EditorResourceConversionPlugin EditorResourcePicker EditorResourcePreview EditorResourcePreviewGenerator EditorSceneFormatImporter EditorScenePostImport EditorScenePostImportPlugin EditorScript EditorScriptPicker EditorSelection EditorSettings EditorSpinSlider EditorSyntaxHighlighter EditorTranslationParserPlugin EditorUndoRedoManager EditorVCSInterface EncodedObjectAsID Engine EngineDebugger EngineProfiler Environment Expression FileAccess FileDialog FileSystemDock FlowContainer FogMaterial FogVolume Font FontFile FontVariation GDExtension GDExtensionManager GPUParticles2D GPUParticles3D GPUParticlesAttractor3D GPUParticlesAttractorBox3D GPUParticlesAttractorSphere3D GPUParticlesAttractorVectorField3D GPUParticlesCollision3D GPUParticlesCollisionBox3D GPUParticlesCollisionHeightField3D GPUParticlesCollisionSDF3D GPUParticlesCollisionSphere3D Generic6DOFJoint3D Geometry2D Geometry3D GeometryInstance3D Gradient GradientTexture1D GradientTexture2D GraphEdit GraphNode GridContainer GrooveJoint2D HBoxContainer HFlowContainer HMACContext HScrollBar HSeparator HSlider HSplitContainer HTTPClient HTTPRequest HashingContext HeightMapShape3D HingeJoint3D IP Image ImageFormatLoader ImageFormatLoaderExtension ImageTexture ImageTexture3D ImageTextureLayered ImmediateMesh ImporterMesh ImporterMeshInstance3D Input InputEvent InputEventAction InputEventFromWindow InputEventGesture InputEventJoypadButton InputEventJoypadMotion InputEventKey InputEventMIDI InputEventMagnifyGesture InputEventMouse InputEventMouseButton InputEventMouseMotion InputEventPanGesture InputEventScreenDrag InputEventScreenTouch InputEventShortcut InputEventWithModifiers InputMap InstancePlaceholder IntervalTweener ItemList JNISingleton JSON JSONRPC JavaClass JavaClassWrapper JavaScriptBridge JavaScriptObject Joint2D Joint3D KinematicCollision2D KinematicCollision3D Label Label3D LabelSettings Light2D Light3D LightOccluder2D LightmapGI LightmapGIData LightmapProbe Lightmapper LightmapperRD Line2D LineEdit LinkButton MainLoop MarginContainer Marker2D Marker3D Marshalls Material MenuBar MenuButton Mesh MeshDataTool MeshInstance2D MeshInstance3D MeshLibrary MeshTexture MethodTweener MissingNode MissingResource MovieWriter MultiMesh MultiMeshInstance2D MultiMeshInstance3D MultiplayerAPI MultiplayerAPIExtension MultiplayerPeer MultiplayerPeerExtension Mutex NavigationAgent2D NavigationAgent3D NavigationLink2D NavigationLink3D NavigationMesh NavigationMeshGenerator NavigationObstacle2D NavigationObstacle3D NavigationPathQueryParameters2D NavigationPathQueryParameters3D NavigationPathQueryResult2D NavigationPathQueryResult3D NavigationPolygon NavigationRegion2D NavigationRegion3D NavigationServer2D NavigationServer3D NinePatchRect Node Node2D Node3D Node3DGizmo NodePath ORMMaterial3D OS Object Occluder3D OccluderInstance3D OccluderPolygon2D OfflineMultiplayerPeer OmniLight3D OptimizedTranslation OptionButton PCKPacker PackedByteArray PackedColorArray PackedDataContainer PackedDataContainerRef PackedFloat32Array PackedFloat64Array PackedInt32Array PackedInt64Array PackedScene PackedStringArray PackedVector2Array PackedVector3Array PacketPeer PacketPeerDTLS PacketPeerExtension PacketPeerStream PacketPeerUDP Panel PanelContainer PanoramaSkyMaterial ParallaxBackground ParallaxLayer ParticleProcessMaterial Path2D Path3D PathFollow2D PathFollow3D Performance PhysicalBone2D PhysicalBone3D PhysicalSkyMaterial PhysicsBody2D PhysicsBody3D PhysicsDirectBodyState2D PhysicsDirectBodyState2DExtension PhysicsDirectBodyState3D PhysicsDirectBodyState3DExtension PhysicsDirectSpaceState2D PhysicsDirectSpaceState2DExtension PhysicsDirectSpaceState3D PhysicsDirectSpaceState3DExtension PhysicsMaterial PhysicsPointQueryParameters2D PhysicsPointQueryParameters3D PhysicsRayQueryParameters2D PhysicsRayQueryParameters3D PhysicsServer2D PhysicsServer2DExtension PhysicsServer2DManager PhysicsServer3D PhysicsServer3DExtension PhysicsServer3DManager PhysicsServer3DRenderingServerHandler PhysicsShapeQueryParameters2D PhysicsShapeQueryParameters3D PhysicsTestMotionParameters2D PhysicsTestMotionParameters3D PhysicsTestMotionResult2D PhysicsTestMotionResult3D PinJoint2D PinJoint3D PlaceholderCubemap PlaceholderCubemapArray PlaceholderMaterial PlaceholderMesh PlaceholderTexture2D PlaceholderTexture2DArray PlaceholderTexture3D PlaceholderTextureLayered Plane PlaneMesh PointLight2D PointMesh Polygon2D PolygonOccluder3D PolygonPathFinder Popup PopupMenu PopupPanel PortableCompressedTexture2D PrimitiveMesh PrismMesh ProceduralSkyMaterial ProgressBar ProjectSettings Projection PropertyTweener QuadMesh QuadOccluder3D Quaternion RDAttachmentFormat RDFramebufferPass RDPipelineColorBlendState RDPipelineColorBlendStateAttachment RDPipelineDepthStencilState RDPipelineMultisampleState RDPipelineRasterizationState RDPipelineSpecializationConstant RDSamplerState RDShaderFile RDShaderSPIRV RDShaderSource RDTextureFormat RDTextureView RDUniform RDVertexAttribute RID RandomNumberGenerator Range RayCast2D RayCast3D Rect2 Rect2i RectangleShape2D RefCounted ReferenceRect ReflectionProbe RemoteTransform2D RemoteTransform3D RenderingDevice RenderingServer Resource ResourceFormatLoader ResourceFormatSaver ResourceImporter ResourceLoader ResourcePreloader ResourceSaver ResourceUID RibbonTrailMesh RichTextEffect RichTextLabel RigidBody2D RigidBody3D RootMotionView SceneState SceneTree SceneTreeTimer Script ScriptCreateDialog ScriptEditor ScriptEditorBase ScriptExtension ScriptLanguage ScriptLanguageExtension ScrollBar ScrollContainer SegmentShape2D Semaphore SeparationRayShape2D SeparationRayShape3D Separator Shader ShaderGlobalsOverride ShaderInclude ShaderMaterial Shape2D Shape3D ShapeCast2D ShapeCast3D Shortcut Signal Skeleton2D Skeleton3D SkeletonIK3D SkeletonModification2D SkeletonModification2DCCDIK SkeletonModification2DFABRIK SkeletonModification2DJiggle SkeletonModification2DLookAt SkeletonModification2DPhysicalBones SkeletonModification2DStackHolder SkeletonModification2DTwoBoneIK SkeletonModificationStack2D SkeletonProfile SkeletonProfileHumanoid Skin SkinReference Sky Slider SliderJoint3D SoftBody3D SphereMesh SphereOccluder3D SphereShape3D SpinBox SplitContainer SpotLight3D SpringArm3D Sprite2D Sprite3D SpriteBase3D SpriteFrames StandardMaterial3D StaticBody2D StaticBody3D StreamPeer StreamPeerBuffer StreamPeerExtension StreamPeerGZIP StreamPeerTCP StreamPeerTLS String StringName StyleBox StyleBoxEmpty StyleBoxFlat StyleBoxLine StyleBoxTexture SubViewport SubViewportContainer SurfaceTool SyntaxHighlighter SystemFont TCPServer TLSOptions TabBar TabContainer TextEdit TextLine TextMesh TextParagraph TextServer TextServerDummy TextServerExtension TextServerManager Texture Texture2D Texture2DArray Texture3D TextureButton TextureLayered TextureProgressBar TextureRect Theme ThemeDB Thread TileData TileMap TileMapPattern TileSet TileSetAtlasSource TileSetScenesCollectionSource TileSetSource Time Timer TorusMesh TouchScreenButton Transform2D Transform3D Translation TranslationServer Tree TreeItem TriangleMesh TubeTrailMesh Tween Tweener UDPServer UndoRedo VBoxContainer VFlowContainer VScrollBar VSeparator VSlider VSplitContainer Variant Vector2 Vector2i Vector3 Vector3i Vector4 Vector4i VehicleBody3D VehicleWheel3D VideoStream VideoStreamPlayback VideoStreamPlayer Viewport ViewportTexture VisibleOnScreenEnabler2D VisibleOnScreenEnabler3D VisibleOnScreenNotifier2D VisibleOnScreenNotifier3D VisualInstance3D VisualShader VisualShaderNode VisualShaderNodeBillboard VisualShaderNodeBooleanConstant VisualShaderNodeBooleanParameter VisualShaderNodeClamp VisualShaderNodeColorConstant VisualShaderNodeColorFunc VisualShaderNodeColorOp VisualShaderNodeColorParameter VisualShaderNodeComment VisualShaderNodeCompare VisualShaderNodeConstant VisualShaderNodeCubemap VisualShaderNodeCubemapParameter VisualShaderNodeCurveTexture VisualShaderNodeCurveXYZTexture VisualShaderNodeCustom VisualShaderNodeDerivativeFunc VisualShaderNodeDeterminant VisualShaderNodeDistanceFade VisualShaderNodeDotProduct VisualShaderNodeExpression VisualShaderNodeFaceForward VisualShaderNodeFloatConstant VisualShaderNodeFloatFunc VisualShaderNodeFloatOp VisualShaderNodeFloatParameter VisualShaderNodeFresnel VisualShaderNodeGlobalExpression VisualShaderNodeGroupBase VisualShaderNodeIf VisualShaderNodeInput VisualShaderNodeIntConstant VisualShaderNodeIntFunc VisualShaderNodeIntOp VisualShaderNodeIntParameter VisualShaderNodeIs VisualShaderNodeLinearSceneDepth VisualShaderNodeMix VisualShaderNodeMultiplyAdd VisualShaderNodeOuterProduct VisualShaderNodeOutput VisualShaderNodeParameter VisualShaderNodeParameterRef VisualShaderNodeParticleAccelerator VisualShaderNodeParticleBoxEmitter VisualShaderNodeParticleConeVelocity VisualShaderNodeParticleEmit VisualShaderNodeParticleEmitter VisualShaderNodeParticleMeshEmitter VisualShaderNodeParticleMultiplyByAxisAngle VisualShaderNodeParticleOutput VisualShaderNodeParticleRandomness VisualShaderNodeParticleRingEmitter VisualShaderNodeParticleSphereEmitter VisualShaderNodeProximityFade VisualShaderNodeRandomRange VisualShaderNodeRemap VisualShaderNodeResizableBase VisualShaderNodeSDFRaymarch VisualShaderNodeSDFToScreenUV VisualShaderNodeSample3D VisualShaderNodeScreenUVToSDF VisualShaderNodeSmoothStep VisualShaderNodeStep VisualShaderNodeSwitch VisualShaderNodeTexture VisualShaderNodeTexture2DArray VisualShaderNodeTexture2DArrayParameter VisualShaderNodeTexture2DParameter VisualShaderNodeTexture3D VisualShaderNodeTexture3DParameter VisualShaderNodeTextureParameter VisualShaderNodeTextureParameterTriplanar VisualShaderNodeTextureSDF VisualShaderNodeTextureSDFNormal VisualShaderNodeTransformCompose VisualShaderNodeTransformConstant VisualShaderNodeTransformDecompose VisualShaderNodeTransformFunc VisualShaderNodeTransformOp VisualShaderNodeTransformParameter VisualShaderNodeTransformVecMult VisualShaderNodeUIntConstant VisualShaderNodeUIntFunc VisualShaderNodeUIntOp VisualShaderNodeUIntParameter VisualShaderNodeUVFunc VisualShaderNodeUVPolarCoord VisualShaderNodeVarying VisualShaderNodeVaryingGetter VisualShaderNodeVaryingSetter VisualShaderNodeVec2Constant VisualShaderNodeVec2Parameter VisualShaderNodeVec3Constant VisualShaderNodeVec3Parameter VisualShaderNodeVec4Constant VisualShaderNodeVec4Parameter VisualShaderNodeVectorBase VisualShaderNodeVectorCompose VisualShaderNodeVectorDecompose VisualShaderNodeVectorDistance VisualShaderNodeVectorFunc VisualShaderNodeVectorLen VisualShaderNodeVectorOp VisualShaderNodeVectorRefract VoxelGI VoxelGIData WeakRef Window WorkerThreadPool World2D World3D WorldBoundaryShape2D WorldBoundaryShape3D WorldEnvironment X509Certificate XMLParser XRAnchor3D XRCamera3D XRController3D XRInterface XRInterfaceExtension XRNode3D XROrigin3D XRPose XRPositionalTracker XRServer bool float int" + + builtin_methods="abs absf absi acos asin atan atan2 bezier_derivative bezier_interpolate bytes_to_var bytes_to_var_with_objects ceil ceilf ceili clamp clampf clampi cos cosh cubic_interpolate cubic_interpolate_angle cubic_interpolate_angle_in_time cubic_interpolate_in_time db_to_linear deg_to_rad ease error_string exp floor floorf floori fmod fposmod hash instance_from_id inverse_lerp is_equal_approx is_finite is_inf is_instance_id_valid is_instance_valid is_nan is_same is_zero_approx lerp lerp_angle lerpf linear_to_db log max maxf maxi min minf mini move_toward nearest_po2 pingpong posmod pow print print_rich print_verbose printerr printraw prints printt push_error push_warning rad_to_deg rand_from_seed randf randf_range randfn randi randi_range randomize remap rid_allocate_id rid_from_int64 round roundf roundi seed sign signf signi sin sinh smoothstep snapped snappedf snappedi sqrt step_decimals str str_to_var tan tanh typeof var_to_bytes var_to_bytes_with_objects var_to_str weakref wrap wrapf wrapi" + + gdscript_methods="Color8 assert char convert dict_to_inst get_stack inst_to_dict is_instance_of len load preload print_debug print_stack range type_exists" + + gdscript_constants="PI TAU INF NAN" + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list gdscript_static_words $(join "${keywords} ${values} ${builtin_classes} ${builtin_methods} ${gdscript_methods} ${gdscript_constants}" ' ')" + + printf %s " + add-highlighter shared/gdscript/code/ regex '\b($(join "${keywords}" '|'))\b' 0:keyword + add-highlighter shared/gdscript/code/ regex '\b($(join "${values}" '|'))\b' 0:value + add-highlighter shared/gdscript/code/ regex '\b($(join "${builtin_classes}" '|'))\b' 0:type + add-highlighter shared/gdscript/code/ regex '\b($(join "${builtin_methods}" '|'))\b\(' 1:builtin + add-highlighter shared/gdscript/code/ regex '\b($(join "${gdscript_methods}" '|'))\b\(' 1:builtin + add-highlighter shared/gdscript/code/ regex '\b($(join "${gdscript_constants}" '|'))\b' 0:keyword + " +} +# nodes +add-highlighter shared/gdscript/code/ regex \$[\w/]+\b 0:module +add-highlighter shared/gdscript/code/ regex \%\w+(?!/)\b 0:string + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden gdscript-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy '#' comment prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*#\h* <ret> y jgh P } + } +} + +define-command -hidden gdscript-indent-on-new-line %< + evaluate-commands -draft -itersel %< + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # cleanup trailing whitespaces from previous line + try %{ execute-keys -draft k x s \h+$ <ret> d } + # indent after line ending with : + try %{ execute-keys -draft , k x <a-k> :$ <ret> <a-K> ^\h*# <ret> j <a-gt> } + # deindent closing brace/bracket when after cursor (for arrays and dictionaries) + try %< execute-keys -draft x <a-k> ^\h*[}\]] <ret> gh / [}\]] <ret> m <a-S> 1<a-&> > + > +> + +§ diff --git a/autoload/filetype/gentoo-linux.kak b/autoload/filetype/gentoo-linux.kak new file mode 100644 index 0000000..251dad1 --- /dev/null +++ b/autoload/filetype/gentoo-linux.kak @@ -0,0 +1,4 @@ +# portage ebuild file +hook global BufCreate .*\.ebuild %{ + set-option buffer filetype sh +} diff --git a/autoload/filetype/git.kak b/autoload/filetype/git.kak new file mode 100644 index 0000000..4501162 --- /dev/null +++ b/autoload/filetype/git.kak @@ -0,0 +1,69 @@ +hook global BufCreate .*(COMMIT_EDITMSG|MERGE_MSG) %{ + set-option buffer filetype git-commit +} + +hook global BufCreate .*/NOTES_EDITMSG %{ + set-option buffer filetype git-notes +} + +hook global BufCreate .*(\.git(config|modules)|git/config) %{ + set-option buffer filetype ini +} + +hook global BufCreate .*\.gitignore %{ + set-option buffer filetype git-ignore +} + +hook global BufCreate .*git-rebase-todo %{ + set-option buffer filetype git-rebase +} + +hook global WinSetOption filetype=git-(commit|ignore|notes|rebase) %{ + require-module "git-%val{hook_param_capture_1}" +} + +hook -group git-commit-highlight global WinSetOption filetype=git-commit %{ + add-highlighter window/git-commit ref git-commit + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/git-commit } +} + +hook -group git-ignore-highlight global WinSetOption filetype=git-ignore %{ + add-highlighter window/git-ignore ref git-ignore + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/git-ignore } +} + +hook -group git-notes-highlight global WinSetOption filetype=git-notes %{ + add-highlighter window/git-notes ref git-notes + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/git-notes } +} + +hook -group git-rebase-highlight global WinSetOption filetype=git-rebase %{ + add-highlighter window/git-rebase ref git-rebase + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/git-rebase } +} + +provide-module git-commit %{ +require-module diff +add-highlighter shared/git-commit regions +add-highlighter shared/git-commit/diff region '^diff --git' '^(?=diff --git)' ref diff # highlight potential diffs from the -v option +add-highlighter shared/git-commit/comments region ^# $ group +add-highlighter shared/git-commit/comments/ fill comment +add-highlighter shared/git-commit/comments/ regex "\b(?:(modified)|(deleted)|(new file)|(renamed|copied)):([^\n]*)$" 1:yellow 2:red 3:green 4:blue 5:magenta +} + +provide-module git-ignore %{ +add-highlighter shared/git-ignore group +add-highlighter shared/git-ignore/glob regex '(?<!\\)(?:\\\\)*\K(\*\*?|\?|\[.*?(?<!\\)(?:\\\\)*\])' 0:operator +add-highlighter shared/git-ignore/negate regex '^!' 0:operator +add-highlighter shared/git-ignore/comments regex '^#.*?$' 0:comment +} + +provide-module git-notes %{ +add-highlighter shared/git-notes regex ^#[^\n]*$ 0:comment +} + +provide-module git-rebase %{ +add-highlighter shared/git-rebase group +add-highlighter shared/git-rebase/ regex "^\h*#[^\n]*\n" 0:comment +add-highlighter shared/git-rebase/ regex "^(?:(pick|p)|(edit|reword|squash|fixup|exec|break|drop|label|reset|merge|[ersfxbdltm])) (\w+)" 1:keyword 2:value 3:meta +} diff --git a/autoload/filetype/github.kak b/autoload/filetype/github.kak new file mode 100644 index 0000000..17e593a --- /dev/null +++ b/autoload/filetype/github.kak @@ -0,0 +1,18 @@ +hook global BufCreate .*/CODEOWNERS %{ + set-option buffer filetype codeowners +} + +hook global WinSetOption filetype=codeowners %{ + require-module codeowners +} + +hook -group codeowners-hightlight global WinSetOption filetype=codeowners %{ + add-highlighter window/codeowners ref codeowners + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/codeowners } +} + +provide-module codeowners %{ +add-highlighter shared/codeowners regions +add-highlighter shared/codeowners/comments region ^# $ group +add-highlighter shared/codeowners/comments/ fill comment +} diff --git a/autoload/filetype/gluon.kak b/autoload/filetype/gluon.kak new file mode 100644 index 0000000..2c4b96b --- /dev/null +++ b/autoload/filetype/gluon.kak @@ -0,0 +1,103 @@ +# http://gluon-lang.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](glu) %{ + set-option buffer filetype gluon +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=gluon %{ + require-module gluon + + set-option window extra_word_chars '_' "'" + hook window ModeChange pop:insert:.* -group gluon-trim-indent gluon-trim-indent + hook window InsertChar \n -group gluon-insert gluon-insert-on-new-line + hook window InsertChar \n -group gluon-indent gluon-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ + remove-hooks window gluon-.+ + } +} + +hook -group gluon-highlight global WinSetOption filetype=gluon %{ + add-highlighter window/gluon ref gluon + hook -once -always window WinSetOption filetype=.* %{ + remove-highlighter window/gluon + } +} + + +provide-module gluon %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/gluon regions +add-highlighter shared/gluon/code default-region group +add-highlighter shared/gluon/string region (?<!')" (?<!\\)(\\\\)*" fill string +add-highlighter shared/gluon/raw_string region -match-capture \br(#+)" \"(#+) fill string +add-highlighter shared/gluon/comment region /\* \*/ fill comment +add-highlighter shared/gluon/line_comment region // $ fill comment +add-highlighter shared/gluon/attribute region -recurse \[ '#\[' \] fill meta +# balance out bracket ] + +# matches hexadecimal literals +add-highlighter shared/gluon/code/ regex \b0x+[A-Fa-f0-9]+ 0:value +# matches decimal and floating-point literals +add-highlighter shared/gluon/code/ regex \b\d+([.]\d+)? 0:value + +# matches keywords +add-highlighter shared/gluon/code/ regex \ + (?<!')\b(type|if|then|else|match|with|let|rec|do|seq|in)\b(?!') 0:keyword + +# matches macros +add-highlighter shared/gluon/code/ regex \b\w+! 0:meta + +# matches uppercase identifiers: Monad Some +add-highlighter shared/gluon/code/ regex \b[A-Z][\w']* 0:variable + +# matches operators: ... > < <= ^ <*> <$> etc +# matches dot: . +# matches keywords: @ : -> +add-highlighter shared/gluon/code/ regex (?<![~<=>|:!?/.@$*&#%+\^\-\\])[~<=>|:!?/.@$*&#%+\^\-\\]+ 0:operator + +# matches 'x' '\\' '\'' '\n' '\0' +# not incomplete literals: '\' +add-highlighter shared/gluon/code/ regex \B'([^\\]|[\\]['"\w\d\\])' 0:string +# this has to come after operators so '-' etc is correct + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden gluon-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden gluon-insert-on-new-line %~ + evaluate-commands -draft -itersel %_ + # copy // and /// comments prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K///?\h* <ret> y gh j P } + _ +~ + +define-command -hidden gluon-indent-on-new-line %~ + evaluate-commands -draft -itersel %_ + # preserve previous line indent + try %{ execute-keys -draft \; K <a-&> } + # filter previous line + try %{ execute-keys -draft k : gluon-trim-indent <ret> } + # indent after lines ending with (open) braces, =, ->, condition, rec, + # or in + try %{ execute-keys -draft \; k x <a-k> (\(|\{|\[|=|->|\b(?:then|else|rec|in))$ <ret> j <a-gt> } + # deindent closing brace(s) when after cursor + try %< execute-keys -draft x <a-k> ^\h*[})\]] <ret> gh / \})\]] <ret> m <a-S> 1<a-&> > + _ +~ + +§ diff --git a/autoload/filetype/go.kak b/autoload/filetype/go.kak new file mode 100644 index 0000000..4f8407c --- /dev/null +++ b/autoload/filetype/go.kak @@ -0,0 +1,174 @@ +# https://golang.org/ +# + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*\.go %{ + set-option buffer filetype go +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=go %{ + require-module go + + set-option window static_words %opt{go_static_words} + + # cleanup trailing whitespaces when exiting insert mode + hook window ModeChange pop:insert:.* -group go-trim-indent %{ try %{ execute-keys -draft xs^\h+$<ret>d } } + hook window InsertChar \n -group go-indent go-indent-on-new-line + hook window InsertChar \{ -group go-indent go-indent-on-opening-curly-brace + hook window InsertChar \} -group go-indent go-indent-on-closing-curly-brace + hook window InsertChar \n -group go-comment-insert go-insert-comment-on-new-line + hook window InsertChar \n -group go-closing-delimiter-insert go-insert-closing-delimiter-on-new-line + + alias window alt go-alternative-file + + hook -once -always window WinSetOption filetype=.* %{ + remove-hooks window go-.+ + unalias window alt go-alternative-file + } +} + +hook -group go-highlight global WinSetOption filetype=go %{ + add-highlighter window/go ref go + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/go } +} + +provide-module go %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/go regions +add-highlighter shared/go/code default-region group +add-highlighter shared/go/back_string region '`' '`' fill string +add-highlighter shared/go/double_string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/go/single_string region "'" (?<!\\)(\\\\)*' fill string +add-highlighter shared/go/comment region /\* \*/ fill comment +add-highlighter shared/go/comment_line region '//' $ fill comment + +add-highlighter shared/go/code/numeric regex %{-?([0-9]*\.(?!0[xX]))?\b([0-9]+|0[xX][0-9a-fA-F]+)\.?([eE][+-]?[0-9]+)?i?\b} 0:value +add-highlighter shared/go/code/function regex "\b(\w*)\b\h*(?:\[[\w\s\.,]*\])?\h*\(" 1:function +add-highlighter shared/go/code/operator regex "(\+|-|\*|/|%|\+\+|--|\+=|-=|\*=|/=|%=|==|!=|>|<|>=|<=|&|&&|\|\||!|<-|:=|\.\.\.)" 1:operator + +evaluate-commands %sh{ + # Grammar + keywords='break default func interface select case defer go map struct + chan else goto package switch const fallthrough if range type + continue for import return var' + types='any bool byte chan comparable complex128 complex64 error float32 float64 int int16 int32 + int64 int8 interface intptr map rune string struct uint uint16 uint32 uint64 uint8 uintptr' + values='false true nil iota' + functions='append cap close complex copy delete imag len make new panic print println real recover' + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list go_static_words $(join "${keywords} ${attributes} ${types} ${values} ${functions}" ' ')" + + # Highlight keywords + printf %s " + add-highlighter shared/go/code/keyword regex \b($(join "${keywords}" '|'))\b 0:keyword + add-highlighter shared/go/code/attribute regex \b($(join "${attributes}" '|'))\b 0:attribute + add-highlighter shared/go/code/type regex \b($(join "${types}" '|'))\b 0:type + add-highlighter shared/go/code/value regex \b($(join "${values}" '|'))\b 0:value + add-highlighter shared/go/code/builtin regex \b($(join "${functions}" '|'))\b 0:builtin + " +} + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command go-alternative-file -docstring 'Jump to the alternate file (implementation ↔ test)' %{ evaluate-commands %sh{ + case $kak_buffile in + *_test.go) + altfile=${kak_buffile%_test.go}.go + test ! -f "$altfile" && echo "fail 'implementation file not found'" && exit + ;; + *.go) + altfile=${kak_buffile%.go}_test.go + test ! -f "$altfile" && echo "fail 'test file not found'" && exit + ;; + *) + echo "fail 'alternative file not found'" && exit + ;; + esac + printf "edit -- '%s'" "$(printf %s "$altfile" | sed "s/'/''/g")" +}} + +define-command -hidden go-indent-on-new-line %~ + evaluate-commands -draft -itersel %= + # preserve previous line indent + try %{ execute-keys -draft <semicolon>K<a-&> } + # cleanup trailing white spaces on the previous line + try %{ execute-keys -draft kx s \h+$ <ret>d } + try %< + try %{ # line comment + execute-keys -draft kx s ^\h*// <ret> + } catch %{ # block comment + execute-keys -draft <a-?> /\* <ret> <a-K>\*/<ret> + } + > catch %< + # indent after lines with an unclosed { or ( + try %< execute-keys -draft [c[({],[)}] <ret> <a-k> \A[({][^\n]*\n[^\n]*\n?\z <ret> j<a-gt> > + # indent after a switch's case/default statements + try %[ execute-keys -draft kx <a-k> ^\h*(case|default).*:$ <ret> j<a-gt> ] + # deindent closing brace(s) when after cursor + try %[ execute-keys -draft x <a-k> ^\h*[})] <ret> gh / [})] <ret> m <a-S> 1<a-&> ] + > + = +~ + +define-command -hidden go-indent-on-opening-curly-brace %[ + # align indent with opening paren when { is entered on a new line after the closing paren + try %[ execute-keys -draft -itersel h<a-F>)M <a-k> \A\(.*\)\h*\n\h*\{\z <ret> s \A|.\z <ret> 1<a-&> ] +] + +define-command -hidden go-indent-on-closing-curly-brace %[ + # align to opening curly brace when alone on a line + try %[ execute-keys -itersel -draft <a-h><a-k>^\h+\}$<ret>hms\A|.\z<ret>1<a-&> ] +] + +define-command -hidden go-insert-comment-on-new-line %[ + evaluate-commands -no-hooks -draft -itersel %[ + # copy // comments prefix and following white spaces + try %{ execute-keys -draft <semicolon><c-s>kx s ^\h*\K/{2,}\h* <ret> y<c-o>P<esc> } + ] +] + +define-command -hidden go-insert-closing-delimiter-on-new-line %[ + evaluate-commands -no-hooks -draft -itersel %[ + # Wisely add '}'. + evaluate-commands -save-regs x %[ + # Save previous line indent in register x. + try %[ execute-keys -draft kxs^\h+<ret>"xy ] catch %[ reg x '' ] + try %[ + # Validate previous line and that it is not closed yet. + execute-keys -draft kx <a-k>^<c-r>x.*\{\h*\(?\h*$<ret> j}iJx <a-K>^<c-r>x\)?\h*\}<ret> + # Insert closing '}'. + execute-keys -draft o<c-r>x}<esc> + # Delete trailing '}' on the line below the '{'. + execute-keys -draft xs\}$<ret>d + ] + ] + + # Wisely add ')'. + evaluate-commands -save-regs x %[ + # Save previous line indent in register x. + try %[ execute-keys -draft kxs^\h+<ret>"xy ] catch %[ reg x '' ] + try %[ + # Validate previous line and that it is not closed yet. + execute-keys -draft kx <a-k>^<c-r>x.*\(\h*$<ret> J}iJx <a-K>^<c-r>x\)<ret> + # Insert closing ')'. + execute-keys -draft o<c-r>x)<esc> + # Delete trailing ')' on the line below the '('. + execute-keys -draft xs\)\h*\}?\h*$<ret>d + ] + ] + ] +] + +§ diff --git a/autoload/filetype/graphql.kak b/autoload/filetype/graphql.kak new file mode 100644 index 0000000..85bf71d --- /dev/null +++ b/autoload/filetype/graphql.kak @@ -0,0 +1,100 @@ +# http://graphql.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](graphqls?) %{ + set-option buffer filetype graphql +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=graphql %{ + require-module graphql + + hook window ModeChange pop:insert:.* -group graphql-trim-indent graphql-trim-indent + hook window InsertChar .* -group graphql-indent graphql-indent-on-char + hook window InsertChar \n -group graphql-indent graphql-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window graphql-.+ } +} + +hook -group graphql-highlight global WinSetOption filetype=graphql %{ + add-highlighter window/graphql ref graphql + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/graphql } +} + + +provide-module graphql %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/graphql regions +add-highlighter shared/graphql/code default-region group +add-highlighter shared/graphql/line-description region '#' '\n' fill comment +add-highlighter shared/graphql/block-description region '"""' '"""' fill comment +add-highlighter shared/graphql/description region '"' '"\s*\n' fill comment +add-highlighter shared/graphql/object region -recurse \{ [{] [}] regions + +# Objects +add-highlighter shared/graphql/object/line-description region '#' '\n' fill comment +add-highlighter shared/graphql/object/block-description region '"""' '"""' fill comment +add-highlighter shared/graphql/object/field default-region group +add-highlighter shared/graphql/object/field/ regex ([A-Za-z][A-Za-z0-9_-]*)(?:\([^)]*\))?\h*[:{] 1:attribute +add-highlighter shared/graphql/object/field/ regex ^\h*([A-Za-z][A-Za-z0-9_-]*)\h*$ 1:attribute + +# Values +add-highlighter shared/graphql/object/field/values regex \b(true|false|null|\d+(?:\.\d+)?(?:[eE][+-]?\d*)?)\b 0:value +add-highlighter shared/graphql/object/field/variables regex \$[a-zA-Z0-9]+\b 0:variable +# add-highlighter shared/graphql/object/field/string regex '"([^"]|\\")*"' 0:string +add-highlighter shared/graphql/object/field/string regex '"(?:[^"\\]|\\.)*"' 0:string + +# Meta +add-highlighter shared/graphql/object/field/directives regex @(?:include|skip) 0:meta + +# Attributes +add-highlighter shared/graphql/object/field/required regex '(?<=[\w\]])(?<bang>!)' bang:operator +add-highlighter shared/graphql/object/field/assignment regex '=' 0:operator + +# Keywords +add-highlighter shared/graphql/code/top-level regex '\bschema\b' 0:keyword +add-highlighter shared/graphql/code/keywords regex '\b(?<name>enum|fragment|input|implements|interface|mutation|on|query|scalar|subscription|type|union)\h+(?:[A-Za-z]\w*)' name:keyword + +# Types +add-highlighter shared/graphql/object/field/scalars regex \b(Boolean|Float|ID|Int|String)\b 0:type + +# Operators +add-highlighter shared/graphql/object/field/expand-fragment regex '\.\.\.(?=\w)' 0:operator + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden graphql-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden graphql-indent-on-char %< + evaluate-commands -draft -itersel %< + # align closer token to its opener when alone on a line + try %< execute-keys -draft <a-h> <a-k> ^\h+[\]}]$ <ret> m <a-S> 1<a-&> > + > +> + +define-command -hidden graphql-indent-on-new-line %< + evaluate-commands -draft -itersel %< + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : graphql-trim-indent <ret> } + # indent after lines ending with opener token + try %< execute-keys -draft k x <a-k> [[{]\h*$ <ret> j <a-gt> > + # deindent closer token(s) when after cursor + try %< execute-keys -draft x <a-k> ^\h*[}\]] <ret> gh / [}\]] <ret> m <a-S> 1<a-&> > + > +> + +§ diff --git a/autoload/filetype/gren.kak b/autoload/filetype/gren.kak new file mode 100644 index 0000000..d61e59d --- /dev/null +++ b/autoload/filetype/gren.kak @@ -0,0 +1,7 @@ +# http://gren-lang.org/ +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](gren) %{ + set-option buffer filetype elm +} + diff --git a/autoload/filetype/groovy.kak b/autoload/filetype/groovy.kak new file mode 100644 index 0000000..b6b7305 --- /dev/null +++ b/autoload/filetype/groovy.kak @@ -0,0 +1,92 @@ +# Adapted from the file created by Daniel Lewan TeddyDD + +hook global BufCreate "(.+\.(groovy|gvy|gy|gsh|gradle))|.+[Jj]enkinsfile.*" %{ + set-option buffer filetype groovy +} + +hook global WinSetOption filetype=groovy %{ + require-module groovy + + set-option window static_words %opt{groovy_static_words} + + hook window ModeChange pop:insert:.* -group groovy-trim-indent %{ try %{ execute-keys -draft xs^\h+$<ret>d } } + hook window InsertChar \n -group groovy-insert groovy-insert-on-new-line + hook window InsertChar \n -group groovy-indent groovy-indent-on-new-line + hook window InsertChar \{ -group groovy-indent groovy-indent-on-opening-curly-brace + hook window InsertChar \} -group groovy-indent groovy-indent-on-closing-curly-brace + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window groovy-.+ } +} + +hook -group groovy-highlight global WinSetOption filetype=groovy %{ + add-highlighter window/groovy ref groovy + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/groovy } +} + +provide-module groovy %§ + +add-highlighter shared/groovy regions + +add-highlighter shared/groovy/code default-region group +add-highlighter shared/groovy/triple_quote region '"{3}' (?<!\\)(\\\\)*"{3} fill string +add-highlighter shared/groovy/double_string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/groovy/single_string region "'" (?<!\\)(\\\\)*' fill string +add-highlighter shared/groovy/comment1 region '/\*[^*]?' '\*/' fill comment +add-highlighter shared/groovy/comment2 region '//[^/]?' $ fill comment +add-highlighter shared/groovy/shellbang region '#!.+' $ fill comment +add-highlighter shared/groovy/dollar_string region "\$/" "(?<!\$)/\$" fill string +# add-highlighter shared/groovy/code/identifiers regex '\b[$_]?[a-zA-Z0-9_]+\b' 0:variable +add-highlighter shared/groovy/code/declaration regex "(?<typ>\w+)(?:\[.*?\])?\s+(\$?\w+)\s=" typ:type +add-highlighter shared/groovy/code/numbers regex '\b[-+]?0x[A-Fa-f0-9_]+[.A-Fa-f0-9_p]*[lLiDgGIF]?|\b[-+]?[\d]+b?[.p_\dEe]*[lLiDgGIF]?' 0:value +add-highlighter shared/groovy/slashy_string region "\b/\w" "(?<!\\)\w/\b" fill string + +evaluate-commands %sh{ + keywords="as|assert|break|case|catch|class|const|continue|def|default" + keywords="${keywords}|do|else|enum|extends|finally|for|goto|if|implements|import|in" + keywords="${keywords}|instanceof|interface|new|package|return|super|switch|this|throw" + keywords="${keywords}|throws|trait|try|while" + builtins="true|false|null" + types="byte|char|short|int|long|BigInteger|float|double|BigDecimal|boolean" + + printf %s " + add-highlighter shared/groovy/code/keyword regex \b(${keywords})\b 0:keyword + add-highlighter shared/groovy/code/builtin regex \b(${builtins})\b 0:builtin + add-highlighter shared/groovy/code/types regex \b(${types})\b 0:type + + declare-option str-list groovy_static_words \"${keywords}|${types}|${builtins}\" + " +} + +define-command -hidden groovy-insert-on-new-line %[ + # copy // comments prefix and following white spaces + try %{ execute-keys -draft <semicolon><c-s>kx s ^\h*\K/{2,}\h* <ret> y<c-o>P<esc> } +] + +define-command -hidden groovy-indent-on-new-line %~ + evaluate-commands -draft -itersel %= + # preserve previous line indent + try %{ execute-keys -draft <semicolon>K<a-&> } + # indent after lines ending with { or ( + try %[ execute-keys -draft kx <a-k> [{(]\h*$ <ret> j<a-gt> ] + # cleanup trailing white spaces on the previous line + try %{ execute-keys -draft kx s \h+$ <ret>d } + # align to opening paren of previous line + try %{ execute-keys -draft [( <a-k> \A\([^\n]+\n[^\n]*\n?\z <ret> s \A\(\h*.|.\z <ret> '<a-;>' & } + # indent after a switch's case/default statements + try %[ execute-keys -draft kx <a-k> ^\h*(case|default).*:$ <ret> j<a-gt> ] + # indent after keywords + try %[ execute-keys -draft <semicolon><a-F>)MB <a-k> \A(if|else|while|for|try|catch)\h*\(.*\)\h*\n\h*\n?\z <ret> s \A|.\z <ret> 1<a-&>1<a-space><a-gt> ] + # deindent closing brace(s) when after cursor + try %[ execute-keys -draft x <a-k> ^\h*[})] <ret> gh / [})] <ret> m <a-S> 1<a-&> ] + = +~ + +define-command -hidden groovy-indent-on-opening-curly-brace %[ + # align indent with opening paren when { is entered on a new line after the closing paren + try %[ execute-keys -draft -itersel h<a-F>)M <a-k> \A\(.*\)\h*\n\h*\{\z <ret> s \A|.\z <ret> 1<a-&> ] +] + +define-command -hidden groovy-indent-on-closing-curly-brace %[ + # align to opening curly brace when alone on a line + try %[ execute-keys -itersel -draft <a-h><a-k>^\h+\}$<ret>hms\A|.\z<ret>1<a-&> ] +] +§ diff --git a/autoload/filetype/haml.kak b/autoload/filetype/haml.kak new file mode 100644 index 0000000..492e78a --- /dev/null +++ b/autoload/filetype/haml.kak @@ -0,0 +1,78 @@ +# http://haml.info +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](haml) %{ + set-option buffer filetype haml +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=haml %{ + require-module haml + + hook window ModeChange pop:insert:.* -group haml-trim-indent haml-trim-indent + hook window InsertChar \n -group haml-insert haml-insert-on-new-line + hook window InsertChar \n -group haml-indent haml-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window haml-.+ } +} + +hook -group haml-highlight global WinSetOption filetype=haml %{ + add-highlighter window/haml ref haml + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/haml } +} + + +provide-module haml %[ +require-module ruby +require-module coffee +require-module sass + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/haml regions +add-highlighter shared/haml/code default-region group +add-highlighter shared/haml/comment region ^\h*/ $ fill comment + +# Filters +# http://haml.info/docs/yardoc/file.REFERENCE.html#filters +add-highlighter shared/haml/eval1 region -recurse \{ ^\h*%([A-Za-z][A-Za-z0-9_-]*)([#.][A-Za-z][A-Za-z0-9_-]*)?\{\K|#\{\K (?=\}) ref ruby +add-highlighter shared/haml/eval2 region ^\h*[=-]\K (?<!\|)(?=\n) ref ruby +add-highlighter shared/haml/coffee region ^\h*:coffee\K ^\h*[%=-]\K ref coffee +add-highlighter shared/haml/sass region ^\h*:sass\K ^\h*[%=-]\K ref sass + +add-highlighter shared/haml/code/ regex ^\h*(:[a-z]+|-|=)|^(!!!)$ 0:meta +add-highlighter shared/haml/code/ regex ^\h*%([A-Za-z][A-Za-z0-9_-]*)([#.][A-Za-z][A-Za-z0-9_-]*)? 1:keyword 2:variable + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden haml-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden haml-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy '/' comment prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K/\h* <ret> y gh j P } + } +} + +define-command -hidden haml-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : haml-trim-indent <ret> } + # indent after lines beginning with : or - + try %{ execute-keys -draft k x <a-k> ^\h*[:-] <ret> j <a-gt> } + } +} + +] diff --git a/autoload/filetype/hare.kak b/autoload/filetype/hare.kak new file mode 100644 index 0000000..19c2296 --- /dev/null +++ b/autoload/filetype/hare.kak @@ -0,0 +1,144 @@ +# detection +hook global BufCreate .*[.]ha %{ + set-option buffer filetype hare +} + +# initialisation +hook global WinSetOption filetype=hare %{ + require-module hare + hook window ModeChange pop:insert:.* -group hare-trim-indent hare-trim-indent + hook window InsertChar \n -group hare-insert hare-insert-on-new-line + hook window InsertChar \n -group hare-indent hare-indent-on-new-line + hook window InsertChar \{ -group hare-indent hare-indent-on-opening-curly-brace + hook window InsertChar \} -group hare-indent hare-indent-on-closing-curly-brace +} + +hook -group hare-highlight global WinSetOption filetype=hare %{ + add-highlighter window/hare ref hare + hook -once -always window WinSetOption filetype=*. %{ remove-highlighter window/hare } +} + +# highlighters +provide-module hare %§ + add-highlighter shared/hare regions + add-highlighter shared/hare/code default-region group + add-highlighter shared/hare/comment region // $ fill comment + + add-highlighter shared/hare/rawstring region ` ` group + add-highlighter shared/hare/rawstring/ fill string + + add-highlighter shared/hare/string region '"' (?<!\\)(\\\\)*" group + add-highlighter shared/hare/string/ fill string + add-highlighter shared/hare/string/ regex '(\\0|\\a|\\b|\\f|\\n|\\r|\\t|\\v|\\\\|\\")' 0:meta + add-highlighter shared/hare/string/ regex "\\'" 0:meta + add-highlighter shared/hare/string/ regex "(\\x[0-9a-fA-F]{2})" 0:meta + add-highlighter shared/hare/string/ regex "(\\u[0-9a-fA-F]{4})" 0:meta + add-highlighter shared/hare/string/ regex "(\\U[0-9a-fA-F]{8})" 0:meta + + add-highlighter shared/hare/rune region "'" (?<!\\)(\\\\)*' group + add-highlighter shared/hare/rune/ fill string + add-highlighter shared/hare/rune/ regex "(\\0|\\a|\\b|\\f|\\n|\\r|\\t|\\v|\\\\|\\')" 0:meta + add-highlighter shared/hare/rune/ regex '\\"' 0:meta + add-highlighter shared/hare/rune/ regex "(\\x[0-9a-fA-F]{2})" 0:meta + add-highlighter shared/hare/rune/ regex "(\\u[0-9a-fA-F]{4})" 0:meta + add-highlighter shared/hare/rune/ regex "(\\U[0-9a-fA-F]{8})" 0:meta + + # imports + add-highlighter shared/hare/code/ regex "\buse\s.*?(?=;)" 0:module + add-highlighter shared/hare/code/ regex "\buse\b" 0:meta + + # functions + add-highlighter shared/hare/code/ regex "\b([0-9a-zA-Z_]*)\h*\(" 1:function + + # attributes + add-highlighter shared/hare/code/ regex "@(packed|offset|init|fini|test|noreturn|symbol)\b" 0:attribute + + # declarations + add-highlighter shared/hare/code/ regex "\b(let|export|const)\b" 0:meta + add-highlighter shared/hare/code/ regex "\b(fn|type|def)\b" 0:keyword + + # builtins + add-highlighter shared/hare/code/ regex "\b(len|offset|free|alloc|assert|append|abort|delete|insert|vastart|vaarg|vaend)\b" 0:builtin + add-highlighter shared/hare/code/ regex "\b(as|is)\b" 0:builtin + + # types + add-highlighter shared/hare/code/ regex "\b(struct|union|enum)\b" 0:type + add-highlighter shared/hare/code/ regex "\b(nullable|null|void)\b" 0:type + add-highlighter shared/hare/code/ regex "\b(u8|u16|u32|u64|uint)\b" 0:type + add-highlighter shared/hare/code/ regex "\b(i8|i16|i32|i64|int)\b" 0:type + add-highlighter shared/hare/code/ regex "\b(size|uintptr|char)\b" 0:type + add-highlighter shared/hare/code/ regex "\b(f32|f64)\b" 0:type + add-highlighter shared/hare/code/ regex "\b(str|rune)\b" 0:type + add-highlighter shared/hare/code/ regex "\b(bool)\b" 0:type + add-highlighter shared/hare/code/ regex "\b(valist)\b" 0:type + + # literals + add-highlighter shared/hare/code/ regex "\b(true|false)\b" 0:value + add-highlighter shared/hare/code/ regex "\b[0-9]+([eE][-+]?[0-9]+)?(z|(i|u)(8|16|32|64)?)?\b" 0:value + add-highlighter shared/hare/code/ regex "\b[0-9]+([eE][-+]?[0-9]+)?((?=e)|(?=u)|(?=i))" 0:value + add-highlighter shared/hare/code/ regex "\b0b[0-1]+(z|(i|u)(8|16|32|64)?)?\b" 0:value + add-highlighter shared/hare/code/ regex "\b0b[0-1]+((?=u)|(?=i))" 0:value + add-highlighter shared/hare/code/ regex "\b0o[0-7]+(z|(i|u)(8|16|32|64)?)?\b" 0:value + add-highlighter shared/hare/code/ regex "\b0o[0-7]+((?=u)|(?=i))" 0:value + add-highlighter shared/hare/code/ regex "\b0x[0-9a-fA-F]+(z|(i|u)(8|16|32|64)?)?\b" 0:value + add-highlighter shared/hare/code/ regex "\b0x[0-9a-fA-F]+((?=u)|(?=i))" 0:value + + # floats + add-highlighter shared/hare/code/ regex "\b[0-9]+\.[0-9]+([eE][-+]?[0-9]+)?(f32|f64)?\b" 0:value + add-highlighter shared/hare/code/ regex "\b[0-9]+\.[0-9]+([eE][-+]?[0-9]+)?((?=e)|(?=f))" 0:value + add-highlighter shared/hare/code/ regex "\b[0-9]+([eE][-+]?[0-9]+)?(f32|f64)\b" 0:value + add-highlighter shared/hare/code/ regex "\b[0-9]+([eE][-+]?[0-9]+)?(?=f)" 0:value + + # constants + add-highlighter shared/hare/code/ regex "\b[0-9A-Z_]*\b" 0:value + + # control flow + add-highlighter shared/hare/code/ regex "\b(for|if|else|switch|match|return|break|continue|defer|yield|case|static)\b" 0:keyword + + # operators + add-highlighter shared/hare/code/ regex "(=|\+|-|\*|/|<|>|!|\?|&|\||\.\.(\.)?)" 0:operator + + # commands + define-command -hidden hare-indent-on-new-line %[ evaluate-commands -draft -itersel %[ + # preserve indentation on new lines + try %{ execute-keys -draft <semicolon> K <a-&> } + # indent after lines ending with { or ( + try %[ execute-keys -draft kx <a-k> [{(]\h*$ <ret> j i<tab> ] + # cleanup trailing white spaces on the previous line + execute-keys -draft k :hare-trim-indent <ret> + # indent after match/switch's case statements + try %[ execute-keys -draft kx <a-k> case\h.*=>\h*$ <ret> j<a-gt> ] + # deindent closing brace(s) when after cursor + try %[ execute-keys -draft x <a-k> ^\h*[})] <ret> gh / [})] <ret> m <a-S> 1<a-&> ] + ] ] + + define-command -hidden hare-insert-on-new-line %{ evaluate-commands -draft -itersel %{ + try %{ evaluate-commands -draft -save-regs '/"' %{ + # copy the comment prefix + execute-keys -save-regs '' k x s ^\h*\K//\h* <ret> y + try %{ + # paste the comment prefix + execute-keys x j x s ^\h* <ret>P + } + } } + try %{ + # remove trailing whitespace on the above line + execute-keys -draft k :hare-trim-indent <ret> + } + } } + + define-command -hidden hare-indent-on-opening-curly-brace %[ + # align indent with opening paren when { is entered on a new line after the closing paren + try %[ execute-keys -draft -itersel h<a-F>)M <a-k> \A\(.*\)\h*\n\h*\{\z <ret> s \A|.\z <ret> 1<a-&> ] + ] + + define-command -hidden hare-indent-on-closing-curly-brace %[ + # align to opening curly brace when alone on a line + try %[ execute-keys -itersel -draft <a-h><a-k>^\h+\}$<ret>hms\A|.\z<ret>1<a-&> ] + ] + + define-command -hidden hare-trim-indent %{ evaluate-commands -draft -itersel %{ + # remove trailing whitespace + try %{ execute-keys -draft x s \h+$ <ret> d } + } } +§ diff --git a/autoload/filetype/haskell.kak b/autoload/filetype/haskell.kak new file mode 100644 index 0000000..9beed99 --- /dev/null +++ b/autoload/filetype/haskell.kak @@ -0,0 +1,127 @@ +# http://haskell.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](hs) %{ + set-option buffer filetype haskell +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=haskell %{ + require-module haskell + + set-option buffer extra_word_chars '_' "'" + hook window ModeChange pop:insert:.* -group haskell-trim-indent haskell-trim-indent + hook window InsertChar \n -group haskell-insert haskell-insert-on-new-line + hook window InsertChar \n -group haskell-indent haskell-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window haskell-.+ } +} + +hook -group haskell-highlight global WinSetOption filetype=haskell %{ + add-highlighter window/haskell ref haskell + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/haskell } +} + + +provide-module haskell %[ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/haskell regions +add-highlighter shared/haskell/code default-region group +add-highlighter shared/haskell/string region (?<!'\\)(?<!')" (?<!\\)(\\\\)*" fill string +add-highlighter shared/haskell/macro region ^\K# (?<!\\)\n fill meta +add-highlighter shared/haskell/pragma region -recurse \{- \{-# '#-\}' fill meta +add-highlighter shared/haskell/comment region -recurse \{- \{- -\} fill comment +add-highlighter shared/haskell/line_comment region --(?![!#$%&*+./<>?@\\\^|~=]) $ fill comment +add-highlighter shared/haskell/quasiquote region \[\b[_a-z]['\w]*#?\| \|\] regex \[\b[_a-z]['\w]*#?\|(.*?)\|\] 1:string + +add-highlighter shared/haskell/code/ regex (?<!')\b0x+[A-Fa-f0-9]+ 0:value +add-highlighter shared/haskell/code/ regex (?<!')\b\d+([.]\d+)? 0:value +add-highlighter shared/haskell/code/ regex (?<!')\b(import|hiding|qualified|module)(?!')\b 0:keyword +add-highlighter shared/haskell/code/ regex (?<!')\b(import)(?!')\b[^\n]+(?<!')\b(as)(?!')\b 2:keyword +add-highlighter shared/haskell/code/ regex (?<!')\b(class|data|default|deriving|infix|infixl|infixr|instance|module|newtype|pattern|type|where)(?!')\b 0:keyword +add-highlighter shared/haskell/code/ regex (?<!')\b(case|do|else|if|in|let|mdo|of|proc|rec|then)(?!')\b 0:attribute +add-highlighter shared/haskell/code/ regex (?<!')\b(type|data)\b\s+(\bfamily\b)?(?!') 0:keyword + +# The complications below is because period has many uses: +# As function composition operator (possibly without spaces) like "." and "f.g" +# Hierarchical modules like "Data.Maybe" +# Qualified imports like "Data.Maybe.Just", "Data.Maybe.maybe", "Control.Applicative.<$>" +# Quantifier separator in "forall a . [a] -> [a]" +# Enum comprehensions like "[1..]" and "[a..b]" (making ".." and "Module..." illegal) + +# matches uppercase identifiers: Monad Control.Monad +# not non-space separated dot: Just.const +add-highlighter shared/haskell/code/ regex \b([A-Z]['\w]*\.)*[A-Z]['\w]*(?!['\w])(?![.a-z]) 0:variable + +# matches infix identifier: `mod` `Apa._T'M` +add-highlighter shared/haskell/code/ regex `\b([A-Z]['\w]*\.)*[\w]['\w]*` 0:operator +# matches imported operators: M.! M.. Control.Monad.>> +# not operator keywords: M... M.-> +add-highlighter shared/haskell/code/ regex \b[A-Z]['\w]*\.[~<=>|:!?/.@$*&#%+\^\-\\]+ 0:operator +# matches dot: . +# not possibly incomplete import: a. +# not other operators: !. .! +add-highlighter shared/haskell/code/ regex (?<![\w~<=>|:!?/.@$*&#%+\^\-\\])\.(?![~<=>|:!?/.@$*&#%+\^\-\\]) 0:operator +# matches other operators: ... > < <= ^ <*> <$> etc +# not dot: . +# not operator keywords: @ .. -> :: ~ +add-highlighter shared/haskell/code/ regex (?<![~<=>|:!?/.@$*&#%+\^\-\\])[~<=>|:!?/.@$*&#%+\^\-\\]+ 0:operator + +# matches operator keywords: @ -> +add-highlighter shared/haskell/code/ regex (?<![~<=>|:!?/.@$*&#%+\^\-\\])(@|~|<-|->|=>|::|=|:|[|])(?![~<=>|:!?/.@$*&#%+\^\-\\]) 1:keyword +# matches: forall [..variables..] . +# not the variables +add-highlighter shared/haskell/code/ regex \b(forall|∀)\b[^.\n]*?(\.) 1:keyword 2:keyword + +# matches 'x' '\\' '\'' '\n' '\0' +# not incomplete literals: '\' +# not valid identifiers: w' _' +add-highlighter shared/haskell/code/ regex \B'([^\\]|[\\]['"\w\d\\])' 0:string +# this has to come after operators so '-' etc is correct + +# matches function names in type signatures +add-highlighter shared/haskell/code/ regex ^\s*(?:where\s+|let\s+|default\s+)?([_a-z]['\w]*#?(?:,\s*[_a-z]['\w]*#?)*)\s+::\s 1:meta + +# matches deriving strategies +add-highlighter shared/haskell/code/ regex \bderiving\s+\b(stock|newtype|anyclass|via)\b 1:keyword +add-highlighter shared/haskell/code/ regex \bderiving\b\s+(?:[A-Z]['\w]+|\([',\w\s]+?\))\s+\b(via)\b 1:keyword + +# Commands +# ‾‾‾‾‾‾‾‾ + +# http://en.wikibooks.org/wiki/Haskell/Indentation + +define-command -hidden haskell-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden haskell-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy -- comments prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K--\h* <ret> y gh j P } + } +} + +define-command -hidden haskell-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # align to first clause + try %{ execute-keys -draft <semicolon> k x X s ^\h*(if|then|else)?\h*(([\w']+\h+)+=)?\h*(case\h+[\w']+\h+of|do|let|where)\h+\K.* <ret> s \A|.\z <ret> & } + # filter previous line + try %{ execute-keys -draft k : haskell-trim-indent <ret> } + # indent after lines beginning with condition or ending with expression or =( + try %{ execute-keys -draft <semicolon> k x <a-k> ^\h*if|[=(]$|\b(case\h+[\w']+\h+of|do|let|where)$ <ret> j <a-gt> } + } +} + +] diff --git a/autoload/filetype/hbs.kak b/autoload/filetype/hbs.kak new file mode 100644 index 0000000..5ea99bc --- /dev/null +++ b/autoload/filetype/hbs.kak @@ -0,0 +1,112 @@ +# http://handlebarsjs.com/ +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](hbs) %{ + set-option buffer filetype hbs +} + +hook global WinSetOption filetype=hbs %{ + require-module hbs + + hook window ModeChange pop:insert:.* -group hbs-trim-indent hbs-trim-indent + hook window InsertChar \n -group hbs-insert hbs-insert-on-new-line + hook window InsertChar \n -group hbs-indent hbs-indent-on-new-line + hook window InsertChar .* -group hbs-indent hbs-indent-on-char + hook window InsertChar '>' -group hbs-indent html-indent-on-greater-than + hook window InsertChar \n -group hbs-indent html-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window hbs-.+ } +} + +hook -group hbs-highlight global WinSetOption filetype=hbs %{ + maybe-add-hbs-to-html + add-highlighter window/hbs-file ref hbs-file + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/hbs-file } +} + + +provide-module hbs %[ + +require-module html + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/hbs regions +add-highlighter shared/hbs/comment region \{\{!-- --\}\} fill comment +add-highlighter shared/hbs/comment_alt region \{\{! \}\} fill comment +add-highlighter shared/hbs/block-expression region \{\{[#/] \}\} regions +add-highlighter shared/hbs/expression region \{\{ \}\} regions + +define-command -hidden add-mutual-highlighters -params 1 %~ + add-highlighter "shared/hbs/%arg{1}/code" default-region group + add-highlighter "shared/hbs/%arg{1}/single-quote" region '"' (?<!\\)(\\\\)*" fill string + add-highlighter "shared/hbs/%arg{1}/double-quote" region "'" (?<!\\)(\\\\)*' fill string + add-highlighter "shared/hbs/%arg{1}/code/variable" regex \b([\w-]+)\b 1:variable + add-highlighter "shared/hbs/%arg{1}/code/attribute" regex \b([\w-]+)= 1:attribute + add-highlighter "shared/hbs/%arg{1}/code/helper" regex (?:(?:\{\{)|\()([#/]?[\w-]+(?:/[\w-]+)*) 1:keyword +~ + +add-mutual-highlighters expression +add-mutual-highlighters block-expression + +add-highlighter shared/hbs/block-expression/code/yield regex \b(as)\s|[\w-]+|\}\} 1:keyword + + +# wrapper around shared/html highlighter. The shared/hbs highlighter will be +# added into shared/html when a buffer of filetype 'hbs' is actively displayed in the window. +add-highlighter shared/hbs-file regions +add-highlighter shared/hbs-file/html default-region ref html + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden hbs-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden hbs-indent-on-char %[ + evaluate-commands -draft -itersel %[ + # de-indent after closing a yielded block tag + try %[ execute-keys -draft , <a-h> s ^\h+\{\{/([\w-.]+(?:/[\w-.]+)*)\}\}$ <ret> {c\{\{#<c-r>1,\{\{/<c-r>1\}\} <ret> s \A|.\z <ret> 1<a-&> ] + ] +] + +define-command -hidden hbs-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy '/' comment prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K/\h* <ret> y j p } + } +} + +define-command -hidden hbs-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : hbs-trim-indent <ret> } + # indent after lines beginning with : or - + try %{ execute-keys -draft k x <a-k> ^\h*[:-] <ret> j <a-gt> } + } +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +declare-option bool hbs_highlighters_enabled false + +define-command -hidden maybe-add-hbs-to-html %{ evaluate-commands %sh{ + if [ "$kak_opt_hbs_highlighters_enabled" == "false" ]; then + printf %s " + add-highlighter shared/html/hbs region '\{\{' '\}\}' ref hbs + add-highlighter shared/html/tag/hbs region '\{\{' '\}\}' ref hbs + set-option global hbs_highlighters_enabled true + " + fi +} } + +] diff --git a/autoload/filetype/html.kak b/autoload/filetype/html.kak new file mode 100644 index 0000000..0b09ef6 --- /dev/null +++ b/autoload/filetype/html.kak @@ -0,0 +1,87 @@ +# http://w3.org/html +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*\.html %{ + set-option buffer filetype html +} + +hook global BufCreate .*\.xml %{ + set-option buffer filetype xml +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=(html|xml) %{ + require-module html + + hook window ModeChange pop:insert:.* -group "%val{hook_param_capture_1}-trim-indent" html-trim-indent + hook window InsertChar '>' -group "%val{hook_param_capture_1}-indent" html-indent-on-greater-than + hook window InsertChar \n -group "%val{hook_param_capture_1}-indent" html-indent-on-new-line + + hook -once -always window WinSetOption "filetype=.*" " + remove-hooks window ""%val{hook_param_capture_1}-.+"" + " +} + +hook -group html-highlight global WinSetOption filetype=(html|xml) %{ + add-highlighter "window/%val{hook_param_capture_1}" ref html + hook -once -always window WinSetOption "filetype=.*" " + remove-highlighter ""window/%val{hook_param_capture_1}"" + " +} + + +provide-module html %[ + +try %{ + require-module css + require-module javascript +} + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/html regions +add-highlighter shared/html/comment region <!-- --> fill comment +add-highlighter shared/html/tag region < > regions +add-highlighter shared/html/style region <style\b.*?>\K (?=</style>) ref css +add-highlighter shared/html/script region <script\b.*?>\K (?=</script>) ref javascript + +add-highlighter shared/html/tag/base default-region group +add-highlighter shared/html/tag/ region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/html/tag/ region "'" "'" fill string + +add-highlighter shared/html/tag/base/ regex \b([a-zA-Z0-9_-]+)=? 1:attribute +add-highlighter shared/html/tag/base/ regex </?(\w+) 1:keyword +add-highlighter shared/html/tag/base/ regex <(!DOCTYPE(\h+\w+)+) 1:meta + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden html-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden html-indent-on-greater-than %[ + evaluate-commands -draft -itersel %[ + # align closing tag to opening when alone on a line + try %[ execute-keys -draft , <a-h> s ^\h+<lt>/(\w+)<gt>$ <ret> {c<lt><c-r>1,<lt>/<c-r>1<gt> <ret> s \A|.\z <ret> 1<a-&> ] + ] +] + +define-command -hidden html-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : html-trim-indent <ret> } + # indent after lines ending with opening tag except when it starts with a closing tag + try %{ execute-keys -draft k x <a-k> <lt>(?!area)(?!base)(?!br)(?!col)(?!command)(?!embed)(?!hr)(?!img)(?!input)(?!keygen)(?!link)(?!menuitem)(?!meta)(?!param)(?!source)(?!track)(?!wbr)(?!/)(?!>)[a-zA-Z0-9_-]+[^>]*?>$ <ret>jx<a-K>^\s*<lt>/<ret><a-gt> } } +} + +] diff --git a/autoload/filetype/i3.kak b/autoload/filetype/i3.kak new file mode 100644 index 0000000..deafb6c --- /dev/null +++ b/autoload/filetype/i3.kak @@ -0,0 +1,94 @@ +hook global BufCreate .*(sway|i3)/config %{ + set buffer filetype i3 +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=i3 %[ + require-module i3 + + # cleanup trailing whitespaces when exiting insert mode + hook window ModeChange pop:insert:.* -group i3-trim-indent %{ try %{ execute-keys -draft xs^\h+$<ret>d } } + hook window InsertChar \n -group i3-insert i3-insert-on-new-line + hook window InsertChar \n -group i3-indent i3-indent-on-new-line + hook window InsertChar \} -group i3-indent i3-indent-on-closing-curly-brace + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window i3-.+ } +] + +hook -group i3-highlight global WinSetOption filetype=i3 %{ + add-highlighter window/i3 ref i3 + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/i3 } +} + + +provide-module i3 %[ + +add-highlighter shared/i3 regions +add-highlighter shared/i3/code default-region group +add-highlighter shared/i3/double_string region %{"} %{"} group +add-highlighter shared/i3/single_string region %{'} %{'} group +add-highlighter shared/i3/exec region %{((?<=exec )|(?<=--no-startup-id ))(?!--no-startup-id)} "$" fill string +add-highlighter shared/i3/comment region "#" "$" fill comment + +add-highlighter shared/i3/double_string/ fill string +add-highlighter shared/i3/single_string/ fill string + +# Symbols +add-highlighter shared/i3/code/ regex "[+|→]" 0:operator +add-highlighter shared/i3/code/ regex "\$\w+" 0:variable + +# keys +add-highlighter shared/i3/code/ regex "\b(Shift|Control|Ctrl|Mod1|Mod2|Mod3|Mod4|Mod5|Mode_switch|Return|Escape|Print)\b" 0:value + +# keywords +add-highlighter shared/i3/code/ regex "\b(bind|bindcode|bindsym|assign|new_window|default_(floating_)?border|popup_during_fullscreen|font|floating_modifier|default_orientation|workspace_layout|for_window|focus_follows_mouse|bar|position|colors|output|tray_output|workspace_buttons|workspace_auto_back_and_forth|binding_mode_indicator|debuglog|floating_minimum_size|floating_maximum_size|force_focus_wrapping|force_xinerama|force_display_urgency_hint|hidden_state|modifier|new_float|shmlog|socket_path|verbose|mouse_warping|strip_workspace_numbers|focus_on_window_activation|no_focus|set|mode|set_from_resource)\b" 0:keyword +# function keywords +add-highlighter shared/i3/code/ regex "\b(exit|reload|restart|kill|fullscreen|global|layout|border|focus|move|open|split|append_layout|mark|unmark|resize|grow|shrink|show|nop|rename|title_format|sticky)\b" 0:function +add-highlighter shared/i3/code/ regex "\b(exec|exec_always|i3bar_command|status_command)\b" 0:function +# " these are not keywords but we add them for consistency +add-highlighter shared/i3/code/ regex "\b(no|false|inactive)\b" 0:value + +# values +add-highlighter shared/i3/code/ regex "\b(1pixel|default|stacked|tabbed|normal|none|tiling|stacking|floating|enable|disable|up|down|horizontal|vertical|auto|up|down|left|right|parent|child|px|or|ppt|leave_fullscreen|toggle|mode_toggle|scratchpad|width|height|top|bottom|client|hide|primary|yes|all|active|window|container|to|absolute|center|on|off|ms|smart|ignore|pixel|splith|splitv|output|true)\b" 0:value +add-highlighter shared/i3/code/ regex "\b(next|prev|next_on_output|prev_on_output|back_and_forth|current|number|none|vertical|horizontal|both|dock|hide|invisible|gaps|smart_gaps|smart_borders|inner|outer|current|all|plus|minus|no_gaps)\b" 0:value + +# double-dash arguments +add-highlighter shared/i3/code/ regex "--(release|border|whole-window|toggle|no-startup-id)" 0:attribute + +# color +add-highlighter shared/i3/double_string/ regex "#[0-9a-fA-F]{6}" 0:value +add-highlighter shared/i3/single_string/ regex "#[0-9a-fA-F]{6}" 0:value + +# attributes +add-highlighter shared/i3/code/ regex "client\.(background|statusline|background|separator|statusline)" 1:attribute +add-highlighter shared/i3/code/ regex "client\.(focused_inactive|focused_tab_title|focused|unfocused|urgent|inactive_workspace|urgent_workspace|focused_workspace|active_workspace|placeholder)" 1:attribute + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden i3-insert-on-new-line %~ + evaluate-commands -draft -itersel %= + # copy # comments prefix + try %{ execute-keys -draft kx s ^\h*#\h* <ret> y jgh P } + = +~ + +define-command -hidden i3-indent-on-new-line %~ + evaluate-commands -draft -itersel %= + # preserve previous line indent + try %{ execute-keys -draft <semicolon>K<a-&> } + # indent after lines ending with { + try %[ execute-keys -draft kx <a-k> \{\h*$ <ret> j<a-gt> ] + # cleanup trailing white spaces on the previous line + try %{ execute-keys -draft kx s \h+$ <ret>d } + = +~ + +define-command -hidden i3-indent-on-closing-curly-brace %[ + # align to opening curly brace when alone on a line + try %[ execute-keys -itersel -draft <a-h><a-k>^\h+\}$<ret>hms\A|.\z<ret>1<a-&> ] +] + +] diff --git a/autoload/filetype/ini.kak b/autoload/filetype/ini.kak new file mode 100644 index 0000000..75762f6 --- /dev/null +++ b/autoload/filetype/ini.kak @@ -0,0 +1,24 @@ +hook global BufCreate .+\.ini %{ + set-option buffer filetype ini +} + +hook global WinSetOption filetype=ini %{ + require-module ini +} + +hook -group ini-highlight global WinSetOption filetype=ini %{ + add-highlighter window/ini ref ini + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/ini } +} + + +provide-module ini %{ + +add-highlighter shared/ini regions +add-highlighter shared/ini/code default-region group +add-highlighter shared/ini/comment region '(^|\h)\K[#;]' $ fill comment + +add-highlighter shared/ini/code/ regex "(?S)^\h*(\[.+?\])\h*$" 1:title +add-highlighter shared/ini/code/ regex "^\h*([^\[][^=\n]*)=([^\n]*)" 1:variable 2:value + +} diff --git a/autoload/filetype/janet.kak b/autoload/filetype/janet.kak new file mode 100644 index 0000000..00f39c2 --- /dev/null +++ b/autoload/filetype/janet.kak @@ -0,0 +1,81 @@ +# http://janet-lang.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](janet|jdn) %{ + set-option buffer filetype janet +} + + +hook global WinSetOption filetype=janet %{ + require-module janet + + hook window ModeChange pop:insert:.* -group janet-trim-indent janet-trim-indent + hook window InsertChar \n -group janet-indent janet-indent-on-new-line + set-option buffer extra_word_chars ! @ $ '%' ^ & * - _ + = : < > . ? + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window janet-.+ } +} + +hook -group janet-highlight global WinSetOption filetype=janet %{ + add-highlighter window/janet ref janet + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/janet } +} + +provide-module janet %{ + +require-module lisp + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/janet regions +add-highlighter shared/janet/code default-region group +add-highlighter shared/janet/comment region '(?<!\\)(?:\\\\)*\K#' '$' fill comment +add-highlighter shared/janet/comment-form region -recurse \( '(?<!\\)(?:\\\\)*\K\(comment ' '\)' fill comment +add-highlighter shared/janet/string region '(?<!\\)(?:\\\\)*\K"' '(?<!\\)(?:\\\\)*"' fill string +add-highlighter shared/janet/raw-string region -match-capture '(`+)' '(`+)' fill string +add-highlighter shared/janet/code/ regex \b(nil|true|false)\b 0:value +add-highlighter shared/janet/code/number regex \W\K(?:[\-+]?\dx?[\der._+a-f]*)\b 0:value +add-highlighter shared/janet/code/function-definition regex \((?:defn-?|fn)\s([!@$%\^&*\-_+=:<>.?\w/]+) 1:function +add-highlighter shared/janet/code/function-call regex \(([!@$%\^&*\-_+=:<>.?\w/]+) 1:function +add-highlighter shared/janet/code/keyword regex \W\K:[!@$%\^&*\-_+=:<>.?\w/]+ 0:value +add-highlighter shared/janet/code/special regex \((def-?|defn-?|var-?|fn|do|quote|if|splice|while|break|set|quasiquote|unquote|upscope)\s 1:keyword +add-highlighter shared/janet/code/ regex \W\K(&|&opt|&keys|&named)\W 1:keyword + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden janet-trim-indent lisp-trim-indent + +declare-option \ + -docstring 'regex matching the head of forms which have options *and* indented bodies' \ + regex janet_special_indent_forms \ + '(?:def.*|while|for|fn\*?|if(-.*|)|let.*|loop|seq|with(-.*|)|when(-.*|))|defer|do|match|var' + +define-command -hidden janet-indent-on-new-line %{ + # registers: i = best align point so far; w = start of first word of form + evaluate-commands -draft -save-regs '/"|^@iw' -itersel %{ + execute-keys -draft 'gk"iZ' + try %{ + execute-keys -draft '[bl"i<a-Z><gt>"wZ' + + try %{ + # If a special form, indent another j + execute-keys -draft '"wze<a-k>\A' %opt{janet_special_indent_forms} '\z<ret><a-L>s.\K.*<ret><a-;>;"i<a-Z><gt>' + } catch %{ + # If not special and parameter appears on line 1, indent to parameter + execute-keys -draft '"wze<a-l>s\h\K[^\s].*<ret><a-;>;"i<a-Z><gt>' + } + } + try %{ execute-keys -draft '[rl"i<a-Z><gt>' } + try %{ execute-keys -draft '[Bl"i<a-Z><gt>' } + execute-keys -draft '"i<a-z>a&,' + # trim trailing whitespace on the previous line + try %{ execute-keys -draft k : janet-trim-indent <ret> } + } +} + +} diff --git a/autoload/filetype/java.kak b/autoload/filetype/java.kak new file mode 100644 index 0000000..69b0d74 --- /dev/null +++ b/autoload/filetype/java.kak @@ -0,0 +1,129 @@ +hook global BufCreate .*\.java %{ + set-option buffer filetype java +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=java %{ + require-module java + + set-option window static_words %opt{java_static_words} + + # cleanup trailing whitespaces when exiting insert mode + hook window ModeChange pop:insert:.* -group java-trim-indent %{ try %{ execute-keys -draft xs^\h+$<ret>d } } + hook window InsertChar \n -group java-insert java-insert-on-new-line + hook window InsertChar \n -group java-indent java-indent-on-new-line + hook window InsertChar \{ -group java-indent java-indent-on-opening-curly-brace + hook window InsertChar \} -group java-indent java-indent-on-closing-curly-brace + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window java-.+ } +} + +hook -group java-highlight global WinSetOption filetype=java %{ + add-highlighter window/java ref java + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/java } +} + +provide-module java %§ + +add-highlighter shared/java regions +add-highlighter shared/java/code default-region group +add-highlighter shared/java/string region %{(?<!')"} %{(?<!\\)(\\\\)*"} fill string +add-highlighter shared/java/character region %{'} %{(?<!\\)'} fill value +add-highlighter shared/java/comment region /\* \*/ fill comment +add-highlighter shared/java/inline_documentation region /// $ fill documentation +add-highlighter shared/java/line_comment region // $ fill comment + +add-highlighter shared/java/code/ regex "(?<!\w)@\w+\b" 0:meta + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden java-insert-on-new-line %[ + # copy // comments prefix and following white spaces + try %{ execute-keys -draft <semicolon><c-s>kx s ^\h*\K/{2,}\h* <ret> y<c-o>P<esc> } +] + +define-command -hidden java-indent-on-new-line %~ + evaluate-commands -draft -itersel %= + # preserve previous line indent + try %{ execute-keys -draft <semicolon>K<a-&> } + # indent after lines ending with { or ( + try %[ execute-keys -draft kx <a-k> [{(]\h*$ <ret> j<a-gt> ] + # cleanup trailing white spaces on the previous line + try %{ execute-keys -draft kx s \h+$ <ret>d } + # align to opening paren of previous line + try %{ execute-keys -draft [( <a-k> \A\([^\n]+\n[^\n]*\n?\z <ret> s \A\(\h*.|.\z <ret> '<a-;>' & } + # indent after a switch's case/default statements + try %[ execute-keys -draft kx <a-k> ^\h*(case|default).*:$ <ret> j<a-gt> ] + # indent after keywords + try %[ execute-keys -draft <semicolon><a-F>)MB <a-k> \A(if|else|while|for|try|catch)\h*\(.*\)\h*\n\h*\n?\z <ret> s \A|.\z <ret> 1<a-&>1<a-,><a-gt> ] + # deindent closing brace(s) when after cursor + try %[ execute-keys -draft x <a-k> ^\h*[})] <ret> gh / [})] <ret> m <a-S> 1<a-&> ] + = +~ + +define-command -hidden java-indent-on-opening-curly-brace %[ + # align indent with opening paren when { is entered on a new line after the closing paren + try %[ execute-keys -draft -itersel h<a-F>)M <a-k> \A\(.*\)\h*\n\h*\{\z <ret> s \A|.\z <ret> 1<a-&> ] +] + +define-command -hidden java-indent-on-closing-curly-brace %[ + # align to opening curly brace when alone on a line + try %[ execute-keys -itersel -draft <a-h><a-k>^\h+\}$<ret>hms\A|.\z<ret>1<a-&> ] +] + +# Shell +# ‾‾‾‾‾ +# Oracle 2021, 3.9 Keywords, Chapter 3. Lexical Structure, Java Language Specification, Java SE 17, viewed 25 September 2021, <https://docs.oracle.com/javase/specs/jls/se17/html/jls-3.html#jls-3.9> +# +evaluate-commands %sh{ + values='false null this true' + + types='boolean byte char double float int long short unsigned void' + + keywords='assert break case catch class continue default do else enum extends + finally for if implements import instanceof interface new package return + static strictfp super switch throw throws try var while yield' + + attributes='abstract final native non-sealed permits private protected public + record sealed synchronized transient volatile' + + modules='exports module open opens provides requires to transitive uses with' + + # ---------------------------------------------------------------------------------------------- # + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + # ---------------------------------------------------------------------------------------------- # + add_highlighter() { printf "add-highlighter shared/java/code/ regex %s %s\n" "$1" "$2"; } + # ---------------------------------------------------------------------------------------------- # + add_word_highlighter() { + + while [ $# -gt 0 ]; do + words=$1 face=$2; shift 2 + regex="\\b($(join "${words}" '|'))\\b" + add_highlighter "$regex" "1:$face" + done + + } + + # highlight: open<space> not open() + add_module_highlighter() { + + while [ $# -gt 0 ]; do + words=$1 face=$2; shift 2 + regex="\\b($(join "${words}" '|'))\\b(?=\\s)" + add_highlighter "$regex" "1:$face" + done + + } + # ---------------------------------------------------------------------------------------------- # + printf %s\\n "declare-option str-list java_static_words $(join "${values} ${types} ${keywords} ${attributes} ${modules}" ' ')" + # ---------------------------------------------------------------------------------------------- # + add_word_highlighter "$values" "value" "$types" "type" "$keywords" "keyword" "$attributes" "attribute" + # ---------------------------------------------------------------------------------------------- # + add_module_highlighter "$modules" "module" + # ---------------------------------------------------------------------------------------------- # +} + +§ diff --git a/autoload/filetype/javascript.kak b/autoload/filetype/javascript.kak new file mode 100644 index 0000000..05e0bc6 --- /dev/null +++ b/autoload/filetype/javascript.kak @@ -0,0 +1,224 @@ +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.][cm]?(js)x? %{ + set-option buffer filetype javascript +} + +hook global BufCreate .*[.][cm]?(ts)x? %{ + set-option buffer filetype typescript +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=(javascript|typescript) %{ + require-module javascript + + hook window ModeChange pop:insert:.* -group "%val{hook_param_capture_1}-trim-indent" javascript-trim-indent + hook window InsertChar .* -group "%val{hook_param_capture_1}-indent" javascript-indent-on-char + hook window InsertChar \n -group "%val{hook_param_capture_1}-insert" javascript-insert-on-new-line + hook window InsertChar \n -group "%val{hook_param_capture_1}-indent" javascript-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* " + remove-hooks window %val{hook_param_capture_1}-.+ + " +} + +hook -group javascript-highlight global WinSetOption filetype=javascript %{ + add-highlighter window/javascript ref javascript + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/javascript } +} + +hook -group typescript-highlight global WinSetOption filetype=typescript %{ + add-highlighter window/typescript ref typescript + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/typescript } +} + + +provide-module javascript %§ + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden javascript-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft x 1s^(\h+)$<ret> d } +} + +define-command -hidden javascript-indent-on-char %< + evaluate-commands -draft -itersel %< + # align closer token to its opener when alone on a line + try %/ execute-keys -draft <a-h> <a-k> ^\h+[\]}]$ <ret> m s \A|.\z <ret> 1<a-&> / + > +> + +define-command -hidden javascript-insert-on-new-line %< + evaluate-commands -draft -itersel %< + execute-keys <semicolon> + try %[ + evaluate-commands -draft -save-regs '/"' %[ + # copy the commenting prefix + execute-keys -save-regs '' k x1s^\h*(//+\h*)<ret> y + try %[ + # if the previous comment isn't empty, create a new one + execute-keys x<a-K>^\h*//+\h*$<ret> jxs^\h*<ret>P + ] catch %[ + # if there is no text in the previous comment, remove it completely + execute-keys d + ] + ] + ] + try %[ + # if the previous line isn't within a comment scope, break + execute-keys -draft kx <a-k>^(\h*/\*|\h+\*(?!/))<ret> + + # find comment opening, validate it was not closed, and check its using star prefixes + execute-keys -draft <a-?>/\*<ret><a-H> <a-K>\*/<ret> <a-k>\A\h*/\*([^\n]*\n\h*\*)*[^\n]*\n\h*.\z<ret> + + try %[ + # if the previous line is opening the comment, insert star preceeded by space + execute-keys -draft kx<a-k>^\h*/\*<ret> + execute-keys -draft i*<space><esc> + ] catch %[ + try %[ + # if the next line is a comment line insert a star + execute-keys -draft jx<a-k>^\h+\*<ret> + execute-keys -draft i*<space><esc> + ] catch %[ + try %[ + # if the previous line is an empty comment line, close the comment scope + execute-keys -draft kx<a-k>^\h+\*\h+$<ret> x1s\*(\h*)<ret>c/<esc> + ] catch %[ + # if the previous line is a non-empty comment line, add a star + execute-keys -draft i*<space><esc> + ] + ] + ] + + # trim trailing whitespace on the previous line + try %[ execute-keys -draft s\h+$<ret> d ] + # align the new star with the previous one + execute-keys Kx1s^[^*]*(\*)<ret><a-(><a-&> + ] + > +> + +define-command -hidden javascript-indent-on-new-line %< + evaluate-commands -draft -itersel %< + execute-keys <semicolon> + try %< + # if previous line is part of a comment, do nothing + execute-keys -draft <a-?>/\*<ret> <a-K>^\h*[^/*\h]<ret> + > catch %< + # else if previous line closed a paren (possibly followed by words and a comment), + # copy indent of the opening paren line + execute-keys -draft kx 1s(\))(\h+\w+)*\h*(\;\h*)?(?://[^\n]+)?\n\z<ret> m<a-semicolon>J <a-S> 1<a-&> + > catch %< + # else indent new lines with the same level as the previous one + execute-keys -draft K <a-&> + > + # remove previous empty lines resulting from the automatic indent + try %< execute-keys -draft k x <a-k>^\h+$<ret> Hd > + # indent after an opening brace or parenthesis at end of line + try %< execute-keys -draft k x <a-k>[{(]\h*$<ret> j <a-gt> > + # indent after a label (works for case statements) + try %< execute-keys -draft k x s[a-zA-Z0-9_-]+:\h*$<ret> j <a-gt> > + # indent after a statement not followed by an opening brace + try %< execute-keys -draft k x s\)\h*(?://[^\n]+)?\n\z<ret> \ + <a-semicolon>mB <a-k>\A\b(if|for|while)\b<ret> <a-semicolon>j <a-gt> > + try %< execute-keys -draft k x s \belse\b\h*(?://[^\n]+)?\n\z<ret> \ + j <a-gt> > + # deindent after a single line statement end + try %< execute-keys -draft K x <a-k>\;\h*(//[^\n]+)?$<ret> \ + K x s\)(\h+\w+)*\h*(//[^\n]+)?\n([^\n]*\n){2}\z<ret> \ + MB <a-k>\A\b(if|for|while)\b<ret> <a-S>1<a-&> > + try %< execute-keys -draft K x <a-k>\;\h*(//[^\n]+)?$<ret> \ + K x s \belse\b\h*(?://[^\n]+)?\n([^\n]*\n){2}\z<ret> \ + <a-S>1<a-&> > + # deindent closing brace(s) when after cursor + try %< execute-keys -draft x <a-k> ^\h*[})] <ret> gh / [})] <esc> m <a-S> 1<a-&> > + # align to the opening parenthesis or opening brace (whichever is first) + # on a previous line if its followed by text on the same line + try %< evaluate-commands -draft %< + # Go to opening parenthesis and opening brace, then select the most nested one + try %< execute-keys [c [({],[)}] <ret> > + # Validate selection and get first and last char + execute-keys <a-k>\A[{(](\h*\S+)+\n<ret> <a-K>"(([^"]*"){2})*<ret> <a-K>'(([^']*'){2})*<ret> <a-:><a-semicolon>L <a-S> + # Remove possibly incorrect indent from new line which was copied from previous line + try %< execute-keys -draft , <a-h> s\h+<ret> d > + # Now indent and align that new line with the opening parenthesis/brace + execute-keys 1<a-&> & + > > + > +> + +# Highlighting and hooks bulder for JavaScript and TypeScript +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +define-command -hidden init-javascript-filetype -params 1 %~ + # Highlighters + # ‾‾‾‾‾‾‾‾‾‾‾‾ + + add-highlighter "shared/%arg{1}" regions + add-highlighter "shared/%arg{1}/code" default-region group + add-highlighter "shared/%arg{1}/double_string" region '"' (?<!\\)(\\\\)*" fill string + add-highlighter "shared/%arg{1}/single_string" region "'" (?<!\\)(\\\\)*' fill string + add-highlighter "shared/%arg{1}/literal" region "`" (?<!\\)(\\\\)*` group + add-highlighter "shared/%arg{1}/comment_line" region // '$' fill comment + add-highlighter "shared/%arg{1}/comment" region /\* \*/ fill comment + add-highlighter "shared/%arg{1}/shebang" region ^#! $ fill meta + add-highlighter "shared/%arg{1}/division" region '[\w\)\]]\K(/|(\h+/\s+))' '(?=\w)' group # Help Kakoune to better detect /…/ literals + add-highlighter "shared/%arg{1}/regex" region / (?<!\\)(\\\\)*/[gimuy]* fill meta + add-highlighter "shared/%arg{1}/jsx" region -recurse (?<![\w<])<[a-zA-Z>][\w:.-]* (?<![\w<])<[a-zA-Z>][\w:.-]*(?!\hextends)(?=[\s/>])(?!>\()) (</.*?>|/>) regions + + # Regular expression flags are: g → global match, i → ignore case, m → multi-lines, u → unicode, y → sticky + # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp + + add-highlighter "shared/%arg{1}/literal/" fill string + add-highlighter "shared/%arg{1}/literal/" regex \$\{.*?\} 0:value + + add-highlighter "shared/%arg{1}/code/" regex (?:^|[^$_])\b(document|false|null|parent|self|this|true|undefined|window)\b 1:value + add-highlighter "shared/%arg{1}/code/" regex "-?\b[0-9]*\.?[0-9]+" 0:value + add-highlighter "shared/%arg{1}/code/" regex \b(Array|Boolean|Date|Function|Number|Object|RegExp|String|Symbol)\b 0:type + + # jsx: In well-formed xml the number of opening and closing tags match up regardless of tag name. + # + # We inline a small XML highlighter here since it anyway need to recurse back up to the starting highlighter. + # To make things simple we assume that jsx is always enabled. + + add-highlighter "shared/%arg{1}/jsx/tag" region -recurse < <(?=[/a-zA-Z>]) (?<!=)> regions + add-highlighter "shared/%arg{1}/jsx/expr" region -recurse \{ \{ \} ref %arg{1} + + add-highlighter "shared/%arg{1}/jsx/tag/base" default-region group + add-highlighter "shared/%arg{1}/jsx/tag/double_string" region =\K" (?<!\\)(\\\\)*" fill string + add-highlighter "shared/%arg{1}/jsx/tag/single_string" region =\K' (?<!\\)(\\\\)*' fill string + add-highlighter "shared/%arg{1}/jsx/tag/expr" region -recurse \{ \{ \} group + + add-highlighter "shared/%arg{1}/jsx/tag/base/" regex (\w+) 1:attribute + add-highlighter "shared/%arg{1}/jsx/tag/base/" regex </?([\w-$]+) 1:keyword + add-highlighter "shared/%arg{1}/jsx/tag/base/" regex (</?|/?>) 0:meta + + add-highlighter "shared/%arg{1}/jsx/tag/expr/" ref %arg{1} + + # Keywords are collected at + # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords + # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get + # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set + add-highlighter "shared/%arg{1}/code/" regex \b(async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|export|extends|finally|for|function|get|if|import|in|instanceof|let|new|of|return|set|static|super|switch|throw|try|typeof|var|void|while|with|yield)\b 0:keyword +~ + +init-javascript-filetype javascript +init-javascript-filetype typescript + +# Highlighting specific to TypeScript +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +add-highlighter shared/typescript/code/ regex \b(array|boolean|date|number|object|regexp|string|symbol)\b 0:type + +# Keywords grabbed from https://github.com/Microsoft/TypeScript/issues/2536 +add-highlighter shared/typescript/code/ regex \b(as|constructor|declare|enum|from|implements|interface|module|namespace|package|private|protected|public|readonly|static|type)\b 0:keyword + +§ + +# Aliases +# ‾‾‾‾‾‾‾ +provide-module typescript %{ require-module javascript } diff --git a/autoload/filetype/jinja.kak b/autoload/filetype/jinja.kak new file mode 100644 index 0000000..890a7ac --- /dev/null +++ b/autoload/filetype/jinja.kak @@ -0,0 +1,35 @@ +# https://palletsprojects.com/p/jinja/ +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +provide-module jinja %[ + +require-module python + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/jinja regions +add-highlighter shared/jinja/comment region '\{#' '#\}' fill comment + +# TODO: line statements # … + +add-highlighter shared/jinja/statement region '\{%' '%\}' group +add-highlighter shared/jinja/statement/ ref python +add-highlighter shared/jinja/statement/ regex \{%[+-]?|[+-]?%\} 0:value +add-highlighter shared/jinja/statement/tests regex \b(callable|even|le|none|string|defined|ge|lower|number|undefined|divisibleby|gt|lt|odd|upper|eq|in|mapping|sameas|escaped|iterable|ne|sequence)\b 0:builtin +add-highlighter shared/jinja/statement/functions regex \b(range|lipsum)\b 0:function +add-highlighter shared/jinja/statement/macro regex \b(((end)?(call|macro)))\b 0:keyword +add-highlighter shared/jinja/statement/extensions regex \b(((end)?(block|trans))|(pluralize))\b 0:keyword +add-highlighter shared/jinja/statement/control regex \b(((end)?(if|for|with))|(break|continue))\b 0:keyword +add-highlighter shared/jinja/statement/filters regex \b(?:(?:(filter)\s+|\|\s*)(abs|attr|batch|capitalize|center|default|dictsort|e|escape|filesizeformat|first|float|forceescape|format|groupby|indent|int|join|last|length|list|lower|map|max|min|pprint|random|reject|rejectattr|replace|reverse|round|safe|select|selectattr|slice|sort|string|striptags|sum|title|tojson|trim|truncate|unique|upper|urlencode|urlize|wordcount|wordwrap|xmlattr)|(endfilter))\b 1:keyword 3:keyword 2:builtin +add-highlighter shared/jinja/statement/ regex \b((end)?(autoescape|raw|set))\b 0:keyword +add-highlighter shared/jinja/statement/ regex \b(do|extends|include)\b 0:keyword +add-highlighter shared/jinja/statement/ regex \bignore\s+missing\b 0:meta +add-highlighter shared/jinja/statement/ regex \bwith(out)?\s+context\b 0:meta + +add-highlighter shared/jinja/expression region '\{\{' '\}\}' group +add-highlighter shared/jinja/expression/ ref python +add-highlighter shared/jinja/expression/ regex \{\{|\}\} 0:value +add-highlighter shared/jinja/expression/filters regex \|\s*(abs|attr|batch|capitalize|center|default|dictsort|e|escape|filesizeformat|first|float|forceescape|format|groupby|indent|int|join|last|length|list|lower|map|max|min|pprint|random|reject|rejectattr|replace|reverse|round|safe|select|selectattr|slice|sort|string|striptags|sum|title|tojson|trim|truncate|unique|upper|urlencode|urlize|wordcount|wordwrap|xmlattr)\b 1:builtin + +] diff --git a/autoload/filetype/json.kak b/autoload/filetype/json.kak new file mode 100644 index 0000000..8ca7c2a --- /dev/null +++ b/autoload/filetype/json.kak @@ -0,0 +1,69 @@ +# http://json.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](json) %{ + set-option buffer filetype json +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=json %{ + require-module json + + hook window ModeChange pop:insert:.* -group json-trim-indent json-trim-indent + hook window InsertChar .* -group json-indent json-indent-on-char + hook window InsertChar \n -group json-indent json-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window json-.+ } +} + +hook -group json-highlight global WinSetOption filetype=json %{ + add-highlighter window/json ref json + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/json } +} + + +provide-module json %( + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/json regions +add-highlighter shared/json/code default-region group +add-highlighter shared/json/string region '"' (?<!\\)(\\\\)*" fill string + +add-highlighter shared/json/code/ regex \b(true|false|null|\d+(?:\.\d+)?(?:[eE][+-]?\d*)?)\b 0:value + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden json-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden json-indent-on-char %< + evaluate-commands -draft -itersel %< + # align closer token to its opener when alone on a line + try %< execute-keys -draft <a-h> <a-k> ^\h+[\]}]$ <ret> m <a-S> 1<a-&> > + > +> + +define-command -hidden json-indent-on-new-line %< + evaluate-commands -draft -itersel %< + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : json-trim-indent <ret> } + # indent after lines ending with opener token + try %< execute-keys -draft k x <a-k> [[{]\h*$ <ret> j <a-gt> > + # deindent closer token(s) when after cursor + try %< execute-keys -draft x <a-k> ^\h*[}\]] <ret> gh / [}\]] <ret> m <a-S> 1<a-&> > + > +> + +) diff --git a/autoload/filetype/julia.kak b/autoload/filetype/julia.kak new file mode 100644 index 0000000..5f6bbaa --- /dev/null +++ b/autoload/filetype/julia.kak @@ -0,0 +1,42 @@ +# http://julialang.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*\.(jl) %{ + set-option buffer filetype julia +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=julia %{ + require-module julia +} + +hook -group julia-highlight global WinSetOption filetype=julia %{ + add-highlighter window/julia ref julia + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/julia } +} + + +provide-module julia %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/julia regions +add-highlighter shared/julia/code default-region group +add-highlighter shared/julia/string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/julia/comment region -recurse '#=' '#=' '=#' fill comment +add-highlighter shared/julia/line_comment region '#' '$' fill comment + +# taken from https://github.com/JuliaEditorSupport/julia-emacs/blob/master/julia-mode.el +add-highlighter shared/julia/code/ regex %{\b(true|false|C_NULL|Inf|NaN|Inf32|NaN32|nothing|\b-?\d+[fdiu]?)\b} 0:value +add-highlighter shared/julia/code/ regex \b(if|else|elseif|while|for|begin|end|quote|try|catch|return|local|abstract|function|macro|ccall|finally|typealias|break|continue|type|global|module|using|import|export|const|let|bitstype|do|in|baremodule|importall|immutable|mutable|struct|where)\b 0:keyword +add-highlighter shared/julia/code/ regex \b(Number|Real|BigInt|Integer|UInt|UInt8|UInt16|UInt32|UInt64|UInt128|Int|Int8|Int16|Int32|Int64|Int128|BigFloat|FloatingPoint|Float16|Float32|Float64|Complex128|Complex64|Bool|Cuchar|Cshort|Cushort|Cint|Cuint|Clonglong|Culonglong|Cintmax_t|Cuintmax_t|Cfloat|Cdouble|Cptrdiff_t|Cssize_t|Csize_t|Cchar|Clong|Culong|Cwchar_t|Cvoid|Char|ASCIIString|UTF8String|ByteString|SubString|AbstractString|Array|DArray|AbstractArray|AbstractVector|AbstractMatrix|AbstractSparseMatrix|SubArray|StridedArray|StridedVector|StridedMatrix|VecOrMat|StridedVecOrMat|DenseArray|SparseMatrixCSC|BitArray|Range|OrdinalRange|StepRange|UnitRange|FloatRange|Tuple|NTuple|Vararg|DataType|Symbol|Function|Vector|Matrix|Union|Type|Any|Complex|String|Ptr|Void|Exception|Task|Signed|Unsigned|Associative|Dict|IO|IOStream|Rational|Regex|RegexMatch|Set|IntSet|Expr|WeakRef|ObjectIdDict|AbstractRNG|MersenneTwister)\b 0:type +add-highlighter shared/julia/code/ regex \w+!*(?=\() 0:function +add-highlighter shared/julia/code/ regex @\w+!*\b 0:meta +add-highlighter shared/julia/code/ regex '(?:\?|=|:=|\+=|-=|\*=|/=|//=|\.//=|\.\*=|\./=|\\=|\.\\=|\^=|\.\^=|÷=|\.÷=|%=|\.%=|\|=|&=|\$=|=>|<<=|>>=|>>>=|~|\.\+=|\.-=|--|-->|←|→|↔|↚|↛|↠|↣|↦|↮|⇎|⇏|⇒|⇔|⇴|⇶|⇷|⇸|⇹|⇺|⇻|⇼|⇽|⇾|⇿|⟵|⟶|⟷|⟷|⟹|⟺|⟻|⟼|⟽|⟾|⟿|⤀|⤁|⤂|⤃|⤄|⤅|⤆|⤇|⤌|⤍|⤎|⤏|⤐|⤑|⤔|⤕|⤖|⤗|⤘|⤝|⤞|⤟|⤠|⥄|⥅|⥆|⥇|⥈|⥊|⥋|⥎|⥐|⥒|⥓|⥖|⥗|⥚|⥛|⥞|⥟|⥢|⥤|⥦|⥧|⥨|⥩|⥪|⥫|⥬|⥭|⥰|⧴|⬱|⬰|⬲|⬳|⬴|⬵|⬶|⬷|⬸|⬹|⬺|⬻|⬼|⬽|⬾|⬿|⭀|⭁|⭂|⭃|⭄|⭇|⭈|⭉|⭊|⭋|⭌|←|→|&&|\|\||>|<|>=|≥|<=|≤|==|===|≡|!=|≠|!==|≢|\.>|\.<|\.>=|\.≥|\.<=|\.≤|\.==|\.!=|\.≠|\.=|\.!|<:|>:|∈|∉|∋|∌|⊆|⊈|⊂|⊄|⊊|∝|∊|∍|∥|∦|∷|∺|∻|∽|∾|≁|≃|≄|≅|≆|≇|≈|≉|≊|≋|≌|≍|≎|≐|≑|≒|≓|≔|≕|≖|≗|≘|≙|≚|≛|≜|≝|≞|≟|≣|≦|≧|≨|≩|≪|≫|≬|≭|≮|≯|≰|≱|≲|≳|≴|≵|≶|≷|≸|≹|≺|≻|≼|≽|≾|≿|⊀|⊁|⊃|⊅|⊇|⊉|⊋|⊏|⊐|⊑|⊒|⊜|⊩|⊬|⊮|⊰|⊱|⊲|⊳|⊴|⊵|⊶|⊷|⋍|⋐|⋑|⋕|⋖|⋗|⋘|⋙|⋚|⋛|⋜|⋝|⋞|⋟|⋠|⋡|⋢|⋣|⋤|⋥|⋦|⋧|⋨|⋩|⋪|⋫|⋬|⋭|⋲|⋳|⋴|⋵|⋶|⋷|⋸|⋹|⋺|⋻|⋼|⋽|⋾|⋿|⟈|⟉|⟒|⦷|⧀|⧁|⧡|⧣|⧤|⧥|⩦|⩧|⩪|⩫|⩬|⩭|⩮|⩯|⩰|⩱|⩲|⩳|⩴|⩵|⩶|⩷|⩸|⩹|⩺|⩻|⩼|⩽|⩾|⩿|⪀|⪁|⪂|⪃|⪄|⪅|⪆|⪇|⪈|⪉|⪊|⪋|⪌|⪍|⪎|⪏|⪐|⪑|⪒|⪓|⪔|⪕|⪖|⪗|⪘|⪙|⪚|⪛|⪜|⪝|⪞|⪟|⪠|⪡|⪢|⪣|⪤|⪥|⪦|⪧|⪨|⪩|⪪|⪫|⪬|⪭|⪮|⪯|⪰|⪱|⪲|⪳|⪴|⪵|⪶|⪷|⪸|⪹|⪺|⪻|⪼|⪽|⪾|⪿|⫀|⫁|⫂|⫃|⫄|⫅|⫆|⫇|⫈|⫉|⫊|⫋|⫌|⫍|⫎|⫏|⫐|⫑|⫒|⫓|⫔|⫕|⫖|⫗|⫘|⫙|⫷|⫸|⫹|⫺|⊢|⊣|\|>|<\||:|\.\.|\+|-|⊕|⊖|⊞|⊟|\.\+|\.-|\+\+|\||∪|∨|\$|⊔|±|∓|∔|∸|≂|≏|⊎|⊻|⊽|⋎|⋓|⧺|⧻|⨈|⨢|⨣|⨤|⨥|⨦|⨧|⨨|⨩|⨪|⨫|⨬|⨭|⨮|⨹|⨺|⩁|⩂|⩅|⩊|⩌|⩏|⩐|⩒|⩔|⩖|⩗|⩛|⩝|⩡|⩢|⩣|<<|>>|>>>|\.<<|\.>>|\.>>>|\*|/|\./|÷|\.÷|%|⋅|∘|×|\.%|\.\*|\\|\.\\|&|∩|∧|⊗|⊘|⊙|⊚|⊛|⊠|⊡|⊓|∗|∙|∤|⅋|≀|⊼|⋄|⋆|⋇|⋉|⋊|⋋|⋌|⋏|⋒|⟑|⦸|⦼|⦾|⦿|⧶|⧷|⨇|⨰|⨱|⨲|⨳|⨴|⨵|⨶|⨷|⨸|⨻|⨼|⨽|⩀|⩃|⩄|⩋|⩍|⩎|⩑|⩓|⩕|⩘|⩚|⩜|⩞|⩟|⩠|⫛|⊍|▷|⨝|⟕|⟖|⟗|//|\.//|\^|\.\^|↑|↓|⇵|⟰|⟱|⤈|⤉|⤊|⤋|⤒|⤓|⥉|⥌|⥍|⥏|⥑|⥔|⥕|⥘|⥙|⥜|⥝|⥠|⥡|⥣|⥥|⥮|⥯|↑|↓|::|\.)' 0:operator +} diff --git a/autoload/filetype/just.kak b/autoload/filetype/just.kak new file mode 100644 index 0000000..8c43fcc --- /dev/null +++ b/autoload/filetype/just.kak @@ -0,0 +1,79 @@ +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*/?[jJ]ustfile %{ + set-option buffer filetype justfile +} + +hook global WinSetOption filetype=justfile %{ + require-module justfile + + hook window ModeChange pop:insert:.* -group justfile-trim-indent justfile-trim-indent + hook window InsertChar \n -group justfile-insert just-insert-on-new-line + hook window InsertChar \n -group justfile-indent just-indent-on-new-line + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window justfile-.+ } +} + +hook -group justfile-highlight global WinSetOption filetype=justfile %{ + add-highlighter window/justfile ref justfile + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/justfile } +} + + +provide-module justfile %{ + +# Indentation +# ‾‾‾‾‾‾‾‾‾‾‾ + +define-command -hidden justfile-trim-indent %{ + evaluate-commands -no-hooks -draft -itersel %{ + execute-keys x + # remove trailing white spaces + try %{ execute-keys -draft s \h + $ <ret> d } + } +} + +define-command -hidden just-insert-on-new-line %{ + # copy '#' comment prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*//\h* <ret> y jgh P } +} + +define-command -hidden just-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon>K<a-&> } + # cleanup trailing white spaces on previous line + try %{ execute-keys -draft kx s \h+$ <ret>"_d } + } +} + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/justfile regions + +add-highlighter shared/justfile/content default-region group +add-highlighter shared/justfile/content/recipe regex '^@?([\w-]+)([^\n]*):(?!=)([^\n]*)' 1:function 2:meta 3:keyword +add-highlighter shared/justfile/content/assignments regex ^([\w-]+\h*:=\h*[^\n]*) 1:meta +add-highlighter shared/justfile/content/operator regex '((^@|:=|=|\+|\(|\)))' 1:operator +add-highlighter shared/justfile/content/strings regions +add-highlighter shared/justfile/content/strings/double region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/justfile/content/strings/single region "'" (?<!\\)(\\\\)*' fill string + +add-highlighter shared/justfile/comment region '#' '$' fill comment + +add-highlighter shared/justfile/inline region '`' '`' ref sh + +add-highlighter shared/justfile/body region '^\h+' '^[^\h]' group +add-highlighter shared/justfile/body/interpreters regions +add-highlighter shared/justfile/body/interpreters/defaultshell default-region group +add-highlighter shared/justfile/body/interpreters/defaultshell/ ref sh +add-highlighter shared/justfile/body/interpreters/defaultshell/ regex '^\h+(@)' 1:operator + +add-highlighter shared/justfile/body/interpreters/bash region '^\h+#!\h?/usr/bin/env bash' '^[^\h]' ref sh +add-highlighter shared/justfile/body/interpreters/sh region '^\h+#!\h?/usr/bin/env sh' '^[^\h]' ref sh + +add-highlighter shared/justfile/body/ regex '(\{{2})([\w-]+(?:\(\))?)(\}{2})' 1:operator 2:variable 3:operator + + +} diff --git a/autoload/filetype/kakrc.kak b/autoload/filetype/kakrc.kak new file mode 100644 index 0000000..1914e46 --- /dev/null +++ b/autoload/filetype/kakrc.kak @@ -0,0 +1,130 @@ +# http://kakoune.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate (.*/)?(kakrc|.*\.kak) %{ + set-option buffer filetype kak +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=kak %~ + require-module kak + + set-option window static_words %opt{kak_static_words} + + hook window InsertChar \n -group kak-insert kak-insert-on-new-line + hook window InsertChar \n -group kak-indent kak-indent-on-new-line + hook window InsertChar [>)}\]] -group kak-indent kak-indent-on-closing-matching + hook window InsertChar (?![[{(<>)}\]])[^\s\w] -group kak-indent kak-indent-on-closing-char + # cleanup trailing whitespaces on current line insert end + hook window ModeChange pop:insert:.* -group kak-trim-indent %{ try %{ execute-keys -draft <semicolon> x s ^\h+$ <ret> d } } + set-option buffer extra_word_chars '_' '-' + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window kak-.+ } +~ + +hook -group kak-highlight global WinSetOption filetype=kak %{ + add-highlighter window/kakrc ref kakrc + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/kakrc } +} + +provide-module kak %§ + +require-module sh + +# Highlighters & Completion +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/kakrc regions +add-highlighter shared/kakrc/code default-region group +add-highlighter shared/kakrc/comment region (^|\h)\K# $ fill comment +add-highlighter shared/kakrc/double_string region -recurse %{(?<!")("")+(?!")} %{(^|\h)\K"} %{"(?!")} group +add-highlighter shared/kakrc/single_string region -recurse %{(?<!')('')+(?!')} %{(^|\h)\K'} %{'(?!')} group +add-highlighter shared/kakrc/shell1 region -recurse '\{' '(^|\h)\K%?%sh\{' '\}' ref sh +add-highlighter shared/kakrc/shell2 region -recurse '\(' '(^|\h)\K%?%sh\(' '\)' ref sh +add-highlighter shared/kakrc/shell3 region -recurse '\[' '(^|\h)\K%?%sh\[' '\]' ref sh +add-highlighter shared/kakrc/shell4 region -recurse '<' '(^|\h)\K%?%sh<' '>' ref sh +add-highlighter shared/kakrc/shell5 region -recurse '\{' '(^|\h)\K-?shell-script(-completion|-candidates)?\h+%\{' '\}' ref sh +add-highlighter shared/kakrc/shell6 region -recurse '\(' '(^|\h)\K-?shell-script(-completion|-candidates)?\h+%\(' '\)' ref sh +add-highlighter shared/kakrc/shell7 region -recurse '\[' '(^|\h)\K-?shell-script(-completion|-candidates)?\h+%\[' '\]' ref sh +add-highlighter shared/kakrc/shell8 region -recurse '<' '(^|\h)\K-?shell-script(-completion|-candidates)?\h+%<' '>' ref sh + +evaluate-commands %sh{ + # Grammar + keywords="add-highlighter alias arrange-buffers buffer buffer-next buffer-previous catch + change-directory colorscheme debug declare-option declare-user-mode define-command complete-command + delete-buffer delete-buffer! echo edit edit! enter-user-mode evaluate-commands execute-keys + fail hook info kill kill! map nop on-key prompt provide-module quit quit! + remove-highlighter remove-hooks rename-buffer rename-client rename-session require-module + select set-face set-option set-register source trigger-user-hook try + unalias unmap unset-face unset-option update-option + write write! write-all write-all-quit write-quit write-quit!" + attributes="global buffer window current + normal insert prompt goto view user object + number-lines show-matching show-whitespaces fill regex dynregex group flag-lines + ranges line column wrap ref regions region default-region replace-ranges" + types="int bool str regex int-list str-list completions line-specs range-specs str-to-str-map" + values="default black red green yellow blue magenta cyan white yes no false true" + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list kak_static_words $(join "${keywords} ${attributes} ${types} ${values}" ' ')'" + + # Highlight keywords (which are always surrounded by whitespace) + printf '%s\n' "add-highlighter shared/kakrc/code/keywords regex (?:\s|\A)\K($(join "${keywords}" '|'))(?:(?=\s)|\z) 0:keyword + add-highlighter shared/kakrc/code/attributes regex (?:\s|\A)\K($(join "${attributes}" '|'))(?:(?=\s)|\z) 0:attribute + add-highlighter shared/kakrc/code/types regex (?:\s|\A)\K($(join "${types}" '|'))(?:(?=\s)|\z) 0:type + add-highlighter shared/kakrc/code/values regex (?:\s|\A)\K($(join "${values}" '|'))(?:(?=\s)|\z) 0:value" +} + +add-highlighter shared/kakrc/code/colors regex \b(rgb:[0-9a-fA-F]{6}|rgba:[0-9a-fA-F]{8})\b 0:value +add-highlighter shared/kakrc/code/numbers regex \b\d+\b 0:value + +add-highlighter shared/kakrc/double_string/fill fill string +add-highlighter shared/kakrc/double_string/escape regex '""' 0:default+b +add-highlighter shared/kakrc/single_string/fill fill string +add-highlighter shared/kakrc/single_string/escape regex "''" 0:default+b + +add-highlighter shared/kak ref kakrc + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden kak-insert-on-new-line %~ + evaluate-commands -draft -itersel %= + # copy '#' comment prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*#\h* <ret> y jgh P } + = +~ + +define-command -hidden kak-indent-on-new-line %~ + evaluate-commands -draft -itersel %= + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # cleanup trailing whitespaces from previous line + try %{ execute-keys -draft k x s \h+$ <ret> d } + # indent after line ending with %\w*[^\s\w] + try %{ execute-keys -draft k x <a-k> \%\w*[^\s\w]$ <ret> j <a-gt> } + # deindent closing brace when after cursor + try %_ execute-keys -draft -itersel x <a-k> ^\h*([>)}\]]) <ret> gh / <c-r>1 <ret> m <a-S> 1<a-&> _ + # deindent closing char(s) + try %{ execute-keys -draft -itersel x <a-k> ^\h*([^\s\w]) <ret> gh / <c-r>1 <ret> <a-?> <c-r>1 <ret> <a-T>% <a-k> \w*<c-r>1$ <ret> <a-S> 1<a-&> } + = +~ + +define-command -hidden kak-indent-on-closing-matching %~ + # align to opening matching brace when alone on a line + try %= execute-keys -draft -itersel <a-h><a-k>^\h*\Q %val{hook_param} \E$<ret> mGi s \A|.\z<ret> 1<a-&> = +~ + +define-command -hidden kak-indent-on-closing-char %{ + # align to opening matching character when alone on a line + try %{ execute-keys -draft -itersel <a-h><a-k>^\h*\Q %val{hook_param} \E$<ret>gi<a-f> %val{hook_param} <a-T>%<a-k>\w*\Q %val{hook_param} \E$<ret> s \A|.\z<ret> gi 1<a-&> } +} + +§ diff --git a/autoload/filetype/kickstart.kak b/autoload/filetype/kickstart.kak new file mode 100644 index 0000000..0e7441b --- /dev/null +++ b/autoload/filetype/kickstart.kak @@ -0,0 +1,38 @@ +hook global BufCreate .*\.ks %{ + set-option buffer filetype kickstart +} + +hook global WinSetOption filetype=kickstart %{ + require-module kickstart +} + +hook -group kickstart-highlight global WinSetOption filetype=kickstart %{ + add-highlighter window/kickstart ref kickstart + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/kickstart } +} + + +provide-module kickstart %{ + +add-highlighter shared/kickstart regions +add-highlighter shared/kickstart/code default-region group +add-highlighter shared/kickstart/comment region '(^|\h)\K#' $ fill comment +add-highlighter shared/kickstart/double_string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/kickstart/single_string region "'" (?<!\\)(\\\\)*' fill string +add-highlighter shared/kickstart/packages region '^\h*\K%packages\b' '^\h*\K%end\b' group +add-highlighter shared/kickstart/shell region '^\h*\K%(pre|pre-install|post)\b' '^\h*\K%end\b' group + +add-highlighter shared/kickstart/code/ regex "^\h*\b(auth|authconfig|autopart|autostep|bootloader|btrfs|clearpart|cmdline|device|dmraid|driverdisk|fcoe|firewall|firstboot|group|graphical|halt|ignoredisk|install|cdrom|harddrive|liveimg|nfs|url|iscsi|iscsiname|keyboard|lang|logvol|logging|mediacheck|monitor|multipath|network|part|partition|poweroff|raid|realm|reboot|repo|rescue|rootpw|selinux|services|shutdown|sshkey|sshpw|skipx|text|timezone|updates|upgrade|user|vnc|volgroup|xconfig|zerombr|zfcp)\b" 1:keyword +add-highlighter shared/kickstart/code/ regex '(--[\w-]+=? ?)([^-"\n][^\h\n]*)?' 1:attribute 2:string +add-highlighter shared/kickstart/code/ regex '%(include|ksappend)\b' 0:keyword + +add-highlighter shared/kickstart/packages/ regex "^\h*[\w-]*" 0:value +add-highlighter shared/kickstart/packages/ regex "#[^\n]*" 0:comment +add-highlighter shared/kickstart/packages/ regex "^\h*@\^?[\h\w-]*" 0:attribute +add-highlighter shared/kickstart/packages/ regex '\A\h*\K%packages\b' 0:type +add-highlighter shared/kickstart/packages/ regex '^\h*%end\b' 0:type +add-highlighter shared/kickstart/shell/ regex '\A\h*\K%(pre-install|pre|post)\b' 0:type +add-highlighter shared/kickstart/shell/ regex '^\h*%end\b' 0:type +add-highlighter shared/kickstart/shell/ ref sh + +} diff --git a/autoload/filetype/kotlin.kak b/autoload/filetype/kotlin.kak new file mode 100644 index 0000000..d1707a8 --- /dev/null +++ b/autoload/filetype/kotlin.kak @@ -0,0 +1,187 @@ +# References --------------------------------------------------------------------------------------- # +# ‾‾‾‾‾‾‾‾‾‾ +# Team: Yerlan & Kirk Duncan +# +# Kotlin 2020, Keywords and Operators, v1.4.0, viewed 9 September 2020, https://kotlinlang.org/docs/reference/keyword-reference.html +# Kdoc 2020, Documenting Kotlin Code, Block Tags, v1.4.0, viewed 9 September 2020, https://kotlinlang.org/docs/reference/kotlin-doc.html +# Oracle 2020, Java Platform, Standard Edition & Java Development Kit, Version 14 API Specification, viewed 8 September 2020, https://docs.oracle.com/en/java/javase/14/docs/api/index.html +# +# File types --------------------------------------------------------------------------------------- # +# ‾‾‾‾‾‾‾‾‾‾ +hook global BufCreate .*[.](kt|kts) %{ + set-option buffer filetype kotlin +} + +# Initialization ----------------------------------------------------------------------------------- # +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +hook global WinSetOption filetype=kotlin %{ + require-module kotlin + + set-option window static_words %opt{kotlin_static_words} + + # cleanup trailing whitespaces when exiting insert mode + hook window ModeChange pop:insert:.* -group kotlin-trim-indent %{ try %{ execute-keys -draft xs^\h+$<ret>d } } + hook window InsertChar \n -group kotlin-indent kotlin-insert-on-new-line + hook window InsertChar \n -group kotlin-indent kotlin-indent-on-new-line + hook window InsertChar \{ -group kotlin-indent kotlin-indent-on-opening-curly-brace + hook window InsertChar \} -group kotlin-indent kotlin-indent-on-closing-curly-brace + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window kotlin-.+ } +} + +hook -group kotlin-highlighter global WinSetOption filetype=kotlin %{ + add-highlighter window/kotlin ref kotlin + add-highlighter window/kdoc ref kdoc + + hook -once -always window WinSetOption filetype=.* %{ + remove-highlighter window/kotlin + remove-highlighter window/kdoc + } +} + +hook global BufSetOption filetype=kotlin %{ + require-module kotlin + + set-option buffer comment_line '//' + set-option buffer comment_block_begin '/*' + set-option buffer comment_block_end '*/' + + hook -once -always buffer BufSetOption filetype=.* %{ remove-hooks buffer kotlin-.+ } +} + +# Module ------------------------------------------------------------------------------------------- # +# ‾‾‾‾‾‾ +provide-module kotlin %§ + +add-highlighter shared/kotlin regions +add-highlighter shared/kotlin/code default-region group +add-highlighter shared/kotlin/string region %{(?<!')"} %{(?<!\\)(\\\\)*"} group +add-highlighter shared/kotlin/character region %{'} %{(?<!\\)'} group +add-highlighter shared/kotlin/comment region /\* \*/ fill comment +add-highlighter shared/kotlin/inline_documentation region /// $ fill documentation +add-highlighter shared/kotlin/line_comment region // $ fill comment + +add-highlighter shared/kotlin/code/annotations regex @\w+\b|\b\w+@(?=\{) 0:meta +add-highlighter shared/kotlin/code/identifiers regex \b(field|it)\b 1:variable +add-highlighter shared/kotlin/code/fields regex \.([A-Za-z_][\w]*)\s*?\. 1:type + +# String interpolation +add-highlighter shared/kotlin/string/ fill string +add-highlighter shared/kotlin/string/ regex \$\{.*?\} 0:value + +# Character +add-highlighter shared/kotlin/character/ fill value +add-highlighter shared/kotlin/character/ regex ('.{1})(.+)(') 2:meta + +# As at 15 March 2021, method see: https://regex101.com/r/Mhy4HG/1 +add-highlighter shared/kotlin/code/methods regex ::([A-Za-z_][\w]*)|\.([A-Za-z_][\w]*)\s*?[\(\{]|\.([A-Za-z_][\w]*)[\s\)\}>](?=[^\(\{]) 1:function 2:function 3:function + +# Test suite functions: fun `this is a valid character function test`() +add-highlighter shared/kotlin/code/fun_tests regex ^\h*?fun\s*?`(.[^<>:/\[\]\\\.]+?)`\h*?(?=\() 1:default+iuf +add-highlighter shared/kotlin/code/delimiters regex (\(|\)|\[|\]|\{|\}|\;|') 1:operator +add-highlighter shared/kotlin/code/operators regex (\+|-|\*|&|=|\\|\?|%|\|-|!|\||->|\.|,|<|>|:|\^|/) 1:operator +add-highlighter shared/kotlin/code/numbers regex \b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)([LlFf])?\b 0:value + +# Generics need improvement, as after a colon will match as a constant only. +# val program: IOU = XXXX; val cat: DOG = XXXX. matches IOU or DOG as a +# CONSTANT when it could be generics. See: https://regex101.com/r/VPO5LE/10 +add-highlighter shared/kotlin/code/constants_and_generics regex \b((?<==\h)\([A-Z][A-Z0-9_]+(?=[<:\;])|(?<!<)[A-Z][A-Z0-9_]+\b(?!<[>\)]))|\b((?<!=\s)(?<!\.)[A-Z]+\d*?(?![\(\;:])(?=[,\)>\s]))\b 1:meta 2:type + +add-highlighter shared/kotlin/code/target regex @(delegate|field|file|get|param|property|receiver|set|setparam)(?=:) 0:meta +add-highlighter shared/kotlin/code/soft regex \b(by|catch|constructor|dynamic|finally|get|import|init|set|where)\b 1:keyword +add-highlighter shared/kotlin/code/hard regex \b(as|as\?|break|class|continue|do|else|false|for|fun|if|in|!in|interface|is|!is|null|object|package|return|super|this|throw|true|try|typealias|val|var|when|while)\b 1:keyword + +add-highlighter shared/kotlin/code/modifier regex \b(actual|abstract|annotation|companion|const|crossinline|data|enum|expect|external|final|infix|inline|inner|internal|lateinit|noinline|open|operator|out|override|private|protected|public|reified|sealed|suspend|tailrec|vararg)\b(?=[\s\n]) 1:attribute + +add-highlighter shared/kotlin/code/type regex \b(Annotation|Any|Boolean|BooleanArray|Byte|ByteArray|Char|Character|CharArray|CharSequence|Class|ClassLoader|Cloneable|Comparable|Compiler|DeprecationLevel|Double|DoubleArray|Enum|Float|FloatArray|Function|Int|IntArray|Integer|Lazy|LazyThreadSafetyMode|Long|LongArray|Math|Nothing|Number|Object|Package|Pair|Process|Runnable|Runtime|SecurityManager|Short|ShortArray|StackTraceElement|StrictMath|String|StringBuffer|System|Thread|ThreadGroup|ThreadLocal|Triple|Unit|Void)\b(?=[^<]) 1:type + +# Kdoc --------------------------------------------------------------------------------------------- # +# ‾‾‾‾ +add-highlighter shared/kdoc group +add-highlighter shared/kdoc/tag regex \*(?:\s+)?(@(author|constructor|exception|param|property|receiver|return|sample|see|since|suppress|throws))\b 1:default+ui + +# Discolour ---------------------------------------------------------------------------------------- # +# ‾‾‾‾‾‾‾‾‾ +add-highlighter shared/kotlin/code/discolour regex ^(package|import)(?S)(.+) 2:default+fa + +# Commands ----------------------------------------------------------------------------------------- # +# ‾‾‾‾‾‾‾‾ +define-command -hidden kotlin-insert-on-new-line %[ + # copy // comments prefix and following white spaces + try %{ execute-keys -draft <semicolon><c-s>kx s ^\h*\K/{2,}\h* <ret> y<c-o>P<esc> } +] + +define-command -hidden kotlin-indent-on-new-line %~ + evaluate-commands -draft -itersel %< + # preserve previous line indent + try %{ execute-keys -draft <semicolon>K<a-&> } + # indent after lines ending with { or ( + try %[ execute-keys -draft kx <a-k> [{(]\h*$ <ret> j<a-gt> ] + # cleanup trailing white spaces on the previous line + try %{ execute-keys -draft kx s \h+$ <ret>d } + # align to opening paren of previous line + try %{ execute-keys -draft [( <a-k> \A\([^\n]+\n[^\n]*\n?\z <ret> s \A\(\h*.|.\z <ret> '<a-;>' & } + # indent after a pattern match on when/where statements + try %[ execute-keys -draft kx <a-k> ^\h*(when|where).*$ <ret> j<a-gt> ] + # indent after term on an expression + try %[ execute-keys -draft kx <a-k> =\h*?$ <ret> j<a-gt> ] + # indent after keywords + try %[ execute-keys -draft <semicolon><a-F>)MB <a-k> \A(catch|do|else|for|if|try|while)\h*\(.*\)\h*\n\h*\n?\z <ret> s \A|.\z <ret> 1<a-&>1<a-,><a-gt> ] + # deindent closing brace(s) when after cursor + try %[ execute-keys -draft x <a-k> ^\h*[})] <ret> gh / [})] <ret> m <a-S> 1<a-&> ] + > +~ + +define-command -hidden kotlin-indent-on-opening-curly-brace %[ + # align indent with opening paren when { is entered on a new line after the closing paren + try %[ execute-keys -draft -itersel h<a-F>)M <a-k> \A\(.*\)\h*\n\h*\{\z <ret> s \A|.\z <ret> 1<a-&> ] +] + +define-command -hidden kotlin-indent-on-closing-curly-brace %[ + # align to opening curly brace when alone on a line + try %[ execute-keys -itersel -draft <a-h><a-k>^\h+\}$<ret>hms\A|.\z<ret>1<a-&> ] +] + +# Exceptions, Errors, and Types -------------------------------------------------------------------- # +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +# macro: 93le<a-;>i<ret><esc><esc> +evaluate-commands %sh{ + + kotlin_keywords='abstract actual annotation as break by catch class companion const + constructor continue crossinline data delegate do dynamic else enum expect external + false field file final finally for fun get if import in infix init inline inner + interface internal is lateinit noinline null object open operator out override + package param private property protected public receiver reified return sealed set + setparam super suspend tailrec this throw true try typealias val var vararg when where while' + + kotlin_types='Annotation Any Boolean BooleanArray Byte ByteArray Char Character CharArray + CharSequence Class ClassLoader Cloneable Comparable Compiler DeprecationLevel Double + DoubleArray Enum Float FloatArray Function Int IntArray Integer Lazy LazyThreadSafetyMode + Long LongArray Math Nothing Number Object Package Pair Process Runnable Runtime + SecurityManager Short ShortArray StackTraceElement StrictMath String StringBuffer System + Thread ThreadGroup ThreadLocal Triple Unit Void' + + # ------------------------------------------------------------------------------------------------ # + + kotlin_kdocs='author constructor exception param property receiver return sample see since suppress throws' + + # ------------------------------------------------------------------------------------------------ # + + kotlin_errors_exceptions='CharacterCodingException Error AssertionError NotImplementedError + OutOfMemoryErrorIllegalCallableAccessException IllegalPropertyDelegateAccessException + NoSuchPropertyException RuntimeException Throwable' + + # ------------------------------------------------------------------------------------------------ # + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # ------------------------------------------------------------------------------------------------ # + + printf %s\\n "declare-option str-list kotlin_static_words $(join "${kotlin_keywords} ${kotlin_types} ${kotlin_kdocs} ${kotlin_errors_exceptions}" ' ')" + + # ------------------------------------------------------------------------------------------------ # + + printf %s\\n "add-highlighter shared/kotlin/code/errors_exceptions regex \b($(join "${kotlin_errors_exceptions}" '|'))\b 0:type" +} +§ +# ------------------------------------------------------------------------------------------------- # diff --git a/autoload/filetype/latex.kak b/autoload/filetype/latex.kak new file mode 100644 index 0000000..70c3767 --- /dev/null +++ b/autoload/filetype/latex.kak @@ -0,0 +1,144 @@ +# https://www.latex-project.org/ +# + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*\.(tex|cls|sty|dtx) %{ + set-option buffer filetype latex +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=latex %( + require-module latex + + hook window InsertChar \n -group latex-insert %{ latex-insert-on-newline } + hook window InsertChar \n -group latex-indent %{ latex-indent-newline } + hook window InsertChar \} -group latex-indent %{ latex-indent-closing-brace } + hook window ModeChange pop:insert:.* -group latex-indent %{ latex-trim-indent } + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window latex-indent } + hook window InsertChar \n -group latex-insert latex-insert-on-new-line +) + +hook -group latex-highlight global WinSetOption filetype=latex %{ + add-highlighter window/latex ref latex + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/latex } +} + +provide-module latex %~ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/latex regions +add-highlighter shared/latex/content default-region group +# Region for control sequence (includes latex2e arguments and options) +# starting with unescaped \ and ending : +# - at eol, or +# - at word boundaries not preceded nor followed by @ : \ { } [ ] *, or +# - after an unescaped } +add-highlighter shared/latex/cs region '(?<!\\)(?:\\\\)*\K\\[@\w]' '/\n|(?<![@:\\{}\[\]*])(?![@:\\{}\[\]*])\b|(?<!\\)(?:\\\\)*\K\}\K' group +add-highlighter shared/latex/comment region '(?<!\\)(?:\\\\)*\K%' '\n' fill comment + +# Document and LaTeX2e control sequence +add-highlighter shared/latex/cs/ regex '(?:\\[a-zA-Z@]+)' 0:keyword +## Options passed to LaTeX2e control sequences, between brackets +add-highlighter shared/latex/cs/ regex '\\[a-zA-Z@]+\b\[([^\]]+)\]' 1:value +## Emphasized text +add-highlighter shared/latex/cs/ regex '\\(?:emph|textit|textsl)\{([^}]+)\}' 1:default+i +## Underlined text +add-highlighter shared/latex/cs/ regex '\\underline\{([^}]+)\}' 1:default+u +## Bold text +add-highlighter shared/latex/cs/ regex '\\textbf\{([^}]+)\}' 1:default+b +## Section headings +add-highlighter shared/latex/cs/ regex '\\(part|section)\*?\{([^}]+)\}' 2:title +add-highlighter shared/latex/cs/ regex '\\(chapter|(sub)+section|(sub)*paragraph)\*?\{([^}]+)\}' 4:header + +# LaTeX3 control sequence +## Functions (expl3 doc) module_name:arguments_types. +add-highlighter shared/latex/cs/ regex '\\(?:__|@@_)?[a-zA-Z@]+_\w+(:[nNpTFDwcVvxefo]+)?' 0:function 1:+db@type +## Variables (expl3 doc): scope_name_type +add-highlighter shared/latex/cs/ regex '\\([lgc]_)[a-zA-Z@]+_\w+' 0:variable 1:+db +## l3kernel modules (l3kernel/doc/l3prefixes.csv) +add-highlighter shared/latex/cs/ regex '\\(alignment|alloc|ampersand|atsign|backslash|bitset|bool|box|catcode|cctab|char|chk|circumflex|clist|code|codedoc|coffin|colon|color|cs|debug|dim|document|dollar|driver|e|else|empty|etex|exp|expl|false|fi|file|flag|fp|group|hash|hbox|hcoffin|if|inf|initex|insert|int|intarray|ior|iow|job|kernel|keys|keyval|left|log|lua|luatex|mark|marks|math|max|minus|mode|msg|muskip|nan|nil|no|novalue|one|or|other|parameter|pdf|pdftex|peek|percent|pi|prg|prop|ptex|quark|recursion|ref|regex|reverse|right|scan|seq|skip|sort|space|stop|str|sys|tag|term|tex|text|tilde|tl|tmpa|tmpb|token|true|underscore|uptex|use|utex|vbox|vcoffin|xetex|zero)_' 0:+db +# LaTeX3 types (expl3 doc) +add-highlighter shared/latex/cs/ regex '_(bool|box|cctab|clist|coffin|dim|fp|ior|iow|int|muskip|prop|seq|skip|str|tl)\b' 0:+db + +# This belongs to content group as the LaTeX3 convention is separating macros names, args and options +# with spaces and thus should not be catched by the cs region +## macros arguments +add-highlighter shared/latex/content/ regex '(?<!\\)(?:\\\\)*\K#+[1-9]' 0:string +## group containing words and numbers (list separated by ; , / or spaces) +add-highlighter shared/latex/content/ regex '(?<!\\)(?:\\\\)*\K\{([\s/;,.\w\d]+)\}' 1:string + +# Math mode between dollar signs/pairs +add-highlighter shared/latex/content/ regex '((?<!\\)(?:\\\\)*\K\$(\\\$|[^$])+\$)|((?<!\\)(?:\\\\)*\K\$\$(\\\$|[^$])+\$\$)|((?<!\\)(?:\\\\)*\K\\\[.*?\\\])|(\\\(.*?\\\))' 0:meta + +# Indent +# ------ + +define-command -hidden latex-trim-indent %{ + evaluate-commands -no-hooks -draft -itersel %{ + try %{ execute-keys x 1s^(\h+)$<ret> d } + } +} + +define-command -hidden latex-insert-on-newline %{ + # copy '%' comment prefix and following white spaces + try %{ execute-keys -draft kx s^\h*%\h*<ret> y jgh P } +} + +define-command -hidden latex-indent-newline %( + evaluate-commands -no-hooks -draft -itersel %( + # preserve previous line indent + try %{ execute-keys -draft K<a-&> } + # cleanup trailing whitespaces from previous line + try %{ execute-keys -draft kx s\h+$<ret> d } + # indent after line ending with { + try %( execute-keys -draft kx <a-k>\{$<ret> j<a-gt> ) + # deindent closing brace(s) when after cursor + try %( execute-keys -draft x <a-k> ^\h*\} <ret> gh / \} <ret> m <a-S> 1<a-&> ) + # indent after line ending with \begin{...}[...]{...}, with multiple + # sets of arguments possible + try %( + execute-keys -draft \ + kx \ + <a-k>\\begin\h*\{[^\}]+\}(\h|\[.*\]|\{.*\})*$<ret> \ + j<a-gt> + ) + ) +) + +define-command -hidden latex-indent-closing-brace %( + evaluate-commands -no-hooks -draft -itersel %( + # Align lone } with matching bracket + try %( execute-keys -draft x_ <a-k>\A\}\z<ret> m<a-S>1<a-&> ) + # Align \end{...} with corresponding \begin{...} + try %( + execute-keys -draft h<a-h> 1s\\end\h*\{([^\}]+)\}\z<ret> \ + <a-?>\\begin\s*\{<c-r>.\}<ret> <a-S>1<a-&> + ) + ) +) + +define-command -hidden latex-insert-on-new-line %( + evaluate-commands -no-hooks -draft -itersel %( + # Wisely add "\end{...}". + evaluate-commands -save-regs xz %( + # Save previous line indent in register x. + try %( execute-keys -draft kxs^\h+<ret>"xy ) catch %( reg x '' ) + # Save item of begin in register z. + try %( execute-keys -draft kxs\{.*\}<ret>"zy ) catch %( reg z '' ) + try %( + # Validate previous line and that it is not closed yet. + execute-keys -draft kx <a-k>^<c-r>x\h*\\begin\{.*\}<ret> J}iJx <a-K>^<c-r>x(\\end\<c-r>z<backspace>\})<ret> + # Auto insert "\end{...}". + execute-keys -draft o<c-r>x\end<c-r>z<esc> + ) + ) + ) +) + +~ diff --git a/autoload/filetype/ledger.kak b/autoload/filetype/ledger.kak new file mode 100644 index 0000000..31417b7 --- /dev/null +++ b/autoload/filetype/ledger.kak @@ -0,0 +1,144 @@ +# Detection +# --------- + +# The .ledger suffix is not required by ledger, but the best I can do. +hook global BufCreate .*\.ledger %{ + set-option buffer filetype ledger +} + +# Initialization +# -------------- + +hook global WinSetOption filetype=ledger %{ + require-module ledger + + hook window InsertChar \n -group ledger-indent ledger-indent-on-new-line + hook window ModeChange pop:insert:.* -group ledger-trim-indent ledger-trim-indent + + hook -once -always window WinSetOption filetype=.* %{ + remove-hooks window ledger-.+ + unset-option window static_words # Remove static completion + } +} + +hook -group ledger-highlight global WinSetOption filetype=ledger %{ + add-highlighter window/ledger ref ledger + hook -once -always window WinSetOption filetype=.* %{ + remove-highlighter window/ledger + } +} + +# Completion +# ---------- + +hook -group ledger-complete global WinSetOption filetype=ledger %{ + set-option window static_words account note alias payee check assert eval \ + default apply fixed bucket capture comment commodity format nomarket \ + define end include tag test year +} + +provide-module ledger %[ + +# Highlighters +# ------------ +# +# TODO: highlight tag comments + +add-highlighter shared/ledger regions + +# The following highlighters implement +# https://www.ledger-cli.org/3.0/doc/ledger3.html#Transactions-and-Comments + +add-highlighter shared/ledger/transaction region '^[0-9]' '^(?=\H)' group +add-highlighter shared/ledger/transaction/first_line regex \ + '^([0-9].*?)\h.*?(( +|\t+);.*?)?$' 1:function 2:string +add-highlighter shared/ledger/transaction/posting regex \ + '^\h+([^\h;].*?)(( +|\t+).*?)?(( +|\t+);.*?)?$' 1:type 2:value 4:string +add-highlighter shared/ledger/transaction/note regex '^\h+;[^$]*?$' 0:string + +add-highlighter shared/ledger/comment region '^(;|#|%|\||\*)' '$' fill comment + +# TODO: Improve +add-highlighter shared/ledger/other region '^(P|=|~)' '$' fill meta + +# The following highlighters implement +# https://www.ledger-cli.org/3.0/doc/ledger3.html#Command-Directives + +add-highlighter shared/ledger/default default-region group + +# Add highlighters for simple one-line command directives +evaluate-commands %sh{ + # TODO: Is `expr` also a command directive? The documentation confuses me. + for cmd in 'apply account' 'apply fixed' 'assert' 'bucket' 'check' 'end' \ + 'include' 'apply tag' 'test' 'year'; do + echo "add-highlighter shared/ledger/default/ regex '^${cmd}\b' 0:function" + done +} + +add-highlighter shared/ledger/account region '^account' '^(?=\H)' group +add-highlighter shared/ledger/account/first_line regex '^account' 0:function +add-highlighter shared/ledger/account/note regex '^\h*note' 0:function +add-highlighter shared/ledger/account/alias regex '^\h*alias' 0:function +add-highlighter shared/ledger/account/payee regex '^\h*payee' 0:function +add-highlighter shared/ledger/account/check regex '^\h*check' 0:function +add-highlighter shared/ledger/account/assert regex '^\h*assert' 0:function +add-highlighter shared/ledger/account/eval regex '^\h*eval' 0:function +add-highlighter shared/ledger/account/default regex '^\h*default' 0:function + +add-highlighter shared/ledger/alias region '^alias' '$' group +add-highlighter shared/ledger/alias/keyword regex '^alias' 0:function +add-highlighter shared/ledger/alias/key regex '^alias\h([^$=]*)=?' 1:variable +add-highlighter shared/ledger/alias/value regex '^alias\h.*?=(.*?)$' 1:value + +add-highlighter shared/ledger/capture region '^capture' '$' group +add-highlighter shared/ledger/capture/keyword regex '^capture' 0:function +add-highlighter shared/ledger/capture/account regex \ + '^capture\h+(.*?)( +|\t+|$)' 1:type +add-highlighter shared/ledger/capture/regex regex \ + '^capture\h+.*?( +|\t+)(.*?)$' 2:value + +add-highlighter shared/ledger/comment_block region '^comment' '^end comment' \ + fill comment + +add-highlighter shared/ledger/commodity region '^commodity' '^(?=\H)' group +add-highlighter shared/ledger/commodity/first_line regex '^commodity' 0:function +add-highlighter shared/ledger/commodity/note regex '^\h*note' 0:function +add-highlighter shared/ledger/commodity/format regex '^\h*format' 0:function +add-highlighter shared/ledger/commodity/nomarket regex '^\h*nomarket' 0:function +add-highlighter shared/ledger/commodity/alias regex '^\h*alias' 0:function +add-highlighter shared/ledger/commodity/default regex '^\h*default' 0:function + +add-highlighter shared/ledger/define region '^define' '$' group +add-highlighter shared/ledger/define/keyword regex '^define' 0:function +add-highlighter shared/ledger/define/key regex '^define\h([^$=]*)=?' 1:variable +add-highlighter shared/ledger/define/value regex '^define\h.*?=(.*?)$' 1:value + +add-highlighter shared/ledger/payee region '^payee' '^(?=\H)' group +add-highlighter shared/ledger/payee/first_line regex '^payee' 0:function +add-highlighter shared/ledger/payee/alias regex '^\h*alias' 0:function +add-highlighter shared/ledger/payee/uuid regex '^\h*uuid' 0:function + +add-highlighter shared/ledger/tag region '^tag' '^(?=\H)' group +add-highlighter shared/ledger/tag/first_line regex '^tag' 0:function +add-highlighter shared/ledger/tag/check regex '^\h*check' 0:function +add-highlighter shared/ledger/tag/assert regex '^\h*assert' 0:function + +# Commands +# -------- + +define-command -hidden ledger-indent-on-new-line %[ + evaluate-commands -draft -itersel %[ + # preserve previous line indent + try %[ execute-keys -draft <semicolon> K <a-&> ] + # cleanup trailing whitespaces from previous line + try %[ execute-keys -draft k x s \h+$ <ret> d ] + # indent after the first line of a transaction + try %[ execute-keys -draft kx <a-k>^[0-9]<ret> j<a-gt> ] + ] +] + +define-command -hidden ledger-trim-indent %{ + try %{ execute-keys -draft <semicolon> x s ^\h+$ <ret> d } +} + +] diff --git a/autoload/filetype/lisp.kak b/autoload/filetype/lisp.kak new file mode 100644 index 0000000..d018e78 --- /dev/null +++ b/autoload/filetype/lisp.kak @@ -0,0 +1,81 @@ +# http://common-lisp.net +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](lisp) %{ + set-option buffer filetype lisp +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=lisp %{ + require-module lisp + + hook window ModeChange pop:insert:.* -group lisp-trim-indent lisp-trim-indent + hook window InsertChar \n -group lisp-indent lisp-indent-on-new-line + set-option buffer extra_word_chars '_' '+' '-' '*' '/' '@' '$' '%' '^' '&' '_' '=' '<' '>' '~' '.' + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window lisp-.+ } +} + +hook -group lisp-highlight global WinSetOption filetype=lisp %{ + add-highlighter window/lisp ref lisp + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/lisp } +} + +provide-module lisp %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/lisp regions +add-highlighter shared/lisp/code default-region group +add-highlighter shared/lisp/string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/lisp/comment region ';' '$' fill comment + +add-highlighter shared/lisp/code/ regex (#?(['`:]|,@?))?\b[a-zA-Z][\w!$%&*+./:<=>?@^_~-]* 0:variable +add-highlighter shared/lisp/code/ regex \b(nil|true|false)\b 0:value +add-highlighter shared/lisp/code/ regex (((\Q***\E)|(///)|(\Q+++\E)){1,3})|(1[+-])|(<|>|<=|=|>=) 0:operator +add-highlighter shared/lisp/code/ regex \b(def[a-z]+|if|do|let|lambda|catch|and|assert|while|def|do|fn|finally|let|loop|new|quote|recur|set!|throw|try|var|case|if-let|if-not|when|when-first|when-let|when-not|(cond(->|->>)?))\b 0:keyword +add-highlighter shared/lisp/code/ regex \*[a-zA-Z][\w!$%&*+./:<=>?@^_~-]*\* 0:variable +add-highlighter shared/lisp/code/ regex (\b\d+)?\.\d+([eEsSfFdDlL]\d+)?\b 0:value + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden lisp-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +declare-option \ + -docstring 'regex matching the head of forms which have options *and* indented bodies' \ + regex lisp_special_indent_forms \ + '(?:def.*|if(-.*|)|let.*|lambda|with-.*|when(-.*|))' + +define-command -hidden lisp-indent-on-new-line %{ + # registers: i = best align point so far; w = start of first word of form + evaluate-commands -draft -save-regs '/"|^@iw' -itersel %{ + execute-keys -draft 'gk"iZ' + try %{ + execute-keys -draft '[bl"i<a-Z><gt>"wZ' + + try %{ + # If a special form, indent another (indentwidth - 1) spaces + execute-keys -draft '"wze<a-k>\A' %opt{lisp_special_indent_forms} '\z<ret>' + execute-keys -draft '"wze<a-L>s.{' %sh{printf $(( kak_opt_indentwidth - 1 ))} '}\K.*<ret><a-;>;"i<a-Z><gt>' + } catch %{ + # If not "special" form and parameter appears on line 1, indent to parameter + execute-keys -draft '"wz<a-K>[()\[\]{}]<ret>e<a-l>s\h\K[^\s].*<ret><a-;>;"i<a-Z><gt>' + } + } + try %{ execute-keys -draft '[rl"i<a-Z><gt>' } + try %{ execute-keys -draft '[Bl"i<a-Z><gt>' } + execute-keys -draft ';"i<a-z>a&,' + } +} + +} diff --git a/autoload/filetype/lua.kak b/autoload/filetype/lua.kak new file mode 100644 index 0000000..d08edd1 --- /dev/null +++ b/autoload/filetype/lua.kak @@ -0,0 +1,152 @@ +# http://lua.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](lua|rockspec) %{ + set-option buffer filetype lua +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=lua %{ + require-module lua + + hook window ModeChange pop:insert:.* -group lua-trim-indent lua-trim-indent + hook window InsertChar .* -group lua-indent lua-indent-on-char + hook window InsertChar \n -group lua-indent lua-indent-on-new-line + hook window InsertChar \n -group lua-insert lua-insert-on-new-line + + alias window alt lua-alternative-file + + hook -once -always window WinSetOption filetype=.* %{ + remove-hooks window lua-.+ + unalias window alt lua-alternative-file + } +} + +hook -group lua-highlight global WinSetOption filetype=lua %{ + add-highlighter window/lua ref lua + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/lua } +} + + +provide-module lua %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/lua regions +add-highlighter shared/lua/code default-region group +add-highlighter shared/lua/raw_string region -match-capture '\[(=*)\[' '\](=*)\]' fill string +add-highlighter shared/lua/raw_comment region -match-capture '--\[(=*)\[' '\](=*)\]' fill comment +add-highlighter shared/lua/double_string region '"' (?<!\\)(?:\\\\)*" fill string +add-highlighter shared/lua/single_string region "'" (?<!\\)(?:\\\\)*' fill string +add-highlighter shared/lua/comment region '--' $ fill comment + +add-highlighter shared/lua/code/variable regex \b\w*\b 0:variable # Everything in Lua is a variable! +add-highlighter shared/lua/code/function_declaration regex \b(?:function\h+)(?:\w+\h*\.\h*)*([a-zA-Z_]\w*)\( 1:function +add-highlighter shared/lua/code/function_call regex \b([a-zA-Z_]\w*)\h*(?=[\(\{]) 1:function +add-highlighter shared/lua/code/keyword regex \b(break|do|else|elseif|end|for|function|goto|if|in|local|repeat|return|then|until|while)\b 0:keyword +add-highlighter shared/lua/code/value regex \b(false|nil|true|self|[0-9]+(:?\.[0-9])?(:?[eE]-?[0-9]+)?|0x[0-9a-fA-F])\b 0:value +add-highlighter shared/lua/code/symbolic_operator regex (\+|-|\*|/|%|\^|==?|~=|<=?|>=?|\.\.|\.\.\.|#) 0:operator +add-highlighter shared/lua/code/keyword_operator regex \b(and|or|not)\b 0:operator +add-highlighter shared/lua/code/module regex \b(_G|_ENV)\b 0:module +add-highlighter shared/lua/code/attribute regex \B(<[a-zA-Z_]\w*>)\B 0:attribute +add-highlighter shared/lua/code/label regex \s(::\w*::) 1:meta +add-highlighter shared/lua/code/goto_label regex "\bgoto (\w*)\b" 1:meta + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command lua-alternative-file -docstring 'Jump to the alternate file (implementation ↔ test)' %{ evaluate-commands %sh{ + case $kak_buffile in + *spec/*_spec.lua) + altfile=$(eval printf %s\\n $(printf %s\\n $kak_buffile | sed s+spec/+'*'/+';'s/_spec//)) + [ ! -f $altfile ] && echo "fail 'implementation file not found'" && exit + ;; + *.lua) + altfile="" + altdir="" + path=$kak_buffile + dirs=$(while [ $path ]; do printf %s\\n $path; path=${path%/*}; done | tail -n +2) + for dir in $dirs; do + altdir=$dir/spec + if [ -d $altdir ]; then + altfile=$altdir/$(realpath $kak_buffile --relative-to $dir | sed s+[^/]'*'/++';'s/.lua$/_spec.lua/) + break + fi + done + [ ! -d "$altdir" ] && echo "fail 'spec/ not found'" && exit + ;; + *) + echo "fail 'alternative file not found'" && exit + ;; + esac + printf %s\\n "edit $altfile" +}} + +define-command -hidden lua-trim-indent %[ + # remove trailing whitespaces + try %[ execute-keys -draft -itersel x s \h+$ <ret> d ] +] + +define-command -hidden lua-indent-on-char %[ + evaluate-commands -no-hooks -draft -itersel %[ + # unindent middle and end structures + try %[ execute-keys -draft \ + <a-h><a-k>^\h*(\b(end|else|elseif|until)\b|[)}])$<ret> \ + :lua-indent-on-new-line<ret> \ + <a-lt> + ] + ] +] + +define-command -hidden lua-indent-on-new-line %[ + evaluate-commands -no-hooks -draft -itersel %[ + # remove trailing white spaces from previous line + try %[ execute-keys -draft k : lua-trim-indent <ret> ] + # preserve previous non-empty line indent + try %[ execute-keys -draft ,gh<a-?>^[^\n]+$<ret>s\A|.\z<ret>)<a-&> ] + # add one indentation level if the previous line is not a comment and: + # - starts with a block keyword that is not closed on the same line, + # - or contains an unclosed function expression, + # - or ends with an enclosed '(' or '{' + try %[ execute-keys -draft \ + , Kx \ + <a-K>\A\h*--<ret> \ + <a-K>\A[^\n]*\b(end|until)\b<ret> \ + <a-k>\A(\h*\b(do|else|elseif|for|function|if|repeat|while)\b|[^\n]*[({]$|[^\n]*\bfunction\b\h*[(])<ret> \ + <a-:><semicolon><a-gt> + ] + ] +] + +define-command -hidden lua-insert-on-new-line %[ + evaluate-commands -no-hooks -draft -itersel %[ + # copy -- comment prefix and following white spaces + try %[ execute-keys -draft kxs^\h*\K--\h*<ret> y gh j x<semicolon> P ] + # wisely add end structure + evaluate-commands -save-regs x %[ + # save previous line indent in register x + try %[ execute-keys -draft kxs^\h+<ret>"xy ] catch %[ reg x '' ] + try %[ + # check that starts with a block keyword that is not closed on the same line + execute-keys -draft \ + kx \ + <a-k>^\h*\b(else|elseif|do|for|function|if|while)\b|[^\n]\bfunction\b\h*[(]<ret> \ + <a-K>\bend\b<ret> + # check that the block is empty and is not closed on a different line + execute-keys -draft <a-a>i <a-K>^[^\n]+\n[^\n]+\n<ret> jx <a-K>^<c-r>x\b(else|elseif|end)\b<ret> + # auto insert end + execute-keys -draft o<c-r>xend<esc> + # auto insert ) for anonymous function + execute-keys -draft kx<a-k>\([^)\n]*function\b<ret>jjA)<esc> + ] + ] + ] +] + +§ diff --git a/autoload/filetype/mail.kak b/autoload/filetype/mail.kak new file mode 100644 index 0000000..b6ef616 --- /dev/null +++ b/autoload/filetype/mail.kak @@ -0,0 +1,30 @@ +hook global BufCreate .+\.eml %{ + set-option buffer filetype mail +} + +hook global WinSetOption filetype=mail %{ + require-module mail + map buffer normal <ret> :diff-jump<ret> + hook -once -always window WinSetOption filetype=.* %{ + unmap buffer normal <ret> :diff-jump<ret> + } +} + +hook -group mail-highlight global WinSetOption filetype=mail %{ + add-highlighter window/mail ref mail + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/mail } +} + + +provide-module mail %{ + +require-module diff + +add-highlighter shared/mail group +add-highlighter shared/mail/ ref diff +add-highlighter shared/mail/ regex ^(From|To|Cc|Bcc|Subject|Reply-To|In-Reply-To|References|Date|Message-Id|User-Agent):([^\n]*(?:\n\h+[^\n]+)*)$ 1:keyword 2:attribute +add-highlighter shared/mail/ regex <[a-zA-Z0-9!#$%&'*+/=?^`{|}~.-]+@[a-zA-Z0-9!#$%&'*+/=?^`{|}~.-]+> 0:string +add-highlighter shared/mail/ regex ^>.*?$ 0:comment +add-highlighter shared/mail/ regex ^--\ \n.* 0:comment + +} diff --git a/autoload/filetype/makefile.kak b/autoload/filetype/makefile.kak new file mode 100644 index 0000000..c668d69 --- /dev/null +++ b/autoload/filetype/makefile.kak @@ -0,0 +1,75 @@ +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*(/?[mM]akefile|\.mk|\.make) %{ + set-option buffer filetype makefile +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=makefile %{ + require-module makefile + + set-option window static_words %opt{makefile_static_words} + + hook window ModeChange pop:insert:.* -group makefile-trim-indent makefile-trim-indent + hook window InsertChar \n -group makefile-indent makefile-indent-on-new-line + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window makefile-.+ } +} + +hook -group makefile-highlight global WinSetOption filetype=makefile %{ + add-highlighter window/makefile ref makefile + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/makefile } +} + +provide-module makefile %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/makefile regions + +add-highlighter shared/makefile/content default-region group +add-highlighter shared/makefile/comment region (?<!\\)(?:\\\\)*(?:^|\h)\K# '$' fill comment +add-highlighter shared/makefile/evaluate-commands region -recurse \( (?<!\$)(?:\$\$)*\K\$\( \) fill value + +add-highlighter shared/makefile/content/ regex ^\S.*?(::|:|!)\s 0:variable +add-highlighter shared/makefile/content/ regex [+?:]= 0:operator + +evaluate-commands %sh{ + # Grammar + keywords="ifeq|ifneq|ifdef|ifndef|else|endif|define|endef" + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list makefile_static_words ${keywords}" | tr '|' ' ' + + # Highlight keywords + printf %s "add-highlighter shared/makefile/content/ regex \b(${keywords})\b 0:keyword" +} + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden makefile-trim-indent %{ + evaluate-commands -no-hooks -draft -itersel %{ + execute-keys x + # remove trailing white spaces + try %{ execute-keys -draft s \h + $ <ret> d } + } +} + +define-command -hidden makefile-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon>K<a-&> } + ## If the line above is a target indent with a tab + try %{ execute-keys -draft Z kx <a-k>^\S.*?(::|:|!)\s<ret> z i<tab> } + # cleanup trailing white space son previous line + try %{ execute-keys -draft kx s \h+$ <ret>d } + # indent after some keywords + try %{ execute-keys -draft Z kx <a-k> ^\h*(ifeq|ifneq|ifdef|ifndef|else|define)\b<ret> z <a-gt> } + } +} + +} diff --git a/autoload/filetype/markdown.kak b/autoload/filetype/markdown.kak new file mode 100644 index 0000000..b515909 --- /dev/null +++ b/autoload/filetype/markdown.kak @@ -0,0 +1,130 @@ +# http://daringfireball.net/projects/markdown +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](markdown|md|mkd) %{ + set-option buffer filetype markdown +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=markdown %{ + require-module markdown + + hook window ModeChange pop:insert:.* -group markdown-trim-indent markdown-trim-indent + hook window InsertChar \n -group markdown-insert markdown-insert-on-new-line + hook window InsertChar \n -group markdown-indent markdown-indent-on-new-line + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window markdown-.+ } +} + +hook -group markdown-load-languages global WinSetOption filetype=markdown %{ + markdown-load-languages '%' +} + +hook -group markdown-load-languages global WinSetOption filetype=markdown %{ + hook -group markdown-load-languages window NormalIdle .* %{markdown-load-languages gtGbGl} + hook -group markdown-load-languages window InsertIdle .* %{markdown-load-languages gtGbGl} +} + + +hook -group markdown-highlight global WinSetOption filetype=markdown %{ + add-highlighter window/markdown ref markdown + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/markdown } +} + + +provide-module markdown %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/markdown regions +add-highlighter shared/markdown/inline default-region regions +add-highlighter shared/markdown/inline/text default-region group + +add-highlighter shared/markdown/listblock region ^\h*[-*]\s ^(?=\S) regions +add-highlighter shared/markdown/listblock/g default-region group +add-highlighter shared/markdown/listblock/g/ ref markdown/inline +add-highlighter shared/markdown/listblock/g/marker regex ^\h*([-*])\s 1:bullet + +add-highlighter shared/markdown/codeblock region -match-capture \ + ^(\h*)```\h* \ + ^(\h*)```\h*$ \ + regions +add-highlighter shared/markdown/codeblock/ default-region fill meta +add-highlighter shared/markdown/listblock/codeblock region -match-capture \ + ^(\h*)```\h* \ + ^(\h*)```\h*$ \ + regions +add-highlighter shared/markdown/listblock/codeblock/ default-region fill meta +add-highlighter shared/markdown/codeline region "^( {4}|\t)" "$" fill meta + +# https://spec.commonmark.org/0.29/#link-destination +add-highlighter shared/markdown/angle_bracket_url region (?<=<)([a-z]+://|(mailto|magnet|xmpp):) (?!\\).(?=>)|\n fill link +add-highlighter shared/markdown/inline/url region -recurse \( (\b[a-z]+://|(mailto|magnet|xmpp):) (?!\\).(?=\))|\s fill link +add-highlighter shared/markdown/listblock/angle_bracket_url region (?<=<)(\b[a-z]+://|(mailto|magnet|xmpp):) (?!\\).(?=>)|\n fill link + +try %{ + require-module html + add-highlighter shared/markdown/inline/tag region (?i)</?[a-z][a-z0-9-]*\s*([a-z_:]|(?=>)) > ref html/tag +} + +add-highlighter shared/markdown/inline/code region -match-capture (`+) (`+) fill mono + +# Setext-style header +add-highlighter shared/markdown/inline/text/ regex (\A|^\n)[^\n]+\n={2,}\h*\n\h*$ 0:title +add-highlighter shared/markdown/inline/text/ regex (\A|^\n)[^\n]+\n-{2,}\h*\n\h*$ 0:header + +# Atx-style header +add-highlighter shared/markdown/inline/text/ regex ^#[^\n]* 0:header + +add-highlighter shared/markdown/inline/text/ regex (?<!\*)(\*([^\s*]|([^\s*](\n?[^\n*])*[^\s*]))\*)(?!\*) 1:+i +add-highlighter shared/markdown/inline/text/ regex (?<!_)(_([^\s_]|([^\s_](\n?[^\n_])*[^\s_]))_)(?!_) 1:+i +add-highlighter shared/markdown/inline/text/ regex (?<!\*)(\*\*([^\s*]|([^\s*](\n?[^\n*])*[^\s*]))\*\*)(?!\*) 1:+b +add-highlighter shared/markdown/inline/text/ regex (?<!_)(__([^\s_]|([^\s_](\n?[^\n_])*[^\s_]))__)(?!_) 1:+b +add-highlighter shared/markdown/inline/text/ regex ^\h*(>\h*)+ 0:comment +add-highlighter shared/markdown/inline/text/ regex "\H( {2,})$" 1:+r@meta + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command markdown-load-languages -params 1 %{ + evaluate-commands -draft %{ try %{ + execute-keys "%arg{1}1s```\h*\{?[.=]?(\w+)\}?<ret>" + evaluate-commands -itersel %{ try %{ + require-module %val{selection} + add-highlighter "shared/markdown/codeblock/%val{selection}" region -match-capture "^(\h*)```\h*(%val{selection}\b|\{[.=]?%val{selection}\})" ^(\h*)``` regions + add-highlighter "shared/markdown/codeblock/%val{selection}/" default-region fill meta + add-highlighter "shared/markdown/codeblock/%val{selection}/inner" region \A\h*```[^\n]*\K (?=```) ref %val{selection} + add-highlighter "shared/markdown/listblock/codeblock/%val{selection}" region -match-capture "^(\h*)```\h*(%val{selection}\b|\{[.=]?%val{selection}\})" ^(\h*)``` regions + add-highlighter "shared/markdown/listblock/codeblock/%val{selection}/" default-region fill meta + add-highlighter "shared/markdown/listblock/codeblock/%val{selection}/inner" region \A\h*```[^\n]*\K (?=```) ref %val{selection} + }} + }} +} + +define-command -hidden markdown-trim-indent %{ + evaluate-commands -no-hooks -draft -itersel %{ + execute-keys x + # remove trailing white spaces + try %{ execute-keys -draft s \h + $ <ret> d } + } +} + +define-command -hidden markdown-insert-on-new-line %{ + try %{ execute-keys -draft -itersel k x s ^\h*\K((>\h*)+([*+-]\h)?|(>\h*)*[*+-]\h)\h* <ret> y gh j P } +} + +define-command -hidden markdown-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # remove trailing white spaces + try %{ execute-keys -draft k x s \h+$ <ret> d } + } +} + +} diff --git a/autoload/filetype/mercurial.kak b/autoload/filetype/mercurial.kak new file mode 100644 index 0000000..255b02b --- /dev/null +++ b/autoload/filetype/mercurial.kak @@ -0,0 +1,37 @@ +# https://www.mercurial-scm.org/ +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*hg-editor-.*\.txt$ %{ + set-option buffer filetype hg-commit +} + +hook global WinSetOption filetype=hg-commit %{ + require-module hg-commit +} + +hook -group hg-commit-highlight global WinSetOption filetype=hg-commit %{ + add-highlighter window/hg-commit ref hg-commit + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/hg-commit-highlight } +} + +provide-module hg-commit %{ + +# Faces +# ‾‾‾‾‾ + +set-face global MercurialCommitComment cyan + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/hg-commit regions +add-highlighter shared/hg-commit/comments region ^HG:\ $ group +add-highlighter shared/hg-commit/comments/ fill comment +add-highlighter shared/hg-commit/comments/ regex \ + "\b(?:(changed)|(removed)|(added)|(bookmark)|(branch)|(user:)) ([^\n]*)$" \ + 1:yellow 2:red 3:green 4:blue 5:magenta 6:white + +} diff --git a/autoload/filetype/mercury.kak b/autoload/filetype/mercury.kak new file mode 100644 index 0000000..813b4ca --- /dev/null +++ b/autoload/filetype/mercury.kak @@ -0,0 +1,124 @@ +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](m) %{ + set-option buffer filetype mercury +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=mercury %{ + require-module mercury + + set-option window static_words %opt{mercury_static_words} + + hook window InsertChar \n -group mercury-insert mercury-insert-on-new-line + hook window InsertChar \n -group mercury-indent mercury-indent-on-new-line + # cleanup trailing whitespaces on current line insert end + hook window ModeChange pop:insert:.* -group mercury-trim-indent %{ try %{ execute-keys -draft <semicolon> x s ^\h+$ <ret> d } } + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window mercury-.+ } +} + +hook -group mercury-highlight global WinSetOption filetype=mercury %{ + add-highlighter window/mercury ref mercury + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/mercury } +} + + +provide-module mercury %§ + + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/mercury regions +add-highlighter shared/mercury/code default-region group +add-highlighter shared/mercury/comment region '%' '$' fill comment +add-highlighter shared/mercury/line_comment region '%' '$' fill comment + +add-highlighter shared/mercury/string region '"' (?<!\\)(\\\\)*" fill string +# Integer formats +add-highlighter shared/mercury/code/ regex '\b0b[01]+\b' 0:value +add-highlighter shared/mercury/code/ regex '\b0x[\da-f]+\b' 0:value +add-highlighter shared/mercury/code/ regex '\b0o?[0-7]+\b' 0:value +add-highlighter shared/mercury/code/ regex '\b([1-9]\d*|0)(i8|i16|i32|i64|u|u8|u16|u32|u64)?\b' 0:value +# Float formats +add-highlighter shared/mercury/code/ regex '\b(\d+_\d+)*\d+[eE][+-]?\d+(\d+_\d+)*\b' 0:value +add-highlighter shared/mercury/code/ regex '(\b\d+)\.\d+\b' 0:value +add-highlighter shared/mercury/code/ regex '`[A-Za-z][A-Za-z_0-9]+`' 0:operator + +add-highlighter shared/mercury/code/ regex \b[a-z][A-Za-z_0-9]*(?=\.\w) 0:module +add-highlighter shared/mercury/code/ regex \b[a-z][A-Za-z_0-9]*(?=__\w) 0:module +# func() and pred() +add-highlighter shared/mercury/code/ regex \b(pred|func)(?=\() 0:builtin +add-highlighter shared/mercury/code/ regex \b[A-Z][A-Za-z_0-9]*\b 0:variable + +# operator symbols +add-highlighter shared/mercury/code/ regex (\.|!|!\.|!:|@|\^|:|\*\*|\\|\*|/|//|<<|>>|\+|\+\+|-|--|/\\|\\/|\.\.|:=|=\^|<|=|=\.\.|=:=|=<|==|=\\=|>|>=|@<|@=<|@>|@>=|\\=|\\==|~=|\\\+|~|<=|<=>|=>|,|&|->|\;|::|==>|--->|-->|:-|\?-) 0:operator + +evaluate-commands %sh{ + # Grammar + values="true fail" + + # There is overlap between all of these. Not sure what to do about that. + operators="event div mod rem for is and or impure semipure not when all arbitrary atomic disable_warning disable_warnings promise_equivalent_solutions promise_equivalent_solution_setspromise_exclusive promise_exclusive_exhaustive promise_exhaustive promise_impure promise_pure promise_semipure require_complete_switch require_switch_arms_det require_switch_arms_semidet require_switch_arms_multi require_switch_arms_nondet require_switch_arms_cc_multi require_switch_arms_cc_nondet require_switch_arms_erroneous require_switch_arms_failure require_det require_semidet require_multi require_nondet require_cc_multi require_cc_nondet require_erroneous require_failure trace try some or_else then if else where catch catch_any initialize finalize rule solver type pred func inst mode typeclass instance pragma promise initialise finalise mutable module import_module use_module include_module" + modes="free bound in out di mdi uo muo" + determinisms="erroneous failure det semidet multi cc_multi nondet cc_nondet" + reserved_insts="any bound bound_unique clobbered clobbered_any free ground is mostly_clobbered mostly_unique mostly_unique_any not_reached unique unique_any" + reserved_modes="any_func any_pred func is pred" + reserved_types="int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 float character string pred func pure semipure impure" + + declarations="type solver type pred func inst mode typeclass instance pragma promise initialise finalise mutable module interface implementation import_module use_module include_module end_module" + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list mercury_static_words $(join "${values} ${declarations} ${operators} ${determinisms} ${modes} ${reserved_insts} ${reserved_modes}" ' ')" + + # Highlight keywords + printf %s " + add-highlighter shared/mercury/code/ regex '\b($(join "${values}" '|'))\b' 0:value + add-highlighter shared/mercury/code/ regex '^:-(\s+($(join "${declarations}" '|')))+\b' 1:keyword + add-highlighter shared/mercury/code/ regex '\b($(join "${operators}" '|'))\b' 0:operator + add-highlighter shared/mercury/code/ regex '\b($(join "${determinisms}" '|'))\b' 0:keyword + add-highlighter shared/mercury/code/ regex '\b($(join "${modes}" '|'))\b' 0:keyword + + # These overlap with previous. Not sure what the solution is. + # add-highlighter shared/mercury/code/ regex '\b($(join "${reserved_types}" '|'))\b' 0:type + # add-highlighter shared/mercury/code/ regex '\b($(join "${reserved_insts}" '|'))\b' 0:builtin + # add-highlighter shared/mercury/code/ regex '\b($(join "${reserved_modes}" '|'))\b' 0:builtin + + # Implementation-defined literals - don't know how to get these to work + # add-highlighter shared/mercury/code/ regex '\$(file|line|module|pred)' 0:keyword + " +} + +define-command -hidden mercury-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy '%' comment prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\%\h* <ret> y gh j P } + } +} + +define-command -hidden mercury-indent-on-char %< + evaluate-commands -draft -itersel %< + # align closer token to its opener when alone on a line + try %/ execute-keys -draft <a-h> <a-k> ^\h+[]}]$ <ret> m s \A|.\z <ret> 1<a-&> / + > +> + +define-command -hidden mercury-indent-on-new-line %< + evaluate-commands -draft -itersel %< + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # cleanup trailing whitespaces from previous line + try %{ execute-keys -draft k x s \h+$ <ret> d } + # indent after line ending with :- + try %{ execute-keys -draft , k x <a-k> :-$ <ret> j <a-gt> } + # deindent closing brace/bracket when after cursor + try %< execute-keys -draft x <a-k> ^\h*[}\])] <ret> gh / [}\])] <ret> m <a-S> 1<a-&> > + > +> + +§ diff --git a/autoload/filetype/meson.kak b/autoload/filetype/meson.kak new file mode 100644 index 0000000..362af32 --- /dev/null +++ b/autoload/filetype/meson.kak @@ -0,0 +1,77 @@ +# meson syntax highlighting for kakoune (https://mesonbuild.com) +# +# For reference see: +# https://mesonbuild.com/Syntax.html +# https://github.com/mesonbuild/meson/blob/master/data/syntax-highlighting/vim/syntax/meson.vim + +## Detection + +hook global BufCreate (.*/|^)(meson\.build|meson_options\.txt) %{ + set-option buffer filetype meson +} + +## Initialization + +hook -group meson-highlight global WinSetOption filetype=meson %{ + require-module meson + + set-option window static_words %opt{meson_static_words} + + add-highlighter window/meson ref meson + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/meson } +} + +provide-module meson %§ + +## Highlighters + +add-highlighter shared/meson regions +add-highlighter shared/meson/code default-region group + +add-highlighter shared/meson/comment region '(\h|^)#' '$' fill comment + +# TODO: highlight escape sequences within strings +add-highlighter shared/meson/string_multiline region "'''" "'''" fill string +add-highlighter shared/meson/string_single region "'" (?<!\\)(\\\\)*' fill string + +# integer literals +add-highlighter shared/meson/code/ regex '\b\d+\b' 0:value + +# operators +add-highlighter shared/meson/code/ regex '(?:\+|-|\*|/|%|!=|=|<|>|\?|:)' 0:operator +add-highlighter shared/meson/code/ regex '\b(?:and|not|or|in)\b' 0:operator + +# functions +add-highlighter shared/meson/code/ regex "\b(\w+)\(" 1:function + +evaluate-commands %sh{ + values="true false" + + keywords="if else endif elif foreach endforeach break continue" + + builtins="add_global_arguments add_global_link_arguments add_languages + add_project_arguments add_project_link_arguments add_test_setup + alias_target assert benchmark both_libraries build_machine build_target + configuration_data configure_file custom_target declare_dependency + dependency disabler environment error executable files find_library + find_program generator get_option get_variable gettext host_machine + import include_directories install_data install_headers install_man + install_subdir is_disabler is_variable jar join_paths library meson + message option project run_command run_target set_variable shared_library + shared_module static_library subdir subdir_done subproject summary + target_machine test vcs_tag warning" + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list meson_static_words $(join "${values} ${keywords} ${builtins}" ' ')" + + # Highlight keywords + printf %s " + add-highlighter shared/meson/code/ regex '\b($(join "${values}" '|'))\b' 0:value + add-highlighter shared/meson/code/ regex '\b($(join "${keywords}" '|'))\b' 0:keyword + add-highlighter shared/meson/code/ regex '\b($(join "${builtins}" '|'))\b\(' 1:builtin + " +} + +§ diff --git a/autoload/filetype/mlb.kak b/autoload/filetype/mlb.kak new file mode 100644 index 0000000..aa17423 --- /dev/null +++ b/autoload/filetype/mlb.kak @@ -0,0 +1,50 @@ +# http://mlton.org/MLBasis +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*\.mlb %{ + set-option buffer filetype mlb +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=mlb %{ + require-module mlb + set-option buffer extra_word_chars '_' '-' '.' + set-option window static_words %opt{mlb_static_words} +} + +hook -group mlb-highlight global WinSetOption filetype=mlb %{ + add-highlighter window/mlb ref mlb + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/mlb } +} + +provide-module mlb %[ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/mlb regions +add-highlighter shared/mlb/code default-region group +add-highlighter shared/mlb/string region '"' '(?<!\\)(\\\\)*"' group +add-highlighter shared/mlb/string/fill fill string +add-highlighter shared/mlb/comment region -recurse '\(\*' '\(\*' '\*\)' fill comment + +evaluate-commands %sh{ + keywords='basis bas and open local let in end structure signature functor ann' + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + printf %s\\n "declare-option str-list mlb_static_words $(join "${keywords}" ' ')" + printf %s\\n "add-highlighter shared/mlb/code/ regex (?<![\w'-/.])($(join "${keywords}" '|'))(?![\w'-/.]) 0:keyword" +} +add-highlighter shared/mlb/code/ regex "=" 0:operator +add-highlighter shared/mlb/code/ regex "\b([A-Z][\w']*)\b" 0:type +add-highlighter shared/mlb/code/ regex "\b[A-Z]{2}[A-Z0-9_']+\b" 0:attribute +add-highlighter shared/mlb/code/ regex "\$\(\w+\)" 0:variable +add-highlighter shared/mlb/string/ regex "\$\(\w*\)" 0:variable + +] diff --git a/autoload/filetype/moon.kak b/autoload/filetype/moon.kak new file mode 100644 index 0000000..43d8dd4 --- /dev/null +++ b/autoload/filetype/moon.kak @@ -0,0 +1,120 @@ +# http://moonscript.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](moon) %{ + set-option buffer filetype moon +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=moon %{ + require-module moon + + hook window ModeChange pop:insert:.* -group moon-trim-indent moon-trim-indent + hook window InsertChar .* -group moon-indent moon-indent-on-char + hook window InsertChar \n -group moon-insert moon-insert-on-new-line + hook window InsertChar \n -group moon-indent moon-indent-on-new-line + + alias window alt moon-alternative-file + + hook -once -always window WinSetOption filetype=.* %{ + remove-hooks window moon-.+ + unalias window alt moon-alternative-file + } +} + +hook -group moon-highlight global WinSetOption filetype=moon %{ + add-highlighter window/moon ref moon + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/moon } +} + + +provide-module moon %[ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/moon regions +add-highlighter shared/moon/code default-region group +add-highlighter shared/moon/double_string region '"' (?<!\\)(\\\\)*" regions +add-highlighter shared/moon/single_string region "'" (?<!\\)(\\\\)*' fill string +add-highlighter shared/moon/comment region '--' '$' fill comment + +add-highlighter shared/moon/double_string/base default-region fill string +add-highlighter shared/moon/double_string/interpolation region -recurse \{ \Q#{ \} fill meta + +add-highlighter shared/moon/code/ regex ([.\\](?=[A-Za-z]))|(\b[A-Za-z]\w*:)|(\b[A-Za-z]\w*\K!+)|(\W\K[@:][A-Za-z]\w*) 0:variable +add-highlighter shared/moon/code/ regex \b(and|break|catch|class|continue|do|else(if)?|export|extends|false|finally|for|from|if|import|in|local|nil|not|or|return|super|switch|then|true|try|unless|using|when|while|with)\b 0:keyword + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command moon-alternative-file -docstring 'Jump to the alternate file (implementation ↔ test)' %{ evaluate-commands %sh{ + case $kak_buffile in + *spec/*_spec.moon) + altfile=$(eval printf %s\\n $(printf %s\\n $kak_buffile | sed s+spec/+'*'/+';'s/_spec//)) + [ ! -f $altfile ] && echo "fail 'implementation file not found'" && exit + ;; + *.moon) + path=$kak_buffile + dirs=$(while [ $path ]; do printf %s\\n $path; path=${path%/*}; done | tail -n +2) + for dir in $dirs; do + altdir=$dir/spec + if [ -d $altdir ]; then + altfile=$altdir/$(realpath $kak_buffile --relative-to $dir | sed s+[^/]'*'/++';'s/.moon$/_spec.moon/) + break + fi + done + [ ! -d $altdir ] && echo "fail 'spec/ not found'" && exit + ;; + *) + echo "fail 'alternative file not found'" && exit + ;; + esac + printf %s\\n "edit $altfile" +}} + +define-command -hidden moon-trim-indent %{ + evaluate-commands -draft -itersel %{ + execute-keys x + # remove trailing white spaces + try %{ execute-keys -draft s \h + $ <ret> d } + } +} + +define-command -hidden moon-indent-on-char %{ + evaluate-commands -draft -itersel %{ + # align _else_ statements to start + try %{ execute-keys -draft x <a-k> ^ \h * (else(if)?) $ <ret> <a-semicolon> <a-?> ^ \h * (if|unless|when) <ret> s \A | \z <ret> ) <a-&> } + # align _when_ to _switch_ then indent + try %{ execute-keys -draft x <a-k> ^ \h * (when) $ <ret> <a-semicolon> <a-?> ^ \h * (switch) <ret> s \A | \z <ret> ) <a-&> ) , <gt> } + # align _catch_ and _finally_ to _try_ + try %{ execute-keys -draft x <a-k> ^ \h * (catch|finally) $ <ret> <a-semicolon> <a-?> ^ \h * (try) <ret> s \A | \z <ret> ) <a-&> } + } +} + +define-command -hidden moon-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy -- comment prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K--\h* <ret> y gh j P } + } +} + +define-command -hidden moon-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : moon-trim-indent <ret> } + # indent after start structure + try %{ execute-keys -draft k x <a-k> ^ \h * (class|else(if)?|for|if|switch|unless|when|while|with) \b | ([:=]|[-=]>) $ <ret> j <a-gt> } + # deindent after return statements + try %{ execute-keys -draft k x <a-k> ^ \h * (break|return) \b <ret> j <a-lt> } + } +} + +] diff --git a/autoload/filetype/nim.kak b/autoload/filetype/nim.kak new file mode 100644 index 0000000..2c00ac3 --- /dev/null +++ b/autoload/filetype/nim.kak @@ -0,0 +1,132 @@ +# https://nim-lang.org/ +# + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*\.nim(s|ble)? %{ + set-option buffer filetype nim +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=nim %{ + require-module nim + + set-option window static_words %opt{nim_static_words} + + hook window InsertChar \n -group nim-insert nim-insert-on-new-line + hook window InsertChar \n -group nim-indent nim-indent-on-new-line + # cleanup trailing whitespaces on current line insert end + hook window ModeChange pop:insert:.* -group nim-trim-indent %{ try %{ exec -draft <semicolon> x s ^\h+$ <ret> d } } + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window nim-.+ } +} + +hook -group nim-highlight global WinSetOption filetype=nim %{ + add-highlighter window/nim ref nim + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/nim } +} + +provide-module nim %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/nim regions +add-highlighter shared/nim/code default-region group +add-highlighter shared/nim/triple_string region '([A-Za-z](_?\w)*)?"""' '"""(?!")' fill string +add-highlighter shared/nim/raw_string region [A-Za-z](_?[A-Za-z])*" (?<!")"(?!") fill string +add-highlighter shared/nim/string region (?<!'\\)" ((?<!\\)(\\\\)*"|$) group +add-highlighter shared/nim/inline_documentation region '##' $ fill documentation +add-highlighter shared/nim/documentation region '##\[' '\]##' fill documentation +add-highlighter shared/nim/comment region '#\[' '\]#' group +add-highlighter shared/nim/comment_line region (?<![^'].')#(?!'\[) $ group + +add-highlighter shared/nim/string/fill fill string +add-highlighter shared/nim/comment/fill fill comment +add-highlighter shared/nim/comment_line/fill fill comment + +evaluate-commands %sh{ + # Grammar + opchars='[=+-/<>@$~&%|!?^.:\\*]' + opnocol='[=+-/<>@$~&%|!?^.\\*]' + letter='A-Za-z\u000080-\u10FFFF' + customsuffix="'[${letter}](_?[${letter}0-9])*" + suffix="(${customsuffix}|[iIuU](8|16|32|64)|[fF](32|64)?|[dDuU])?" + floatsuffix="(${customsuffix}|[fF](32|64)?|[dD])?" + hexdigit='[0-9a-fA-F]' + octdigit='[0-7]' + bindigit='[01]' + hexlit="0[xX]${hexdigit}(_?${hexdigit})*" + declit="\d(_?\d)*" + octlit="0o${octdigit}(_?${octdigit})*" + binlit="0[bB]${bindigit}(_?${bindigit})*" + intlit="\b(${declit}|${hexlit}|${octlit}|${binlit})${suffix}\b" + exponent="([eE][+-]?${declit})" + floatlit="\b${declit}(\.${declit}${exponent}?|${exponent})${floatsuffix}\b" + + keywords="addr asm bind block break case cast concept const continue + converter defer discard distinct do elif else end enum except export + finally for func if import include interface iterator let macro + method mixin nil out proc ptr raise ref return static template try type + unsafeAddr using var when while yield with without atomic generic" + operators="or xor and is isnot in notin of div mod shl shr not as from" + types="int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 float + float32 float64 bool char object seq array cstring string tuple varargs + typedesc pointer byte set typed untyped void auto" + values="false true on off" + + join() { sep=$2; set -- $1; IFS="$sep"; echo "$*"; } + + static_words="$(join "${keywords} ${types} ${operator} ${values}" ' ')" + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list nim_static_words ${static_words}" + + keywords="$(join "${keywords}" '|')" + operators="$(join "${operators}" '|')" + types="$(join "${types}" '|')" + values="$(join "${values}" '|')" + + # Highlight keywords + printf %s " + add-highlighter shared/nim/code/ regex ${opchars}+ 0:operator + add-highlighter shared/nim/code/ regex (?<!${opchars}):{1,2}(?!${opchars}) 0:meta + add-highlighter shared/nim/code/ regex :${opnocol}${opchars}* 0:operator + add-highlighter shared/nim/code/ regex (?<!${opchars})(\*)(:)(?!${opchars}) 1:operator 2:meta + add-highlighter shared/nim/code/ regex \b(${keywords})\b 0:keyword + add-highlighter shared/nim/code/ regex \b(${operators})\b 0:operator + add-highlighter shared/nim/code/ regex \b(${types})\b 0:type + add-highlighter shared/nim/code/ regex \b(${values})\b 0:value + add-highlighter shared/nim/code/ regex ${intlit} 0:value + add-highlighter shared/nim/code/ regex ${floatlit} 0:value + " +} + +add-highlighter shared/nim/code/ regex '(,|;|`|\(\.?|\.?\)|\[[.:]?|\.?\]|\{\.?|\.?\})' 0:meta +add-highlighter shared/nim/code/ regex %{'(\\([rcnlftvabe\\"']|0*[12]?\d?\d|x[0-9a-fA-F]{2})|[^'\n])'} 0:value + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden nim-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy '#' comment prefix and following white spaces + try %{ exec -draft k x s ^\h*#\h* <ret> y jgh P } + } +} + +define-command -hidden nim-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ exec -draft <semicolon> K <a-&> } + # cleanup trailing whitespaces from previous line + try %{ exec -draft k x s \h+$ <ret> d } + # indent after line ending with enum, tuple, object, type, import, export, const, let, var, ':' or '=' + try %{ exec -draft , k x <a-k> (:|=|\b(?:enum|tuple|object|const|let|var|import|export|type))$ <ret> j <a-gt> } + } +} + +} diff --git a/autoload/filetype/ninja.kak b/autoload/filetype/ninja.kak new file mode 100644 index 0000000..757b7ad --- /dev/null +++ b/autoload/filetype/ninja.kak @@ -0,0 +1,106 @@ +# ref: https://ninja-build.org/manual.html#ref_ninja_file + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .+\.ninja %{ + set-option buffer filetype ninja +} + + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=ninja %{ + require-module ninja + + set-option window static_words %opt{ninja_static_words} + + hook window ModeChange pop:insert:.* -group ninja-trim-indent ninja-trim-indent + hook window InsertChar \n -group ninja-insert ninja-insert-on-new-line + hook window InsertChar \n -group ninja-indent ninja-indent-on-new-line + # cleanup trailing whitespaces on current line insert end + hook window ModeChange pop:insert:.* -group ninja-trim-indent %{ try %{ execute-keys -draft <semicolon> x s ^\h+$ <ret> d } } + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window ninja-.+ } +} + +hook -group ninja-highlight global WinSetOption filetype=ninja %{ + add-highlighter window/ninja ref ninja + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/ninja } +} + + +provide-module ninja %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/ninja regions + +# `#` +add-highlighter shared/ninja/comment region '#' '\n' fill comment + +# `subninja`, `include`, `rule`, `pool` and `default` declarations +add-highlighter shared/ninja/sirpd region '^(subninja|include|rule|pool|default)\b' '(?<!\$)\n' group +add-highlighter shared/ninja/sirpd/default regex '^(subninja|include)\b' 0:module +add-highlighter shared/ninja/sirpd/rulepool regex '^(rule|pool|default)\b' 0:keyword +add-highlighter shared/ninja/sirpd/linebreak regex '\$$' 0:operator + +# `build` +add-highlighter shared/ninja/build region '^build\b' '(?<!\$)\n' group +add-highlighter shared/ninja/build/build regex '^build\b' 0:keyword +add-highlighter shared/ninja/build/rule regex ':\h+((\w|-)+)' 0:function +add-highlighter shared/ninja/build/colonpipe regex ':|\||\|\|' 0:operator +add-highlighter shared/ninja/build/linebreak regex '\$$' 0:operator +add-highlighter shared/ninja/build/variables regex '\$(\w|-)+|\$\{(\w|-)+\}' 0:value + +# variables declarations +add-highlighter shared/ninja/variable region '^\h*(\w|-)+\h*=' '(?<!\$)\n' group +add-highlighter shared/ninja/variable/declaredname regex '^\h*((\w|-)+)\h*(=)' 1:variable 0:operator +add-highlighter shared/ninja/variable/linebreak regex '\$$' 0:operator +add-highlighter shared/ninja/variable/variables regex '\$(\w|-)+|\$\{(\w|-)+\}' 0:value + +# keywords/builtin variable names +evaluate-commands %sh{ + keywords="rule build command default subninja include" + reserved_names="builddir ninja_required_version pool depfile deps depfile msvc_deps_prefix description dyndep generator restat rspfile rspfile_content" + + printf %s " + declare-option str-list ninja_static_words ${keywords} ${reserved_names} + " + + reserved_names_regex="$(echo ${reserved_names} | tr ' ' '|')" + printf %s " + add-highlighter shared/ninja/variable/reserved_names regex '^\h*(${reserved_names_regex})\b' 0:meta + " +} + + +# Indent +# ‾‾‾‾‾‾ + +define-command -hidden ninja-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden ninja-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy -- comments prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K--\h* <ret> y gh j P } + } +} + +define-command -hidden ninja-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft \; K <a-&> } + # filter previous line + try %{ execute-keys -draft k : ninja-trim-indent <ret> } + # indent after lines begining with rule and pool + try %{ execute-keys -draft \; k x <a-k> ^(rule|pool|build)\b <ret> j <a-gt> } + } +} + +} diff --git a/autoload/filetype/nix.kak b/autoload/filetype/nix.kak new file mode 100644 index 0000000..35e5e4e --- /dev/null +++ b/autoload/filetype/nix.kak @@ -0,0 +1,124 @@ +# Nix package manager language +# https://nixos.org/nix/manual/ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](nix) %{ + set-option buffer filetype nix +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=nix %{ + require-module nix + + hook window ModeChange pop:insert:.* -group nix-trim-indent nix-trim-indent + hook window InsertChar .* -group nix-indent nix-indent-on-char + hook window InsertChar \n -group nix-insert nix-insert-on-new-line + hook window InsertChar \n -group nix-indent nix-indent-on-new-line + + set-option buffer extra_word_chars _ - + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window nix-.+ } +} + +hook -group nix-highlight global WinSetOption filetype=nix %{ + add-highlighter window/nix ref nix + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/nix } +} + +provide-module nix %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/nix regions +add-highlighter shared/nix/code default-region group +# Define strings. They can contain interpolated nix code, +# which itself can contain strings. +# Note that we currently cannot properly support nesting of the same-delimiter strings +# because of https://github.com/mawww/kakoune/issues/1670 +add-highlighter shared/nix/double_string region '"' (?<!\\)(?:\\\\)*" regions +# this is hard one: it is terminated by '', but ''$, ''\* and ''' are escapes. +add-highlighter shared/nix/indent_string region "''" (?<!')(?:''')*''(?![\\'$]) regions +add-highlighter shared/nix/comment1 region '#' '$' fill comment +add-highlighter shared/nix/comment2 region /\* \*/ fill comment + + +#add-highlighter shared/nix/code/ regex "([a-zA-Z_][a-zA-Z0-9-_.]*)\s*([=])" 1:variable +add-highlighter shared/nix/code/ regex "(\b|-)[0-9]*\.?[0-9eE]+\b" 0:value + +add-highlighter shared/nix/double_string/str default-region fill string +add-highlighter shared/nix/double_string/variable region -recurse \{ (?<!\\)(\\\\)*\$\{ \} ref nix +add-highlighter shared/nix/indent_string/str default-region fill string +# FIXME: the opening regex is not ideal. See https://nixos.org/nix/manual/#idm140737317975776 +# It should usually match "${", should match "'''${" (as "'''" is escaped itself), +# but should not match "''${" and "''\${". +# Seems that negative lookbehind semantics is not enough for some complex cases. +add-highlighter shared/nix/indent_string/variable region -recurse \{ (?<![^']'')\$\{ \} ref nix + +add-highlighter shared/nix/code/ regex \b(true|false|null|let|in|with|if|then|else)\b 0:keyword +add-highlighter shared/nix/code/ regex \b(rec)\b\s*\{ 1:keyword +# Those are builtin functions available in global scope. +# They should not be assigned to. +add-highlighter shared/nix/code/ regex '[^.]\s*\b(builtins|inherit|baseNameOf|derivation|dirOf|fetchTarball|import|isNull|map|removeAttrs|throw|toString)\b\s*[^=]' 1:builtin + +add-highlighter shared/nix/code/ regex '\b\s*(\.)\s*\b' 1:operator +add-highlighter shared/nix/code/ regex '[^-a-zA-Z0-9_](-+)' 1:operator +add-highlighter shared/nix/code/ regex '\?' 0:operator +add-highlighter shared/nix/code/ regex '\+\+=?' 0:operator +add-highlighter shared/nix/code/ regex '(\*|/|\+)' 0:operator +add-highlighter shared/nix/code/ regex '!' 0:operator +add-highlighter shared/nix/code/ regex '//=?' 0:operator +add-highlighter shared/nix/code/ regex '[<>]=?\??' 0:operator +add-highlighter shared/nix/code/ regex '(==|!=)' 0:operator +add-highlighter shared/nix/code/ regex '(&&|\|\|)' 0:operator +add-highlighter shared/nix/code/ regex '->' 0:operator +add-highlighter shared/nix/code/ regex \bor\b 0:operator + +# override any operators matched before +# path: +add-highlighter shared/nix/code/ regex '\s\(*(\.?\.?[-A-Za-z0-9/_+.]*/[-A-Za-z0-9/_+.]*)[;?]?' 1:meta +# imported path: +add-highlighter shared/nix/code/ regex <[-A-Za-z0-9/_+.]+> 0:meta +# RFC 2396 URIs can be used without quoting. Strangely, "string" ends URL but ''indented'' one doesn't +# List of prohibited characters was tested manually in nix-repl as it is not properly documented. +add-highlighter shared/nix/code/ regex '([^:/?#\s]+):([^#(){}\[\]";`|\s\\]+)' 0:string + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden nix-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden nix-indent-on-char %< + evaluate-commands -draft -itersel %< + # align closer token to its opener when alone on a line + try %/ execute-keys -draft <a-h> <a-k> ^\h+[\]}]$ <ret> m s \A|.\z <ret> 1<a-&> / + > +> + +define-command -hidden nix-insert-on-new-line %< + evaluate-commands -draft -itersel %< + # copy // comments prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K#\h* <ret> y gh j P } + > +> + +define-command -hidden nix-indent-on-new-line %< + evaluate-commands -draft -itersel %< + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : nix-trim-indent <ret> } + # indent after lines beginning / ending with opener token + try %_ execute-keys -draft k x <a-k> ^\h*[[{]|[[{]$ <ret> j <a-gt> _ + # deindent closer token(s) when after cursor + try %_ execute-keys -draft x <a-k> ^\h*[}\]] <ret> gh / [}\]] <ret> m <a-S> 1<a-&> _ + > +> + +§ diff --git a/autoload/filetype/ocaml.kak b/autoload/filetype/ocaml.kak new file mode 100644 index 0000000..06a1bf5 --- /dev/null +++ b/autoload/filetype/ocaml.kak @@ -0,0 +1,130 @@ +# http://ocaml.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*\.(ml|mli|mll|mly)$ %{ + set-option buffer filetype ocaml +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=ocaml %{ + require-module ocaml + set-option window static_words %opt{ocaml_static_words} + hook window InsertChar -group ocaml-insert '\*' ocaml-insert-closing-comment-bracket + hook window InsertChar \n -group ocaml-insert ocaml-insert-on-new-line + hook window ModeChange pop:insert:.* -group ocaml-trim-indent ocaml-trim-indent +} + +hook -group ocaml-highlight global WinSetOption filetype=ocaml %{ + add-highlighter window/ocaml ref ocaml + alias window alt ocaml-alternative-file + hook -once -always window WinSetOption filetype=.* %{ + unalias window alt ocaml-alternative-file + remove-highlighter window/ocaml + } +} + +provide-module ocaml %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/ocaml regions +add-highlighter shared/ocaml/code default-region group +add-highlighter shared/ocaml/string region (?<!['\\])" (?<!\\)(\\\\)*" fill string +add-highlighter shared/ocaml/quotedstring region -match-capture %"\{(\w*)\|" %"\|(\w*)\}" fill string +add-highlighter shared/ocaml/comment region -recurse \Q(* \Q(* \Q*) fill comment + +add-highlighter shared/ocaml/code/char regex %{\B'([^'\\]|(\\[\\"'nrtb])|(\\\d{3})|(\\x[a-fA-F0-9]{2})|(\\o[0-7]{3}))'\B} 0:value + +# integer literals +add-highlighter shared/ocaml/code/ regex \b[0-9][0-9_]*([lLn]?)\b 0:value +add-highlighter shared/ocaml/code/ regex \b0[xX][A-Fa-f0-9][A-Fa-f0-9_]*([lLn]?)\b 0:value +add-highlighter shared/ocaml/code/ regex \b0[oO][0-7][0-7_]*([lLn]?)\b 0:value +add-highlighter shared/ocaml/code/ regex \b0[bB][01][01_]*([lLn]?)\b 0:value +# float literals +add-highlighter shared/ocaml/code/ regex \b[0-9][0-9_]*(\.[0-9_]*)?([eE][+-]?[0-9][0-9_]*)? 0:value +add-highlighter shared/ocaml/code/ regex \b0[xX][A-Fa-f0-9][A-Fa-f0-9]*(\.[a-fA-F0-9_]*)?([pP][+-]?[0-9][0-9_]*)? 0:value +# constructors. must be put before any module name highlighter, as a fallback for capitalized identifiers +add-highlighter shared/ocaml/code/ regex \b[A-Z][a-zA-Z0-9_]*\b 0:value +# the module name in a module path, e.g. 'M' in 'M.x' +add-highlighter shared/ocaml/code/ regex (\b[A-Z][a-zA-Z0-9_]*[\h\n]*)(?=\.) 0:module +# (simple) module declarations +add-highlighter shared/ocaml/code/ regex (?<=module)([\h\n]+[A-Z][a-zA-Z0-9_]*) 0:module +# (simple) signature declarations. 'type' is also highlighted, due to the lack of quantifiers in lookarounds. +# Hence we must put keyword highlighters after this to recover proper highlight for 'type' +add-highlighter shared/ocaml/code/ regex (?<=module)([\h\n]+type[\h\n]+[A-Z][a-zA-Z0-9_]*) 0:module +# (simple) open statements +add-highlighter shared/ocaml/code/ regex (?<=open)([\h\n]+[A-Z][a-zA-Z0-9_]*) 0:module +# operators +add-highlighter shared/ocaml/code/ regex [@!$%%^&*\-+=|<>/?]+ 0:operator + + +# Macro +# ‾‾‾‾‾ + +evaluate-commands %sh{ + keywords="and|as|asr|assert|begin|class|constraint|do|done|downto|else|end|exception|external|false" + keywords="${keywords}|for|fun|function|functor|if|in|include|inherit|initializer|land|lazy|let|lor" + keywords="${keywords}|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|object|of|open|or" + keywords="${keywords}|private|rec|sig|struct|then|to|true|try|type|val|virtual|when|while|with" + + printf %s\\n "declare-option str-list ocaml_static_words ${keywords}" | tr '|' ' ' + +# must be put at last, since we have highlighted some keywords ('type' in 'module type') to other things + printf %s " + add-highlighter shared/ocaml/code/ regex \b(${keywords})\b 0:keyword + " +} + +# Conveniences +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +# C has header and source files and you need to often switch between them. +# Similarly OCaml has .ml (implementation) and .mli (interface files) and +# one often needs to switch between them. +# +# This command provides a simple functionality that allows you to accomplish this. +define-command ocaml-alternative-file -docstring 'Switch between .ml and .mli file or vice versa' %{ + evaluate-commands %sh{ + if [ "${kak_buffile##*.}" = 'ml' ]; then + printf "edit -- '%s'" "$(printf %s "${kak_buffile}i" | sed "s/'/''/g")" + elif [ "${kak_buffile##*.}" = 'mli' ]; then + printf "edit -- '%s'" "$(printf %s "${kak_buffile%i}" | sed "s/'/''/g")" + fi + } +} + +} + +# Remove trailing whitespaces +define-command -hidden ocaml-trim-indent %{ + evaluate-commands -no-hooks -draft -itersel %{ + try %{ execute-keys -draft x s \h+$ <ret> d } + } +} + +# Preserve indentation when creating new line +define-command -hidden ocaml-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy white spaces at the beginnig of the previous line + try %{ execute-keys -draft k x s ^\h+ <ret> y jgh P x s \h+$ <a-d> } + # increase indentation if the previous line ended with either '=' sign or do keyword + try %{ execute-keys -draft k x s (=|\bdo)$ <ret> j <a-gt> } + } +} + +# The OCaml comment is `(* Some comment *)`. Like the C-family this can be a multiline comment. +# +# Recognize when the user is trying to commence a comment when they type `(*` and +# then automatically insert `*)` on behalf of the user. A small convenience. +define-command -hidden ocaml-insert-closing-comment-bracket %{ + try %{ + execute-keys -draft 'HH<a-k>\(\*<ret>' + execute-keys ' *)<left><left><left>' + } +} diff --git a/autoload/filetype/odin.kak b/autoload/filetype/odin.kak new file mode 100644 index 0000000..4f43dea --- /dev/null +++ b/autoload/filetype/odin.kak @@ -0,0 +1,119 @@ +hook global BufCreate .*\.odin %{ + set-option buffer filetype odin +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=odin %{ + require-module odin + + set-option window static_words %opt{odin_static_words} + + # cleanup trailing whitespaces when exiting insert mode + hook window ModeChange pop:insert:.* -group odin-trim-indent %{ try %{ execute-keys -draft xs^\h+$<ret>d } } + hook window InsertChar \n -group odin-insert odin-insert-on-new-line + hook window InsertChar \n -group odin-indent odin-indent-on-new-line + hook window InsertChar \{ -group odin-indent odin-indent-on-opening-curly-brace + hook window InsertChar \} -group odin-indent odin-indent-on-closing-curly-brace + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window odin-.+ } +} + +hook -group odin-highlight global WinSetOption filetype=odin %{ + add-highlighter window/odin ref odin + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/odin } +} + +provide-module odin %§ + +add-highlighter shared/odin regions +add-highlighter shared/odin/code default-region group +add-highlighter shared/odin/string region %{(?<!')"} %{(?<!\\)(\\\\)*"} fill string +add-highlighter shared/odin/rawstring region ` ` fill string +add-highlighter shared/odin/character region %{'} %{(?<!\\)'} fill value + +add-highlighter shared/odin/comment region -recurse /\* /\* \*/ fill comment +add-highlighter shared/odin/inline_documentation region /// $ fill documentation +add-highlighter shared/odin/line_comment region // $ fill comment + +add-highlighter shared/odin/code/ regex "(?<!\w)@\w+\b" 0:meta + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden odin-insert-on-new-line %[ + # copy // comments prefix and following white spaces + try %{ execute-keys -draft <semicolon><c-s>kx s ^\h*\K/{2,}\h* <ret> y<c-o>P<esc> } +] + +define-command -hidden odin-indent-on-new-line %< + evaluate-commands -draft -itersel %= + # preserve previous line indent + try %{ execute-keys -draft <semicolon>K<a-&> } + # indent after lines ending with { or ( + try %[ execute-keys -draft kx <a-k> [{(]\h*$ <ret> j<a-gt> ] + # cleanup trailing white spaces on the previous line + try %{ execute-keys -draft kx s \h+$ <ret>d } + # align to opening paren of previous line + try %{ execute-keys -draft [( <a-k> \A\([^\n]+\n[^\n]*\n?\z <ret> s \A\(\h*.|.\z <ret> '<a-;>' & } + # indent after a switch's case/default statements + try %[ execute-keys -draft kx <a-k> ^\h*(case|default).*:$ <ret> j<a-gt> ] + # indent after keywords + try %[ execute-keys -draft <semicolon><a-F>)MB <a-k> \A(if|else|while|for|try|catch)\h*\(.*\)\h*\n\h*\n?\z <ret> s \A|.\z <ret> 1<a-&>1<a-,><a-gt> ] + # deindent closing brace(s) when after cursor + try %[ execute-keys -draft x <a-k> ^\h*[})] <ret> gh / [})] <ret> m <a-S> 1<a-&> ] + = +> + +define-command -hidden odin-indent-on-opening-curly-brace %[ + # align indent with opening paren when { is entered on a new line after the closing paren + try %[ execute-keys -draft -itersel h<a-F>)M <a-k> \A\(.*\)\h*\n\h*\{\z <ret> s \A|.\z <ret> 1<a-&> ] +] + +define-command -hidden odin-indent-on-closing-curly-brace %[ + # align to opening curly brace when alone on a line + try %[ execute-keys -itersel -draft <a-h><a-k>^\h+\}$<ret>hms\A|.\z<ret>1<a-&> ] +] + +evaluate-commands %sh{ + values='false true nil ---' + types='bool b8 b16 b32 b64 + int i8 i16 i32 i64 i128 + uint u8 u16 u32 u64 u128 uintptr + i16le i32le i64le i128le u16le u32le u64le u128le + i16be i32be i64be i128be u16be u32be u64be u128be + f16 f32 f64 + f16le f32le f64le + f16be f32be f64be + complex32 complex64 complex128 + quaternion64 quaternion128 quaternion256 + rune + string cstring + rawptr + typeid + any' + keywords='asm auto_cast bit_set break case cast context continue defer distinct do dynamic else enum + fallthrough for foreign if import in map not_in or_else or_return package proc return struct + switch transmute typeid union using when where' + attributes='' + # ---------------------------------------------------------------------------------------------- # + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + # ---------------------------------------------------------------------------------------------- # + add_highlighter() { printf "add-highlighter shared/odin/code/ regex %s %s\n" "$1" "$2"; } + # ---------------------------------------------------------------------------------------------- # + add_word_highlighter() { + while [ $# -gt 0 ]; do + words=$1 face=$2; shift 2 + regex="\\b($(join "${words}" '|'))\\b" + add_highlighter "$regex" "1:$face" + done + } + # ---------------------------------------------------------------------------------------------- # + printf %s\\n "declare-option str-list odin_static_words $(join "${values} ${types} ${keywords} ${attributes} ${modules}" ' ')" + # ---------------------------------------------------------------------------------------------- # + add_word_highlighter "$values" "value" "$types" "type" "$keywords" "keyword" "$attributes" "attribute" + # ---------------------------------------------------------------------------------------------- # +} + +§ diff --git a/autoload/filetype/pascal.kak b/autoload/filetype/pascal.kak new file mode 100644 index 0000000..eae4577 --- /dev/null +++ b/autoload/filetype/pascal.kak @@ -0,0 +1,217 @@ +# https://www.freepascal.org/docs-html/ref/ref.html +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection, see https://wiki.freepascal.org/file_types +hook global BufCreate .*\.(p|pp|pas|pascal)$ %{ + set-option buffer filetype pascal +} +hook global BufCreate .*\.(dpr|dpk|dfm)$ %{ + set-option buffer filetype delphi +} +hook global BufCreate .*\.(lpr|lfm)$ %{ + set-option buffer filetype freepascal +} + +hook global WinSetOption filetype=((free|object)?pascal|delphi) %[ + require-module pascal + hook window ModeChange pop:insert:.* -group pascal-trim-indent pascal-trim-indent + hook window InsertChar \n -group pascal-indent pascal-indent-on-new-line + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window pascal-.+ } + set-option window static_words %opt{static_words} +] + +hook -group pascal-highlight global WinSetOption filetype=((free|object)?pascal|delphi) %[ + add-highlighter window/pascal ref pascal + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/pascal } +] + +provide-module pascal %§ + +add-highlighter shared/pascal regions +add-highlighter shared/pascal/code default-region group + +evaluate-commands %sh¶ + # This might seem like a lot of effort to highlight routines and + # properties correctly but it is worth it + + id='([_a-zA-Z][\w]{,126})\s*' # identifier for variables etc. + id2="(?:$id\.)?$id(?:<.*?>)?" # (module|type).id + id4="(?:$id\.)?(?:$id\.)?(?:$id\.)?$id" # type.type.type.id + type=":\s*(specialize\s+)?(?:(array\s+of\s+)?$id2)" # 1:attribute 2:keyword 3:module 4:type + + cat <<EOF + # routine without parameters + add-highlighter shared/pascal/code/simple_routine regex \ + "\b(?i)(function|procedure|constructor|destructor|operator)\s+$id4(?:$type)?" \ + 2:type 3:type 4:type 5:function 6:attribute 7:keyword 8:module 9:type + add-highlighter shared/pascal/simple_property region \ + "\b(?i)property\s+$id2:" ";" group + + # routine with parameters + add-highlighter shared/pascal/routine region \ + "\b(?i)(function|procedure|constructor|destructor|operator)(\s+$id4)?\s*(<.*?>)?\s*\(" "\).*?;" regions + add-highlighter shared/pascal/property region \ + "\b(?i)property\s+$id4\[" "\].*?;" regions + + add-highlighter shared/pascal/routine/parameters region -recurse \( \( \) regions + add-highlighter shared/pascal/property/parameters region -recurse \[ \[ \] regions +EOF + + # Used to highlight "var1, var2, var3, var4 : type" declarations + x="(?:$id,\s*)?" + + for r in property routine; do + cat <<EOF + add-highlighter shared/pascal/$r/parameters/default default-region group + add-highlighter shared/pascal/$r/parameters/default/ regex \ + "(?i)(?:(constref|const|var|out|univ)\s+)?$x$x$x$x$x$id(?:$type)?" \ + 1:attribute 2:variable 3:variable 4:variable 5:variable 6:variable 7:variable 8:attribute 9:keyword 10:module 11:type + add-highlighter shared/pascal/$r/default default-region group +EOF + done + + cat <<EOF + add-highlighter shared/pascal/routine/default/ regex \ + "\b(?i)(function|procedure|constructor|destructor|operator)(?:\s+$id4)?" \ + 1:keyword 2:type 3:type 4:type 5:function + add-highlighter shared/pascal/routine/default/return_type regex \ + "(?i)$type" 1:attribute 2:keyword 3:module 4:type + add-highlighter shared/pascal/routine/default/ regex \ + "(?i)(of\s+object|is\s+nested)" 1:keyword +EOF + + for r in property/default simple_property; do + cat <<EOF + add-highlighter shared/pascal/$r/ regex "\b(?i)(property)" 1:keyword + add-highlighter shared/pascal/$r/type regex ":\s*$id" 1:type + + # https://www.freepascal.org/docs-html/ref/refsu33.html + add-highlighter shared/pascal/$r/specifier regex \ + "\b(?i)(index|read|write|implements|(no)?default|stored)\b" 0:attribute +EOF + done + + for r in pascal pascal/routine pascal/routine/parameters pascal/property; do + cat <<EOF + # Example string: 'You''re welcome!' + add-highlighter shared/$r/string region \ + -recurse %{(?<!')('')+(?!')} %{'} %{'(?!')|\$} group + add-highlighter shared/$r/string/ fill string + add-highlighter shared/$r/string/escape regex "''" 0:+b + + add-highlighter shared/$r/directive region \{\\$[a-zA-Z] \} fill meta + + # comments (https://www.freepascal.org/docs-html/ref/refse2.html) + add-highlighter shared/$r/comment_old region -recurse \(\* \(\* \*\) fill comment + add-highlighter shared/$r/comment_new region -recurse \{ \{ \} fill comment + add-highlighter shared/$r/comment_oneline region // $ fill comment +EOF + done + + + # The types "string" and "file", the value "nil", and the modifiers + # "bitpacked" and "packed" are not included. + reserved='and array as asm begin case class const constructor cppclass + destructor dispinterface div do downto else end except exports + finalization finally for function goto if implementation in + inherited initialization interface is label library mod not + object of operator or otherwise procedure program property raise + record repeat resourcestring set shl shr then threadvar to try + type unit until uses var while with xor' + + # These are not reserved words in Free Pascal, but for consistency + # with other programming languages are highlighted as reserved words: + keywords='Break Continue Exit at on package' + # "at" is used in Delphi, e.g. 'raise object at address' + + # https://www.freepascal.org/docs-html/ref/refsu3.html and + # https://wiki.freepascal.org/Reserved_words + # "name" and "alias" are not included beacuse they produce too many + # false positives. Some modifiers like "index" are only highlighted in + # certain places. + modifiers='absolute abstract assembler automated bitpacked cdecl contains + cppdecl cvar default deprecated dispid dynamic enumerator + experimental export external far far16 final forward generic + helper inline interrupt iocheck local near noreturn + nostackframe oldfpccall overload override packed pascal + platform private protected public published readonly register + reintroduce requires safecall saveregisters softfloat specialize + static stdcall strict syscall unaligned unimplemented varargs + virtual winapi writeonly' + + # https://wiki.freepascal.org/Category:Data_types + # not highlighted for consistency with not built-in types + types='AnsiChar AnsiString Boolean Boolean16 Boolean32 Boolean64 Buffer + Byte ByteBool Cardinal Char Comp Currency Double DWord Extended + Int16 Int32 Int64 Int8 Integer IUnknown LongBool LongInt Longword + NativeInt NativeUInt OleVariant PAnsiChar PAnsiString PBoolean PByte + PByteArray PCardinal PChar PComp PCurrency PDate PDateTime PDouble + PDWord PExtended PHandle PInt64 PInteger PLongInt PLongWord Pointer + PPointer PQWord PShortInt PShortString PSingle PSmallInt PString + PUnicodeChar PUnicodeString PVariant PWideChar PWideString PWord + PWordArray PWordBool QWord QWordBool RawBytestring Real Real48 + ShortInt ShortString Single SmallInt TClass TDate TDateTime Text + TextFile THandle TObject TTime UInt16 UInt32 UInt8 UnicodeChar + UnicodeString UTF16String UTF8String Variant WideChar WideString + Word WordBool file string' + + constants='False True nil MaxInt Self' + + # Add the language's grammar to the static completion list + echo declare-option str-list static_words $reserved $keywords $modifiers \ + $types $constants name index result constref out read write implements \ + nodefault stored message + + # Replace spaces with a pipe + join() { eval set -- $1; IFS='|'; echo "$*"; } + + cat <<EOF + add-highlighter shared/pascal/code/keywords regex \ + (?i)(?<!&)\b($(join "$reserved $keywords")|file\s+of)\b 0:keyword + add-highlighter shared/pascal/code/modifiers regex \ + (?i)(?<!\.)\b($(join "$modifiers"))\b(?!\()|message\s+(?!:) 0:attribute + add-highlighter shared/pascal/code/index regex \ + '\b(?i)(index)\s+\w+\s*;' 1:attribute +EOF + + for r in code routine/parameters/default routine/default property/default simple_property; do + cat <<EOF + add-highlighter shared/pascal/$r/ regex '[.:=<>@^*/+-]' 0:operator + add-highlighter shared/pascal/$r/constants regex \ + \b(?i)($(join "$constants"))\b 0:value + + # numbers (https://www.freepascal.org/docs-html/ref/refse6.html) + add-highlighter shared/pascal/$r/decimal regex \b\d+([eE][+-]?\d+)?\b 0:value + add-highlighter shared/pascal/$r/hex regex \\\$[\da-fA-F]+\b 0:value + add-highlighter shared/pascal/$r/octal regex &[0-7]+\b 0:value + add-highlighter shared/pascal/$r/binary regex \%[01]+\b 0:value + add-highlighter shared/pascal/$r/char regex '#\d+\b' 0:value +EOF + done +¶ + +define-command -hidden pascal-trim-indent %{ + evaluate-commands -no-hooks -draft -itersel %{ + execute-keys x + # remove trailing white spaces + try %{ execute-keys -draft s \h + $ <ret> d } + } +} + +define-command -hidden pascal-indent-on-new-line %{ + evaluate-commands -no-hooks -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # cleanup trailing whitespaces from previous line + try %{ execute-keys -draft k x s \h+$ <ret> d } + # indent after certain keywords + try %{ execute-keys -draft kx<a-k>(?i)(asm|begin|const|else|except|exports|finalization|finally|label|of|otherwise|private|property|public|protected|published|record|repeat|resourcestring|threadvar|try|type|uses|var|:)\h*$<ret>j<a-gt> } + } +} +§ + +# Other syntax highlighters for reference: +# https://github.com/pygments/pygments/blob/master/pygments/lexers/pascal.py +# https://github.com/codemirror/CodeMirror/blob/master/mode/pascal/pascal.js +# https://github.com/vim/vim/blob/master/runtime/syntax/pascal.vim +# https://github.com/highlightjs/highlight.js/blob/master/src/languages/delphi.js diff --git a/autoload/filetype/perl.kak b/autoload/filetype/perl.kak new file mode 100644 index 0000000..2fcb026 --- /dev/null +++ b/autoload/filetype/perl.kak @@ -0,0 +1,146 @@ +# https://www.perl.org/ +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*\.(t|p[lm])$ %{ + set-option buffer filetype perl +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=perl %{ + require-module perl + + set-option window static_words %opt{perl_static_words} + + # cleanup trailing whitespaces when exiting insert mode + hook window ModeChange pop:insert:.* -group perl-trim-indent %{ try %{ execute-keys -draft xs^\h+$<ret>d } } + hook window InsertChar \n -group perl-insert perl-insert-on-new-line + hook window InsertChar \n -group perl-indent perl-indent-on-new-line + hook window InsertChar \{ -group perl-indent perl-indent-on-opening-curly-brace + hook window InsertChar \} -group perl-indent perl-indent-on-closing-curly-brace + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window perl-.+ } +} + +hook -group perl-highlight global WinSetOption filetype=perl %{ + add-highlighter window/perl ref perl + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/perl } +} + +provide-module perl %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/perl regions +add-highlighter shared/perl/code default-region group +add-highlighter shared/perl/command region (?<!\$)(?<!\\)` (?<!\\)(\\\\)*` fill meta +add-highlighter shared/perl/double_string region (?<!\$)" (?<!\\)(\\\\)*" fill string +add-highlighter shared/perl/single_string region (?<!\$)(?<!\\\\)' (?<!\\)(\\\\)*' fill string +add-highlighter shared/perl/comment region (?<!\$)(?<!\\)# $ fill comment + +add-highlighter shared/perl/regex region m?(?<!/)(?<!qr)/[^/\n]+(?=/) /\w* fill meta +add-highlighter shared/perl/sregex region s/[^/\n]+/[^/\n]+(?=/) /\w* fill meta +add-highlighter shared/perl/bregex region s\{[^\}\n]+\}\{[^\}\n]*(?=\}) \}\w* fill meta + +add-highlighter shared/perl/quote_brace region -recurse \{ \bq[qrwx]?\{ \} fill string +add-highlighter shared/perl/quote_paren region -recurse \( \bq[qrwx]?\( \) fill string +add-highlighter shared/perl/quote_brack region -recurse \[ \bq[qrwx]?\[ \] fill string +add-highlighter shared/perl/quote_angle region -recurse < \bq[qrwx]?< > fill string +add-highlighter shared/perl/quote_punct region -match-capture '\bq[qwx]?([:;!@#$%^&*|,.?/~=+-])' '(.)' fill string +add-highlighter shared/perl/quote_regex region -match-capture '\bqr([:;!@#$%^&*|,.?/~=+-])' '(.)' fill meta + +add-highlighter shared/perl/double_heredoc region -match-capture <<~?\h*'(\w*)' ^\t*(\w*)$ fill string +add-highlighter shared/perl/single_heredoc region -match-capture <<~?\h*"(\w*)" ^\t*(\w*)$ fill string +add-highlighter shared/perl/bare_heredoc region -match-capture <<~?(\w+) ^\t*(\w+)$ fill string +add-highlighter shared/perl/pod region ^=\w+ ^=cut\b fill string + +evaluate-commands %sh{ + # Grammar + keywords="else lock qw elsif lt qx eq exp ne sub for no my not tr goto and foreach or break exit unless cmp ge package until continue gt while if qq xor do le qr return" + attributes="END AUTOLOAD BEGIN CHECK UNITCHECK INIT DESTROY + length setpgrp endgrent link setpriority endhostent listen setprotoent endnetent local setpwent + endprotoent localtime setservent endpwent log setsockopt endservent lstat shift eof map shmctl eval mkdir shmget exec msgctl shmread + exists msgget shmwrite msgrcv shutdown fcntl msgsnd sin fileno sleep flock next socket fork socketpair format oct sort + formline open splice getc opendir split getgrent ord sprintf getgrgid our sqrt getgrnam pack srand gethostbyaddr pipe stat gethostbyname + pop state gethostent pos study getlogin print substr getnetbyaddr printf symlink abs getnetbyname prototype syscall accept getnetent + push sysopen alarm getpeername quotemeta sysread atan2 getpgrp rand sysseek getppid read system getpriority readdir syswrite bind + getprotobyname readline tell binmode getprotobynumber readlink telldir bless getprotoent readpipe tie getpwent recv tied caller + getpwnam redo time chdir getpwuid ref times getservbyname rename truncate chmod getservbyport require uc chomp getservent reset ucfirst + chop getsockname umask chown getsockopt reverse undef chr glob rewinddir chroot gmtime rindex unlink close rmdir unpack + closedir grep say unshift connect hex scalar untie cos index seek use crypt seekdir utime dbmclose int select values dbmopen ioctl semctl + vec defined join semget wait delete keys semop waitpid kill send wantarray die last setgrent warn dump lc sethostent write each lcfirst setnetent" + values="ARGV STDERR STDOUT ARGVOUT STDIN __DATA__ __END__ __FILE__ __LINE__ __PACKAGE__" + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list perl_static_words $(join "${keywords} ${attributes} ${values}" ' ')" + + # Highlight keywords + printf %s " + add-highlighter shared/perl/code/ regex \b($(join "${keywords}" '|'))\b 0:keyword + add-highlighter shared/perl/code/ regex \b($(join "${attributes}" '|'))\b 0:attribute + add-highlighter shared/perl/code/ regex \b($(join "${values}" '|'))\b 0:value + " +} + +add-highlighter shared/perl/code/ regex (?!\$)-?([0-9]*\.(?!0[xXbB]))?\b([0-9]+|0[xX][0-9a-fA-F]+|0[bb][01_]+)\.?([eE][+-]?[0-9]+)?i?\b 0:value +add-highlighter shared/perl/code/ regex %{\$!|\$"|\$#|\$\$|\$%|\$&|\$'|\$\(|\$\)|\$\*|\$\+|\$,|\$_|\$-|\$`|\$\.|\$/|\$:|\$;|\$<|\$=|\$>|\$\?|\$@|\$\[|\$\\|\$\]|\$\^|\$\||\$~|%!|@\+|@-|@_} 0:value +add-highlighter shared/perl/code/ regex (%ENV|%INC|%OVERLOAD|%SIG|@ARGV|@INC|@LAST_MATCH_START) 0:value +add-highlighter shared/perl/code/ regex %{%\^(H)\b} 0:value +add-highlighter shared/perl/code/ regex \$\^(S|T|V|W|X|A|C|D|E|F|H|I|L|M|N|O|P|R)\b 0:value +add-highlighter shared/perl/code/ regex \$\^(RE_TRIE_MAXBUF|TAINT|UNICODE|UTF8LOCALE|WARNING_BITS|WIDE_SYSTEM_CALLS|CHILD_ERROR_NATIVE|ENCODING|OPEN|RE_DEBUG_FLAGS)\b 0:value + +add-highlighter shared/perl/code/ regex \$[0-9]+ 0:attribute +add-highlighter shared/perl/code/ regex \b-(B|b|C|c|d|e|f|g|k|l|M|O|o|p|r|R|S|s|T|t|u|w|W|X|x|z)\b 0:attribute + +add-highlighter shared/perl/code/ regex \$[a-zA-Z_][a-zA-Z0-9_]* 0:variable + +add-highlighter shared/perl/code/ regex \$(a|b|LAST_REGEXP_CODE_RESULT|LIST_SEPARATOR|MATCH|MULTILINE_MATCHING|NR|OFMT|OFS|ORS|OS_ERROR|OSNAME|OUTPUT_AUTO_FLUSH|OUTPUT_FIELD_SEPARATOR|OUTPUT_RECORD_SEPARATOR)\b 0:value +add-highlighter shared/perl/code/ regex \$(LAST_REGEXP_CODE_RESULT|LIST_SEPARATOR|MATCH|MULTILINE_MATCHING|NR|OFMT|OFS|ORS|OS_ERROR|OSNAME|OUTPUT_AUTO_FLUSH|OUTPUT_FIELD_SEPARATOR|OUTPUT_RECORD_SEPARATOR|PERL_VERSION|ACCUMULATOR|PERLDB|ARG|PID|ARGV|POSTMATCH|PREMATCH|BASETIME|PROCESS_ID|CHILD_ERROR|PROGRAM_NAME|COMPILING|REAL_GROUP_ID|DEBUGGING|REAL_USER_ID|EFFECTIVE_GROUP_ID|RS|EFFECTIVE_USER_ID|SUBSCRIPT_SEPARATOR|EGID|SUBSEP|ERRNO|SYSTEM_FD_MAX|EUID|UID|EVAL_ERROR|WARNING|EXCEPTIONS_BEING_CAUGHT|EXECUTABLE_NAME|EXTENDED_OS_ERROR|FORMAT_FORMFEED|FORMAT_LINE_BREAK_CHARACTERS|FORMAT_LINES_LEFT|FORMAT_LINES_PER_PAGE|FORMAT_NAME|FORMAT_PAGE_NUMBER|FORMAT_TOP_NAME|GID|INPLACE_EDIT|INPUT_LINE_NUMBER|INPUT_RECORD_SEPARATOR|LAST_MATCH_END|LAST_PAREN_MATCH)\b 0:value + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden perl-insert-on-new-line %~ + evaluate-commands -draft -itersel %= + # copy # comments prefix and following white spaces + try %{ execute-keys -draft <semicolon><c-s>kx s ^\h*\K#\h* <ret> y<c-o>P<esc> } + = +~ + +define-command -hidden perl-indent-on-new-line %~ + evaluate-commands -draft -itersel %= + # preserve previous line indent + try %{ execute-keys -draft <semicolon>K<a-&> } + # indent after lines ending with { or ( + try %[ execute-keys -draft kx <a-k> [{(]\h*$ <ret> j<a-gt> ] + # cleanup trailing white spaces on the previous line + try %{ execute-keys -draft kx s \h+$ <ret>d } + # align to opening paren of previous line + try %{ execute-keys -draft [( <a-k> \A\([^\n]+\n[^\n]*\n?\z <ret> s \A\(\h*.|.\z <ret> '<a-;>' & } + # indent after a switch's case/default statements + try %[ execute-keys -draft kx <a-k> ^\h*(case|default).*:$ <ret> j<a-gt> ] + # indent after if|else|while|for + try %[ execute-keys -draft <semicolon><a-F>)MB <a-k> \A(if|else|while|for)\h*\(.*\)\h*\n\h*\n?\z <ret> s \A|.\z <ret> 1<a-&>1<a-,><a-gt> ] + # deindent closing brace(s) when after cursor + try %[ execute-keys -draft x <a-k> ^\h*[})] <ret> gh / [})] <ret> m <a-S> 1<a-&> ] + = +~ + +define-command -hidden perl-indent-on-opening-curly-brace %[ + # align indent with opening paren when { is entered on a new line after the closing paren + try %[ execute-keys -draft -itersel h<a-F>)M <a-k> \A\(.*\)\h*\n\h*\{) <ret> s \A|.\z <ret> 1<a-&> ] +] + +define-command -hidden perl-indent-on-closing-curly-brace %[ + # align to opening curly brace when alone on a line + try %[ execute-keys -itersel -draft <a-h><a-k>^\h+\}$<ret>hms\A|.\z<ret>1<a-&> ] +] + +§ diff --git a/autoload/filetype/php.kak b/autoload/filetype/php.kak new file mode 100644 index 0000000..62ba6dd --- /dev/null +++ b/autoload/filetype/php.kak @@ -0,0 +1,107 @@ +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](phpt?) %{ + set-option buffer filetype php +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=php %{ + require-module php + + hook window ModeChange pop:insert:.* -group php-trim-indent php-trim-indent + hook window InsertChar .* -group php-indent php-indent-on-char + hook window InsertChar \n -group php-insert php-insert-on-new-line + hook window InsertChar \n -group php-indent php-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window php-.+ } +} + +hook -group php-highlight global WinSetOption filetype=php %{ + add-highlighter window/php-file ref php-file + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/php-file } +} + +provide-module php %§ +require-module html + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/php regions +add-highlighter shared/php/code default-region group +add-highlighter shared/php/double_string region '"' (?<!\\)(\\\\)*" group +add-highlighter shared/php/single_string region "'" (?<!\\)(\\\\)*' fill string +add-highlighter shared/php/doc_comment region /// '$' group +add-highlighter shared/php/doc_comment2 region /\*\* \*/ ref php/doc_comment +add-highlighter shared/php/comment1 region // '$' fill comment +add-highlighter shared/php/comment2 region /\* \*/ fill comment +add-highlighter shared/php/comment3 region '#' '$' fill comment +add-highlighter shared/php/heredoc region -match-capture '<<<(.*?)$' '^\h*(.*?);' fill string + + +add-highlighter shared/php/code/ regex &?\$\w* 0:variable +add-highlighter shared/php/code/ regex \b(false|null|parent|self|this|true)\b 0:value +add-highlighter shared/php/code/ regex "(\b|-)[0-9]*\.?[0-9]+\b" 0:value +add-highlighter shared/php/code/ regex \b((string|int|bool)|[A-Z][a-z].*?)\b 0:type +add-highlighter shared/php/code/ regex \B/[^\n/]+/[gimy]* 0:meta +add-highlighter shared/php/code/ regex '<\?(php)?|\?>' 0:meta + +add-highlighter shared/php/double_string/ fill string +add-highlighter shared/php/double_string/ regex (?<!\\)(\\\\)*(\$\w+)(->\w+)* 0:variable +add-highlighter shared/php/double_string/ regex \{(?<!\\)(\\\\)*(\$\w+)(->\w+)*\} 0:variable + +# Highlight doc comments +add-highlighter shared/php/doc_comment/ fill string +add-highlighter shared/php/doc_comment/ regex '`.*`' 0:module +add-highlighter shared/php/doc_comment/ regex '@\w+' 0:meta + +# Keywords are collected at +# http://php.net/manual/en/reserved.keywords.php +add-highlighter shared/php/code/ regex \b(__halt_compiler|abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|final|finally|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|new|or|print|private|protected|public|require|require_once|return|static|switch|throw|trait|try|unset|use|var|while|xor|yield|__CLASS__|__DIR__|__FILE__|__FUNCTION__|__LINE__|__METHOD__|__NAMESPACE__|__TRAIT__)\b 0:keyword + +# Highlighter for html with php tags in it, i.e. the structure of conventional php files +add-highlighter shared/php-file regions +add-highlighter shared/php-file/html default-region ref html +add-highlighter shared/php-file/php region '<\?(php)?' '\?>' ref php + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden php-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden php-indent-on-char %< + evaluate-commands -draft -itersel %< + # align closer token to its opener when alone on a line + try %/ execute-keys -draft <a-h> <a-k> ^\h+[\]}]$ <ret> m s \A|.\z <ret> 1<a-&> / + > +> + +define-command -hidden php-insert-on-new-line %< + evaluate-commands -draft -itersel %< + # copy // comments or docblock * prefix and following white spaces + try %{ execute-keys -draft s [^/] <ret> k x s ^\h*\K(?://|[*][^/])\h* <ret> y gh j P } + # append " * " on lines starting a multiline /** or /* comment + try %{ execute-keys -draft k x s ^\h*/[*][* ]? <ret> j gi i <space>*<space> } + > +> + +define-command -hidden php-indent-on-new-line %< + evaluate-commands -draft -itersel %< + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : php-trim-indent <ret> } + # indent after lines beginning / ending with opener token + try %_ execute-keys -draft k x <a-k> ^\h*[[{]|[[{]$ <ret> j <a-gt> _ + # deindent closer token(s) when after cursor + try %_ execute-keys -draft x <a-k> ^\h*[})] <ret> gh / [})] <ret> m <a-S> 1<a-&> _ + > +> + +§ diff --git a/autoload/filetype/pony.kak b/autoload/filetype/pony.kak new file mode 100644 index 0000000..6a91688 --- /dev/null +++ b/autoload/filetype/pony.kak @@ -0,0 +1,155 @@ +# http://ponylang.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](pony) %{ + set-option buffer filetype pony +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=pony %{ + require-module pony + + set-option window static_words %opt{pony_static_words} + + # cleanup trailing whitespaces on current line insert end + hook window ModeChange pop:insert:.* -group pony-trim-indent %{ try %{ execute-keys -draft <semicolon> x s ^\h+$ <ret> d } } + hook window InsertChar \n -group pony-indent pony-indent-on-new-line + hook window InsertChar \n -group pony-insert pony-insert-on-new-line + + set-option buffer extra_word_chars '_' "'" + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window pony-.+ } +} + +hook -group pony-highlight global WinSetOption filetype=pony %{ + add-highlighter window/pony ref pony + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter pony } +} + +provide-module pony %§ + +# Highlighters & Completion +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/pony regions +add-highlighter shared/pony/code default-region group + +add-highlighter shared/pony/comment region '/\*' '\*/' fill comment +add-highlighter shared/pony/line_comment region '//' '$' fill comment + +# String literals +add-highlighter shared/pony/string region -match-capture '("""|")' '(?<!\\)(?:\\\\)*("""|")' group +add-highlighter shared/pony/string/ fill string +add-highlighter shared/pony/string/ regex '(?:\\a|\\b|\\e|\\f|\\n|\\r|\\t||\\v|\\\\|\\''|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}|\\u[0-9a-fA-F]{6})' 0:meta + +# Character literals +# negative lookbehind to account for variables with prime such as myvar' or myvar'' +add-highlighter shared/pony/character region "(?<![a-z0-9'])'" (?<!\\)(\\\\)*' group +add-highlighter shared/pony/character/ fill string +add-highlighter shared/pony/character/ regex '(?:\\a|\\b|\\e|\\f|\\n|\\r|\\t||\\v|\\\\|\\''|\\0|\\x[0-9a-fA-F]{2})' 0:meta + +# Operators +add-highlighter shared/pony/code/ regex '=|\+|-|\*|/|%|%%|<<|>>|==|!=|<|<=|>=|>|=>|;' 0:operator +add-highlighter shared/pony/code/ regex '(\+|-|\*|/|%|%%|<<|>>|==|!=|<|<=|>=|>)~' 0:operator +add-highlighter shared/pony/code/ regex '(\+|-|\*|/|%|%%)\?' 0:operator +add-highlighter shared/pony/code/ regex '^\h*|' 0:operator +add-highlighter shared/pony/code/ regex '\b_\b' 0:operator + +# Integer literals +add-highlighter shared/pony/code/ regex '\b[0-9](_?[0-9])*\b' 0:value +add-highlighter shared/pony/code/ regex '\b0x[0-9a-fA-F](_?[0-9a-fA-F])*\b' 0:value +add-highlighter shared/pony/code/ regex '\b0b[01](_?[01])*\b' 0:value + +# Float literals +add-highlighter shared/pony/code/ regex '\b[0-9]+\.[0-9]+(?:[eE][-+]?[0-9]+)?\b' 0:value +add-highlighter shared/pony/code/ regex '\b[0-9]+[eE][-+]?[0-9]+\b' 0:value + +# Type literals +add-highlighter shared/pony/code/ regex '\b_?[A-Z][A-Za-z0-9]*\b' 0:type + +# Literal words are highlighted below to also allow for autocompletion by appending +# them to static_words. +evaluate-commands %sh{ + # Grammar + values="true|false|this" + meta='use' + # Keyword list is collected using `keyword.kwlist` from `keyword` + keywords="as|break|match|continue|else|elseif|try|in|return|end|for|is" + keywords="${keywords}|recover|consume|error|do|then|if|while|where|with" + keywords="${keywords}|class|struct|object|actor|interface|trait|primitive" + keywords="${keywords}|type|var|let|embed|repeat|until|addressof" + func_decl="new|fun|be" + capabilities="iso|ref|box|tag|val|trn" + operators="and|or|xor|not" + builtin_types="String|None|Any|Array" + + # Add the language's grammar to the static completion list + static_words="${values} ${meta} ${keywords} ${types_decl} ${capabilities}" + static_words="${static_words} ${operators} ${builtin_types}" + printf %s\\n "declare-option str-list pony_static_words ${static_words}" | tr '|' ' ' + + # Highlight keywords + # The (?!') ensures that keywords with prime are highlighted as usual, for example try' + printf %s " + add-highlighter shared/pony/code/ regex \b(${values})\b(?!') 0:value + add-highlighter shared/pony/code/ regex \b(${operators})\b(?!') 0:operator + add-highlighter shared/pony/code/ regex \b(${meta})\b(?!') 0:meta + add-highlighter shared/pony/code/ regex \b(${func_decl})(\s+(${capabilities}))?(\s+\w+)[\[(] 1:keyword 3:attribute 4:function + add-highlighter shared/pony/code/ regex \b(${func_decl})\b(?!') 0:keyword + add-highlighter shared/pony/code/ regex \b(${keywords})\b(?!') 0:keyword + add-highlighter shared/pony/code/ regex \b(${capabilities})\b(?!')(!|\\^)? 1:attribute 2:attribute + " + + # Highlight types and attributes + printf %s " + add-highlighter shared/pony/code/ regex '@[\w_]+\b' 0:attribute + " +} + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden pony-insert-on-new-line %< + evaluate-commands -no-hooks -draft -itersel %< + # copy // comments prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K//\h* <ret> y jgi P } + + # wisely add `end` keyword + evaluate-commands -save-regs x %< + try %{ execute-keys -draft k x s ^ \h + <ret> \" x y } catch %{ reg x '' } + try %< + evaluate-commands -draft %< + # Check if previous line opens a block + execute-keys -draft kx <a-k>^<c-r>x(try|match|recover|repeat|object|.+\bdo$|.+\bthen$)[^0-9A-Za-z_']<ret> + # Check that we didn't put an end on the previous line that closes the block + execute-keys -draft kx <a-K> \bend$<ret> + # Check that we do not already have an end for this indent level which is first set via `pony-indent-on-new-line` hook + execute-keys -draft }i J x <a-K> ^<c-r>x(end|else|elseif|until)[^0-9A-Za-z_']<ret> + > + execute-keys -draft o<c-r>xend<esc> # insert a new line with containing end + > + > + > +> + +define-command -hidden pony-indent-on-new-line %{ + evaluate-commands -no-hooks -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft , K <a-&> } + # cleanup trailing whitespaces from previous line + try %{ execute-keys -draft k x s \h+$ <ret> d } + # indent after line ending with: =>, do, try, then, else, =; or + # starting with: actor, class, struct, trait, interface, if, elseif, recover, repeat + # excluding: primitive, type -- because they are often written in a single line + try %{ execute-keys -draft , k x <a-k> (\b(?:do|try|then|else|recover|repeat)|=>|=)$ | ^\h*(actor|class|struct|trait|interface|object)\b <ret> j <a-gt> } + # else, end are always de-indented + try %{ execute-keys -draft , k x <a-k> \b(else|end):$ <ret> k x s ^\h* <ret> y j x <a-k> ^<c-r>" <ret> J <a-lt> } + } +} + +§ diff --git a/autoload/filetype/prolog.kak b/autoload/filetype/prolog.kak new file mode 100644 index 0000000..fa183c1 --- /dev/null +++ b/autoload/filetype/prolog.kak @@ -0,0 +1,49 @@ +# Prolog +# ---------------------- + +# Adapted from rc/filetype/erlang.kak + +# Detection +# ‾‾‾‾‾‾‾‾‾ +hook global BufCreate .*[.](pl|P) %{ + set-option buffer filetype prolog +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +hook global WinSetOption filetype=prolog %{ + require-module prolog + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window prolog-.+ } +} + +hook -group prolog-highlight global WinSetOption filetype=prolog %{ + add-highlighter window/prolog ref prolog + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/prolog } +} + +provide-module prolog %[ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/prolog regions +add-highlighter shared/prolog/default default-region group + +add-highlighter shared/prolog/comment region '(?<!)%' '$' fill comment +add-highlighter shared/prolog/attribute_atom_single_quoted region %{-'} %{(?<!\\)(?:\\\\)*'(?=[\( \.])} fill builtin +add-highlighter shared/prolog/attribute region '\b-[a-z][\w@]*(?=[\( \.])' '\K' fill builtin +add-highlighter shared/prolog/atom_single_quoted region %{'} %{(?<!\\)(?:\\\\)*'} fill type +add-highlighter shared/prolog/char_list region %{"} %{(?<!\\)(?:\\\\)*"} fill string + +# default-region regex highlighters +add-highlighter shared/prolog/default/atom regex '\b[a-z]\w*\b' 0:type +add-highlighter shared/prolog/default/pred_call regex '\b[a-z]\w*(?=\()' 0:function +add-highlighter shared/prolog/default/keywords regex '\b(div|rem|is)\b' 0:keyword +add-highlighter shared/prolog/default/variable_name regex '\b(?<!\?)[A-Z_][\w]*\b' 0:variable + +add-highlighter shared/prolog/default/base_number regex '\b(\d[_\d]*(?<!_)#[a-zA-Z0-9][a-z_A-Z0-9]*(?<!_)(?!\{))\b' 1:value +add-highlighter shared/prolog/default/float regex '\b(?<![\.])(\d[\d_]*(?<!_)\.\d[\d_]*(?<!_)(?:e[+-]?\d[\d_]*(?<!_))?)\b' 1:value +add-highlighter shared/prolog/default/integer regex '\b(?<!/)(\d[\d_]*)(?<!_)\b' 1:value + +] diff --git a/autoload/filetype/protobuf.kak b/autoload/filetype/protobuf.kak new file mode 100644 index 0000000..b85295e --- /dev/null +++ b/autoload/filetype/protobuf.kak @@ -0,0 +1,109 @@ +# https://developers.google.com/protocol-buffers/ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*\.proto$ %{ + set-option buffer filetype protobuf +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=protobuf %[ + require-module protobuf + + set-option window static_words %opt{protobuf_static_words} + + hook window ModeChange pop:insert:.* -group protobuf-trim-indent protobuf-trim-indent + hook -group protobuf-insert window InsertChar \n protobuf-insert-on-newline + hook -group protobuf-indent window InsertChar \n protobuf-indent-on-newline + hook -group protobuf-indent window InsertChar \{ protobuf-indent-on-opening-curly-brace + hook -group protobuf-indent window InsertChar \} protobuf-indent-on-closing-curly-brace + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window protobuf-.+ } +] + +hook -group protobuf-highlight global WinSetOption filetype=protobuf %{ + add-highlighter window/protobuf ref protobuf + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/protobuf } +} + +provide-module protobuf %[ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/protobuf regions +add-highlighter shared/protobuf/code default-region group +add-highlighter shared/protobuf/double_string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/protobuf/comment region /\* \*/ fill comment +add-highlighter shared/protobuf/comment_line region '//' $ fill comment + +add-highlighter shared/protobuf/code/ regex %{(0x)?[0-9]+\b} 0:value + +evaluate-commands %sh{ + # Grammer + keywords='default deprecated enum extend import message oneof option + package service syntax' + attributes='optional repeated required' + types='double float int32 int64 uint32 uint64 sint32 sint64 fixed32 fixed64 + sfixed32 sfixed64 bool string bytes rpc' + values='false true' + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # Add the language's grammer to the static completion list + printf %s\\n "declare-option str-list protobuf_static_words $(join "${keywords} ${attributes} ${types} ${values}" ' ')" + + # Highlight keywords + printf %s " + add-highlighter shared/protobuf/code/keywords regex \b($(join "${keywords}" '|'))\b 0:keyword + add-highlighter shared/protobuf/code/attributes regex \b($(join "${attributes}" '|'))\b 0:attribute + add-highlighter shared/protobuf/code/types regex \b($(join "${types}" '|'))\b 0:type + add-highlighter shared/protobuf/code/values regex \b($(join "${values}" '|'))\b 0:value + " +} + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden protobuf-trim-indent %{ + evaluate-commands -no-hooks -draft -itersel %{ + execute-keys x + # remove trailing white spaces + try %{ execute-keys -draft s \h + $ <ret> d } + } +} + +define-command -hidden protobuf-insert-on-newline %{ + evaluate-commands -draft -itersel %[ + # copy // comments prefix + try %{ execute-keys -draft <semicolon><c-s>kx s ^\h*\K/{2,}(\h*(?=\S))? <ret> y<c-o>P<esc> } + ] +} + +define-command -hidden protobuf-indent-on-newline %~ + evaluate-commands -draft -itersel %[ + # preserve previous line indent + try %{ execute-keys -draft <semicolon>K<a-&> } + # indent after lines ending with { + try %[ execute-keys -draft kx <a-k> \{\h*$ <ret> j<a-gt> ] + # cleanup trailing white spaces on the previous line + try %{ execute-keys -draft kx s \h+$ <ret>d } + # deindent closing brace(s) when after cursor + try %[ execute-keys -draft x <a-k> ^\h*\} <ret> gh / \} <ret> m <a-S> 1<a-&> ] + ] +~ + +define-command -hidden protobuf-indent-on-opening-curly-brace %[ + # align indent with opening paren when { is entered on a new line after the closing paren + try %[ execute-keys -draft -itersel h<a-F>)M <a-k> \A\(.*\)\h*\n\h*\{\z <ret> s \A|.\z <ret> 1<a-&> ] +] + +define-command -hidden protobuf-indent-on-closing-curly-brace %[ + # align to opening curly brace when alone on a line + try %[ execute-keys -itersel -draft <a-h><a-k>^\h+\}$<ret>hms\A|.\z<ret>1<a-&> ] +] + +] diff --git a/autoload/filetype/pug.kak b/autoload/filetype/pug.kak new file mode 100644 index 0000000..db05c9b --- /dev/null +++ b/autoload/filetype/pug.kak @@ -0,0 +1,81 @@ +# Note: jade is changing its name to pug (https://github.com/pugjs/pug/issues/2184) +# This appears to be a work in progress -- the pug-lang domain is parked, while +# the jade-lang one is active. This highlighter will recognize .pug and .jade extensions, + +# http://jade-lang.com (will be http://pug-lang.com) +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](pug|jade) %{ + set-option buffer filetype pug +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=pug %{ + require-module pug + + hook window ModeChange pop:insert:.* -group pug-trim-indent pug-trim-indent + hook window InsertChar \n -group pug-indent pug-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window pug-.+ } +} + +hook -group pug-highlight global WinSetOption filetype=pug %{ + add-highlighter window/pug ref pug + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/pug } +} + + +provide-module pug %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/pug regions +add-highlighter shared/pug/code default-region group +add-highlighter shared/pug/text region ^\h*\|\s $ regex \h*(\|) 1:meta +add-highlighter shared/pug/text2 region '^\h*([A-Za-z][A-Za-z0-9_-]*)?(#[A-Za-z][A-Za-z0-9_-]*)?((?:\.[A-Za-z][A-Za-z0-9_-]*)*)?(?<!\t)(?<! )(?<!\n)\h+\K.*' $ regex \h*(\|) 1:meta +add-highlighter shared/pug/javascript region ^\h*[-=!] $ ref javascript +add-highlighter shared/pug/double_string region '"' (?:(?<!\\)(\\\\)*"|$) fill string +add-highlighter shared/pug/single_string region "'" (?:(?<!\\)(\\\\)*'|$) fill string +add-highlighter shared/pug/comment region // $ fill comment +add-highlighter shared/pug/attribute region -recurse \( \( \) group +add-highlighter shared/pug/puglang region ^\h*\b(\block|extends|include|append|prepend|if|unless|else|case|when|default|each|while|mixin)\b $ group + +# Filters +# ‾‾‾‾‾‾‾ + +add-highlighter shared/pug/attribute/ ref javascript +add-highlighter shared/pug/attribute/ regex [()=] 0:operator +add-highlighter shared/pug/puglang/ ref javascript +add-highlighter shared/pug/puglang/ regex \b(\block|extends|include|append|prepend|if|unless|else|case|when|default|each|while|mixin|of|in)\b 0:keyword +add-highlighter shared/pug/code/ regex ^\h*([A-Za-z][A-Za-z0-9_-]*) 1:type +add-highlighter shared/pug/code/ regex '(#[A-Za-z][A-Za-z0-9_-]*)' 1:variable +add-highlighter shared/pug/code/ regex ((?:\.[A-Za-z][A-Za-z0-9_-]*)*) 1:value + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden pug-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden pug-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : pug-trim-indent <ret> } + # copy '//', '|', '-' or '(!)=' prefix and following whitespace + try %{ execute-keys -draft k x s ^\h*\K[/|!=-]{1,2}\h* <ret> y gh j P } + # indent unless we copied something above + try %{ execute-keys -draft <a-gt> , b s \S <ret> g l <a-lt> } + } +} + +} diff --git a/autoload/filetype/purescript.kak b/autoload/filetype/purescript.kak new file mode 100644 index 0000000..8945ae6 --- /dev/null +++ b/autoload/filetype/purescript.kak @@ -0,0 +1,120 @@ +# http://purescript.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +# Syntax reference +# https://github.com/purescript/documentation/blob/master/language/Syntax.md + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](purs) %{ + set-option buffer filetype purescript +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=purescript %{ + require-module purescript + + set-option buffer extra_word_chars '_' "'" + hook window ModeChange pop:insert:.* -group purescript-trim-indent purescript-trim-indent + hook window InsertChar \n -group purescript-insert purescript-insert-on-new-line + hook window InsertChar \n -group purescript-indent purescript-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window purescript-.+ } +} + +hook -group purescript-highlight global WinSetOption filetype=purescript %{ + add-highlighter window/purescript ref purescript + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/purescript } +} + + +provide-module purescript %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/purescript regions +add-highlighter shared/purescript/code default-region group +add-highlighter shared/purescript/string region (?<!'\\)(?<!')" (?<!\\)(\\\\)*" fill string +add-highlighter shared/purescript/comment region -recurse \{- \{- -\} fill comment +add-highlighter shared/purescript/line_comment region --(?:[^!#$%&*+./<>?@\\\^|~=]|$) $ fill comment + +add-highlighter shared/purescript/code/ regex (?<!')\b0x+[A-Fa-f0-9]+ 0:value +add-highlighter shared/purescript/code/ regex (?<!')\b\d+([.]\d+)? 0:value +add-highlighter shared/purescript/code/ regex (?<!')\b(import|hiding|module)(?!')\b 0:keyword +add-highlighter shared/purescript/code/ regex (?<!')\b(import)(?!')\b[^\n]+(?<!')\b(as)(?!')\b 2:keyword +add-highlighter shared/purescript/code/ regex (?<!')\b(class|data|default|derive|infix|infixl|infixr|instance|module|newtype|pattern|type|where)(?!')\b 0:keyword +add-highlighter shared/purescript/code/ regex (?<!')\b(case|do|else|if|in|let|mdo|of|proc|rec|then)(?!')\b 0:attribute +add-highlighter shared/purescript/code/ regex (?<!')\b(type|data)\b\s+(\bfamily\b)?(?!') 0:keyword + +# The complications below is because period has many uses: +# As function composition operator (possibly without spaces) like "." and "f.g" +# Hierarchical modules like "Data.Maybe" +# Qualified imports like "Data.Maybe.Just", "Data.Maybe.maybe", "Control.Applicative.<$>" +# Quantifier separator in "forall a . [a] -> [a]" +# Enum comprehensions like "[1..]" and "[a..b]" (making ".." and "Module..." illegal) + +# matches uppercase identifiers: Monad Control.Monad +# not non-space separated dot: Just.const +add-highlighter shared/purescript/code/ regex \b([A-Z]['\w]*\.)*[A-Z]['\w]*(?!['\w])(?![.a-z]) 0:variable + +# matches infix identifier: `mod` `Apa._T'M` +add-highlighter shared/purescript/code/ regex `\b([A-Z]['\w]*\.)*[\w]['\w]*` 0:operator +# matches imported operators: M.! M.. Control.Monad.>> +# not operator keywords: M... M.-> +add-highlighter shared/purescript/code/ regex \b[A-Z]['\w]*\.[~<=>|:!?/.@$*&#%+\^\-\\]+ 0:operator +# matches dot: . +# not possibly incomplete import: a. +# not other operators: !. .! +add-highlighter shared/purescript/code/ regex (?<![\w~<=>|:!?/.@$*&#%+\^\-\\])\.(?![~<=>|:!?/.@$*&#%+\^\-\\]) 0:operator +# matches other operators: ... > < <= ^ <*> <$> etc +# not dot: . +# not operator keywords: @ .. -> :: ~ +add-highlighter shared/purescript/code/ regex (?<![~<=>|:!?/.@$*&#%+\^\-\\])[~<=>|:!?/.@$*&#%+\^\-\\]+ 0:operator + +# matches operator keywords: @ -> +add-highlighter shared/purescript/code/ regex (?<![~<=>|:!?/.@$*&#%+\^\-\\])(@|~|<-|->|=>|::|=|:|[|])(?![~<=>|:!?/.@$*&#%+\^\-\\]) 1:keyword +# matches: forall [..variables..] . +# not the variables +add-highlighter shared/purescript/code/ regex \b(forall|∀)\b[^.\n]*?(\.) 1:keyword 2:keyword + +# matches 'x' '\\' '\'' '\n' '\0' +# not incomplete literals: '\' +# not valid identifiers: w' _' +add-highlighter shared/purescript/code/ regex \B'([^\\]|[\\]['"\w\d\\])' 0:string +# this has to come after operators so '-' etc is correct + +# matches function names in type signatures +add-highlighter shared/purescript/code/ regex ^\s*(?:where\s+|let\s+|default\s+)?([_a-z]['\w]*#?(?:,\s*[_a-z]['\w]*#?)*)\s+::\s 1:meta + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden purescript-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden purescript-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy -- comments prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K--\h* <ret> y gh j P } + } +} + +define-command -hidden purescript-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # align to first clause + try %{ execute-keys -draft <semicolon> k x X s ^\h*(if|then|else)?\h*(([\w']+\h+)+=)?\h*(case\h+[\w']+\h+of|do|let|where)\h+\K.* <ret> s \A|.\z <ret> & } + # filter previous line + try %{ execute-keys -draft k : purescript-trim-indent <ret> } + # indent after lines beginning with condition or ending with expression or =( + try %{ execute-keys -draft <semicolon> k x <a-k> ^\h*if|[=(]$|\b(case\h+[\w']+\h+of|do|let|where)$ <ret> j <a-gt> } + } +} + +§ diff --git a/autoload/filetype/python.kak b/autoload/filetype/python.kak new file mode 100644 index 0000000..65da1a8 --- /dev/null +++ b/autoload/filetype/python.kak @@ -0,0 +1,199 @@ +# http://python.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](py) %{ + set-option buffer filetype python +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=python %{ + require-module python + + set-option window static_words %opt{python_static_words} + + hook window InsertChar \n -group python-insert python-insert-on-new-line + hook window InsertChar \n -group python-indent python-indent-on-new-line + # cleanup trailing whitespaces on current line insert end + hook window ModeChange pop:insert:.* -group python-trim-indent %{ try %{ execute-keys -draft <semicolon> x s ^\h+$ <ret> d } } + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window python-.+ } +} + +hook -group python-highlight global WinSetOption filetype=python %{ + add-highlighter window/python ref python + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/python } +} + +provide-module python %§ + +# Highlighters & Completion +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/python regions +add-highlighter shared/python/code default-region group +add-highlighter shared/python/docstring region -match-capture ^\h*("""|''') (?<!\\)(?:\\\\)*("""|''') regions + +add-highlighter shared/python/documentation region '##' '$' fill documentation +add-highlighter shared/python/comment region '#' '$' fill comment + +# String interpolation +add-highlighter shared/python/f_triple_string region -match-capture [fF]("""|''') (?<!\\)(?:\\\\)*("""|''') group +add-highlighter shared/python/f_triple_string/ fill string +add-highlighter shared/python/f_triple_string/ regex \{.*?\} 0:value + +add-highlighter shared/python/f_double_string region '[fF]"' (?<!\\)(\\\\)*" group +add-highlighter shared/python/f_double_string/ fill string +add-highlighter shared/python/f_double_string/ regex \{.*?\} 0:value + +add-highlighter shared/python/f_single_string region "[fF]'" (?<!\\)(\\\\)*' group +add-highlighter shared/python/f_single_string/ fill string +add-highlighter shared/python/f_single_string/ regex \{.*?\} 0:value + + +# Regular string +add-highlighter shared/python/triple_string region -match-capture ("""|''') (?<!\\)(?:\\\\)*("""|''') fill string +add-highlighter shared/python/double_string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/python/single_string region "'" (?<!\\)(\\\\)*' fill string + +# Integer formats +add-highlighter shared/python/code/ regex '(?i)\b0b[01]+l?\b' 0:value +add-highlighter shared/python/code/ regex '(?i)\b0x[\da-f]+l?\b' 0:value +add-highlighter shared/python/code/ regex '(?i)\b0o?[0-7]+l?\b' 0:value +add-highlighter shared/python/code/ regex '(?i)\b([1-9]\d*|0)l?\b' 0:value +# Float formats +add-highlighter shared/python/code/ regex '\b\d+[eE][+-]?\d+\b' 0:value +add-highlighter shared/python/code/ regex '(\b\d+)?\.\d+\b' 0:value +add-highlighter shared/python/code/ regex '\b\d+\.' 0:value +# Imaginary formats +add-highlighter shared/python/code/ regex '\b\d+\+\d+[jJ]\b' 0:value + +add-highlighter shared/python/docstring/ default-region fill documentation +add-highlighter shared/python/docstring/ region '(>>>|\.\.\.) \K' (?=''')|(?=""") ref python + +evaluate-commands %sh{ + # Grammar + values="True False None self inf" + meta="import from" + + # attributes and methods list based on https://docs.python.org/3/reference/datamodel.html + attributes="__annotations__ __closure__ __code__ __defaults__ __dict__ __doc__ + __globals__ __kwdefaults__ __module__ __name__ __qualname__" + methods="__abs__ __add__ __aenter__ __aexit__ __aiter__ __and__ __anext__ + __await__ __bool__ __bytes__ __call__ __complex__ __contains__ + __del__ __delattr__ __delete__ __delitem__ __dir__ __divmod__ + __enter__ __eq__ __exit__ __float__ __floordiv__ __format__ + __ge__ __get__ __getattr__ __getattribute__ __getitem__ + __gt__ __hash__ __iadd__ __iand__ __ifloordiv__ __ilshift__ + __imatmul__ __imod__ __imul__ __index__ __init__ + __init_subclass__ __int__ __invert__ __ior__ __ipow__ + __irshift__ __isub__ __iter__ __itruediv__ __ixor__ __le__ + __len__ __length_hint__ __lshift__ __lt__ __matmul__ + __missing__ __mod__ __mul__ __ne__ __neg__ __new__ __or__ + __pos__ __pow__ __radd__ __rand__ __rdivmod__ __repr__ + __reversed__ __rfloordiv__ __rlshift__ __rmatmul__ __rmod__ + __rmul__ __ror__ __round__ __rpow__ __rrshift__ __rshift__ + __rsub__ __rtruediv__ __rxor__ __set__ __setattr__ + __setitem__ __set_name__ __slots__ __str__ __sub__ + __truediv__ __xor__" + + # built-in exceptions https://docs.python.org/3/library/exceptions.html + exceptions="ArithmeticError AssertionError AttributeError BaseException BlockingIOError + BrokenPipeError BufferError BytesWarning ChildProcessError + ConnectionAbortedError ConnectionError ConnectionRefusedError + ConnectionResetError DeprecationWarning EOFError Exception + FileExistsError FileNotFoundError FloatingPointError FutureWarning + GeneratorExit ImportError ImportWarning IndentationError + IndexError InterruptedError IsADirectoryError KeyboardInterrupt + KeyError LookupError MemoryError ModuleNotFoundError NameError + NotADirectoryError NotImplementedError OSError OverflowError + PendingDeprecationWarning PermissionError ProcessLookupError + RecursionError ReferenceError ResourceWarning RuntimeError + RuntimeWarning StopAsyncIteration StopIteration SyntaxError + SyntaxWarning SystemError SystemExit TabError TimeoutError TypeError + UnboundLocalError UnicodeDecodeError UnicodeEncodeError UnicodeError + UnicodeTranslateError UnicodeWarning UserWarning ValueError Warning + ZeroDivisionError" + + # Keyword list is collected using `keyword.kwlist` from `keyword` + keywords="and as assert async await break class continue def del elif else except exec + finally for global if in is lambda nonlocal not or pass print + raise return try while with yield" + + # Collected from `keyword.softkwlist` + soft_keywords="_ case match" + + types="bool buffer bytearray bytes complex dict file float frozenset int + list long memoryview object set str tuple unicode xrange" + + functions="abs all any ascii bin breakpoint callable chr classmethod compile complex + delattr dict dir divmod enumerate eval exec filter + format frozenset getattr globals hasattr hash help + hex id __import__ input isinstance issubclass iter + len locals map max memoryview min next oct open ord + pow print property range repr reversed round + setattr slice sorted staticmethod sum super type vars zip" + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list python_static_words $(join "${values} ${meta} ${attributes} ${methods} ${exceptions} ${keywords} ${types} ${functions}" ' ')" + + # Highlight keywords + printf %s " + add-highlighter shared/python/code/ regex '\b($(join "${values}" '|'))\b' 0:value + add-highlighter shared/python/code/ regex '\b($(join "${meta}" '|'))\b' 0:meta + add-highlighter shared/python/code/ regex '\b($(join "${attributes}" '|'))\b' 0:attribute + add-highlighter shared/python/code/ regex '\bdef\s+($(join "${methods}" '|'))\b' 1:function + add-highlighter shared/python/code/ regex '\b($(join "${exceptions}" '|'))\b' 0:function + add-highlighter shared/python/code/ regex '\b($(join "${keywords} ${soft_keywords}" '|'))\b' 0:keyword + add-highlighter shared/python/code/ regex '\b($(join "${functions}" '|'))\b\(' 1:builtin + add-highlighter shared/python/code/ regex '\b($(join "${types}" '|'))\b' 0:type + add-highlighter shared/python/code/ regex '^\h*(@[\w_.]+))' 1:attribute + " +} + +add-highlighter shared/python/code/ regex (?<=[\w\s\d\)\]'"_])(<=|<<|>>|>=|<>?|>|!=|==|\||\^|&|\+|-|\*\*?|//?|%|~) 0:operator +add-highlighter shared/python/code/ regex (?<=[\w\s\d'"_])((?<![=<>!]):?=(?![=])|[+*-]=) 0:builtin +add-highlighter shared/python/code/ regex ^\h*(?:from|import)\h+(\S+) 1:module + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden python-insert-on-new-line %{ evaluate-commands -itersel -draft %{ + execute-keys <semicolon> + try %{ + evaluate-commands -draft -save-regs '/"' %{ + # copy the commenting prefix + execute-keys -save-regs '' k x1s^\h*(#+\h*)<ret> y + try %{ + # if the previous comment isn't empty, create a new one + execute-keys x<a-K>^\h*#+\h*$<ret> jxs^\h*<ret>P + } catch %{ + # if there is no text in the previous comment, remove it completely + execute-keys d + } + } + + # trim trailing whitespace on the previous line + try %{ execute-keys -draft k x s\h+$<ret> d } + } +} } + +define-command -hidden python-indent-on-new-line %< + evaluate-commands -draft -itersel %< + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # cleanup trailing whitespaces from previous line + try %{ execute-keys -draft k x s \h+$ <ret> d } + # indent after line ending with : + try %{ execute-keys -draft , k x <a-k> :$ <ret> <a-K> ^\h*# <ret> j <a-gt> } + # deindent closing brace/bracket when after cursor (for arrays and dictionaries) + try %< execute-keys -draft x <a-k> ^\h*[}\]] <ret> gh / [}\]] <ret> m <a-S> 1<a-&> > + > +> + +§ diff --git a/autoload/filetype/r.kak b/autoload/filetype/r.kak new file mode 100644 index 0000000..d3d9854 --- /dev/null +++ b/autoload/filetype/r.kak @@ -0,0 +1,155 @@ +# http://kakoune.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate (.*/)?(\.Rprofile|.*\.[rR]) %{ + set-option buffer filetype r +} + +provide-module r %§ + +# Highlighters & Completion +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/r regions +add-highlighter shared/r/code default-region group +add-highlighter shared/r/double_string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/r/single_string region "'" (?<!\\)(\\\\)*' fill string +add-highlighter shared/r/comment region '#' '$' fill comment +add-highlighter shared/r/identifier region '`' (?<!\\)(\\\\)*` fill attribute + +# see base::NumericConstants +add-highlighter shared/r/code/ regex '(?i)\b(?<![.\d])\d+(\.\d*)?(e[-+]?\d+)?(?I)[iL]?(?![\d.e\w])' 0:value +add-highlighter shared/r/code/ regex '(?i)(?<![.\d\w])\.\d+(e[-+]?\d+)?(?I)[iL]?(?![\d.e])' 0:value +add-highlighter shared/r/code/ regex '(?i)\b(?<![.\d])0x[0-9a-f]+?(p[-+]?\d+)?(?I)[iL]?(?![\d.e\w])' 0:value + +evaluate-commands %sh{ + # see base::Reserved + values="TRUE|FALSE|NULL|Inf|NaN|NA|NA_integer_|NA_real_|NA_complex_|NA_character_|\.{3}|\.{2}\d+|" + keywords="if|else|repeat|while|function|for|in|next|break" + + # see base::Ops and methods::Ops + math_functions="abs|sign|sqrt|floor|ceiling|trunc|round|signif|exp|log|expm1|log1p|cos|sin|tan|cospi|sinpi|tanpi|acos|asin|atan|cosh|sinh|tanh|acosh|asinh|atanh|lgamma|gamma|digamma|trigamma" + summary_functions="all|any|sum|prod|min|max|range" + complex_functions="Arg|Conj|Im|Mod|Re" + + # Add the language's grammar to the static completion list + printf %s\\n "hook global WinSetOption filetype=python %{ + set-option window static_words ${values} ${keywords} ${math_functions} ${summary_functions} ${complex_functions} + }" | tr '|' ' ' + + printf %s " + add-highlighter shared/r/code/ regex '\b(${values})\b' 0:value + add-highlighter shared/r/code/ regex '\b(${keywords})\b' 0:keyword + add-highlighter shared/r/code/ regex '\b(${math_functions}|${summary_functions}|${complex_functions})\b' 0:function + " +} + +# see base::Syntax +add-highlighter shared/r/code/ regex (?<=[\w\s\d'"_)])(\$|@|\^|-|\+|%[^%^\n]+%|\*|/|<|>|<=|>=|!|&{1,2}|\|{1,2}|~|\?|:{1,3}|\[{1,2}|\]{1,2}|={1,2}|<{1,2}-|->{1,2}|!=|%%) 0:operator + + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden r-trim-indent %{ + # remove the line if it's empty when leaving the insert mode + try %{ execute-keys -draft x 1s^(\h+)$<ret> d } +} + +define-command -hidden r-indent-on-newline %< evaluate-commands -draft -itersel %< + execute-keys <semicolon> + try %< + # if previous line closed a paren (possibly followed by words and a comment), + # copy indent of the opening paren line + execute-keys -draft kx 1s(\))(\h+\w+)*\h*(\;\h*)?(?:#[^\n]+)?\n\z<ret> m<a-semicolon>J <a-S> 1<a-&> + > catch %< + # else indent new lines with the same level as the previous one + execute-keys -draft K <a-&> + > + # remove previous empty lines resulting from the automatic indent + try %< execute-keys -draft k x <a-k>^\h+$<ret> Hd > + # indent after an opening brace or parenthesis at end of line + try %< execute-keys -draft k x s[{(]\h*$<ret> j <a-gt> > + # indent after a statement not followed by an opening brace + try %< execute-keys -draft k x s\)\h*(?:#[^\n]+)?\n\z<ret> \ + <a-semicolon>mB <a-k>\A\b(if|for|while)\b<ret> <a-semicolon>j <a-gt> > + try %< execute-keys -draft k x s \belse\b\h*(?:#[^\n]+)?\n\z<ret> \ + j <a-gt> > + # deindent after a single line statement end + try %< execute-keys -draft K x <a-k>\;\h*(#[^\n]+)?$<ret> \ + K x s\)(\h+\w+)*\h*(#[^\n]+)?\n([^\n]*\n){2}\z<ret> \ + MB <a-k>\A\b(if|for|while)\b<ret> <a-S>1<a-&> > + try %< execute-keys -draft K x <a-k>\;\h*(#[^\n]+)?$<ret> \ + K x s \belse\b\h*(?:#[^\n]+)?\n([^\n]*\n){2}\z<ret> \ + <a-S>1<a-&> > + # align to the opening parenthesis or opening brace (whichever is first) + # on a previous line if its followed by text on the same line + try %< evaluate-commands -draft %< + # Go to opening parenthesis and opening brace, then select the most nested one + try %< execute-keys [c [({],[)}] <ret> > + # Validate selection and get first and last char + execute-keys <a-k>\A[{(](\h*\S+)+\n<ret> <a-K>"(([^"]*"){2})*<ret> <a-K>'(([^']*'){2})*<ret> <a-:><a-semicolon>L <a-S> + # Remove possibly incorrect indent from new line which was copied from previous line + try %< execute-keys -draft , <a-h> s\h+<ret> d > + # Now indent and align that new line with the opening parenthesis/brace + execute-keys 1<a-&> & + > > +> > + +define-command -hidden r-indent-on-opening-curly-brace %[ + # align indent with opening paren when { is entered on a new line after the closing paren + try %[ execute-keys -draft -itersel h<a-F>)M <a-k> \A\(.*\)\h*\n\h*\{\z <ret> <a-S> 1<a-&> ] +] + +define-command -hidden r-indent-on-closing-curly-brace %[ + # align to opening curly brace when alone on a line + try %[ + # in case open curly brace follows a closing paren, align indent with opening paren + execute-keys -itersel -draft <a-h><a-:><a-k>^\h+\}$<ret>hm <a-F>)M <a-k> \A\(.*\)\h\{.*\}\z <ret> <a-S>1<a-&> + ] catch %[ + # otherwise align with open curly brace + execute-keys -itersel -draft <a-h><a-:><a-k>^\h+\}$<ret>hm<a-S>1<a-&> + ] catch %[] +] + +define-command -hidden r-insert-on-newline %[ evaluate-commands -itersel -draft %[ + execute-keys <semicolon> + try %[ + evaluate-commands -draft -save-regs '/"' %[ + # copy the commenting prefix + execute-keys -save-regs '' k x1s^\h*(#+\h*)<ret> y + try %[ + # if the previous comment isn't empty, create a new one + execute-keys x<a-K>^\h*#+\h*$<ret> jxs^\h*<ret>P + ] catch %[ + # if there is no text in the previous comment, remove it completely + execute-keys d + ] + ] + ] +] ] + +§ + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook -group r-highlight global WinSetOption filetype=r %{ + require-module r + add-highlighter window/r ref r + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/r } +} + +hook global WinSetOption filetype=r %~ + require-module r + hook window ModeChange pop:insert:.* r-trim-indent + hook window InsertChar \n r-insert-on-newline + hook window InsertChar \n r-indent-on-newline + hook window InsertChar \{ r-indent-on-opening-curly-brace + hook window InsertChar \} r-indent-on-closing-curly-brace + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window r-.+ } +~ diff --git a/autoload/filetype/ragel.kak b/autoload/filetype/ragel.kak new file mode 100644 index 0000000..e0a77db --- /dev/null +++ b/autoload/filetype/ragel.kak @@ -0,0 +1,84 @@ +# http://complang.org/ragel +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# ragel.kak does not try to detect host language. + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](ragel|rl) %{ + set-option buffer filetype ragel +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=ragel %{ + require-module ragel + + hook window ModeChange pop:insert:.* -group ragel-trim-indent ragel-trim-indent + hook window InsertChar .* -group ragel-indent ragel-indent-on-char + hook window InsertChar \n -group ragel-insert ragel-insert-on-new-line + hook window InsertChar \n -group ragel-indent ragel-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window ragel-.+ } +} + +hook -group ragel-highlight global WinSetOption filetype=ragel %{ + add-highlighter window/ragel ref ragel + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/ragel } +} + +provide-module ragel %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/ragel regions +add-highlighter shared/ragel/code default-region group +add-highlighter shared/ragel/double_string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/ragel/single_string region "'" "'" fill string +add-highlighter shared/ragel/comment region '#' '$' fill comment + +add-highlighter shared/ragel/code/ regex \b(true|false)\b 0:value +add-highlighter shared/ragel/code/ regex '%%\{|\}%%|<\w+>' 0:variable +add-highlighter shared/ragel/code/ regex :=|=>|->|:>|:>>|<: 0:operator +add-highlighter shared/ragel/code/ regex \b(action|alnum|alpha|any|ascii|case|cntrl|contained|context|data|digit|empty|eof|err|error|exec|export|exports|extend|fblen|fbreak|fbuf|fc|fcall|fcurs|fentry|fexec|fgoto|fhold|first_final|fnext|fpc|fret|from|fstack|ftargs|graph|import|include|init|inwhen|lerr|lower|machine|nocs|noend|noerror|nofinal|noprefix|outwhen|postpop|prepush|print|punct|range|space|start|to|upper|when|write|xdigit|zlen)\b 0:keyword + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden ragel-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden ragel-indent-on-char %< + evaluate-commands -draft -itersel %< + # align closer token to its opener when alone on a line + try %< execute-keys -draft <a-h> <a-k> ^\h+[\]})]$ <ret> m s \A|.\z <ret> 1<a-&> > + try %< execute-keys -draft <a-h> <a-k> ^\h+ [*]$ <ret> <a-?> [*]$ <ret> s \A|.\z <ret> 1<a-&> > + > +> + +define-command -hidden ragel-insert-on-new-line %< + evaluate-commands -draft -itersel %< + # copy _#_ comment prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K#\h* <ret> y gh j P } + > +> + +define-command -hidden ragel-indent-on-new-line %< + evaluate-commands -draft -itersel %< + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : ragel-trim-indent <ret> } + # indent after lines ending with opener token + try %< execute-keys -draft k x <a-k> [[{(*]$ <ret> j <a-gt> > + # align closer token to its opener when after cursor + try %< execute-keys -draft x <a-k> ^\h*[})\]] <ret> gh / [})\]] <ret> m <a-S> 1<a-&> > + > +> + +§ diff --git a/autoload/filetype/restructuredtext.kak b/autoload/filetype/restructuredtext.kak new file mode 100644 index 0000000..7853b30 --- /dev/null +++ b/autoload/filetype/restructuredtext.kak @@ -0,0 +1,92 @@ +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](rst) %{ + set-option buffer filetype restructuredtext +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=restructuredtext %{ + require-module restructuredtext +} + +hook -group restructuredtext-load-languages global WinSetOption filetype=restructuredtext %{ + restructuredtext-load-languages '%' +} + +hook -group restructuredtext-load-languages global WinSetOption filetype=restructuredtext %{ + hook -group restructuredtext-load-languages window NormalIdle .* %{restructuredtext-load-languages gtGbGl} + hook -group restructuredtext-load-languages window InsertIdle .* %{restructuredtext-load-languages gtGbGl} +} + +hook -group restructuredtext-highlight global WinSetOption filetype=restructuredtext %{ + add-highlighter window/restructuredtext ref restructuredtext + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/restructuredtext } +} + +provide-module restructuredtext %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/restructuredtext regions +add-highlighter shared/restructuredtext/content default-region group +add-highlighter shared/restructuredtext/code region ::\h*\n ^(?=\S) fill meta + +# Setext-style header +# Valid header characters: +# # ! " $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~ + +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(#{3,}\n)?[^\n]+\n(#{3,})$ 0:title +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(!{3,}\n)?[^\n]+\n(!{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)("{3,}\n)?[^\n]+\n("{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(\${3,}\n)?[^\n]+\n(\${3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(%{3,}\n)?[^\n]+\n(%{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(&{3,}\n)?[^\n]+\n(&{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)('{3,}\n)?[^\n]+\n('{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(\({3,}\n)?[^\n]+\n(\({3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(\){3,}\n)?[^\n]+\n(\){3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(\*{3,}\n)?[^\n]+\n(\*{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(\+{3,}\n)?[^\n]+\n(\+{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(,{3,}\n)?[^\n]+\n(,{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(-{3,}\n)?[^\n]+\n(-{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(\.{3,}\n)?[^\n]+\n(\.{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(/{3,}\n)?[^\n]+\n(/{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(:{3,}\n)?[^\n]+\n(:{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(\;{3,}\n)?[^\n]+\n(\;{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(<{3,}\n)?[^\n]+\n(<{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(={3,}\n)?[^\n]+\n(={3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(>{3,}\n)?[^\n]+\n(>{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(\?{3,}\n)?[^\n]+\n(\?{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(@{3,}\n)?[^\n]+\n(@{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(\[{3,}\n)?[^\n]+\n(\[{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(\\{3,}\n)?[^\n]+\n(\\{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(\]{3,}\n)?[^\n]+\n(\]{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(\^{3,}\n)?[^\n]+\n(\^{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(_{3,}\n)?[^\n]+\n(_{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(`{3,}\n)?[^\n]+\n(`{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(\{{3,}\n)?[^\n]+\n(\{{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(\|{3,}\n)?[^\n]+\n(\|{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(\}{3,}\n)?[^\n]+\n(\}{3,})$ 0:header +add-highlighter shared/restructuredtext/content/ regex (\A|\n\n)(~{3,}\n)?[^\n]+\n(~{3,})$ 0:header + +# Inline markup +add-highlighter shared/restructuredtext/content/ regex [^*](\*\*([^\s*]|([^\s*][^*]*[^\s*]))\*\*)[^*] 1:+b +add-highlighter shared/restructuredtext/content/ regex [^*](\*([^\s*]|([^\s*][^*]*[^\s*]))\*)[^*] 1:+i +add-highlighter shared/restructuredtext/content/ regex [^`](``([^\s`]|([^\s`][^`]*[^\s`]))``)[^`] 1:mono + +define-command restructuredtext-load-languages -params 1 %{ + evaluate-commands -draft %{ try %{ + execute-keys "%arg{1}s^\.\.\h*code-block::\h*\K\w+<ret>" + evaluate-commands -itersel %{ try %{ + require-module %val{selection} + add-highlighter "shared/restructuredtext/%val{selection}" region "\.\.\h*code-block::\h*%val{selection}\h*\n" '^(?=\S)' regions + add-highlighter "shared/restructuredtext/%val{selection}/" default-region fill meta + add-highlighter "shared/restructuredtext/%val{selection}/inner" region \A\.\.\h*code-block::[^\n]*\K '^(?=\S)' ref %val{selection} + }} + }} +} + +} diff --git a/autoload/filetype/ruby.kak b/autoload/filetype/ruby.kak new file mode 100644 index 0000000..0a57264 --- /dev/null +++ b/autoload/filetype/ruby.kak @@ -0,0 +1,194 @@ +# http://ruby-lang.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*(([.](rb))|(irbrc)|(pryrc)|(Brewfile)|(Capfile|[.]cap)|(Gemfile|[.]gemspec)|(Guardfile)|(Rakefile|[.]rake)|(Thorfile|[.]thor)|(Vagrantfile)) %{ + set-option buffer filetype ruby +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=ruby %{ + require-module ruby + + set-option window static_words %opt{ruby_static_words} + + hook window ModeChange pop:insert:.* -group ruby-trim-indent ruby-trim-indent + hook window InsertChar .* -group ruby-indent ruby-indent-on-char + hook window InsertChar \n -group ruby-indent ruby-indent-on-new-line + hook window InsertChar \n -group ruby-insert ruby-insert-on-new-line + + alias window alt ruby-alternative-file + + hook -once -always window WinSetOption filetype=.* %{ + remove-hooks window ruby-.+ + unalias window alt ruby-alternative-file + } +} + +hook -group ruby-highlight global WinSetOption filetype=ruby %{ + add-highlighter window/ruby ref ruby + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/ruby } +} + +provide-module ruby %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/ruby regions +add-highlighter shared/ruby/code default-region group +add-highlighter shared/ruby/double_symbol region ':"' (?<!\\)(\\\\)*" regions +add-highlighter shared/ruby/single_symbol region ":'" (?<!\\)(\\\\)*' fill variable +add-highlighter shared/ruby/double_string region '"' (?<!\\)(\\\\)*" regions +add-highlighter shared/ruby/single_string region "'" (?<!\\)(\\\\)*' fill string +add-highlighter shared/ruby/backtick region '(?<![$:])`' (?<!\\)(\\\\)*` regions +add-highlighter shared/ruby/regex region '(?<![$:])/' (?<!\\)(\\\\)*/[imox]* regions +add-highlighter shared/ruby/ region '#' '$' fill comment +add-highlighter shared/ruby/ region ^=begin ^=end fill comment +add-highlighter shared/ruby/ region -recurse \( '%[qwQW]?\(' \) fill string +add-highlighter shared/ruby/ region -recurse \{ '%[qwQW]?\{' \} fill string +add-highlighter shared/ruby/ region -recurse \[ '%[qwQW]?\[' \] fill string +add-highlighter shared/ruby/ region -recurse < '%[qwQW]?<' > fill string +add-highlighter shared/ruby/ region -recurse \( '%[isIS]\(' \) fill variable +add-highlighter shared/ruby/ region -recurse \{ '%[isIS]\{' \} fill variable +add-highlighter shared/ruby/ region -recurse \[ '%[isIS]\[' \] fill variable +add-highlighter shared/ruby/ region -recurse < '%[isIS]<' > fill variable +add-highlighter shared/ruby/ region -recurse \( '%[rxRX]\(' \) fill meta +add-highlighter shared/ruby/ region -recurse \{ '%[rxRX]\{' \} fill meta +add-highlighter shared/ruby/ region -recurse \[ '%[rxRX]\[' \] fill meta +add-highlighter shared/ruby/ region -recurse < '%[rxRX]<' > fill meta +add-highlighter shared/ruby/ region -match-capture '%[qwQW]?([^\s0-9A-Za-z\(\{\[<>\]\}\)])' ([^\s0-9A-Za-z\(\{\[<>\]\}\)]) fill string +add-highlighter shared/ruby/ region -match-capture '%[isIS]([^\s0-9A-Za-z\(\{\[<>\]\}\)])' ([^\s0-9A-Za-z\(\{\[<>\]\}\)]) fill variable +add-highlighter shared/ruby/ region -match-capture '%[rxRX]([^\s0-9A-Za-z\(\{\[<>\]\}\)])' ([^\s0-9A-Za-z\(\{\[<>\]\}\)]) fill meta +add-highlighter shared/ruby/heredoc region -match-capture '<<[-~]?(?!self)(\w+)' '^\h*(\w+)$' fill string +add-highlighter shared/ruby/division region '[\w\)\]]\K(/|(\h+/\h+))' '\w' group # Help Kakoune to better detect /…/ literals + +# Regular expression flags are: i → ignore case, m → multi-lines, o → only interpolate #{} blocks once, x → extended mode (ignore white spaces) +# Literals are: i → array of symbols, q → string, r → regular expression, s → symbol, w → array of words, x → capture shell result + +add-highlighter shared/ruby/double_string/ default-region fill string +add-highlighter shared/ruby/double_string/interpolation region -recurse \{ \Q#{ \} fill meta + +add-highlighter shared/ruby/double_symbol/ default-region fill variable +add-highlighter shared/ruby/double_symbol/interpolation region -recurse \{ \Q#{ \} fill meta + +add-highlighter shared/ruby/backtick/ default-region fill meta +add-highlighter shared/ruby/backtick/interpolation region -recurse \{ \Q#{ \} fill meta + +add-highlighter shared/ruby/regex/ default-region fill meta +add-highlighter shared/ruby/regex/interpolation region -recurse \{ \Q#{ \} fill meta + +evaluate-commands %sh{ + # Grammar + # Keywords are collected searching for keywords at + # https://github.com/ruby/ruby/blob/trunk/parse.y + keywords="alias|and|begin|break|case|class|def|defined|do|else|elsif|end" + keywords="${keywords}|ensure|false|for|if|in|module|next|nil|not|or|private|protected|public|redo" + keywords="${keywords}|rescue|retry|return|self|super|then|true|undef|unless|until|when|while|yield" + attributes="attr_reader|attr_writer|attr_accessor" + values="false|true|nil" + meta="require|require_relative|include|extend" + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list ruby_static_words ${keywords} ${attributes} ${values} ${meta}" | tr '|' ' ' + + # Highlight keywords + printf %s " + add-highlighter shared/ruby/code/ regex \b(${keywords})[^0-9A-Za-z_!?] 1:keyword + add-highlighter shared/ruby/code/ regex \b(${attributes})\b 0:attribute + add-highlighter shared/ruby/code/ regex \b(${values})\b 0:value + add-highlighter shared/ruby/code/ regex \b(${meta})\b 0:meta + " +} + +add-highlighter shared/ruby/code/ regex \b(\w+:(?!:))|(:?(\$(-[0FIKWadilpvw]|["'`/~&+=!$*,:.\;<>?@\\])|(\$|@@?)\w+))|((?<!:):(![~=]|=~|>[=>]?|<((=>?)|<)?|[+\-]@?|\*\*?|===?|[/`%&!^|~]|(\w+[=?!]?)|(\[\]=?)))|([A-Z]\w*|^|\h)\K::(?=[A-Z]) 0:variable + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command ruby-alternative-file -docstring 'Jump to the alternate file (implementation ↔ test)' %{ evaluate-commands %sh{ + case $kak_buffile in + *spec/*_spec.rb) + altfile=$(eval echo $(echo $kak_buffile | sed s+spec/+'*'/+';'s/_spec//)) + [ ! -f $altfile ] && echo "fail 'implementation file not found'" && exit + ;; + *test/*_test.rb) + altfile=$(eval echo $(echo $kak_buffile | sed s+test/+'*'/+';'s/_test//)) + [ ! -f $altfile ] && echo "fail 'implementation file not found'" && exit + ;; + *.rb) + altfile="" + altdir="" + path=$kak_buffile + dirs=$(while [ $path ]; do echo $path; path=${path%/*}; done | tail -n +2) + for dir in $dirs; do + altdir=$dir/spec && suffix=spec + [ ! -d $altdir ] && altdir=$dir/test && suffix=test + if [ -d $altdir ]; then + altfile=$altdir/$(realpath $kak_buffile --relative-to $dir | sed s+[^/]'*'/++';'s/.rb$/_${suffix}.rb/) + break + fi + done + [ ! -d "$altdir" ] && echo "fail 'spec/ and test/ not found'" && exit + ;; + *) + echo "fail 'alternative file not found'" && exit + ;; + esac + echo "edit $altfile" +}} + +define-command -hidden ruby-trim-indent %{ + evaluate-commands -no-hooks -draft -itersel %{ + execute-keys x + # remove trailing white spaces + try %{ execute-keys -draft s \h + $ <ret> d } + } +} + +define-command -hidden ruby-indent-on-char %{ + evaluate-commands -no-hooks -draft -itersel %{ + # align middle and end structures to start + try %{ execute-keys -draft x <a-k> ^ \h * (else) $ <ret> <a-a> i <a-semicolon> <a-?> ^ \h * (if|case) <ret> <a-S> 1<a-&> } + try %{ execute-keys -draft x <a-k> ^ \h * (elsif) $ <ret> <a-a> i <a-semicolon> <a-?> ^ \h * (if) <ret> <a-S> 1<a-&> } + try %{ execute-keys -draft x <a-k> ^ \h * (when) $ <ret> <a-a> i <a-semicolon> <a-?> ^ \h * (case) <ret> <a-S> 1<a-&> } + try %{ execute-keys -draft x <a-k> ^ \h * (rescue) $ <ret> <a-a> i <a-semicolon> <a-?> ^ \h * (begin|def) <ret> <a-S> 1<a-&> } + } +} + +define-command -hidden ruby-indent-on-new-line %{ + evaluate-commands -no-hooks -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft K <a-&> } + # filter previous line + try %{ execute-keys -draft k : ruby-trim-indent <ret> } + # indent after start structure + try %{ execute-keys -draft k x <a-k> ^ \h * (begin|case|class|def|else|elsif|ensure|for|if|module|rescue|unless|until|when|while|.+\bdo$|.+\bdo\h\|.+(?=\|)) [^0-9A-Za-z_!?] <ret> j <a-gt> } + } +} + +define-command -hidden ruby-insert-on-new-line %[ + evaluate-commands -no-hooks -draft -itersel %[ + # copy _#_ comment prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K#\h* <ret> y jgi P } + # wisely add end structure + evaluate-commands -save-regs x %[ + try %{ execute-keys -draft k x s ^ \h + <ret> \" x y } catch %{ reg x '' } + try %[ + evaluate-commands -draft %[ + # Check if previous line opens a block + execute-keys -draft kx <a-k>^<c-r>x(begin|case|class|def|for|if|module|unless|until|while|.+\bdo$|.+\bdo\h\|.+(?=\|))[^0-9A-Za-z_!?]<ret> + # Check that we do not already have an end for this indent level which is first set via `ruby-indent-on-new-line` hook + execute-keys -draft }i J x <a-K> ^<c-r>x(end|else|elsif|rescue|when)[^0-9A-Za-z_!?]<ret> + ] + execute-keys -draft o<c-r>xend<esc> # insert a new line with containing end + ] + ] + ] +] + +§ diff --git a/autoload/filetype/rust.kak b/autoload/filetype/rust.kak new file mode 100644 index 0000000..3aacc73 --- /dev/null +++ b/autoload/filetype/rust.kak @@ -0,0 +1,209 @@ +# http://rust-lang.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](rust|rs) %{ + set-option buffer filetype rust +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=rust %< + require-module rust + hook window ModeChange pop:insert:.* -group rust-trim-indent rust-trim-indent + hook window InsertChar \n -group rust-indent rust-indent-on-new-line + hook window InsertChar \{ -group rust-indent rust-indent-on-opening-curly-brace + hook window InsertChar [)}\]] -group rust-indent rust-indent-on-closing + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window rust-.+ } +> + +hook -group rust-highlight global WinSetOption filetype=rust %{ + add-highlighter window/rust ref rust + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/rust } +} + +provide-module rust %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/rust regions +add-highlighter shared/rust/code default-region group +add-highlighter shared/rust/string region %{(?<!')"} (?<!\\)(\\\\)*" fill string +add-highlighter shared/rust/raw_string region -match-capture %{(?<!')r(#*)"} %{"(#*)} fill string + +add-highlighter shared/rust/line_doctest region ^\h*//[!/]\h*```($|should_panic|no_run|ignore|allow_fail|rust|test_harness|compile_fail|E\d{4}|edition201[58]) ^\h*//[!/]\h*```$ regions +add-highlighter shared/rust/line_doctest/marker region ``` $ group +add-highlighter shared/rust/line_doctest/marker/fence regex ``` 0:meta +add-highlighter shared/rust/line_doctest/marker/keywords regex [\d\w] 0:meta # already matched above, just ignore comma +add-highlighter shared/rust/line_doctest/inner region '^\h*//[!/]( #(?= ))?' '$| ' group +add-highlighter shared/rust/line_doctest/inner/comment regex //[!/] 0:documentation +add-highlighter shared/rust/line_doctest/inner/hidden regex '#' 0:meta +add-highlighter shared/rust/line_doctest/code default-region ref rust +add-highlighter shared/rust/line_code_rest region ^\h*//[!/]\h*``` ^\h*//[!/]\h*```$ fill documentation # reset invalid doctest +add-highlighter shared/rust/line_comment2 region //[!/]{2} $ fill comment +add-highlighter shared/rust/line_doc region //[!/] $ fill documentation +add-highlighter shared/rust/line_comment1 region // $ group +add-highlighter shared/rust/line_comment1/comment fill comment +add-highlighter shared/rust/line_comment1/todo regex (TODO|NOTE|FIXME): 1:meta + +add-highlighter shared/rust/block_comment2 region -recurse /\*\*\* /\*\*\* \*/ fill comment +add-highlighter shared/rust/block_doc region -recurse /\*\* /\*\* \*/ regions +add-highlighter shared/rust/block_doc/doctest region ```($|should_panic|no_run|ignore|allow_fail|rust|test_harness|compile_fail|E\d{4}|edition201[58]) ```$ regions +add-highlighter shared/rust/block_doc/doctest/marker region ``` $ group +add-highlighter shared/rust/block_doc/doctest/marker/fence regex ``` 0:meta +add-highlighter shared/rust/block_doc/doctest/marker/keywords regex [\d\w] 0:meta # already matched above, just ignore comma +add-highlighter shared/rust/block_doc/doctest/inner default-region group +add-highlighter shared/rust/block_doc/doctest/inner/hidden regex '^\h*\**\h*#' 0:meta +add-highlighter shared/rust/block_doc/doctest/inner/comment regex ^\h*\* 0:documentation +add-highlighter shared/rust/block_doc/doctest/inner/code ref rust +add-highlighter shared/rust/block_doc/code_rest region ``` ``` fill documentation +add-highlighter shared/rust/block_doc/doc default-region fill documentation +add-highlighter shared/rust/block_comment1 region -recurse /\* /\* \*/ group +add-highlighter shared/rust/block_comment1/comment fill comment +add-highlighter shared/rust/block_comment1/todo regex (TODO|NOTE|FIXME): 1:meta + +add-highlighter shared/rust/macro_attributes region -recurse "\[" "#!?\[" "\]" regions +add-highlighter shared/rust/macro_attributes/ default-region fill meta +add-highlighter shared/rust/macro_attributes/string region %{(?<!')"} (?<!\\)(\\\\)*" fill string +add-highlighter shared/rust/macro_attributes/raw_string region -match-capture %{(?<!')r(#*)"} %{"(#*)} fill string + +add-highlighter shared/rust/code/operators_arithmetic regex (\+|-|/|\*|=|\^|&|\||!|>|<|%)=? 0:operator +add-highlighter shared/rust/code/operators_as regex \bas\b 0:operator +add-highlighter shared/rust/code/ref_ref regex (&\h+[&~@*])[^)=\s\t\r\n] 1:type +add-highlighter shared/rust/code/ref regex ([&~@*])[^)=\s\t\r\n] 1:type +add-highlighter shared/rust/code/operators_logic regex &&|\|\| 0:operator + +add-highlighter shared/rust/code/lifetime_or_loop_label regex ('([a-zA-Z]\w+|_\w+))\b 1:meta +add-highlighter shared/rust/code/namespace regex \b[a-zA-Z](\w+)?(\h+)?(?=::) 0:module +add-highlighter shared/rust/code/mod_path_sep regex :: 0:meta +add-highlighter shared/rust/code/question_mark regex \? 0:meta +# the language keywords are defined here, but many of them are reserved and unused yet: +# https://doc.rust-lang.org/reference/keywords.html +add-highlighter shared/rust/code/function_call regex _?[a-zA-Z]\w*\s*(?=\() 0:function +add-highlighter shared/rust/code/generic_function_call regex _?[a-zA-Z]\w*\s*(?=::<) 0:function +add-highlighter shared/rust/code/function_declaration regex (?:fn\h+)(_?\w+)(?:<[^>]+?>)?\( 1:function +add-highlighter shared/rust/code/keywords regex \b(?:as|break|continue|crate|else|enum|extern|false|fn|for|if|impl|in|let|loop|match|mod|pub|return|self|Self|struct|super|trait|true|type|union|unsafe|use|where|while|async|await|dyn|abstract|become|box|do|try)\b 0:keyword +add-highlighter shared/rust/code/storage regex \b(move|mut|ref|static|const)\b 0:type +add-highlighter shared/rust/code/pub_with_scope regex \b(pub)\h*(\()\h*(crate|super|self|in\h+[\w:]+)\h*(\)) 1:keyword 2:meta 4:meta +# after let can be an arbitrary pattern match +add-highlighter shared/rust/code/macro regex \b\w+! 0:meta +# the number literals syntax is defined here: +# https://doc.rust-lang.org/reference/tokens.html#numb ers +add-highlighter shared/rust/code/values regex \b(?:self|true|false|[0-9][_0-9]*(?:\.[0-9][_0-9]*|(?:\.[0-9][_0-9]*)?E[\+\-][_0-9]+)(?:f(?:32|64))?|(?:0x[_0-9a-fA-F]+|0o[_0-7]+|0b[_01]+|[0-9][_0-9]*)(?:(?:i|u|f)(?:8|16|32|64|128|size))?)\b 0:value +add-highlighter shared/rust/code/char_character regex "'([^\\]|\\(.|x[0-9a-fA-F]{2}|u\{[0-9a-fA-F]{1,6}\}))'" 0:value +# TODO highlight error for unicode or single escape by te character +add-highlighter shared/rust/code/byte_character regex b'([\x00-\x5B\x5D-\x7F]|\\(.|x[0-9a-fA-F]{2}))' 0:value +add-highlighter shared/rust/code/builtin_types regex \b(?:u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize|f32|f64|bool|char|str|Self)\b 0:type +add-highlighter shared/rust/code/return regex \breturn\b 0:meta + +add-highlighter shared/rust/code/enum regex \b(Option|Result)\b 0:type +add-highlighter shared/rust/code/enum_variant regex \b(Some|None|Ok|Err)\b 0:value +add-highlighter shared/rust/code/std_traits regex \b(Copy|Send|Sized|Sync|Drop|Fn|FnMut|FnOnce|Box|ToOwned|Clone|PartialEq|PartialOrd|Eq|Ord|AsRef|AsMut|Into|From|Default|Iterator|Extend|IntoIterator|DoubleEndedIterator|ExactSizeIterator|SliceConcatExt|String|ToString|Vec)\b 0:type + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden rust-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden rust-indent-on-new-line %~ + evaluate-commands -draft -itersel %@ + try %{ + try %[ # line comment + evaluate-commands -draft -save-regs '/"' %[ + # copy the commenting prefix + execute-keys -save-regs '' k x s ^\h*//[!/]{0,2}\h* <ret> y + try %[ + # if the previous comment isn't empty, create a new one + execute-keys x<a-K>^\h*//[!/]{0,2}$<ret> jxs^\h*<ret>P + ] catch %[ + # TODO figure out a way to not delete empty comment in current line + # if there is no space and text in the previous comment, remove it completely + execute-keys s //.*<ret> d + ] + ] + ] catch %[ # block comment + # if the previous line isn't within a comment scope, break + execute-keys -draft kx <a-k>^(\h*/\*|\h+\*(?!/))<ret> + + # find comment opening, validate it was not closed, and check its using star prefixes + execute-keys -draft <a-?>/\*<ret><a-H> <a-K>\*/<ret> <a-k>\A\h*/\*([^\n]*\n\h*\*)*[^\n]*\n\h*.\z<ret> + + try %[ + # if the previous line is opening the comment, insert star preceeded by space + execute-keys -draft kx<a-k>^\h*/\*<ret> + execute-keys -draft i*<space><esc> + ] catch %[ + try %[ + # if the next line is a comment line insert a star + execute-keys -draft jx<a-k>^\h+\*<ret> + execute-keys -draft i*<space><esc> + ] catch %[ + try %[ + # if the previous line is an empty comment line, close the comment scope + execute-keys -draft kx<a-k>^\h+\*\h+$<ret> x1s\*(\h*)<ret>c/<esc> + ] catch %[ + # if the previous line is a non-empty comment line, add a star + execute-keys -draft i*<space><esc> + ] + ] + ] + + # trim trailing whitespace on the previous line + try %[ execute-keys -draft s\h+$<ret> d ] + # align the new star with the previous one + execute-keys Kx1s^[^*]*(\*)<ret>& + ] + } catch %` + # re-indent previous line if it starts with where to match previous block + # string literal parsing within extern does not handle escape + try %% execute-keys -draft k x <a-k> ^\h*where\b <ret> hh <a-?> ^\h*\b(impl|((|pub\ |pub\((crate|self|super|in\ (::)?([a-zA-Z][a-zA-Z0-9_]*|_[a-zA-Z0-9_]+)(::[a-zA-Z][a-zA-Z0-9_]*|_[a-zA-Z0-9_]+)*)\)\ )((async\ |const\ )?(unsafe\ )?(extern\ ("[^"]*"\ )?)?fn|struct|enum|union)))\b <ret> <a-S> 1<a-&> % + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # indent after lines ending with [{([].+ and move first parameter to own line + try %< execute-keys -draft [c[({[],[)}\]] <ret> <a-k> \A[({[][^\n]+\n[^\n]*\n?\z <ret> L i<ret><esc> <gt> <a-S> <a-&> > + # indent after non-empty lines not starting with operator and not ending with , or ; or { + # XXX simplify this into a single <a-k> without s + try %< execute-keys -draft k x s [^\h].+ <ret> <a-K> \A[-+*/&|^})<gt><lt>#] <ret> <a-K> [,<semicolon>{](\h*/[/*].*|)$ <ret> j <a-gt> > + # indent after lines ending with { + try %+ execute-keys -draft k x <a-k> \{$ <ret> j <a-gt> + + # dedent after lines starting with . and ending with } or ) or , or ; or .await (} or ) or .await maybe with ?) + try %_ execute-keys -draft k x <a-k> ^\h*\. <ret> <a-k> ([,<semicolon>]|(([})]|\.await)\?*))\h*$ <ret> j <a-lt> _ + # dedent after lines ending with " => {}" - part of empty match + try %# execute-keys -draft k x <a-k> \ =>\ \{\}\h*$ <ret> j <a-lt> # + # align to opening curly brace or paren when newline is inserted before a single closing + try %< execute-keys -draft <a-h> <a-k> ^\h*[)}] <ret> h m <a-S> 1<a-&> > + # todo dedent additional unmatched parenthesis + # try %& execute-keys -draft k x s \((?:[^)(]+|\((?:[^)(]+|\([^)(]*\))*\))*\) l Gl s\) %sh{ + # count previous selections length + # printf "j $(echo $kak_selections_length | wc -w) <a-lt>" + # } & + ` + # filter previous line + try %{ execute-keys -draft k : rust-trim-indent <ret> } + @ +~ + +define-command -hidden rust-indent-on-opening-curly-brace %[ + evaluate-commands -draft -itersel %~ + # align indent with opening paren when { is entered on a new line after the closing paren + try %[ execute-keys -draft h <a-F> ) M <a-k> \A\(.*\)\h*\n\h*\{\z <ret> s \A|.\z <ret> 1<a-&> ] + # dedent standalone { after impl and related block without any { in between + try %@ execute-keys -draft hh <a-?> ^\h*\b(impl|((|pub\ |pub\((crate|self|super|in\ (::)?([a-zA-Z][a-zA-Z0-9_]*|_[a-zA-Z0-9_]+)(::[a-zA-Z][a-zA-Z0-9_]*|_[a-zA-Z0-9_]+)*)\)\ )((async\ |const\ )?(unsafe\ )?(extern\ ("[^"]*"\ )?)?fn|struct|enum|union))|if|for)\b <ret> <a-K> \{ <ret> <a-semicolon> <semicolon> ll x <a-k> ^\h*\{$ <ret> <a-lt> @ + ~ +] + +define-command -hidden rust-indent-on-closing %~ + evaluate-commands -draft -itersel %_ + # align to opening curly brace or paren when alone on a line + try %< execute-keys -draft <a-h> <a-k> ^\h*[)}\]]$ <ret> h m <a-S> 1<a-&> > + _ +~ + +§ diff --git a/autoload/filetype/sass.kak b/autoload/filetype/sass.kak new file mode 100644 index 0000000..5f2cce0 --- /dev/null +++ b/autoload/filetype/sass.kak @@ -0,0 +1,86 @@ +# http://sass-lang.com +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](sass) %{ + set-option buffer filetype sass +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=sass %< + require-module sass + + hook window ModeChange pop:insert:.* -group sass-trim-indent sass-trim-indent + hook window InsertChar \} -group sass-indent sass-indent-on-closing-brace + hook window InsertChar \n -group sass-insert sass-insert-on-new-line + hook window InsertChar \n -group sass-indent sass-indent-on-new-line + set-option buffer extra_word_chars '_' '-' + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window sass-.+ } +> + +hook -group sass-highlight global WinSetOption filetype=sass %{ + add-highlighter window/sass ref sass + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/sass } +} + + +provide-module sass %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/sass regions +add-highlighter shared/sass/code default-region group +add-highlighter shared/sass/single_string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/sass/double_string region "'" "'" fill string +add-highlighter shared/sass/comment region '//' '$' fill comment +add-highlighter shared/sass/css_comment region /[*] [*]/ fill comment + +add-highlighter shared/sass/code/ regex [*]|[#.][A-Za-z][A-Za-z0-9_-]* 0:variable +add-highlighter shared/sass/code/ regex &|@[A-Za-z][A-Za-z0-9_-]* 0:meta +add-highlighter shared/sass/code/ regex (#[0-9A-Fa-f]+)|((\d*\.)?\d+(em|px)) 0:value +add-highlighter shared/sass/code/ regex ([A-Za-z][A-Za-z0-9_-]*)\h*: 1:keyword +add-highlighter shared/sass/code/ regex :(before|after) 0:attribute +add-highlighter shared/sass/code/ regex !important 0:keyword + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden sass-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden sass-indent-on-closing-brace %< + evaluate-commands -draft -itersel %< + # align closing brace to same indentation as the line that the opening brace resides on + try %[ execute-keys -draft <a-h> <a-k> ^\h+\}$ <ret> m <a-S> 1<a-&> ] + > +> + +define-command -hidden sass-insert-on-new-line %< + evaluate-commands -draft -itersel %< + # copy // comment prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K/{2,}\h* <ret> y gh j P } + > +> + +define-command -hidden sass-indent-on-new-line %< + evaluate-commands -draft -itersel %< + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : sass-trim-indent <ret> } + # avoid indent after properties and comments + try %{ execute-keys -draft k x <a-K> [:/] <ret> j <a-gt> } + # deindent closing brace when after cursor + try %[ execute-keys -draft x <a-k> ^\h*\} <ret> gh / \} <ret> m <a-S> 1<a-&> ] + > +> + +§ diff --git a/autoload/filetype/scala.kak b/autoload/filetype/scala.kak new file mode 100644 index 0000000..05d7b28 --- /dev/null +++ b/autoload/filetype/scala.kak @@ -0,0 +1,90 @@ +# http://scala-lang.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](scala|sbt|sc) %{ + set-option buffer filetype scala +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=scala %[ + require-module scala + + hook window ModeChange pop:insert:.* -group scala-trim-indent scala-trim-indent + hook window InsertChar \n -group scala-insert scala-insert-on-new-line + hook window InsertChar \n -group scala-indent scala-indent-on-new-line + hook window InsertChar \} -group scala-indent scala-indent-on-closing-curly-brace + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window scala-.+ } +] + +hook -group scala-highlight global WinSetOption filetype=scala %{ + add-highlighter window/scala ref scala + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/scala } +} + + +provide-module scala %[ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/scala regions +add-highlighter shared/scala/code default-region group +add-highlighter shared/scala/string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/scala/literal region ` ` fill variable +add-highlighter shared/scala/comment region -recurse /[*] /[*] [*]/ fill comment +add-highlighter shared/scala/line_comment region // $ fill comment + +# Keywords are collected at +# http://tutorialspoint.com/scala/scala_basic_syntax.htm + +add-highlighter shared/scala/code/ regex (?:\b|\W)(@\w+|import|package)\b 0:meta +add-highlighter shared/scala/code/ regex \b(true|false|null)\b 0:value +add-highlighter shared/scala/code/ regex \b(?:class|extends|with)\s+(\w+) 0:type +add-highlighter shared/scala/code/ regex \b([A-Z]\w*)\b 0:type +add-highlighter shared/scala/code/ regex (?:def|var|val)\s+(\w+) 0:variable +add-highlighter shared/scala/code/ regex \b(become|case|catch|class|def|do|else|extends|final|finally|for|forSome|goto|if|initialize|macro|match|new|object|onTransition|return|startWith|stay|this|super|throw|trait|try|unbecome|using|val|var|when|while|with|yield)\b 0:keyword +add-highlighter shared/scala/code/ regex \b(abstract|final|implicit|implicitly|lazy|override|private|protected|require|sealed)\b 0:attribute +add-highlighter shared/scala/code/ regex (\[|\]|=>|<:|:>|=:=|::|&&|\|\|) 0:operator + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden scala-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden scala-insert-on-new-line %[ + evaluate-commands -draft -itersel %[ + # copy // comments prefix and following white spaces + try %{ execute-keys -draft <semicolon><c-s>kx s ^\h*\K#\h* <ret> y<c-o>P<esc> } + ] +] + +define-command -hidden scala-indent-on-new-line %[ + evaluate-commands -draft -itersel %[ + # preserve previous line indent + try %[ execute-keys -draft <semicolon> K <a-&> ] + # filter previous line + try %[ execute-keys -draft k : scala-trim-indent <ret> ] + # indent after lines ending with { + try %[ execute-keys -draft k x <a-k> \{$ <ret> j <a-gt> ] + # deindent closing brace when after cursor + try %[ execute-keys -draft x <a-k> ^\h*\} <ret> gh / \} <ret> m <a-S> 1<a-&> ] + ] +] + +define-command -hidden scala-indent-on-closing-curly-brace %[ + evaluate-commands -draft -itersel %[ + # align to opening curly brace when alone on a line + try %[ execute-keys -draft <a-h> <a-k> ^\h+\}$ <ret> m s \A|.\z <ret> 1<a-&> ] + ] +] + +] diff --git a/autoload/filetype/scheme.kak b/autoload/filetype/scheme.kak new file mode 100644 index 0000000..5e2e97c --- /dev/null +++ b/autoload/filetype/scheme.kak @@ -0,0 +1,170 @@ +# http://www.scheme-reports.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate (.*/)?(.*\.(scm|ss|sld|sps|sls)) %{ + set-option buffer filetype scheme +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=scheme %{ + require-module scheme + + set-option window static_words %opt{scheme_static_words} + + set-option buffer extra_word_chars '!' '$' '%' '&' '*' '+' '-' '.' '/' ':' '<' '=' '>' '?' '@' '^' '_' '~' + hook window ModeChange pop:insert:.* -group scheme-trim-indent lisp-trim-indent + hook window InsertChar \n -group scheme-indent lisp-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window scheme-.+ } +} + +hook -group scheme-highlight global WinSetOption filetype=scheme %{ + add-highlighter window/scheme ref scheme + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/scheme } +} + +provide-module scheme %{ + +require-module lisp + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/scheme regions +add-highlighter shared/scheme/code default-region group + +add-highlighter shared/scheme/string region %{(?<!#\\)"} (?<!\\)(\\\\)*" fill string +add-highlighter shared/scheme/comment region %{(?<!#\\);} '$' fill comment +add-highlighter shared/scheme/comment-form region -recurse "\(" "#;\(" "\)" fill comment +add-highlighter shared/scheme/comment-block region "#\|" "\|#" fill comment +add-highlighter shared/scheme/quoted-form region -recurse "\(" "'\(" "\)" fill variable + +add-highlighter shared/scheme/code/ regex (#t|#f) 0:value + +# Numbers +add-highlighter shared/scheme/code/ regex '(#[bB]#[eiEI]|#[eiEI]#[bB]|#[bB])[01]+' 0:value +add-highlighter shared/scheme/code/ regex '(#[oO]#[eiEI]|#[eiEI]#[oO]|#[oO])[0-7]+' 0:value +add-highlighter shared/scheme/code/ regex '(#[dD](#[eiEI])?|#[eiEI]#[dD]|#[eiEI])(\d+(?:\.\d*)?|\.\d+)([esfdlESFDL][-+]?\d+)?' 0:value +add-highlighter shared/scheme/code/ regex '(#[xX]#[eiEI]|#[eiEI]#[xX]|#[xX])[0-9a-fA-F]+' 0:value + +add-highlighter shared/scheme/code/ regex (#\\((\w+)|(.))) 0:value + +add-highlighter shared/scheme/code/ regex '#!(?:no-)?fold-case\b' 0:meta + +evaluate-commands %sh{ exec awk -f - <<'EOF' + BEGIN { + split("and begin call-with-current-continuation call/cc case case-lambda cond define "\ + "define-record-type define-values delay delay-force do else guard if lambda "\ + "let let* let-values let*-values letrec letrec* or set! unless when", keywords); + + # Macro expressions, imports/exports/library + split("begin-syntax cond-expand define-library define-syntax export import include "\ + "include-ci include-library-declarations let-syntax letrec-syntax quote "\ + "quasiquote syntax-rules syntax-case unquote unquote-splicing", meta); + + # Basic operators. + split("* + - ... / < <= = => > >=", operators); + + # Procedures that create a base type and their predicates (for easier type checking) + split("list vector bytevector cons string boolean? list? pair? vector? bytevector? "\ + "string? char? complex? eof-object eof-object? input-port? null? number? "\ + "output-port? port? procedure? symbol?", types); + + # R7RS available procedures + split("abs acos angle append apply asin assoc assq assv atan boolean=? "\ + "bytevector-append bytevector-copy bytevector-copy! bytevector-length "\ + "bytevector-u8-ref bytevector-u8-set! caaaar caaadr caaar caadar caaddr caadr "\ + "caar cadaar cadadr cadar caddar cadddr caddr cadr call-with-input-file "\ + "call-with-output-file call-with-values car cdaaar cdaadr cdaar cdadar cdaddr "\ + "cdadr cdar cddaar cddadr cddar cdddar cddddr cdddr cddr cdr ceiling "\ + "char->integer char-alphabetic? char-ci<=? char-ci<? char-ci=? char-ci>=? "\ + "char-ci>? char-downcase char-foldcase char-lower-case? char-numeric? "\ + "char-ready? char-upcase char-upper-case? char-whitespace? char<=? char<? "\ + "char=? char>=? char>? close-input-port close-output-port close-port cons cos "\ + "current-input-port current-output-port denominator digit-value display "\ + "dynamic-wind eq? equal? eqv? error error-object-irritants "\ + "error-object-message error-object? eval even? exact exact->inexact "\ + "exact-integer? exact-integer-sqrt exact? exp expt features file-error? "\ + "finite? floor floor/ floor-quotient floor-remainder for-each force "\ + "flush-output-port gcd get-output-bytevector get-output-string guard imag-part "\ + "inexact->exact inexact inexact? infinite? input-port-open? integer->char "\ + "integer? interaction-environment lcm length list list-copy list-set! "\ + "list->string list->vector list-ref list-tail load log magnitude "\ + "make-bytevector make-list make-parameter make-polar make-promise "\ + "make-rectangular make-string make-vector map max member memq memv min modulo "\ + "nan? negative? newline not null-environment number->string numerator odd? "\ + "open-input-bytevector open-input-file open-input-string "\ + "open-output-bytevector open-output-file open-output-string output-port-open? "\ + "or parameterize peek-char peek-u8 positive? promise? quotient raise "\ + "raise-continuable rational? rationalize read read-bytevector read-bytevector! "\ + "read-char read-error? read-line read-string read-u8 real-part real? remainder "\ + "reverse round scheme-report-environment set-car! set-cdr! sin square sqrt "\ + "string->list string->number string->symbol string->utf8 string->vector "\ + "string-append string-ci<=? string-ci<? string-ci=? string-ci>=? string-ci>? "\ + "string-copy string-copy! string-downcase string-fill! string-foldcase "\ + "string-for-each string-length string-map string-ref string-set! string-upcase "\ + "string<=? string<? string=? string>=? string>? substring symbol=? "\ + "symbol->string syntax-error tan textual-port? truncate truncate/ "\ + "truncate-quotient truncate-remainder u8-ready? unless utf8->string values "\ + "vector vector->list vector->string vector-append vector-copy vector-copy! "\ + "vector-for-each vector-fill! vector-length vector-map vector-ref vector-set! "\ + "when with-exception-handler with-input-from-file with-output-to-file write "\ + "write-bytevector write-char write-string write-u8 zero?", builtins); + + non_word_chars="['\"\\s\\(\\)\\[\\]\\{\\};]"; + + normal_identifiers="-!$%&\\*\\+\\./:<=>\\?@\\^_~a-zA-Z0-9"; + identifier_chars="[" normal_identifiers "][" normal_identifiers ",#]*"; + } + function kak_escape(s) { + gsub(/'/, "''", s); + return "'" s "'"; + } + function add_highlighter(regex, highlight) { + printf("add-highlighter shared/scheme/code/ regex %s %s\n", kak_escape(regex), highlight); + } + function quoted_join(words, quoted, first) { + first=1 + for (i in words) { + if (!first) { quoted=quoted "|"; } + quoted=quoted "\\Q" words[i] "\\E"; + first=0; + } + return quoted; + } + function add_word_highlighter(words, face, regex) { + regex = "(?<![" normal_identifiers "])(" quoted_join(words) ")(?![" normal_identifiers "])"; + add_highlighter(regex, "1:" face); + } + function print_words(words) { + for (i in words) { printf(" %s", words[i]); } + } + + BEGIN { + printf("declare-option str-list scheme_static_words "); + print_words(keywords); print_words(meta); print_words(operators); print_words(builtins); + printf("\n"); + + add_word_highlighter(keywords, "keyword"); + add_word_highlighter(meta, "meta"); + add_word_highlighter(operators, "operator"); + add_word_highlighter(builtins, "function"); + add_word_highlighter(types, "type"); + add_highlighter(non_word_chars "+('" identifier_chars ")", "1:attribute"); + add_highlighter("\\(define\\W+\\((" identifier_chars ")", "1:function"); + add_highlighter("\\(define\\W+(" identifier_chars ")\\W+\\(lambda", "1:function"); + + # unprefixed decimals + add_highlighter("(?<![" normal_identifiers "])(\\d+(\\.\\d*)?|\\.\\d+)(?:[esfdlESFDL][-+]?\\d+)?(?![" normal_identifiers "])", "0:value"); + # inf and nan + add_highlighter("(?<![" normal_identifiers "])[+-](?:inf|nan)\\.0(?![" normal_identifiers "])", "0:value"); + } +EOF +} + +} diff --git a/autoload/filetype/scss.kak b/autoload/filetype/scss.kak new file mode 100644 index 0000000..a4ac7b0 --- /dev/null +++ b/autoload/filetype/scss.kak @@ -0,0 +1,55 @@ +# http://sass-lang.com +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](scss) %{ + set-option buffer filetype scss +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=scss %[ + require-module scss + + hook window ModeChange pop:insert:.* -group scss-trim-indent scss-trim-indent + hook window InsertChar \n -group scss-indent scss-insert-on-new-line + hook window InsertChar \n -group scss-indent scss-indent-on-new-line + hook window InsertChar \} -group scss-indent scss-indent-on-closing-curly-brace + set-option buffer extra_word_chars '_' '-' + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window scss-.+ } +] + +hook -group scss-highlight global WinSetOption filetype=scss %{ + add-highlighter window/scss ref scss + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/scss } +} + + +provide-module scss %[ + +require-module css + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/scss regions +add-highlighter shared/scss/core default-region group +add-highlighter shared/scss/comment region ^\h*// $ fill comment + +add-highlighter shared/scss/core/ ref css +add-highlighter shared/scss/core/ regex & 0:keyword +add-highlighter shared/scss/core/ regex \$[A-Za-z][A-Za-z0-9_-]* 0:variable + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden scss-trim-indent css-trim-indent +define-command -hidden scss-insert-on-new-line css-insert-on-new-line +define-command -hidden scss-indent-on-new-line css-indent-on-new-line +define-command -hidden scss-indent-on-closing-curly-brace css-indent-on-closing-curly-brace + +] diff --git a/autoload/filetype/sh.kak b/autoload/filetype/sh.kak new file mode 100644 index 0000000..9a9f51e --- /dev/null +++ b/autoload/filetype/sh.kak @@ -0,0 +1,206 @@ +hook global BufCreate .*\.((z|ba|c|k|mk)?sh(rc|_profile)?|profile) %{ + set-option buffer filetype sh +} + +hook global WinSetOption filetype=sh %{ + require-module sh + set-option window static_words %opt{sh_static_words} + + hook window ModeChange pop:insert:.* -group sh-trim-indent sh-trim-indent + hook window InsertChar \n -group sh-insert sh-insert-on-new-line + hook window InsertChar \n -group sh-indent sh-indent-on-new-line + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window sh-.+ } +} + +hook -group sh-highlight global WinSetOption filetype=sh %{ + add-highlighter window/sh ref sh + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/sh } +} + +# using non-ascii characters here so that we can use the '[' command +provide-module sh %§ + +add-highlighter shared/sh regions +add-highlighter shared/sh/code default-region group +add-highlighter shared/sh/arithmetic region -recurse \(.*?\( (\$|(?<=for)\h*)\(\( \)\) group +add-highlighter shared/sh/double_string region %{(?<!\\)(?:\\\\)*\K"} %{(?<!\\)(?:\\\\)*"} group +add-highlighter shared/sh/single_string region %{(?<!\\)(?:\\\\)*\K'} %{'} fill string +add-highlighter shared/sh/expansion region -recurse (?<!\\)(?:\\\\)*\K\$\{ (?<!\\)(?:\\\\)*\K\$\{ \}|\n fill value +add-highlighter shared/sh/comment region (?<!\\)(?:\\\\)*(?:^|\h)\K# '$' fill comment +add-highlighter shared/sh/heredoc region -match-capture '<<-?\h*''?(\w+)''?' '^\t*(\w+)$' fill string + +add-highlighter shared/sh/arithmetic/expansion ref sh/double_string/expansion +add-highlighter shared/sh/double_string/fill fill string + +evaluate-commands %sh{ + # Grammar + # Generated with `compgen -k` in bash + keywords="if then else elif fi case esac for select while until do done in + function time coproc" + + # Generated with `compgen -b` in bash + builtins="alias bg bind break builtin caller cd command compgen complete + compopt continue declare dirs disown echo enable eval exec + exit export false fc fg getopts hash help history jobs kill + let local logout mapfile popd printf pushd pwd read readarray + readonly return set shift shopt source suspend test times trap + true type typeset ulimit umask unalias unset wait" + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list sh_static_words $(join "${keywords}" ' ') $(join "${builtins}" ' ')" + + # Highlight keywords + printf %s\\n "add-highlighter shared/sh/code/ regex (?<!-)\b($(join "${keywords}" '|'))\b(?!-) 0:keyword" + + # Highlight builtins + printf %s "add-highlighter shared/sh/code/builtin regex (?<!-)\b($(join "${builtins}" '|'))\b(?!-) 0:builtin" +} + +add-highlighter shared/sh/code/operators regex [\[\]\(\)&|]{1,2} 0:operator +add-highlighter shared/sh/code/variable regex ((?<![-:])\b\w+)= 1:variable +add-highlighter shared/sh/code/alias regex \balias(\h+[-+]\w)*\h+([\w-.]+)= 2:variable +add-highlighter shared/sh/code/function regex ^\h*(\S+(?<!=))\h*\(\) 1:function + +add-highlighter shared/sh/code/unscoped_expansion regex (?<!\\)(?:\\\\)*\K\$(\w+|#|@|\?|\$|!|-|\*) 0:value +add-highlighter shared/sh/double_string/expansion regex (?<!\\)(?:\\\\)*\K\$(\w+|#|@|\?|\$|!|-|\*|\{.+?\}) 0:value + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden sh-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +# This is at best an approximation, since shell syntax is very complex. +# Also note that this targets plain sh syntax, not bash - bash adds a whole +# other level of complexity. If your bash code is fairly portable this will +# probably work. +# +# Of necessity, this is also fairly opinionated about indentation styles. +# Doing it "properly" would require far more context awareness than we can +# bring to this kind of thing. +define-command -hidden sh-insert-on-new-line %[ + evaluate-commands -draft -itersel %[ + # copy '#' comment prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K#\h* <ret> y gh j P } + ] +] + +# Use custom object matching to copy indentation for the various logical +# blocks. +# +# Note that we're using a weird non-ascii character instead of [ or { here +# because the '[' and '{' characters need to be available for the commands. +define-command -hidden sh-indent-on-new-line %¶ + evaluate-commands -draft -itersel %@ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : sh-trim-indent <ret> } + + # Indent loop syntax, e.g.: + # for foo in bar; do + # things + # done + # + # or: + # + # while foo; do + # things + # done + # + # or equivalently: + # + # while foo + # do + # things + # done + # + # indent after do + try %{ execute-keys -draft , k x <a-k> \bdo$ <ret> j <a-gt> } + # copy the indentation of the matching for/when - matching on the do + # statement, so we don't need to duplicate this for the two loop + # structures. + try %{ execute-keys -draft , k x <a-k> \bdone$ <ret> gh [c\bdo\b,\bdone\b <ret> x <a-S> 1<a-&> , j K <a-&> } + + # Indent if/then/else syntax, e.g.: + # if [ $foo = $bar ]; then + # things + # else + # other_things + # fi + # + # or equivalently: + # if [ $foo = $bar ] + # then + # things + # else + # other_things + # fi + # + # indent after then + try %{ execute-keys -draft , k x <a-k> \bthen$ <ret> j <a-gt> } + # copy the indentation of the matching if + try %{ execute-keys -draft , k x <a-k> \bfi$ <ret> gh [c\bif\b,\bfi\b <ret> x <a-S> 1<a-&> , j K <a-&> } + # copy the indentation of the matching if, and then re-indent afterwards + try %{ execute-keys -draft , k x <a-k> \belse$ <ret> gh [c\bif\b,\bfi\b <ret> x <a-S> 1<a-&> , j K <a-&> j <a-gt> } + + # Indent case syntax, e.g.: + # case "$foo" in + # bar) thing1;; + # baz) + # things + # ;; + # *) + # default_things + # ;; + # esac + # + # or equivalently: + # case "$foo" + # in + # bar) thing1;; + # esac + # + # indent after in + try %{ execute-keys -draft , k x <a-k> \bin$ <ret> j <a-gt> } + # copy the indentation of the matching case + try %{ execute-keys -draft , k x <a-k> \besac$ <ret> gh [c\bcase\b,\besac\b <ret> x <a-S> 1<a-&> , j K <a-&> } + # indent after ) + try %{ execute-keys -draft , k x <a-k> ^\s*\(?[^(]+[^)]\)$ <ret> j <a-gt> } + # deindent after ;; + try %{ execute-keys -draft , k x <a-k> ^\s*\;\;$ <ret> j <a-lt> } + + # Indent compound commands as logical blocks, e.g.: + # { + # thing1 + # thing2 + # } + # + # or in a function definition: + # foo () { + # thing1 + # thing2 + # } + # + # We don't handle () delimited compond commands - these are technically very + # similar, but the use cases are quite different and much less common. + # + # Note that in this context the '{' and '}' characters are reserved + # words, and hence must be surrounded by a token separator - typically + # white space (including a newline), though technically it can also be + # ';'. Only vertical white space makes sense in this context, though, + # since the syntax denotes a logical block, not a simple compound command. + try %= execute-keys -draft , k x <a-k> (\s|^)\{$ <ret> j <a-gt> = + # deindent closing } + try %= execute-keys -draft , k x <a-k> ^\s*\}$ <ret> <a-lt> j K <a-&> = + # deindent closing } when after cursor + try %= execute-keys -draft x <a-k> ^\h*\} <ret> gh / \} <ret> m <a-S> 1<a-&> = + + @ +¶ + +§ diff --git a/autoload/filetype/sml.kak b/autoload/filetype/sml.kak new file mode 100644 index 0000000..961d58d --- /dev/null +++ b/autoload/filetype/sml.kak @@ -0,0 +1,86 @@ +# https://smlfamily.github.io +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*\.(sml|fun|sig) %{ + set-option buffer filetype sml +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=sml %{ + require-module sml + set-option buffer extra_word_chars '_' "'" + set-option window static_words %opt{sml_static_words} +} + +hook -group sml-highlight global WinSetOption filetype=sml %{ + add-highlighter window/sml ref sml + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/sml } +} + +provide-module sml %[ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/sml regions +add-highlighter shared/sml/code default-region group +add-highlighter shared/sml/string region '#?"' '(?<!\\)(\\\\)*"' fill string +add-highlighter shared/sml/comment region -recurse '\(\*' '\(\*' '\*\)' fill comment + +evaluate-commands %sh{ + keywords='abstype and andalso as case datatype do else end exception fn fun + handle if in infix infixr let local nonfix of op open orelse raise + rec then type val with withtype while eqtype functor include + sharing sig signature struct structure' + types='unit exn ref' + ops='before ignore o + div mod quot rem abs + not chr ord ceil floor round trunc + andb orb xorb notb' + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + printf %s\\n "declare-option str-list sml_static_words $(join "${keywords} ${types} ${ops}" ' ')" + + printf %s " + add-highlighter shared/sml/code/ regex \b($(join "${keywords}" '|'))\b 0:keyword + add-highlighter shared/sml/code/ regex \b($(join "${types}" '|'))\b 0:builtin + add-highlighter shared/sml/code/ regex \b($(join "${ops}" '|'))\b 0:operator + " +} + +# Symbolic identifiers +add-highlighter shared/sml/code/ regex "[!*/+\-~\^@=<>%%&$?`\\#:|]+" 0:operator + +# Record projection functions +add-highlighter shared/sml/code/ regex "(?<![!*/+\-~\^@=<>%%&$?`\\#:|])#([\w']+)?(?![!*/+\-~\^@=<>%%&$?`\\#:|])" 0:function + +# Symbolic keywords +add-highlighter shared/sml/code/ regex "(?<![!*/+\-~\^@=<>%%&$?`\\#:|])(=>|=|\*|->|:>|:|;|\.\.\.|\b_\b|\|)(?![!*/+\-~\^@=<>%%&$?`\\#:|])" 0:keyword + +# Type variables +add-highlighter shared/sml/code/ regex "(?<![\w'])'[\w']+(?![\w'])" 0:variable + +# Structure identifiers and value constructors +add-highlighter shared/sml/code/ regex "(?<![\w'])([A-Z][\w']*\.?)" 0:type + +# Signature identifiers and all-caps value constructors +add-highlighter shared/sml/code/ regex "(?<![\w'])[A-Z]{2}[A-Z0-9_']+(?![\w'])" 0:attribute + +# Constants +add-highlighter shared/sml/code/ regex "(?<![\w'])(true|false|nil)\b" 0:value + +# Numeric literals +add-highlighter shared/sml/code/ regex "(?<![\w'])0w[0-9]+\b" 0:value +add-highlighter shared/sml/code/ regex "(?<![\w'])(0wx|0xw)[0-9a-fA-F]+\b" 0:value +add-highlighter shared/sml/code/ regex "(?<![\w'])(0wb|0bw)[01]+\b" 0:value +add-highlighter shared/sml/code/ regex "(~|(?<![\w']))0x[0-9a-fA-F]+\b" 0:value +add-highlighter shared/sml/code/ regex "(~|(?<![\w']))0b[01]+\b" 0:value +add-highlighter shared/sml/code/ regex "(?<!#)(~|(?<![\w']))[0-9]+(\.[0-9]+)?([eE]~?[0-9]+)?\b" 0:value + +] diff --git a/autoload/filetype/sql.kak b/autoload/filetype/sql.kak new file mode 100644 index 0000000..befa9de --- /dev/null +++ b/autoload/filetype/sql.kak @@ -0,0 +1,115 @@ +# https://www.w3schools.com/sql/default.asp +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*/?(?i)sql %{ + set-option buffer filetype sql +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=sql %{ + require-module sql + set-option window static_words %opt{sql_static_words} +} + +hook -group sql-highlight global WinSetOption filetype=sql %{ + add-highlighter window/sql ref sql + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/sql } +} + + +provide-module sql %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/sql regions +add-highlighter shared/sql/code default-region group +add-highlighter shared/sql/double_string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/sql/single_string region "'" (?<!\\)(\\\\)*' fill string +add-highlighter shared/sql/comment1 region '--' '$' fill comment +add-highlighter shared/sql/comment2 region '#' '$' fill comment +add-highlighter shared/sql/comment3 region '/\*' '\*/' fill comment + +evaluate-commands %sh{ + # Keywords + keywords="ALTER|AS|ASC|AUTO_INCREMENT|CHECK|CONSTRAINT|CREATE|DATABASE|DEFAULT|DELETE|DESC|DISTINCT|DROP" + keywords="${keywords}|EXISTS|FOREIGN KEY|FROM|FULL JOIN|FULL OUTER JOIN|GROUP BY|HAVING|INDEX|INNER JOIN" + keywords="${keywords}|INSERT INTO|INTO|JOIN|LEFT JOIN|LEFT OUTER JOIN|LIMIT|MODIFY|NOT NULL|ON|ORDER BY|PRIMARY KEY" + keywords="${keywords}|REFERENCES|RIGHT JOIN|RIGHT OUTER JOIN|SELECT|SELECT TOP|SET|TABLE|TRUNCATE|UNION|UNIQUE" + keywords="${keywords}|UPDATE|VALUES|VIEW|WHERE" + + # Operators + operators="ALL|AND|ANY|BETWEEN|EXISTS|IN|IS|LIKE|NOT|OR|SOME" + + # MySQL functions + functions="ABS|ACOS|ADDDATE|ADDTIME|ASCII|ASIN|ATAN|AVG|BIN|BINARY|CASE|CAST|CEIL|CEILING" + functions="${functions}|CHARACTER_LENGTH|CHAR_LENGTH|COALESCE|CONCAT|CONCAT_WS|CONNECTION_ID|CONV|CONVERT" + functions="${functions}|COS|COT|COUNT|CURDATE|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER" + functions="${functions}|CURTIME|DATABASE|DATE|DATE_ADD|DATEDIFF|DATE_FORMAT|DATE_SUB|DAY|DAYNAME" + functions="${functions}|DAYOFMONTH|DAYOFWEEK|DAYOFYEAR|DEGREES|DIV|EXP|EXTRACT|FIELD|FIND_IN_SET|FLOOR" + functions="${functions}|FORMAT|FROM_DAYS|GREATEST|HOUR|IF|IFNULL|INSERT|INSTR|ISNULL|LAST_DAY" + functions="${functions}|LAST_INSERT_ID|LCASE|LEAST|LEFT|LENGTH|LN|LOCALTIME|LOCALTIMESTAMP|LOCATE|LOG" + functions="${functions}|LOWER|LPAD|LTRIM|MAKEDATE|MAKETIME|MAX|MICROSECOND|MID|MIN|MINUTE|MOD|MONTH" + functions="${functions}|MONTHNAME|NOW|NULLIF|PERIOD_ADD|PERIOD_DIFF|PI|POSITION|POW|POWER|QUARTER|RADIANS" + functions="${functions}|RAND|REPEAT|REPLACE|REVERSE|RIGHT|ROUND|RPAD|RTRIM|SECOND|SEC_TO_TIME|SESSION_USER" + functions="${functions}|SIGN|SIN|SPACE|SQRT|STRCMP|STR_TO_DATE|SUBDATE|SUBSTR|SUBSTRING|SUBSTRING_INDEX" + functions="${functions}|SUBTIME|SUM|SYSDATE|SYSTEM_USER|TAN|TIME|TIMEDIFF|TIME_FORMAT|TIMESTAMP" + functions="${functions}|TIME_TO_SEC|TO_DAYS|TRIM|TRUNCATE|UCASE|UPPER|USER|VERSION|WEEK|WEEKDAY|WEEKOFYEAR" + functions="${functions}|YEAR|YEARWEEK" + + # SQL Server functions + functions="${functions}|CHAR|CHARINDEX|DATALENGTH|DATEADD|DATENAME|DATEPART|GETDATE|GETUTCDATE|ISDATE" + functions="${functions}|ISNUMERIC|LEN|NCHAR|PATINDEX|SESSIONPROPERTY|STR|STUFF|USER_NAME" + + # MS Access functions + functions="${functions}|Abs|Asc|Atn|Avg|Chr|Cos|Count|CurDir|CurrentUser|Date|DateAdd|DateDiff|DatePart" + functions="${functions}|DateSerial|DateValue|Day|Environ|Exp|Fix|Format|Hour|InStr|InstrRev|Int|IsDate" + functions="${functions}|IsNull|IsNumeric|LCase|Left|Len|LTrim|Max|Mid|Min|Minute|Month|MonthName|Now" + functions="${functions}|Randomize|Replace|Right|Rnd|Round|RTrim|Second|Sgn|Space|Split|Sqr|Str|StrComp" + functions="${functions}|StrConv|StrReverse|Sum|Time|TimeSerial|TimeValue|Trim|UCase|Val|Weekday" + functions="${functions}|WeekdayName|Year" + + # Oracle functions + functions="${functions}|ADD_MONTHS|ASCIISTR|BITAND|CHR|COMPOSE|COSH|DBTIMEZONE|DECOMPOSE|DUMP|INITCAP|INSTRB" + functions="${functions}|INSTRC|LENGTHB|LENGTHC|MEDIAN|MONTHS_BETWEEN|NCHR|NEW_TIME|NEXT_DAY|REGEXP_COUNT" + functions="${functions}|REGEXP_INSTR|REGEXP_REPLACE|REGEXP_SUBSTR|REMAINDER|ROWNUM|SESSIONTIMEZONE|SOUNDEX" + functions="${functions}|SYSTIMESTAMP|TANH|TRANSLATE|TRUNC|TZ_OFFSET|VSIZE" + + # MySQL data types + data_types="LONGBLOB|LONGTEXT|MEDIUMBLOB|MEDIUMTEXT|SET|TEXT|TINYTEXT" + data_types_fn="BIGINT|BLOB|CHAR|DATE|DATETIME|DECIMAL|DOUBLE|ENUM|FLOAT|INT" + data_types_fn="${data_types_fn}|MEDIUMINT|SMALLINT|TIME|TIMESTAMP|TINYINT|VARCHAR|YEAR" + + # SQL Server data types + data_types="${data_types}|bigint|bit|cursor|date|datetime|datetime2|datetimeoffset|image|int|money|nchar|ntext" + data_types="${data_types}|nvarchar|real|smalldatetime|smallint|smallmoney|sql_variant|table|text|time" + data_types="${data_types}|timestamp|tinyint|uniqueidentifier|varbinary|xml" + data_types_fn="${data_types_fn}|binary|char|decimal|float|numeric|nvarchar|varbinary|varchar|varchar" + + # MS Access data types + data_types="${data_types}|Text|Memo|Byte|Integer|Long|Single|Double|Currency|AutoNumber|Date" + data_types="${data_types}|Time|Ole Object|Hyperlink|Lookup Wizard" + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list sql_static_words ${keywords} ${operators} ${functions} ${data_types} ${data_types_fn} NULL" | tr '|' ' ' + + # Highlight keywords + printf %s " + add-highlighter shared/sql/code/ regex '(?i)\b(${functions})\(.*?\)' 0:function + add-highlighter shared/sql/code/ regex '(?i)\b(${data_types_fn})\(.*?\)' 0:type + add-highlighter shared/sql/code/ regex '(?i)\b(${keywords})\b' 0:keyword + add-highlighter shared/sql/code/ regex '(?i)\b(${operators})\b' 0:operator + add-highlighter shared/sql/code/ regex '(?i)\b(${data_types})\b' 0:type + " +} + +add-highlighter shared/sql/code/ regex '\+|-|\*|/|%|&|\||^|=|>|<|>=|<=|<>|\+=|-=|\*=|/=|%=|&=|^-=|\|\*=' 0:operator +add-highlighter shared/sql/code/ regex \bNULL\b 0:value +add-highlighter shared/sql/code/ regex \b\d+(?:\.\d+)?\b 0:value + +} diff --git a/autoload/filetype/svelte.kak b/autoload/filetype/svelte.kak new file mode 100644 index 0000000..a4469f2 --- /dev/null +++ b/autoload/filetype/svelte.kak @@ -0,0 +1,35 @@ +hook global BufCreate .*\.svelte %[ + set-option buffer filetype svelte +] + +hook global WinSetOption filetype=(svelte) %{ + require-module html + + hook window ModeChange pop:insert:.* -group "svelte-trim-indent" html-trim-indent + hook window InsertChar '>' -group "svelte-indent" html-indent-on-greater-than + hook window InsertChar \n -group "svelte-indent" html-indent-on-new-line + + hook -once -always window WinSetOption "filetype=.*" " + remove-hooks window ""svelte-.+"" + " +} + +hook -group svelte-highlight global WinSetOption filetype=(svelte) %{ + add-highlighter "window/svelte" ref svelte + hook -once -always window WinSetOption "filetype=.*" " + remove-highlighter ""window/svelte"" + " +} + +add-highlighter shared/svelte regions +add-highlighter shared/svelte/comment region <!-- --> fill comment +add-highlighter shared/svelte/tag region < > regions +add-highlighter shared/svelte/style region <style\b.*?>\K (?=</style>) ref css +add-highlighter shared/svelte/script region <script\b.*?>\K (?=</script>) ref javascript + +add-highlighter shared/svelte/block region \{((#|:|/)\w+)? \} regions +add-highlighter shared/svelte/block/ default-region fill meta +add-highlighter shared/svelte/block/inner region -recurse \{ \{((#|:|/)\w+)?\K (?=\}) ref javascript + +add-highlighter shared/svelte/tag/base default-region ref html/tag +add-highlighter shared/svelte/tag/block region -recurse \{ \{ \} ref svelte/block diff --git a/autoload/filetype/swift.kak b/autoload/filetype/swift.kak new file mode 100644 index 0000000..10c2b77 --- /dev/null +++ b/autoload/filetype/swift.kak @@ -0,0 +1,37 @@ +hook global BufCreate .*\.(swift) %{ + set-option buffer filetype swift +} + +hook global WinSetOption filetype=swift %{ + require-module swift +} + +hook -group swift-highlight global WinSetOption filetype=swift %{ + add-highlighter window/swift ref swift + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/swift } +} + + +provide-module swift %{ + +add-highlighter shared/swift regions +add-highlighter shared/swift/code default-region group +add-highlighter shared/swift/string_multiline region %{(?<!')"""} %{(?<!\\)(\\\\)*"""} ref swift/string +add-highlighter shared/swift/string region %{(?<!')"} %{(?<!\\)(\\\\)*"} fill string +add-highlighter shared/swift/comment region /\* \*/ group +add-highlighter shared/swift/line_comment region // $ ref swift/comment + +add-highlighter shared/swift/comment/ fill comment + +add-highlighter shared/swift/code/ regex %{\b(true|false|nil)\b|\b-?(?!\$)\d+[fdiu]?|'((\\.)?|[^'\\])'} 0:value +add-highlighter shared/swift/code/ regex "\b(let|var|while|in|for|if|guard|else|do|switch|case|default|break|continue|return|try|catch|throw|new|delete|and|or|not|operator|explicit|func|import|return|init|deinit|get|set)\b" 0:keyword +add-highlighter shared/swift/code/ regex "\bas\b[!?]?" 0:keyword +add-highlighter shared/swift/code/ regex "(\$[0-9])\b" 0:keyword +add-highlighter shared/swift/code/ regex "\b(const|mutable|auto|namespace|inline|static|volatile|class|struct|enum|union|extension|open|public|protected|private|fileprivate|internal|typedef|virtual|friend|extern|typename|override|final|required|convenience|dynamic)\b" 0:attribute + +add-highlighter shared/swift/code/ regex "\b(self|nil|id|super)\b" 0:value +add-highlighter shared/swift/code/ regex "\b(Bool|String|UInt|UInt16|UInt32|UInt64|UInt8)\b" 0:type +add-highlighter shared/swift/code/ regex "\b(IBAction|IBOutlet)\b" 0:attribute +add-highlighter shared/swift/code/ regex "@\w+\b" 0:attribute + +} diff --git a/autoload/filetype/systemd.kak b/autoload/filetype/systemd.kak new file mode 100644 index 0000000..3810d00 --- /dev/null +++ b/autoload/filetype/systemd.kak @@ -0,0 +1,14 @@ +# https://freedesktop.org/wiki/Software/systemd/ +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*/systemd/.+\.(automount|conf|link|mount|network|path|service|slice|socket|target|timer) %{ + set-option buffer filetype ini + + # NOTE: INI files define the commenting character to be `;`, which won't work in `systemd` files + hook -once buffer BufSetOption comment_line=.+ %{ + set-option buffer comment_line "#" + } +} diff --git a/autoload/filetype/taskpaper.kak b/autoload/filetype/taskpaper.kak new file mode 100644 index 0000000..187aa09 --- /dev/null +++ b/autoload/filetype/taskpaper.kak @@ -0,0 +1,63 @@ +# https://www.taskpaper.com +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*\.taskpaper %{ + set-option buffer filetype taskpaper +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=taskpaper %{ + require-module taskpaper + + hook window ModeChange pop:insert:.* -group taskpaper-trim-indent taskpaper-trim-indent + hook window InsertChar \n -group taskpaper-indent taskpaper-indent-on-new-line + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window taskpaper-.+ } +} + +hook -group taskpaper-highlight global WinSetOption filetype=taskpaper %{ + add-highlighter window/taskpaper ref taskpaper + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/taskpaper } +} + + +provide-module taskpaper %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/taskpaper group + +add-highlighter shared/taskpaper/ regex ^\h*([^:\n]+):\h*\n 1:header +add-highlighter shared/taskpaper/ regex \h@\w+(?:\(([^)]*)\))? 0:variable 1:value +add-highlighter shared/taskpaper/ regex ^\h*([^-:\n]+)\n 1:+i +add-highlighter shared/taskpaper/ regex ^\h*-\h+[^\n]*@done[^\n]* 0:+d +add-highlighter shared/taskpaper/ regex \b(([a-z]+://\S+)|((mailto:)[\w+-]+@\S+)) 0:link + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden taskpaper-trim-indent %{ + evaluate-commands -no-hooks -draft -itersel %{ + execute-keys x + # remove trailing white spaces + try %{ execute-keys -draft s \h + $ <ret> d } + } +} + +define-command -hidden taskpaper-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon>K<a-&> } + ## If the line above is a project indent with a tab + try %{ execute-keys -draft Z kx <a-k>^\h*([^:\n]+):<ret> z i<tab> } + # cleanup trailing white spaces on previous line + try %{ execute-keys -draft kx s \h+$ <ret>d } + } +} + +} diff --git a/autoload/filetype/tcl.kak b/autoload/filetype/tcl.kak new file mode 100644 index 0000000..5823eb5 --- /dev/null +++ b/autoload/filetype/tcl.kak @@ -0,0 +1,79 @@ +hook global BufCreate .*[.](tcl) %{ + set-option buffer filetype tcl +} + +hook global WinSetOption filetype=tcl %{ + require-module tcl + + hook window ModeChange pop:insert:.* -group tcl-trim-indent tcl-trim-indent + hook window InsertChar \n -group tcl-insert tcl-insert-on-new-line + hook window InsertChar \n -group tcl-indent tcl-indent-on-new-line + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window tcl-.+ } +} + +hook -group tcl-highlight global WinSetOption filetype=tcl %{ + add-highlighter window/tcl ref tcl + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/tcl } +} + +# Using non-ascii characters here so that we can use the '[' command +provide-module tcl %§ + +add-highlighter shared/tcl regions +add-highlighter shared/tcl/code default-region group +add-highlighter shared/tcl/comment region (?<!\\)(?:\\\\)*(?:^|\h)\K# '$' fill comment +add-highlighter shared/tcl/double_string region %{(?<!\\)(?:\\\\)*\K"} %{(?<!\\)(?:\\\\)*"} group +add-highlighter shared/tcl/double_string/fill fill string + +evaluate-commands %sh{ + # Tcl does not have keywords, as everything in Tcl is a command. + # Highlight all builtin commads does not make a lot of sense as there are plenty of them. + # What is more, sometimes user defines varaibles have the same names as commands. + # On the other hand, highlight no commads makes the code harder to read. + # The approach for builtin commads highlighting is very simply. + # Highlight only two types of commands: + # 1. "Control statement" like commands, for exmaple, "if", "break", "return", etc. + # 2. Commands defining new scope, for exmaple, "proc", "namespace". + keywords="break catch continue default else elseif error exit for foreach if return switch while proc namespace" + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # Highlight keywords + printf %s\\n "add-highlighter shared/tcl/code/ regex (?<!-)\b($(join "${keywords}" '|'))\b(?!-) 0:keyword" +} + +add-highlighter shared/tcl/code/function regex ^\h*proc\h+((\w|-)+) 1:function +add-highlighter shared/tcl/code/brackets regex [\[\]]{1,2} 0:operator +add-highlighter shared/tcl/code/parameters regex \s-\w+\b 0:attribute +add-highlighter shared/tcl/code/variable regex \$(\w|:)+ 0:value +add-highlighter shared/tcl/code/numbers regex '\b\d+\.?' 0:value + +add-highlighter shared/tcl/double_string/variable regex \$(\w|:)+ 0:value +add-highlighter shared/tcl/double_string/brackets regex [\[\]]{1,2} 0:operator + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden tcl-trim-indent %{ + # Remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden tcl-insert-on-new-line %[ + # Copy '#' comment prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K#\h* <ret> y gh j P } +] + +define-command -hidden tcl-indent-on-new-line %¶ + evaluate-commands -draft -itersel %@ + # Preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + + # Filter previous line + try %{ execute-keys -draft k : tcl-trim-indent <ret> } + + # Indent after { + try %= execute-keys -draft , k x <a-k> (\s|^)\{$ <ret> j <a-gt> = + @ +¶ +§ diff --git a/autoload/filetype/terraform.kak b/autoload/filetype/terraform.kak new file mode 100644 index 0000000..3ad975a --- /dev/null +++ b/autoload/filetype/terraform.kak @@ -0,0 +1,120 @@ +# Terraform configuration language +# https://www.terraform.io/docs/configuration/ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](tf|tfvars) %{ + set-option buffer filetype terraform +} + + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=terraform %{ + require-module terraform + + set-option window static_words %opt{terraform_static_words} + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window terraform-.+ } +} + + +hook -group terraform-highlight global WinSetOption filetype=terraform %{ + add-highlighter window/terraform ref terraform + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/terraform } +} + + +provide-module terraform %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/terraform regions +add-highlighter shared/terraform/code default-region group + +add-highlighter shared/terraform/comment1 region '#' '$' fill comment +add-highlighter shared/terraform/comment2 region '\\' '$' fill comment +add-highlighter shared/terraform/comment3 region /\* \*/ fill comment + +# Strings can contain interpolated terraform expressions, which can contain +# strings. Currently, we cannot support nesting of the same type of delimiter, +# so instead we render the full interpolation as a value (otherwise, it +# looks bad). +# See https://github.com/mawww/kakoune/issues/1670 +add-highlighter shared/terraform/string region '"' '(?<!\\)(?:\\\\)*"' group +add-highlighter shared/terraform/string/fill fill string +add-highlighter shared/terraform/string/inter regex \$\{.+?\} 0:value + +add-highlighter shared/terraform/heredoc region -match-capture '<<-?(\w+)' '^\h*(\w+)$' regions +add-highlighter shared/terraform/heredoc/fill default-region fill string +add-highlighter shared/terraform/heredoc/inter region -recurse \{ (?<!\\)(\\\\)*\$\{ \} ref terraform + + +add-highlighter shared/terraform/code/valueDec regex '\b[0-9]+([kKmMgG]b?)?\b' 0:value +add-highlighter shared/terraform/code/valueHex regex '\b0x[0-9a-f]+([kKmMgG]b?)?\b' 0:value + +add-highlighter shared/terraform/code/operators regex [\[\]] 0:operator + +add-highlighter shared/terraform/code/field regex '^\h+(\w+)\s*(=)' 1:variable 2:keyword + +evaluate-commands %sh{ + blocks="connection content data dynamic locals module output provider + provisioner resource terraform variable" + + constants="true false null" + + keywords="for for_each if in" + + types="bool list map number object set string tuple" + + var_subs="local module var" + + # Builtin functions + fun_num="abs ceil floor log max min parseint pow signum" + + fun_str="chomp format formatlist indent join lower regex regexall replace + split strrev substr title trimspace upper" + + fun_coll="chunklist coalesce coalescelist compact concat contains + distinct element flatten index keys length lookup + matchkeys merge range reverse setintersection setproduct + setunion slice sort transpose values zipmap" + + fun_enc="base64decode base64encode base64gzip csvdecode jsondecode + jsonencode urlencode yamldecode yamlencode" + + fun_file="abspath dirname pathexpand basename file fileexists fileset + filebase64 templatefile" + + fun_dt="formatdate timeadd timestamp" + + fun_crypt="base64sha256 base64sha512 bcrypt filebase64sha256 + filebase64sha512 filemd5 filesha1 filesha256 filesha512 md5 + rsadecrypt sha1 sha256 sha512 uuid uuidv5" + + fun_net="cidrhost cidrnetmask cidrsubnet" + + fun_cast="tobool tolist tomap tonumber toset tostring" + + functions="$fun_num $fun_str $fun_coll $fun_enc $fun_file $fun_dt $fun_crypt $fun_net $fun_cast" + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # Add grammar elements to the static completion list + printf %s\\n "declare-option str-list terraform_static_words $(join "$blocks $keywords $constants $types $var_subs $functions" ' ')" + + # Highlight grammar elements + printf %s " + add-highlighter shared/terraform/code/ regex '\b($(join "$blocks" '|'))\b[^.]' 1:keyword + add-highlighter shared/terraform/code/ regex '\b($(join "$keywords" '|'))\b' 1:keyword + add-highlighter shared/terraform/code/ regex '\b($(join "$constants" '|'))\b' 1:value + add-highlighter shared/terraform/code/ regex '\b($(join "$types" '|'))\b' 1:type + add-highlighter shared/terraform/code/ regex '\b($(join "$var_subs" '|'))\b\.' 1:meta + add-highlighter shared/terraform/code/ regex '\b($(join "$functions" '|'))\s*\(' 1:builtin + " +} + +§ diff --git a/autoload/filetype/toml.kak b/autoload/filetype/toml.kak new file mode 100644 index 0000000..d02e074 --- /dev/null +++ b/autoload/filetype/toml.kak @@ -0,0 +1,76 @@ +# https://github.com/toml-lang/toml/tree/v0.4.0 +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*\.(toml) %{ + set-option buffer filetype toml +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=toml %{ + require-module toml + + hook window ModeChange pop:insert:.* -group toml-trim-indent toml-trim-indent + hook window InsertChar \n -group toml-insert toml-insert-on-new-line + hook window InsertChar \n -group toml-indent toml-indent-on-new-line + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window toml-.+ } +} + +hook -group toml-highlight global WinSetOption filetype=toml %{ + add-highlighter window/toml ref toml + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/toml } +} + + +provide-module toml %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/toml regions +add-highlighter shared/toml/code default-region group +add-highlighter shared/toml/comment region '#' $ fill comment +add-highlighter shared/toml/string1 region '"""' (?<!\\)(\\\\)*"""(?!") fill string +add-highlighter shared/toml/string2 region "'''" "'''(?!')" fill string +add-highlighter shared/toml/string3 region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/toml/string4 region "'" "'" fill string + +add-highlighter shared/toml/code/ regex \ + "^\h*\[\[?([A-Za-z0-9._-]*)\]\]?" 1:title +add-highlighter shared/toml/code/ regex \ + (?<!\w)[+-]?[0-9](_?\d)*(\.[0-9](_?\d)*)?([eE][+-]?[0-9](_?\d)*)?\b 0:value +add-highlighter shared/toml/code/ regex \ + true|false 0:value +add-highlighter shared/toml/code/ regex \ + '\d{4}-\d{2}-\d{2}[Tt ]\d{2}:\d{2}:\d{2}(.\d+)?([Zz]|[+-]\d{2}:\d{2})' 0:value + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden toml-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden toml-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy # comments prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K#\h* <ret> y gh j P } + } +} + +define-command -hidden toml-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : toml-trim-indent <ret> } + } +} + +} diff --git a/autoload/filetype/troff.kak b/autoload/filetype/troff.kak new file mode 100644 index 0000000..205c288 --- /dev/null +++ b/autoload/filetype/troff.kak @@ -0,0 +1,51 @@ +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*\.\d+ %{ + set-option buffer filetype troff +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=troff %{ + require-module troff +} + +hook -group troff-highlight global WinSetOption filetype=troff %{ + add-highlighter window/troff ref troff + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/troff } +} + +provide-module troff %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/troff regions + +add-highlighter shared/troff/text default-region group +add-highlighter shared/troff/text/ regex '(^\.)?\\".*?\n' 0:comment +add-highlighter shared/troff/text/ regex '\\f[A-Z]' 0:attribute +add-highlighter shared/troff/text/ regex '\\fB(.+?)\\f[A-Z]' 1:+b +add-highlighter shared/troff/text/ regex '\\fI(.+?)\\f[A-Z]' 1:+i +add-highlighter shared/troff/text/ regex '^\.[a-zA-Z]{1,2}\b' 0:meta +add-highlighter shared/troff/text/ regex '^\.(PSPIC|PDFPIC|pdfhref)\b' 0:meta +add-highlighter shared/troff/text/ regex '^\.\.$' 0:meta +add-highlighter shared/troff/text/ regex '^\.TH\s+[^\n]+' 0:title +add-highlighter shared/troff/text/ regex '^\.NH(\s+\d+(\s+\d+)?)?\s*\n' 0:header +add-highlighter shared/troff/text/ regex '^\.SH(\s+\d+)?\s*\n' 0:header +add-highlighter shared/troff/text/ regex '^\.IR\s+(\S+)' 1:+i +add-highlighter shared/troff/text/ regex '^\.BR\s+(\S+)' 1:+b +add-highlighter shared/troff/text/ regex '^\.I\s+([^\n]+)' 1:+i +add-highlighter shared/troff/text/ regex '^\.B\s+([^\n]+)' 1:+b +add-highlighter shared/troff/text/ regex '(ftp:|http:|https:|www\.)+[^\s]+[\w]' 0:link + +add-highlighter shared/troff/pic region '^\.PS\b' '^\.PE\b' group +add-highlighter shared/troff/pic/ regex '^(\.PS\b|\.PE\b)' 1:meta +add-highlighter shared/troff/pic/ regex '^(copy)\s+' 1:keyword +add-highlighter shared/troff/pic/ regex '\b(arc|arrow|box|circle|ellipse|line|move|spline)\b' 1:type +add-highlighter shared/troff/pic/ regex '\b(above|at|below|by|center|chop|dashed|diam|diameter|down|dotted|fill|from|ht|height|invis|left|ljust|rad|radius|right|rjust|solid|then|to|up|wid|width|with)\b' 1:attribute +add-highlighter shared/troff/pic/ regex '(\s+|\+|-|\*|/)(\d+(\.\d+)?)' 2:value +add-highlighter shared/troff/pic/ regex '"[^"]*"' 0:string +} diff --git a/autoload/filetype/tupfile.kak b/autoload/filetype/tupfile.kak new file mode 100644 index 0000000..33e570d --- /dev/null +++ b/autoload/filetype/tupfile.kak @@ -0,0 +1,40 @@ +# http://gittup.org/tup/ +# + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*/?Tup(file|rules)(\.\w+)?$ %{ + set-option buffer filetype tupfile +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook -group tupfile-highlight global WinSetOption filetype=tupfile %{ + require-module tupfile + + add-highlighter window/tupfile ref tupfile + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/tupfile } +} + + +provide-module tupfile %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/tupfile regions +add-highlighter shared/tupfile/code default-region group +add-highlighter shared/tupfile/string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/tupfile/comment region '#' $ fill comment + +add-highlighter shared/tupfile/code/ regex '%[fbBeoOdg]\b' 0:value +add-highlighter shared/tupfile/code/ regex '[$@]\([\w_]+\)' 0:value +add-highlighter shared/tupfile/code/ regex '^\h*:\s*(foreach)\b' 1:keyword +add-highlighter shared/tupfile/code/ regex '^\h*(\.gitignore)\b' 1:keyword +add-highlighter shared/tupfile/code/ regex '^\h*\b(ifn?eq|ifn?def|else|endif|error|include|include_rules|run|preload|export)\b' 0:keyword +add-highlighter shared/tupfile/code/ regex '^\h*\b(&?[\w_]+)\s*[:+]?=' 1:keyword +add-highlighter shared/tupfile/code/ regex '`[^`\n]+`' 0:meta + +} diff --git a/autoload/filetype/twig.kak b/autoload/filetype/twig.kak new file mode 100644 index 0000000..2f5ef18 --- /dev/null +++ b/autoload/filetype/twig.kak @@ -0,0 +1,89 @@ +# https://twig.symfony.com/doc/3.x/templates.html +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](twig) %{ + set-option buffer filetype twig +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=twig %[ + require-module twig + + hook window ModeChange pop:insert:.* -group twig-trim-indent twig-trim-indent + hook window InsertChar \n -group twig-insert twig-insert-on-new-line + hook window InsertChar \n -group twig-indent twig-indent-on-new-line + hook window InsertChar '>' -group twig-indent twig-indent-on-greater-than + hook window InsertChar '#' -group twig-auto-close twig-auto-close-delim + hook window InsertChar '%' -group twig-auto-close twig-auto-close-delim + set-option buffer extra_word_chars '_' '-' + + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window twig-.+ } +] + +hook -group twig-highlight global WinSetOption filetype=twig %{ + add-highlighter window/twig ref twig + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/twig } +} + + +provide-module twig %[ + +require-module html + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/twig regions +add-highlighter shared/twig/core default-region group +add-highlighter shared/twig/comment region \{# [#]\} fill comment +add-highlighter shared/twig/delim region \{([%]-?|\{) (-?[%]|\})\} regions + +add-highlighter shared/twig/core/ ref html + +add-highlighter shared/twig/delim/base default-region group +add-highlighter shared/twig/delim/double_string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/twig/delim/single_string region "'" (?<!\\)(\\\\)*' fill string +add-highlighter shared/twig/delim/base/ regex (\w+)\h= 1:variable + +add-highlighter shared/twig/delim/base/functions regex \b(\w+)\( 1:function + +add-highlighter shared/twig/delim/base/filters regex \b(abs|batch|capitalize|column|convert_encoding|country_name|currency_name|currency_symbol|data_uri|date|date_modify|default|e|escape|filter|first|format|format_currency|format_date|format_datetime|format_number|format_time|html_to_markdown|inline_css|inky_to_html|join|json_encode|keys|language_name|last|length|locale_name|lower|map|markdown_to_html|merge|nl2br|number_format|raw|reduce|replace|reverse|round|slice|slug|sort|spaceless|split|striptags|timezone_name|title|trim|u|upper|url_encode)(\()?\b 1:operator + +add-highlighter shared/twig/delim/base/tags regex \b((extends|deprecated|do|flush|import|from|elseif|else|include|set|use)|(end)?(apply|autoescape|block|cache|embed|for|if|macro|sandbox|set|verbatim|with))\b 0:keyword 0:+i + + +add-highlighter shared/twig/delim/base/delimiter_code regex (\{[%]|[%]\}) 0:function +add-highlighter shared/twig/delim/base/delimiter_output regex (\{\{|\}\}) 0:operator + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden twig-trim-indent html-trim-indent +define-command -hidden twig-indent-on-new-line html-indent-on-new-line +define-command -hidden twig-indent-on-greater-than html-indent-on-greater-than + +define-command -hidden twig-auto-close-delim %[ + evaluate-commands -itersel %[ + try %[ + execute-keys -draft <semicolon>hH<a-k>\h*\{<ret>lyp + execute-keys <esc>hi<space><esc>hi<space> + ] + ] +] + +define-command -hidden twig-insert-on-new-line %[ + evaluate-commands -draft -itersel %/ + execute-keys <semicolon> + try %[ + execute-keys -draft kx<a-k>^\h*\{\[%#\{\]\h+$<ret> + execute-keys -draft jghd + ] + / +] + +] diff --git a/autoload/filetype/vhdl.kak b/autoload/filetype/vhdl.kak new file mode 100644 index 0000000..71aa7ed --- /dev/null +++ b/autoload/filetype/vhdl.kak @@ -0,0 +1,410 @@ +# Based on IEEE Std 1076‐2019 + +# Detection +hook global BufCreate .*[.](vhd[l]?) %[ + set-option buffer filetype vhdl +] + +# Initialization +hook global WinSetOption filetype=vhdl %[ + require-module vhdl + set-option window static_words %opt{vhdl_static_words} + hook -group vhdl-indent window InsertChar \n vhdl-indent-on-new-line + hook -group vhdl-indent window InsertChar \) vhdl-indent-on-closing-parenthesis + hook -group vhdl-insert window InsertChar \n vhdl-insert-on-new-line + # Cleanup trailing whitespaces on current line insert end. + hook -group vhdl-trim-indent window ModeChange pop:insert:.* %[ try %[ execute-keys -draft <semicolon> x s ^\h+$ <ret> d ] ] + hook -once -always window WinSetOption filetype=.* %[ remove-hooks window vhdl-.+ ] +] + +hook -group vhdl-highlight global WinSetOption filetype=vhdl %[ + add-highlighter window/vhdl ref vhdl + hook -once -always window WinSetOption filetype=.* %[ remove-highlighter window/vhdl ] +] + +provide-module vhdl %§ + +# Highlighters & Completion +add-highlighter shared/vhdl regions +add-highlighter shared/vhdl/code default-region group +add-highlighter shared/vhdl/comment_line region '--' $ fill comment +add-highlighter shared/vhdl/comment region /\* \*/ fill comment + +# Integer formats +add-highlighter shared/vhdl/code/ regex '(?i)\b0b[01]+l?\b' 0:value +add-highlighter shared/vhdl/code/ regex '(?i)\b0x[\da-f]+l?\b' 0:value +add-highlighter shared/vhdl/code/ regex '(?i)\b0o?[0-7]+l?\b' 0:value +add-highlighter shared/vhdl/code/ regex '(?i)\b([1-9]\d*|0)l?\b' 0:value +# Float formats +add-highlighter shared/vhdl/code/ regex '\b\d+[eE][+-]?\d+\b' 0:value +add-highlighter shared/vhdl/code/ regex '(\b\d+)?\.\d+\b' 0:value +add-highlighter shared/vhdl/code/ regex '\b\d+\.' 0:value +# Imaginary formats +add-highlighter shared/vhdl/code/ regex '\b\d+\+\d+[jJ]\b' 0:value + +evaluate-commands %sh[ + values="true false note warning error failure nul" + + # LRM 5.2.4.1 + units="fs ps ns us ms sec min hr Å nm um mm cm m km" + + # LRM 16.2 + predefined_attributes=" + base left right high low ascending length range reverse_range + subtype image pos succ pred leftof rightof value val + designated_subtype reflect high low index element delayed + stable quiet transaction event active last_event last_active + last_value driving driving_value simple_name instance_name + path_name record signal converse + " + + libraries="ieee std work" + + packages=" + math_real math_complex std_logic_1164 std_logic_textio numeric_bit numeric_std + numeric_bit_unsigned numeric_std_unsigned fixed_float_types fixed_generic_pkg + fixed_pkg float_generic_pkg float_pkg + standard textio env + " + + # LRM 15.10 + reserved_words=" + abs access after alias all and architecture array assert assume assume_guarantee attribute + begin block body buffer bus + case component configuration constant context cover + default disconnect downto + else elsif end entity exit + fairness file for force function + generate generic group guarded + if impure in inertial inout is + label library linkage literal loop + map mod + nand new next nor not null + of on open or others out + package parameter port postponed procedure process property protected pure + range record register reject release rem report restrict restrict_guarantee return rol ror + select sequence severity signal shared sla sll sra srl strong subtype + then to transport type + unaffected units until use + variable view vpkg vmode vprop vunit + wait when while with + xnor xor + " + + types=" + bit bit_vector + boolean boolean_vector + character + file_open_state file_origin_kind + integer integer_vector + natural positive + line line_vector + real real_vector + std_logic std_logic_vector + std_ulogic std_ulogic_vector + side + signed unsigned + string text + time time_vector + " + + functions=" + find_leftmost find_rightmost divide reciprocal remainder modulo minimum maximum + std_match add_carry scalb + resize to_ufixed to_sfixed to_unsigned to_signed to_real to_integer to_slv + to_std_logic_vector to_stdlogicvector to_sulv to_std_ulogic_vector to_std_ulogicvector + to_01 is_x to_x01 to_ux01 to_x01z + ufixed_high ufixed_low sfixed_high sfixed_low to_ufix to_sfix ufix_high ufix_low + sfix_high sfix_low + write read bwrite binary_write bread binary_read owrite oread octal_write octal_read + hwrite hread hex_write hex_read to_string to_bstring to_binary_string to_ostring + to_octal_string to_hstring to_hex_string from_string from_bstring from_binary_string + from_ostring from_octal_string from_hstring from_hex_string + rising_edge falling_edge + " + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + + # Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list vhdl_static_words $(join "${values} ${units} ${predefined_attributes} ${libraries} ${packages} ${reserved_words} ${types} ${functions}" ' ')" + + # Highlight keywords + printf %s " + add-highlighter shared/vhdl/code/ regex '(?i)\b($(join "${values}" '|'))\b' 0:value + add-highlighter shared/vhdl/code/ regex '(?i)\b($(join "${units}" '|'))\b' 0:meta + add-highlighter shared/vhdl/code/ regex \"'(?i)\b($(join "${predefined_attributes}" '|'))\b\" 0:attribute + add-highlighter shared/vhdl/code/ regex '(?i)\b($(join "${libraries}" '|'))\b' 0:builtin + add-highlighter shared/vhdl/code/ regex '(?i)\b($(join "${packages}" '|'))\b' 0:builtin + add-highlighter shared/vhdl/code/ regex '(?i)\b($(join "${reserved_words}" '|'))\b' 0:keyword + add-highlighter shared/vhdl/code/ regex '(?i)\b($(join "${functions}" '|'))\b\(' 1:builtin + add-highlighter shared/vhdl/code/ regex '(?i)\b($(join "${types}" '|'))\b' 0:type + add-highlighter shared/vhdl/code/ regex '^\h*(@[\w_.]+))' 1:attribute + " +] + +add-highlighter shared/vhdl/code/ regex \(|\)|\;|\.|,|:|\| 0:attribute + +add-highlighter shared/vhdl/code/ regex \?\?|=|/=|<|<=|>|>=|\?=|\?/=|\?<|\?<=|\?>|\?>=|\+|-|&|\*|/|:= 0:operator + +# Meta values highlight. +# The values 'U', 'X', 'W', and '–' are metalogical values; they define the behavior of the model itself rather than the behavior of the hardware being synthesized. +add-highlighter shared/vhdl/code/ regex "(?i)'[U|X|W|-]'" 0:meta +# Highlight other logical values. +add-highlighter shared/vhdl/code/ regex "(?i)'[0|1|Z|L|H]'" 0:value + +# String +add-highlighter shared/vhdl/code/ regex '"[^"]*"' 0:string + +# Binary vector. +add-highlighter shared/vhdl/code/ regex '[bB]"[01_]*"' 0:value + +# Octal vector. +add-highlighter shared/vhdl/code/ regex '[oO]"[01234567_]*"' 0:value + +# Hex vector. +add-highlighter shared/vhdl/code/ regex '(?i)x"[0123456789abcdef_]*"' 0:value + +define-command -hidden vhdl-insert-on-new-line %[ + # Handle comment lines. + evaluate-commands -itersel %[ + # Copy '--' comment prefix and following white spaces. + try %[ + # <a-lt> is needed because of "Preserve previous line indent" command. + try %[ execute-keys -draft k x s ^\h*--\h* <ret> y j <a-lt> gh P ] + ] + ] + + evaluate-commands -save-regs x %[ + # Save previous line indent in register x. + try %[ execute-keys -draft kxs^\h+<ret>"xy ] catch %[ reg x '' ] + + # All "wisely add" commands share the same concept. + # Only "end if" has extra comments. + # Wisely add "end if;". + evaluate-commands %[ + try %[ + # Validate previous line and that it is not closed yet. + execute-keys -draft kx <a-k>^\h*(?i)((then|(.*:\h*)?if\b.*\bthen)$)<ret> j}ijx <a-K>^<c-r>x(?i)(elsif|else|end)\b<ret> + # Don't add for "if ... generate", it requires "end generate;". + execute-keys -draft kx <a-K>(?i)\bgenerate\b<ret> + execute-keys -draft o<c-r>xend<space>if<semicolon><esc> + ] + ] + # Wisely add "end generate;". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^\h*(?i).*\bgenerate$<ret> j}ijx <a-K>^<c-r>x(?i)(begin|elsif|else|end)\b<ret> + # Don't add in case of comment line. + execute-keys -draft kx <a-K>^\h*--<ret> + execute-keys -draft o<c-r>xend<space>generate<semicolon><esc> + ] + ] + # Wisely add "when" and "end case;". + evaluate-commands %[ + try %[ + # TODO: Case needs special handling. + execute-keys -draft kx <a-k>^\h*(?i)(case|.*\h*:\h*case)\b<ret> jwx <a-K>^<c-r>x(?i)(end|when)<ret> + execute-keys -draft <c-r>xo<c-r>xend<space>case<semicolon><esc>kAwhen<space><esc> + ] + ] + # Wisely add "begin" and "end block;". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^\h*(?i)((block|.*:\h*block)\b)<ret> j}ijx <a-K>^<c-r>x(?i)(begin|end)\b<ret> + execute-keys -draft o<c-r>xbegin<ret><c-r>xend<space>block<semicolon><esc> + ] + ] + # Wisely add "begin" and "end process;". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^\h*(?i)(.*:\h*)?(postponed\h+)?process\b<ret> j}ijx <a-K>^<c-r>x(?i)(begin|end)<ret> + execute-keys -draft o<c-r>xbegin<ret><c-r>xend<space>process<semicolon><esc> + ] + ] + # Wisely add "end loop;". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^\h*(?i)(.*\bloop|.*\h*:\h*(for|loop))$<ret> j}ijx <a-K>^<c-r>x(?i)(end)<ret> + execute-keys -draft o<c-r>xend<space>loop<semicolon><esc> + ] + ] + # Wisely add "end protected;". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^\h*(?i)(type\b.*\bis\h+protected)$<ret> j}ijx <a-K>^<c-r>x(?i)(end)<ret> + execute-keys -draft o<c-r>xend<space>protected<semicolon><esc> + ] + ] + # Wisely add "end protected body;". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^(?i)(\h*type\h+\w+\h+is\h+protected\h+body$)<ret> j}ijx <a-K>^<c-r>x(?i)end\h+protected\h+body\b<ret> + execute-keys -draft o<c-r>xend<space>protected<space>body<semicolon><esc> + ] + ] + # Wisely add "end record;". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^\h*(?i)(type\b.*\bis\h+record\h*)$<ret> j}ijx <a-K>^<c-r>x(?i)(end)<ret> + execute-keys -draft o<c-r>xend<space>record<semicolon><esc> + ] + ] + # Wisely add ");" for "type ... is (". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^\h*(?i)(type\b.*\bis\h+\(\h*)$<ret> j}ijx <a-K>^<c-r>x(\))<ret> + execute-keys -draft o<c-r>x)<semicolon><esc> + ] + ] + # Wisely add "end entity;". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^(?i)\h*entity\b.*\bis$<ret> j}ijx <a-K>^<c-r>x(?i)(begin|end)\b<ret> + execute-keys -draft o<c-r>xend<space>entity<semicolon><esc> + ] + ] + # Wisely add "begin" and "end function;". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^(?i)(\h*\)?\h*return\b.*\bis$)<ret> j}ijx <a-K>^<c-r>x(?i)(begin|end)\b<ret> + execute-keys -draft o<c-r>xbegin<ret><c-r>xend<space>function<semicolon><esc> + ] + try %[ + execute-keys -draft kx <a-k>^(?i)(\h*((pure|impure)\h+)?function\b.*\bis$)<ret> j}ijx <a-K>^<c-r>x(?i)(begin|end)\b<ret> + execute-keys -draft o<c-r>xbegin<ret><c-r>xend<space>function<semicolon><esc> + ] + ] + # Wisely add "begin" and "end procedure;". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^(?i)(\h*procedure\b.*\bis$)<ret> j}ijx <a-K>^<c-r>x(?i)\b(begin|end)\b<ret> + execute-keys -draft o<c-r>xbegin<ret><c-r>xend<space>procedure<semicolon><esc> + ] + try %[ + execute-keys -draft kx <a-k>^(?i)\h*\)\h*\bis$<ret> j}ijx <a-K>^<c-r>x(?i)\b(begin|end)\b<ret> + # Verify that line with opening parenthesis contains "procedure" keyword. + execute-keys -draft kx s\)<ret> <a-m><semicolon> x<a-k> (?i)\bprocedure\b<ret> + execute-keys -draft o<c-r>xbegin<ret><c-r>xend<space>procedure<semicolon><esc> + ] + ] + # Wisely add "end package;". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^(?i)(package\b)<ret> j}ijx <a-K>^<c-r>x(?i)(end)\b<ret> + # Make sure it is not package body. + execute-keys -draft kx<a-K>(?i)\bbody\b<ret> + execute-keys -draft oend<space>package<semicolon><esc> + ] + ] + # Wisely add "end package body;". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^(?i)(package\h+body\b)<ret> j}ijx <a-K>^<c-r>x(?i)(end)\b<ret> + execute-keys -draft oend<space>package<space>body<semicolon><esc> + ] + ] + # Wisely add "begin" and "end architecture;". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^(?i)\h*architecture\b<ret> j}ijx <a-K>^<c-r>x(?i)(begin|end)\b<ret> + execute-keys -draft o<c-r>xbegin<ret><c-r>xend<space>architecture<semicolon><esc> + ] + ] + # Wisely add ");" for "port (". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^\h*(?i)port\h*\($<ret> j}ijx <a-K>^<c-r>x(\)\;)<ret> + execute-keys -draft o<c-r>x)<semicolon><esc> + ] + ] + # Wisely add ");" for "port map (". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^\h*(?i)port\h+map\h*\($<ret> j}ijx <a-K>^<c-r>x(\)\;)<ret> + execute-keys -draft o<c-r>x)<semicolon><esc> + ] + ] + # Wisely add ");" for "generic (". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^\h*(?i)generic\h*\($<ret> j}ijx <a-K>^<c-r>x(\)\;)<ret> + execute-keys -draft o<c-r>x)<semicolon><esc> + ] + ] + # Wisely add ")" for "generic map (". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^\h*(?i)generic\h+map\h*\($<ret> j}ijx <a-K>^<c-r>x(\))<ret> + execute-keys -draft o<c-r>x)<esc> + ] + ] + # Wisely add ") return ;" for "[pure|impure] function ... (". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^\h*(?i)(pure\b|impure\b)?\h*function\b.*\h*\($<ret> j}ijx <a-K>^<c-r>x(\)\h*return.*)<ret> + execute-keys -draft o<c-r>x)<space>return<space><semicolon><esc> + ] + ] + # Wisely add ");" for "procedure ... (". + evaluate-commands %[ + try %[ + execute-keys -draft kx <a-k>^\h*(?i)procedure\b.*\h*\($<ret> j}ijx <a-K>^<c-r>x(\)\h*\;)<ret> + execute-keys -draft o<c-r>x)<semicolon><esc> + ] + ] + ] +] + +define-command -hidden vhdl-indent-on-new-line %{ + evaluate-commands -itersel %{ + # Align "then" to previous "if|elsif". + evaluate-commands -itersel -save-regs x %[ + try %[ + execute-keys -draft k x <a-k> (?i)^\h*then$ <ret> + try %[ execute-keys -draft <a-/>(?i)\b(if|elsif)\b<ret>xs^\h+<ret>"xy ] catch %[ reg x '' ] + try %[ execute-keys -draft k xs^\h+<ret>d ] catch %[ ] + execute-keys -draft kgh i<c-r>x<esc> + ] + ] + + # Align "generate" to previous "if|for". + evaluate-commands -itersel -save-regs x %[ + try %[ + execute-keys -draft k x <a-k> (?i)^\h*generate$ <ret> + try %[ execute-keys -draft <a-/>(?i)\b(if|for)\b<ret>xs^\h+<ret>"xy ] catch %[ reg x '' ] + try %[ execute-keys -draft k xs^\h+<ret>d ] catch %[ ] + execute-keys -draft kgh i<c-r>x<esc> + ] + ] + + # Preserve previous line indent. + try %[ execute-keys -draft <semicolon> K <a-&> ] + + # Cleanup trailing whitespaces from previous line. + try %[ execute-keys -draft k x s \h+$ <ret> d ] + + # Increase indent after some keywords. + try %[ + execute-keys -draft kx<a-k> (?i)\b(begin|block|body|else|for|generate|if|is|loop|process|protected|record|select|then)$ <ret> + # Do not indent if in comment line. + execute-keys -draft kx<a-K>(?i)^\h*--<ret> + # Do not indent for "case ... is". + execute-keys -draft kx<a-K>^\h*(?i)(case|.*\h*:\h*case)\b<ret> + execute-keys -draft <semicolon> <a-gt> + ] + # Copy the indentation of the matching if. + try %{ execute-keys -draft , k x <a-k> ^\h*(elsif\b|else$) <ret> gh [c^\h*(\S*\h*:\h*)?if\b,\bend\sif\b <ret> x <a-S> 1<a-&> , j K <a-&> } + + # Increase indent after some operators. + try %[ execute-keys -draft <semicolon> k x <a-k> (\(|=>|<=|:=)$ <ret> j <a-gt> ] + } +} + +define-command vhdl-indent-on-closing-parenthesis %[ + evaluate-commands -itersel %[ + # Decrease indent after ")" at the beginning of line. + try %[ execute-keys -draft x <a-k> (^\h+\)$) <ret> <a-lt> ] + ] +] + +§ diff --git a/autoload/filetype/void-linux.kak b/autoload/filetype/void-linux.kak new file mode 100644 index 0000000..23a0206 --- /dev/null +++ b/autoload/filetype/void-linux.kak @@ -0,0 +1,4 @@ +# Void Linux package template +hook global BufCreate .*/?srcpkgs/.+/template %{ + set-option buffer filetype sh +} diff --git a/autoload/filetype/yaml.kak b/autoload/filetype/yaml.kak new file mode 100644 index 0000000..db6a4f9 --- /dev/null +++ b/autoload/filetype/yaml.kak @@ -0,0 +1,73 @@ +# http://yaml.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](ya?ml) %{ + set-option buffer filetype yaml +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=yaml %{ + require-module yaml + + hook window ModeChange pop:insert:.* -group yaml-trim-indent yaml-trim-indent + hook window InsertChar \n -group yaml-insert yaml-insert-on-new-line + hook window InsertChar \n -group yaml-indent yaml-indent-on-new-line + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window yaml-.+ } +} + +hook -group yaml-highlight global WinSetOption filetype=yaml %{ + add-highlighter window/yaml ref yaml + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/yaml } +} + + +provide-module yaml %{ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/yaml regions +add-highlighter shared/yaml/code default-region group +add-highlighter shared/yaml/double_string region '"' (?<!\\)(\\\\)*" fill string +add-highlighter shared/yaml/single_string region "'" "'" fill string +add-highlighter shared/yaml/comment region '(?:^| )#' $ fill comment + +add-highlighter shared/yaml/code/ regex ^(---|\.\.\.)$ 0:meta +add-highlighter shared/yaml/code/ regex ^(\h*:\w*) 0:keyword +add-highlighter shared/yaml/code/ regex \b(true|false|null)\b 0:value +add-highlighter shared/yaml/code/ regex ^\h*-?\h*(\S+): 1:attribute + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden yaml-trim-indent %{ + # remove trailing white spaces + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden yaml-insert-on-new-line %{ + evaluate-commands -draft -itersel %{ + # copy '#' comment prefix and following white spaces + try %{ execute-keys -draft k x s ^\h*\K#\h* <ret> y gh j P } + } +} + +define-command -hidden yaml-indent-on-new-line %{ + evaluate-commands -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft <semicolon> K <a-&> } + # filter previous line + try %{ execute-keys -draft k : yaml-trim-indent <ret> } + # indent after : + try %{ execute-keys -draft , k x <a-k> :$ <ret> j <a-gt> } + # indent after - + try %{ execute-keys -draft , k x <a-k> ^\h*- <ret> j <a-gt> } + } +} + +} diff --git a/autoload/filetype/zig.kak b/autoload/filetype/zig.kak new file mode 100644 index 0000000..b322c82 --- /dev/null +++ b/autoload/filetype/zig.kak @@ -0,0 +1,144 @@ +# zig syntax highlighting for kakoune (https://ziglang.org) +# +# based off of https://github.com/ziglang/zig.vim/blob/master/syntax/zig.vim +# as well as https://ziglang.org/documentation/master/#Grammar + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](zig|zon) %{ + set-option buffer filetype zig +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=zig %< + require-module zig + hook window ModeChange pop:insert:.* -group zig-trim-indent zig-trim-indent + hook window InsertChar \n -group zig-insert zig-insert-on-new-line + hook window InsertChar \n -group zig-indent zig-indent-on-new-line + hook window InsertChar \} -group zig-indent zig-indent-on-closing + + hook -once -always window WinSetOption filetype=.* %< remove-hooks window zig-.+ > +> + +hook -group zig-highlight global WinSetOption filetype=zig %{ + require-module zig + add-highlighter window/zig ref zig + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/zig } +} + +provide-module zig %§ + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/zig regions +add-highlighter shared/zig/code default-region group + +add-highlighter shared/zig/doc_comment region '///(?=[^/])' '$' fill documentation +add-highlighter shared/zig/comment region '//' '$' fill comment + +# strings and characters +add-highlighter shared/zig/string region '"' (?<!\\)(\\\\)*" group +add-highlighter shared/zig/string/ fill string +add-highlighter shared/zig/string/ regex '(?:\\n|\\r|\\t|\\\\|\\''|\\"|\\x[0-9a-fA-F]{2}|\\u\{[0-9a-fA-F]+\})' 0:meta + +add-highlighter shared/zig/character region "'" (?<!\\)(\\\\)*' group +add-highlighter shared/zig/character/ fill string +add-highlighter shared/zig/character/ regex '(?:\\n|\\r|\\t|\\\\|\\''|\\"|\\x[0-9a-fA-F]{2}|\\u\{[0-9a-fA-F]+\})' 0:meta + +add-highlighter shared/zig/multiline_string region '\\\\' '$' fill string + +# attributes +add-highlighter shared/zig/code/ regex '\b(?:const|var|extern|packed|export|pub|noalias|inline|noinline|comptime|callconv|volatile|allowzero|align|linksection|threadlocal)\b' 0:attribute +# structures +add-highlighter shared/zig/code/ regex '\b(?:struct|enum|union|error|opaque)\b' 0:attribute + +# statement +add-highlighter shared/zig/code/ regex '\b(?:break|return|continue|asm|defer|errdefer|unreachable|try|catch|async|noasync|await|suspend|nosuspend|resume)\b' 0:keyword +# conditional +add-highlighter shared/zig/code/ regex '\b(?:if|else|switch|and|or|orelse)\b' 0:keyword +# repeat +add-highlighter shared/zig/code/ regex '\b(?:while|for)\b' 0:keyword +# other keywords +add-highlighter shared/zig/code/ regex '\b(?:fn|usingnamespace|test)\b' 0:keyword + +# types +add-highlighter shared/zig/code/ regex '\b(?:bool|f16|f32|f64|f80|f128|void|noreturn|type|anyerror|anyframe|anytype|anyopaque)\b' 0:type +add-highlighter shared/zig/code/ regex '\b(?:i0|u0|isize||usize|comptime_int|comptime_float)\b' 0:type +add-highlighter shared/zig/code/ regex '\b(?:[iu][1-9]\d*)\b' 0:type +add-highlighter shared/zig/code/ regex '\b(?:c_char|c_short|c_ushort|c_int|c_uint|c_long|c_ulong|c_longlong|c_ulonglong|c_longdouble)\b' 0:type + +# primitive values +add-highlighter shared/zig/code/ regex '\b(?:true|false|null|undefined)\b' 0:value + +# integer literals +add-highlighter shared/zig/code/ regex '\b[0-9](_?[0-9])*\b' 0:value +add-highlighter shared/zig/code/ regex '\b0x[0-9a-fA-F](_?[0-9a-fA-F])*\b' 0:value +add-highlighter shared/zig/code/ regex '\b0o[0-7](_?[0-7])*\b' 0:value +add-highlighter shared/zig/code/ regex '\b0b[01](_?[01])*\b' 0:value + +# float literals +add-highlighter shared/zig/code/ regex '\b[0-9]+\.[0-9]+(?:[eE][-+]?[0-9]+)?\b' 0:value +add-highlighter shared/zig/code/ regex '\b0x[0-9a-fA-F]+\.[0-9a-fA-F]+(?:[pP][-+]?[0-9a-fA-F]+)?\b' 0:value +add-highlighter shared/zig/code/ regex '\b[0-9]+\.?[eE][-+]?[0-9]+\b' 0:value +add-highlighter shared/zig/code/ regex '\b0x[0-9a-fA-F]+\.?[eE][-+]?[0-9a-fA-F]+\b' 0:value + +# operators +add-highlighter shared/zig/code/ regex '(?:\+|-|\*|/|%|=|<|>|&|\||\^|~|\?|!)' 0:operator + +# builtin functions +add-highlighter shared/zig/code/ regex "@(?:addWithOverflow|as|atomicLoad|atomicStore|bitCast|breakpoint|trap|alignCast|alignOf|cDefine|cImport|cInclude|cUndef|clz|cmpxchgWeak|cmpxchgStrong|compileError|compileLog|constCast|ctz|popCount|divExact|divFloor|divTrunc|embedFile|export|extern|tagName|TagType|errorName|call|errorReturnTrace|fence|fieldParentPtr|field|unionInit|frameAddress|import|inComptime|newStackCall|asyncCall|ptrFromInt|max|min|memcpy|memset|mod|mulAdd|mulWithOverflow|splat|src|bitOffsetOf|byteOffsetOf|offsetOf|OpaqueType|panic|prefetch|ptrCast|intFromPtr|rem|returnAddress|setCold|Type|shuffle|reduce|select|setRuntimeSafety|setEvalBranchQuota|setFloatMode|shlExact|This|hasDecl|hasField|shlWithOverflow|shrExact|sizeOf|bitSizeOf|sqrt|byteSwap|subWithOverflow|intCast|floatCast|floatFromInt|intFromFloat|intFromBool|errSetCast|truncate|typeInfo|typeName|TypeOf|atomicRmw|errorFromInt|intFromError|enumFromInt|intFromEnum|setAlignStack|frame|Frame|frameSize|bitReverse|Vector|volatileCast|sin|cos|tan|exp|exp2|log|log2|log10|abs|floor|ceil|trunc|wasmMemorySize|wasmMemoryGrow|round)\b" 0:meta + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden zig-trim-indent %{ + # delete trailing whitespace + try %{ execute-keys -draft -itersel x s \h+$ <ret> d } +} + +define-command -hidden zig-insert-on-new-line %< + try %[ + evaluate-commands -draft -save-regs '/"' %[ + # copy // or /// comments prefix or \\ string literal prefix and following whitespace + execute-keys -save-regs '' k x1s^\h*((///?|\\\\)+\h*)<ret> y + try %[ + # if the previous comment isn't empty, create a new one + execute-keys x<a-K>^\h*//+\h*$<ret> jxs^\h*<ret>P + ] catch %[ + # if there is no text in the previous comment, remove it completely + execute-keys d + ] + ] + + # trim trailing whitespace on the previous line + try %[ execute-keys -draft k x s\h+$<ret> d ] + ] +> + +define-command -hidden zig-indent-on-new-line %< + evaluate-commands -draft -itersel %< + # preserve indent level + try %< execute-keys -draft <semicolon> K <a-&> > + try %< + # only if we didn't copy a comment or multiline string + execute-keys -draft x <a-K> ^\h*(//|\\\\) <ret> + # indent after lines ending in { + try %< execute-keys -draft k x <a-k> \{\h*$ <ret> j <a-gt> > + # deindent closing } when after cursor + try %< execute-keys -draft x <a-k> ^\h*\} <ret> gh / \} <ret> m <a-S> 1<a-&> > + > + # filter previous line + try %< execute-keys -draft k : zig-trim-indent <ret> > + > +> + +define-command -hidden zig-indent-on-closing %< + # align lone } to indent level of opening line + try %< execute-keys -draft -itersel <a-h> <a-k> ^\h*\}$ <ret> h m <a-S> 1<a-&> > +> + +§ |