From 904cec3c4a329cf89fc3219d359239910d61f3f6 Mon Sep 17 00:00:00 2001 From: thing1 Date: Tue, 28 Jan 2025 09:14:32 +0000 Subject: init commit --- autoload/filetype/crystal.kak | 258 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 autoload/filetype/crystal.kak (limited to 'autoload/filetype/crystal.kak') 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 +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 ':"' '(?[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 +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="(? d } + } +} + +define-command -hidden crystal-indent-on-char %{ + evaluate-commands -no-hooks -draft -itersel %{ + # align 'else' to 'if/case' + try %{ execute-keys -draft x ^\h*else$ i ^\h*(?:if|case) 1 } + # align 'elsif' to 'if' + try %{ execute-keys -draft x ^\h*elsif$ i ^\h*(?:if) 1 } + # align 'when' to 'case' + try %{ execute-keys -draft x ^\h*when$ i ^\h*(?:case) 1 } + # align 'rescue' to 'begin/def' + try %{ execute-keys -draft x ^\h*rescue$ i ^\h*(?:begin|def) 1 } + # align 'end' to opening structure + try %{ execute-keys -draft x ^\h*end$ i ^\h*(?:begin|case|class|def|for|if|module|unless|until|while) 1 } + } +} + +define-command -hidden crystal-indent-on-new-line %{ + evaluate-commands -no-hooks -draft -itersel %{ + # Copy previous line indent + try %{ execute-keys -draft K } + # Remove previous line's trailing spaces + try %{ execute-keys -draft k :crystal-trim-indent } + # Indent after start structure/opening statement + try %{ execute-keys -draft k x ^\h*(?:begin|case|class|def|else|elsif|ensure|for|if|module|rescue|unless|until|when|while|.+\bdo$|.+\bdo\h\|.+(?=\|))[^0-9A-Za-z_!?] j } + } +} + +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*' y j x P } + # wisely add end structure + evaluate-commands -save-regs x %[ + try %{ execute-keys -draft k x s ^ \h + \" x y } catch %{ reg x '' } + try %[ + evaluate-commands -draft %[ + # Check if previous line opens a block + execute-keys -draft kx ^x(?:begin|case|class|def|for|if|module|unless|until|while|.+\bdo$|.+\bdo\h\|.+(?=\|))[^0-9A-Za-z_!?] + # 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 ^x(?:end|else|elsif|rescue|when)[^0-9A-Za-z_!?] + ] + execute-keys -draft oxend # 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+\)y%aa|sort' + } +} + +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 =x1s:"([^"]+)"y%i''a''a' + } +} + +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+)")y%aa' + } +} + +§ -- cgit v1.2.3