summaryrefslogtreecommitdiff
path: root/rc/filetype
diff options
context:
space:
mode:
authorAlex Leferry 2 <alexherbo2@gmail.com>2019-03-18 19:56:34 +0100
committerAlex Leferry 2 <alexherbo2@gmail.com>2019-03-21 01:06:16 +0100
commitc0dccdd90dd615cf663d95fd94fbdbdf2a88b165 (patch)
treecb48fb1b7fb74e6e3b98a62f6e2768686bb75c98 /rc/filetype
parentf87e844244d5ee81e9c1ceb04c354726002ae760 (diff)
Add categories in rc/
Closes #2783
Diffstat (limited to 'rc/filetype')
-rw-r--r--rc/filetype/arch-linux.kak4
-rw-r--r--rc/filetype/asciidoc.kak43
-rw-r--r--rc/filetype/c-family.kak437
-rw-r--r--rc/filetype/cabal.kak74
-rw-r--r--rc/filetype/clojure.kak208
-rw-r--r--rc/filetype/cmake.kak27
-rw-r--r--rc/filetype/coffee.kak79
-rw-r--r--rc/filetype/css.kak76
-rw-r--r--rc/filetype/cucumber.kak89
-rw-r--r--rc/filetype/d.kak132
-rw-r--r--rc/filetype/dart.kak106
-rw-r--r--rc/filetype/diff.kak13
-rw-r--r--rc/filetype/dockerfile.kak48
-rw-r--r--rc/filetype/elixir.kak77
-rw-r--r--rc/filetype/elm.kak67
-rw-r--r--rc/filetype/etc.kak79
-rw-r--r--rc/filetype/exherbo.kak121
-rw-r--r--rc/filetype/fish.kak84
-rw-r--r--rc/filetype/gas.kak91
-rw-r--r--rc/filetype/git.kak40
-rw-r--r--rc/filetype/go.kak97
-rw-r--r--rc/filetype/haml.kak62
-rw-r--r--rc/filetype/haskell.kak105
-rw-r--r--rc/filetype/hbs.kak97
-rw-r--r--rc/filetype/html.kak75
-rw-r--r--rc/filetype/i3.kak81
-rw-r--r--rc/filetype/ini.kak15
-rw-r--r--rc/filetype/java.kak65
-rw-r--r--rc/filetype/javascript.kak117
-rw-r--r--rc/filetype/json.kak60
-rw-r--r--rc/filetype/julia.kak30
-rw-r--r--rc/filetype/just.kak48
-rw-r--r--rc/filetype/kakrc.kak110
-rw-r--r--rc/filetype/kickstart.kak30
-rw-r--r--rc/filetype/latex.kak35
-rw-r--r--rc/filetype/lisp.kak74
-rw-r--r--rc/filetype/lua.kak103
-rw-r--r--rc/filetype/mail.kak13
-rw-r--r--rc/filetype/makefile.kak60
-rw-r--r--rc/filetype/markdown.kak85
-rw-r--r--rc/filetype/mercurial.kak18
-rw-r--r--rc/filetype/moon.kak107
-rw-r--r--rc/filetype/nim.kak112
-rw-r--r--rc/filetype/ocaml.kak38
-rw-r--r--rc/filetype/perl.kak114
-rw-r--r--rc/filetype/php.kak90
-rw-r--r--rc/filetype/pony.kak92
-rw-r--r--rc/filetype/protobuf.kak85
-rw-r--r--rc/filetype/pug.kak74
-rw-r--r--rc/filetype/python.kak148
-rw-r--r--rc/filetype/ragel.kak70
-rw-r--r--rc/filetype/restructuredtext.kak74
-rw-r--r--rc/filetype/ruby.kak168
-rw-r--r--rc/filetype/rust.kak88
-rw-r--r--rc/filetype/sass.kak62
-rw-r--r--rc/filetype/scala.kak75
-rw-r--r--rc/filetype/scheme.kak133
-rw-r--r--rc/filetype/scss.kak45
-rw-r--r--rc/filetype/sh.kak43
-rw-r--r--rc/filetype/sql.kak107
-rw-r--r--rc/filetype/swift.kak28
-rw-r--r--rc/filetype/systemd.kak14
-rw-r--r--rc/filetype/taskpaper.kak47
-rw-r--r--rc/filetype/toml.kak63
-rw-r--r--rc/filetype/troff.kak30
-rw-r--r--rc/filetype/tupfile.kak33
-rw-r--r--rc/filetype/void-linux.kak4
-rw-r--r--rc/filetype/yaml.kak58
68 files changed, 5277 insertions, 0 deletions
diff --git a/rc/filetype/arch-linux.kak b/rc/filetype/arch-linux.kak
new file mode 100644
index 00000000..08135a76
--- /dev/null
+++ b/rc/filetype/arch-linux.kak
@@ -0,0 +1,4 @@
+# package build description file
+hook global BufCreate (.*/)?PKGBUILD %{
+ set-option buffer filetype sh
+}
diff --git a/rc/filetype/asciidoc.kak b/rc/filetype/asciidoc.kak
new file mode 100644
index 00000000..8bdcce07
--- /dev/null
+++ b/rc/filetype/asciidoc.kak
@@ -0,0 +1,43 @@
+# http://asciidoc.org/
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .+\.(a(scii)?doc|asc) %{
+ set-option buffer filetype asciidoc
+}
+
+# Highlighters
+# ‾‾‾‾‾‾‾‾‾‾‾‾
+
+add-highlighter shared/asciidoc group
+
+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
+
+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
+
+add-highlighter shared/asciidoc/ regex ^\h+([-\*])\h+[^\n]*(\n\h+[^-\*]\S+[^\n]*)*$ 0:list 1:bullet
+add-highlighter shared/asciidoc/ regex ^(-{3,})\n[^\n\h].*?\n(-{3,})$ 0:block
+add-highlighter shared/asciidoc/ regex ^(={3,})\n[^\n\h].*?\n(={3,})$ 0:block
+add-highlighter shared/asciidoc/ regex ^(~{3,})\n[^\n\h].*?\n(~{3,})$ 0:block
+add-highlighter shared/asciidoc/ regex ^(\*{3,})\n[^\n\h].*?\n(\*{3,})$ 0:block
+add-highlighter shared/asciidoc/ regex \B(?:\+[^\n]+?\+|`[^\n]+?`)\B 0:mono
+add-highlighter shared/asciidoc/ regex \b_[^\n]+?_\b 0:italic
+add-highlighter shared/asciidoc/ regex \B\*[^\n]+?\*\B 0:bold
+add-highlighter shared/asciidoc/ regex ^:[-\w]+: 0:meta
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group asciidoc-highlight global WinSetOption filetype=asciidoc %{
+ add-highlighter window/asciidoc ref asciidoc
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/asciidoc }
+}
diff --git a/rc/filetype/c-family.kak b/rc/filetype/c-family.kak
new file mode 100644
index 00000000..461545fb
--- /dev/null
+++ b/rc/filetype/c-family.kak
@@ -0,0 +1,437 @@
+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
+}
+
+define-command -hidden c-family-trim-indent %{
+ # remove the line if it's empty when leaving the insert mode
+ try %{ execute-keys -draft <a-x> 1s^(\h+)$<ret> d }
+}
+
+define-command -hidden c-family-indent-on-newline %< evaluate-commands -draft -itersel %<
+ execute-keys \;
+ 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 k<a-x> 1s(\))(\h+\w+)*\h*(\;\h*)?(?://[^\n]+)?\n\z<ret> m<a-\;>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 <a-x> <a-k>^\h+$<ret> Hd >
+ # indent after an opening brace or parenthesis at end of line
+ try %< execute-keys -draft k <a-x> s[{(]\h*$<ret> j <a-gt> >
+ # indent after a label
+ try %< execute-keys -draft k <a-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 <a-x> s\)\h*(?://[^\n]+)?\n\z<ret> \
+ <a-\;>mB <a-k>\A\b(if|for|while)\b<ret> <a-\;>j <a-gt> >
+ try %< execute-keys -draft k <a-x> s \belse\b\h*(?://[^\n]+)?\n\z<ret> \
+ j <a-gt> >
+ # deindent after a single line statement end
+ try %< execute-keys -draft K <a-x> <a-k>\;\h*(//[^\n]+)?$<ret> \
+ K <a-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 <a-x> <a-k>\;\h*(//[^\n]+)?$<ret> \
+ K <a-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-:><a-\;>L <a-S>
+ # Remove eventual indent from new line
+ try %< execute-keys -draft <space> <a-h> s\h+<ret> d >
+ # Now align that new line with the opening parenthesis/brace
+ execute-keys &
+ > >
+> >
+
+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-&> ]
+]
+
+define-command -hidden c-family-indent-on-closing-curly-brace %[
+ # align to opening curly brace when alone on a line
+ try %[ execute-keys -itersel -draft <a-h><a-:><a-k>^\h+\}$<ret>hm<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
+ try %[ execute-keys -itersel -draft hm<a-x>B<a-x><a-k>\A\h*(class|struct|union|enum)<ret> '<a-;>;i;<esc>' ]
+]
+
+define-command -hidden c-family-insert-on-newline %[ evaluate-commands -itersel -draft %[
+ execute-keys \;
+ try %[
+ evaluate-commands -draft -save-regs '/"' %[
+ # copy the commenting prefix
+ execute-keys -save-regs '' k <a-x>1s^\h*(//+\h*)<ret> y
+ try %[
+ # if the previous comment isn't empty, create a new one
+ execute-keys <a-x><a-K>^\h*//+\h*$<ret> j<a-x>s^\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 k<a-x> <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 k<a-x><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 j<a-x><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 k<a-x><a-k>^\h+\*\h+$<ret> <a-x>1s\*(\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 K<a-x>1s^[^*]*(\*)<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/raw_string region -match-capture %{R"([^(]*)\\(} %{\\)([^")]*)"} fill string
+ 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/macro region %{^\\h*?\\K#} %{(?<!\\\\)(?=\\n)|(?=//)} group
+
+ add-highlighter shared/$ft/macro/ fill meta
+ add-highlighter shared/$ft/macro/ regex ^\\h*#include\\h+(\\S*) 1:module
+ add-highlighter shared/$ft/macro/ regex /\\*.*?\\*/ 0:comment
+ EOF
+ done
+}
+
+# c specific
+add-highlighter shared/c/code/numbers regex %{\b-?(0x[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' "hook global WinSetOption filetype=c %{
+ set-option window 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
+
+# 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 "hook global WinSetOption filetype=cpp %{
+ set-option window 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 "hook global WinSetOption filetype=objc %{
+ set-option window 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
+ "
+}
+
+hook global WinSetOption filetype=(c|cpp|objc) %[
+ hook -group "%val{hook_param_capture_1}-trim-indent" window ModeChange 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 }
+}
+
+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 ggi<c-r>%<ret><esc>ggxs\.<ret>c_<esc><space>A_INCLUDED<esc>ggxyppI#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_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
+ altname="${dir}/${alt_dir}/${file_noext}.${ext}"
+ 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
+ altname="${dir}/${alt_dir}/${file_noext}.${ext}"
+ if [ -f ${altname} ]; then
+ printf 'edit %%{%s}\n' "${altname}"
+ exit
+ fi
+ done
+ done
+ ;;
+ *)
+ echo "echo -markup '{Error}extension not recognized'"
+ exit
+ ;;
+ esac
+ echo "echo -markup '{Error}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
+}
diff --git a/rc/filetype/cabal.kak b/rc/filetype/cabal.kak
new file mode 100644
index 00000000..b3e7e58c
--- /dev/null
+++ b/rc/filetype/cabal.kak
@@ -0,0 +1,74 @@
+# http://haskell.org/cabal
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](cabal) %{
+ set-option buffer filetype 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 <a-x> s \h+$ <ret> d }
+}
+
+define-command -hidden cabal-indent-on-new-line %[
+ evaluate-commands -draft -itersel %[
+ # copy '#' comment prefix and following white spaces
+ try %[ execute-keys -draft k <a-x> s ^\h*\K#\h* <ret> y gh j P ]
+ # preserve previous line indent
+ try %[ execute-keys -draft \; K <a-&> ]
+ # filter previous line
+ try %[ execute-keys -draft k : cabal-trim-indent <ret> ]
+ # indent after lines ending with { or :
+ try %[ execute-keys -draft <space> k <a-x> <a-k> [:{]$ <ret> j <a-gt> ]
+ ]
+]
+
+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-&> ]
+ ]
+]
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group cabal-highlight global WinSetOption filetype=cabal %{
+ add-highlighter window/cabal ref cabal
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/cabal }
+
+}
+
+hook global WinSetOption filetype=cabal %[
+ hook window ModeChange insert:.* -group cabal-trim-indent cabal-trim-indent
+ 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-.+ }
+]
diff --git a/rc/filetype/clojure.kak b/rc/filetype/clojure.kak
new file mode 100644
index 00000000..da6134a6
--- /dev/null
+++ b/rc/filetype/clojure.kak
@@ -0,0 +1,208 @@
+# http://clojure.org
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# require lisp.kak
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](clj|cljc|cljs|cljx|edn) %{
+ set-option buffer filetype clojure
+}
+
+# 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
+
+hook global WinSetOption filetype=clojure %{
+ set-option window extra_word_chars '_' . / * ? + - < > ! : "'"
+}
+
+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(" hook global WinSetOption filetype=clojure %%{\n"\
+ " set-option window static_words ");
+ print_static_words(keywords);
+ print_static_words(core_fns);
+ print_static_words(core_vars);
+ printf("\n }\n");
+ }
+EOF
+}
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+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>\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 '"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&<space>'
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+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 global WinSetOption filetype=clojure %[
+ hook window ModeChange insert:.* -group clojure-trim-indent clojure-trim-indent
+ hook window InsertChar \n -group clojure-indent clojure-indent-on-new-line
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window clojure-.+ }
+]
diff --git a/rc/filetype/cmake.kak b/rc/filetype/cmake.kak
new file mode 100644
index 00000000..77ec18c5
--- /dev/null
+++ b/rc/filetype/cmake.kak
@@ -0,0 +1,27 @@
+hook global BufCreate .+\.cmake|.*/CMakeLists.txt %{
+ set-option buffer filetype cmake
+}
+
+hook global BufCreate .*/CMakeCache.txt %{
+ set-option buffer filetype ini
+}
+
+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/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
+
+hook -group cmake-highlight global WinSetOption filetype=cmake %{
+ add-highlighter window/cmake ref cmake
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/cmake }
+}
diff --git a/rc/filetype/coffee.kak b/rc/filetype/coffee.kak
new file mode 100644
index 00000000..c8e7384e
--- /dev/null
+++ b/rc/filetype/coffee.kak
@@ -0,0 +1,79 @@
+# http://coffeescript.org
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](coffee) %{
+ set-option buffer filetype 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 <a-x>
+ # remove trailing white spaces
+ try %{ execute-keys -draft s \h + $ <ret> d }
+ }
+}
+
+define-command -hidden coffee-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # copy '#' comment prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s '^\h*\K#\h*' <ret> y gh j P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; K <a-&> }
+ # filter previous line
+ try %{ execute-keys -draft k : coffee-trim-indent <ret> }
+ # indent after start structure
+ try %{ execute-keys -draft k <a-x> <a-k> ^ \h * (case|catch|class|else|finally|for|function|if|switch|try|while|with) \b | (=|->) $ <ret> j <a-gt> }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group coffee-highlight global WinSetOption filetype=coffee %{
+ add-highlighter window/coffee ref coffee
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/coffee }
+}
+
+hook global WinSetOption filetype=coffee %{
+ hook window ModeChange insert:.* -group coffee-trim-indent coffee-trim-indent
+ hook window InsertChar \n -group coffee-indent coffee-indent-on-new-line
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window coffee-.+ }
+}
diff --git a/rc/filetype/css.kak b/rc/filetype/css.kak
new file mode 100644
index 00000000..ecc456ed
--- /dev/null
+++ b/rc/filetype/css.kak
@@ -0,0 +1,76 @@
+# http://w3.org/Style/CSS
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](css) %{
+ set-option buffer filetype css
+}
+
+# Highlighters
+# ‾‾‾‾‾‾‾‾‾‾‾‾
+
+add-highlighter shared/css regions
+add-highlighter shared/css/selector default-region group
+add-highlighter shared/css/declaration region [{] [}] regions
+add-highlighter shared/css/comment region /[*] [*]/ fill comment
+
+add-highlighter shared/css/declaration/base default-region group
+add-highlighter shared/css/declaration/double_string region '"' (?<!\\)(\\\\)*" fill string
+add-highlighter shared/css/declaration/single_string region "'" "'" fill string
+
+# https://developer.mozilla.org/en-US/docs/Web/CSS/length
+add-highlighter shared/css/declaration/base/ regex (#[0-9A-Fa-f]+)|((\d*\.)?\d+(ch|cm|em|ex|mm|pc|pt|px|rem|vh|vmax|vmin|vw)) 0:value
+
+add-highlighter shared/css/declaration/base/ regex ([A-Za-z][A-Za-z0-9_-]*)\h*: 1:keyword
+add-highlighter shared/css/declaration/base/ regex :(before|after) 0:attribute
+add-highlighter shared/css/declaration/base/ regex !important 0:keyword
+
+# element#id element.class
+# universal selector
+add-highlighter shared/css/selector/ regex [A-Za-z][A-Za-z0-9_-]* 0:keyword
+add-highlighter shared/css/selector/ regex [*]|[#.][A-Za-z][A-Za-z0-9_-]* 0:variable
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+define-command -hidden css-trim-indent %{
+ # remove trailing white spaces
+ try %{ execute-keys -draft -itersel <a-x> s \h+$ <ret> d }
+}
+
+define-command -hidden css-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 : css-trim-indent <ret> ]
+ # indent after lines ending with with {
+ try %[ execute-keys -draft k <a-x> <a-k> \{$ <ret> j <a-gt> ]
+ ]
+]
+
+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-&> ]
+ ]
+]
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group css-highlight global WinSetOption filetype=css %{
+ add-highlighter window/css ref css
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/css }
+}
+
+hook global WinSetOption filetype=css %[
+ hook window ModeChange insert:.* -group css-trim-indent css-trim-indent
+ 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 '_' '-'
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window css-.+ }
+]
diff --git a/rc/filetype/cucumber.kak b/rc/filetype/cucumber.kak
new file mode 100644
index 00000000..180da7d0
--- /dev/null
+++ b/rc/filetype/cucumber.kak
@@ -0,0 +1,89 @@
+# http://cukes.info
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](feature|story) %{
+ set-option buffer filetype 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 <a-x> s \h+$ <ret> d }
+}
+
+define-command -hidden cucumber-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # copy '#' comment prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*\K#\h* <ret> y gh j P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; K <a-&> }
+ # filter previous line
+ try %{ execute-keys -draft k : cucumber-trim-indent <ret> }
+ # indent after lines containing :
+ try %{ execute-keys -draft <space> k x <a-k> : <ret> j <a-gt> }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group cucumber-highlight global WinSetOption filetype=cucumber %{
+ add-highlighter window/cucumber ref cucumber
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/cucumber }
+}
+
+hook global WinSetOption filetype=cucumber %{
+ hook window ModeChange insert:.* -group cucumber-trim-indent cucumber-trim-indent
+ hook window InsertChar \n -group cucumber-indent cucumber-indent-on-new-line
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window cucumber-.+ }
+}
diff --git a/rc/filetype/d.kak b/rc/filetype/d.kak
new file mode 100644
index 00000000..f0f08248
--- /dev/null
+++ b/rc/filetype/d.kak
@@ -0,0 +1,132 @@
+# http://dlang.org/
+#
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*\.di? %{
+ set-option buffer filetype 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_string1 region ` ` fill meta
+add-highlighter shared/d/verbatim_string2 region %{(?<!')(?<!'\\)`} %{(?<!\\)(?:\\\\)*`} fill meta
+add-highlighter shared/d/verbatim_string_prefixed region %{r`([^(]*)\(} %{\)([^)]*)`} fill meta
+add-highlighter shared/d/disabled region '/\+[^+]?' '\+/' fill comment
+add-highlighter shared/d/comment1 region '/\*[^*]?' '\*/' fill comment
+add-highlighter shared/d/comment2 region '//[^/]?' $ fill comment
+add-highlighter shared/d/docstring1 region '/\+\+' '\+/' fill comment
+add-highlighter shared/d/docstring2 region '/\*\*' '\*/' fill comment
+add-highlighter shared/d/docstring3 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 '#\s*line\b.*' 0:meta
+
+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 "hook global WinSetOption filetype=d %{
+ set-option window 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-indent-on-new-line %~
+ evaluate-commands -draft -itersel %=
+ # preserve previous line indent
+ try %{ execute-keys -draft \;K<a-&> }
+ # indent after lines ending with { or (
+ 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 }
+ # 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-;>' & }
+ # copy // comments prefix
+ try %{ execute-keys -draft \;<c-s>k<a-x> s ^\h*\K/{2,} <ret> y<c-o>P<esc> }
+ # indent after a switch's case/default statements
+ try %[ execute-keys -draft k<a-x> <a-k> ^\h*(case|default).*:$ <ret> j<a-gt> ]
+ # indent after if|else|while|for
+ try %[ execute-keys -draft \;<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-space><a-gt> ]
+ =
+~
+
+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-&> ]
+]
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group d-highlight global WinSetOption filetype=d %{
+ add-highlighter window/d ref d
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/d }
+}
+
+hook global WinSetOption filetype=d %{
+ # cleanup trailing whitespaces when exiting insert mode
+ hook window ModeChange insert:.* -group d-trim-indent %{ try %{ execute-keys -draft <a-x>s^\h+$<ret>d } }
+ 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-.+ }
+}
diff --git a/rc/filetype/dart.kak b/rc/filetype/dart.kak
new file mode 100644
index 00000000..5b5600cb
--- /dev/null
+++ b/rc/filetype/dart.kak
@@ -0,0 +1,106 @@
+# https://dartlang.org/
+#
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*\.dart %{
+ set-option buffer filetype dart
+}
+
+# Highlighters
+# ‾‾‾‾‾‾‾‾‾‾‾‾
+
+add-highlighter shared/dart regions
+add-highlighter shared/dart/code default-region group
+add-highlighter shared/dart/back_string region '`' '`' fill string
+add-highlighter shared/dart/double_string region '"' (?<!\\)(\\\\)*" fill string
+add-highlighter shared/dart/single_string region "'" (?<!\\)(\\\\)*' fill string
+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
+
+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"
+ 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 "hook global WinSetOption filetype=dart %{
+ set-option window 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 \b(${annotations})\b 0:meta
+ add-highlighter shared/dart/code/ regex \b(${classes})\b 0:module
+ "
+}
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+define-command -hidden dart-indent-on-new-line %~
+ evaluate-commands -draft -itersel %=
+ # preserve previous line indent
+ try %{ execute-keys -draft \;K<a-&> }
+ # indent after lines ending with { or (
+ 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 }
+ # 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-;>' & }
+ # copy // comments prefix
+ try %{ execute-keys -draft \;<c-s>k<a-x> s ^\h*\K/{2,} <ret> y<c-o>P<esc> }
+ # indent after a switch's case/default statements
+ try %[ execute-keys -draft k<a-x> <a-k> ^\h*(case|default).*:$ <ret> j<a-gt> ]
+ # indent after if|else|while|for
+ try %[ execute-keys -draft \;<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-space><a-gt> ]
+ =
+~
+
+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-&> ]
+]
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group dart-highlight global WinSetOption filetype=dart %{
+ add-highlighter window/dart ref dart
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/dart }
+}
+
+hook global WinSetOption filetype=dart %{
+ # cleanup trailing whitespaces when exiting insert mode
+ hook window ModeChange insert:.* -group dart-trim-indent %{ try %{ execute-keys -draft <a-x>s^\h+$<ret>d } }
+ 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-.+ }
+}
diff --git a/rc/filetype/diff.kak b/rc/filetype/diff.kak
new file mode 100644
index 00000000..5b4e065b
--- /dev/null
+++ b/rc/filetype/diff.kak
@@ -0,0 +1,13 @@
+hook global BufCreate .*\.(diff|patch) %{
+ set-option buffer filetype 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
+
+hook -group diff-highlight global WinSetOption filetype=diff %{
+ add-highlighter window/diff ref diff
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/diff }
+}
diff --git a/rc/filetype/dockerfile.kak b/rc/filetype/dockerfile.kak
new file mode 100644
index 00000000..07da2347
--- /dev/null
+++ b/rc/filetype/dockerfile.kak
@@ -0,0 +1,48 @@
+# http://docker.com
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# See https://docs.docker.com/reference/builder
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*/?Dockerfile(\.\w+)?$ %{
+ set-option buffer filetype 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 "hook global WinSetOption filetype=dockerfile %{
+ set window 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 '\$\{[\w_]+\}' 0:value
+add-highlighter shared/dockerfile/code/ regex '\$[\w_]+' 0:value
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group dockerfile-highlight global WinSetOption filetype=dockerfile %{
+ add-highlighter window/dockerfile ref dockerfile
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/dockerfile }
+}
diff --git a/rc/filetype/elixir.kak b/rc/filetype/elixir.kak
new file mode 100644
index 00000000..a2587d1e
--- /dev/null
+++ b/rc/filetype/elixir.kak
@@ -0,0 +1,77 @@
+# http://elixir-lang.org
+# ----------------------
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](ex|exs) %{
+ set-option buffer filetype elixir
+}
+
+
+# Highlighters
+# ‾‾‾‾‾‾‾‾‾‾‾‾
+
+add-highlighter shared/elixir regions
+add-highlighter shared/elixir/code default-region group
+add-highlighter shared/elixir/double_string region '"' (?<!\\)(\\\\)*" regions
+add-highlighter shared/elixir/triple_string region '"""' (?<!\\)(\\\\)*""" ref shared/elixir/double_string
+add-highlighter shared/elixir/single_string region "'" (?<!\\)(\\\\)*' fill string
+add-highlighter shared/elixir/comment region '#' '$' fill comment
+
+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 <a-x> s \h+$ <ret> d }
+}
+
+define-command -hidden elixir-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # copy -- comments prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*\K--\h* <ret> y gh j P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; K <a-&> }
+ # indent after line ending with:
+ # try %{ execute-keys -draft k x <a-k> (do|else|->)$ <ret> & }
+ # filter previous line
+ try %{ execute-keys -draft k : elixir-trim-indent <ret> }
+ # indent after lines ending with do or ->
+ try %{ execute-keys -draft \\; k x <a-k> ^.+(do|->)$ <ret> j <a-gt> }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+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=elixir %{
+ hook window ModeChange insert:.* -group elixir-trim-indent elixir-trim-indent
+ hook window InsertChar \n -group elixir-indent elixir-indent-on-new-line
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window elixir-.+ }
+}
diff --git a/rc/filetype/elm.kak b/rc/filetype/elm.kak
new file mode 100644
index 00000000..05d1248b
--- /dev/null
+++ b/rc/filetype/elm.kak
@@ -0,0 +1,67 @@
+# http://elm-lang.org
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](elm) %{
+ set-option buffer filetype elm
+}
+
+# Highlighters
+# ‾‾‾‾‾‾‾‾‾‾‾‾
+
+add-highlighter shared/elm regions
+add-highlighter shared/elm/code default-region group
+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(import|exposing|as|module|where)\b 0:meta
+add-highlighter shared/elm/code/ regex \b(True|False)\b 0:value
+add-highlighter shared/elm/code/ regex \b(if|then|else|case|of|let|in|type|port|alias)\b 0:keyword
+add-highlighter shared/elm/code/ regex \b(Array|Bool|Char|Float|Int|String)\b 0:type
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+# http://elm-lang.org/docs/style-guide
+
+define-command -hidden elm-trim-indent %{
+ # remove trailing white spaces
+ try %{ execute-keys -draft -itersel <a-x> s \h+$ <ret> d }
+}
+
+define-command -hidden elm-indent-after "
+ execute-keys -draft \\; k x <a-k> ^\\h*(if)|(case\\h+[\\w']+\\h+of|let|in|\\{\\h+\\w+|\\w+\\h+->|[=(])$ <ret> j <a-gt>
+"
+
+define-command -hidden elm-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # copy -- comments prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*\K--\h* <ret> y gh j P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; K <a-&> }
+ # align to first clause
+ try %{ execute-keys -draft \; 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 }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group elm-highlight global WinSetOption filetype=elm %{
+ add-highlighter window/elm ref elm
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/elm }
+}
+
+hook global WinSetOption filetype=elm %{
+ hook window ModeChange insert:.* -group elm-trim-indent elm-trim-indent
+ hook window InsertChar \n -group elm-indent elm-indent-on-new-line
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window elm-.+ }
+}
diff --git a/rc/filetype/etc.kak b/rc/filetype/etc.kak
new file mode 100644
index 00000000..1e2067fe
--- /dev/null
+++ b/rc/filetype/etc.kak
@@ -0,0 +1,79 @@
+# 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 }
+
+# Highlighters
+## /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
+
+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 }
+}
+
+## /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
+
+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 }
+}
+
+## /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
+
+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 }
+}
+
+## /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
+
+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 }
+}
+
+## /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
+
+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 }
+}
+
+## /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
+
+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 }
+}
+
+## /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
+
+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 }
+}
diff --git a/rc/filetype/exherbo.kak b/rc/filetype/exherbo.kak
new file mode 100644
index 00000000..42cc618c
--- /dev/null
+++ b/rc/filetype/exherbo.kak
@@ -0,0 +1,121 @@
+## 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 }
+
+# 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
+
+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 }
+}
+
+## 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
+
+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 }
+}
+
+## 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 -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 }
+}
+
+## 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
+
+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 }
+}
+
+## 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
+
+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 }
+}
+
+## 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
+
+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 }
+}
+
+## 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 -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 }
+}
+
+## 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
+
+hook -group glep42-highlight global WinSetOption filetype=glep42 %{
+ add-highlighter window/glep42 ref glep42
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/glep42 }
+}
diff --git a/rc/filetype/fish.kak b/rc/filetype/fish.kak
new file mode 100644
index 00000000..8e23ede4
--- /dev/null
+++ b/rc/filetype/fish.kak
@@ -0,0 +1,84 @@
+# http://fishshell.com
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](fish) %{
+ set-option buffer filetype fish
+}
+
+# Highlighters
+# ‾‾‾‾‾‾‾‾‾‾‾‾
+
+add-highlighter shared/fish regions
+add-highlighter shared/fish/code default-region group
+add-highlighter shared/fish/double_string region '"' (?<!\\)(\\\\)*" group
+add-highlighter shared/fish/single_string region "'" "'" fill string
+add-highlighter shared/fish/comment region '#' '$' fill comment
+
+add-highlighter shared/fish/double_string/ fill string
+add-highlighter shared/fish/double_string/ regex (\$\w+)|(\{\$\w+\}) 0:variable
+
+add-highlighter shared/fish/code/ regex (\$\w+)|(\{\$\w+\}) 0:variable
+
+# Command names are collected using `builtin --names` and 'eval' from `functions --names`
+add-highlighter shared/fish/code/ regex \b(and|begin|bg|bind|block|break|breakpoint|builtin|case|cd|command|commandline|complete|contains|continue|count|echo|else|emit|end|eval|exec|exit|fg|for|function|functions|history|if|jobs|not|or|printf|pwd|random|read|return|set|set_color|source|status|switch|test|ulimit|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 <a-x>s\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 <a-x><a-k>^\h*(else)$<ret><a-\;><a-?>^\h*(if)<ret>s\A|\z<ret>)<a-&> }
+ try %{ execute-keys -draft <a-x><a-k>^\h*(end)$<ret><a-\;><a-?>^\h*(begin|for|function|if|switch|while)<ret>s\A|\z<ret>)<a-&> }
+ try %{ execute-keys -draft <a-x><a-k>^\h*(case)$<ret><a-\;><a-?>^\h*(switch)<ret>s\A|\z<ret>)<a-&>)<space><a-gt> }
+ }
+}
+
+define-command -hidden fish-indent-on-new-line %{
+ evaluate-commands -no-hooks -draft -itersel %{
+ # preserve previous line indent
+ try %{ execute-keys -draft <space>K<a-&> }
+ # filter previous line
+ try %{ execute-keys -draft k:fish-trim-indent<ret> }
+ # indent after start structure
+ try %{ execute-keys -draft k<a-x><a-k>^\h*(begin|case|else|for|function|if|switch|while)\b<ret>j<a-gt> }
+ }
+}
+
+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<a-x>s^\h*\K#\h*<ret>yjp }
+ # wisely add end structure
+ evaluate-commands -save-regs x %{
+ try %{ execute-keys -draft k<a-x>s^\h+<ret>"xy } catch %{ reg x '' }
+ try %{ execute-keys -draft k<a-x><a-k>^<c-r>x(begin|for|function|if|switch|while)<ret>j<a-a>iX<a-\;>K<a-K>^<c-r>x(begin|for|function|if|switch|while).*\n<c-r>xend$<ret>jxypjaend<esc><a-lt> }
+ }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group fish-highlight global WinSetOption filetype=fish %{
+ add-highlighter window/fish ref fish
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/fish }
+}
+
+hook global WinSetOption filetype=fish %{
+ 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-.+ }
+}
diff --git a/rc/filetype/gas.kak b/rc/filetype/gas.kak
new file mode 100644
index 00000000..0c1f79f8
--- /dev/null
+++ b/rc/filetype/gas.kak
@@ -0,0 +1,91 @@
+# Detection
+# ---------
+hook global BufCreate .*\.(s|S|asm)$ %{
+ set-option buffer filetype 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 <a-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 \; K <a-&> }
+ # filter previous line
+ try %{ execute-keys -draft k : gas-trim-indent <ret> }
+ # indent after label
+ try %[ execute-keys -draft k <a-x> <a-k> :$ <ret> j <a-gt> ]
+ >
+~
+
+hook -group gas-highlight global WinSetOption filetype=gas %{
+ add-highlighter window/gas ref gas
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/gas }
+}
+
+hook global WinSetOption filetype=gas %{
+ hook window InsertChar \n -group gas-indent gas-indent-on-new-line
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window gas-.+ }
+}
diff --git a/rc/filetype/git.kak b/rc/filetype/git.kak
new file mode 100644
index 00000000..13d58f0a
--- /dev/null
+++ b/rc/filetype/git.kak
@@ -0,0 +1,40 @@
+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 .*(\.gitconfig|git/config) %{
+ set-option buffer filetype ini
+}
+
+hook -group git-commit-highlight global WinSetOption filetype=git-commit %{
+ add-highlighter window/git-commit-highlight regions
+ add-highlighter window/git-commit-highlight/diff region '^diff --git' '^(?=diff --git)' ref diff # highlight potential diffs from the -v option
+ add-highlighter window/git-commit-highlight/comments region '^\h*#' '$' group
+ add-highlighter window/git-commit-highlight/comments/ fill comment
+ add-highlighter window/git-commit-highlight/comments/ regex "\b(?:(modified)|(deleted)|(new file)|(renamed|copied)):([^\n]*)$" 1:yellow 2:red 3:green 4:blue 5:magenta
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/git-commit-highlight }
+}
+
+hook -group git-commit-highlight global WinSetOption filetype=git-notes %{
+ add-highlighter window/git-notes-highlight regex '^\h*#[^\n]*$' 0:comment
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/git-notes-highlight }
+}
+
+
+hook global BufCreate .*git-rebase-todo %{
+ set-option buffer filetype git-rebase
+}
+
+hook -group git-rebase-highlight global WinSetOption filetype=git-rebase %{
+ add-highlighter window/git-rebase-highlight group
+ add-highlighter window/git-rebase-highlight/ regex "#[^\n]*\n" 0:comment
+ add-highlighter window/git-rebase-highlight/ regex "^(pick|edit|reword|squash|fixup|exec|break|drop|label|reset|merge|[persfxbdltm]) (\w+)" 1:keyword 2:meta
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/git-rebase-highlight }
+}
diff --git a/rc/filetype/go.kak b/rc/filetype/go.kak
new file mode 100644
index 00000000..8aebe657
--- /dev/null
+++ b/rc/filetype/go.kak
@@ -0,0 +1,97 @@
+# https://golang.org/
+#
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*\.go %{
+ set-option buffer filetype 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/ regex %{-?([0-9]*\.(?!0[xX]))?\b([0-9]+|0[xX][0-9a-fA-F]+)\.?([eE][+-]?[0-9]+)?i?\b} 0:value
+
+evaluate-commands %sh{
+ # Grammar
+ keywords="break|default|func|interface|select|case|defer|go|map|struct"
+ keywords="${keywords}|chan|else|goto|package|switch|const|fallthrough|if|range|type"
+ keywords="${keywords}|continue|for|import|return|var"
+ types="bool|byte|chan|complex128|complex64|error|float32|float64|int|int16|int32"
+ types="${types}|int64|int8|interface|intptr|map|rune|string|struct|uint|uint16|uint32|uint64|uint8"
+ values="false|true|nil|iota"
+ functions="append|cap|close|complex|copy|delete|imag|len|make|new|panic|print|println|real|recover"
+
+ # Add the language's grammar to the static completion list
+ printf %s\\n "hook global WinSetOption filetype=go %{
+ set-option window static_words ${keywords} ${attributes} ${types} ${values} ${functions}
+ }" | tr '|' ' '
+
+ # Highlight keywords
+ printf %s "
+ add-highlighter shared/go/code/ regex \b(${keywords})\b 0:keyword
+ add-highlighter shared/go/code/ regex \b(${attributes})\b 0:attribute
+ add-highlighter shared/go/code/ regex \b(${types})\b 0:type
+ add-highlighter shared/go/code/ regex \b(${values})\b 0:value
+ add-highlighter shared/go/code/ regex \b(${functions})\b 0:builtin
+ "
+}
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+define-command -hidden go-indent-on-new-line %~
+ evaluate-commands -draft -itersel %=
+ # preserve previous line indent
+ try %{ execute-keys -draft \;K<a-&> }
+ # indent after lines ending with { or (
+ 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 }
+ # 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-;>' & }
+ # copy // comments prefix
+ try %{ execute-keys -draft \;<c-s>k<a-x> s ^\h*\K/{2,} <ret> y<c-o>P<esc> }
+ # indent after a switch's case/default statements
+ try %[ execute-keys -draft k<a-x> <a-k> ^\h*(case|default).*:$ <ret> j<a-gt> ]
+ # indent after if|else|while|for
+ try %[ execute-keys -draft \;<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-space><a-gt> ]
+ =
+~
+
+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-&> ]
+]
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group go-highlight global WinSetOption filetype=go %{
+ add-highlighter window/go ref go
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/go }
+}
+
+hook global WinSetOption filetype=go %{
+ # cleanup trailing whitespaces when exiting insert mode
+ hook window ModeChange insert:.* -group go-trim-indent %{ try %{ execute-keys -draft <a-x>s^\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 -once -always window WinSetOption filetype=.* %{ remove-hooks window go-.+ }
+}
diff --git a/rc/filetype/haml.kak b/rc/filetype/haml.kak
new file mode 100644
index 00000000..e3e7f593
--- /dev/null
+++ b/rc/filetype/haml.kak
@@ -0,0 +1,62 @@
+# http://haml.info
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](haml) %{
+ set-option buffer filetype haml
+}
+
+# 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 <a-x> s \h+$ <ret> d }
+}
+
+define-command -hidden haml-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # copy '/' comment prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*\K/\h* <ret> y gh j P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; 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 <a-x> <a-k> ^\h*[:-] <ret> j <a-gt> }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group haml-highlight global WinSetOption filetype=haml %{
+ add-highlighter window/haml ref haml
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/haml }
+}
+
+hook global WinSetOption filetype=haml %{
+ hook window ModeChange insert:.* -group haml-trim-indent haml-trim-indent
+ hook window InsertChar \n -group haml-indent haml-indent-on-new-line
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window haml-.+ }
+}
diff --git a/rc/filetype/haskell.kak b/rc/filetype/haskell.kak
new file mode 100644
index 00000000..c51bcaf4
--- /dev/null
+++ b/rc/filetype/haskell.kak
@@ -0,0 +1,105 @@
+# http://haskell.org
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](hs) %{
+ set-option buffer filetype 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 ^\h*?\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/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
+
+# 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
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+# http://en.wikibooks.org/wiki/Haskell/Indentation
+
+define-command -hidden haskell-trim-indent %{
+ # remove trailing white spaces
+ try %{ execute-keys -draft -itersel <a-x> s \h+$ <ret> d }
+}
+
+define-command -hidden haskell-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # copy -- comments prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*\K--\h* <ret> y gh j P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; K <a-&> }
+ # align to first clause
+ try %{ execute-keys -draft \; 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 \; k x <a-k> ^\h*(if)|(case\h+[\w']+\h+of|do|let|where|[=(])$ <ret> j <a-gt> }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group haskell-highlight global WinSetOption filetype=haskell %{
+ add-highlighter window/haskell ref haskell
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/haskell }
+}
+
+hook global WinSetOption filetype=haskell %{
+ set-option window extra_word_chars '_' "'"
+ hook window ModeChange insert:.* -group haskell-trim-indent haskell-trim-indent
+ hook window InsertChar \n -group haskell-indent haskell-indent-on-new-line
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window haskell-.+ }
+}
diff --git a/rc/filetype/hbs.kak b/rc/filetype/hbs.kak
new file mode 100644
index 00000000..a0948e6f
--- /dev/null
+++ b/rc/filetype/hbs.kak
@@ -0,0 +1,97 @@
+# http://handlebarsjs.com/
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](hbs) %{
+ set-option buffer filetype hbs
+}
+
+# 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 <a-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 <space> <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-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # copy '/' comment prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*\K/\h* <ret> y j p }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; 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 <a-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
+} }
+
+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 }
+}
+
+hook global WinSetOption filetype=hbs %{
+ hook window ModeChange insert:.* -group hbs-trim-indent hbs-trim-indent
+ 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-.+ }
+}
diff --git a/rc/filetype/html.kak b/rc/filetype/html.kak
new file mode 100644
index 00000000..5f76721d
--- /dev/null
+++ b/rc/filetype/html.kak
@@ -0,0 +1,75 @@
+# http://w3.org/html
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*\.html %{
+ set-option buffer filetype html
+}
+
+hook global BufCreate .*\.xml %{
+ set-option buffer filetype xml
+}
+
+# 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 <a-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 <space> <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 \; K <a-&> }
+ # filter previous line
+ try %{ execute-keys -draft k : html-trim-indent <ret> }
+ # indent after lines ending with opening tag
+ try %{ execute-keys -draft k <a-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> j <a-gt> } }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+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}""
+ "
+}
+
+hook global WinSetOption filetype=(html|xml) %{
+ hook window ModeChange 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}-.+""
+ "
+}
diff --git a/rc/filetype/i3.kak b/rc/filetype/i3.kak
new file mode 100644
index 00000000..e661fcd7
--- /dev/null
+++ b/rc/filetype/i3.kak
@@ -0,0 +1,81 @@
+hook global BufCreate .*(sway|i3)/config %{
+ set buffer filetype 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|unfocused|urgent|inactive_workspace|urgent_workspace|focused_workspace|active_workspace|placeholder)" 1:attribute
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+define-command -hidden i3-indent-on-new-line %~
+ evaluate-commands -draft -itersel %=
+ # copy # comments prefix
+ try %{ execute-keys -draft k<a-x> s ^\h*#\h* <ret> y jgh P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \;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 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-&> ]
+]
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group i3-highlight global WinSetOption filetype=i3 %{
+ add-highlighter window/i3 ref i3
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/i3 }
+}
+
+hook global WinSetOption filetype=i3 %[
+ # cleanup trailing whitespaces when exiting insert mode
+ hook window ModeChange insert:.* -group i3-trim-indent %{ try %{ execute-keys -draft <a-x>s^\h+$<ret>d } }
+ 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-.+ }
+]
diff --git a/rc/filetype/ini.kak b/rc/filetype/ini.kak
new file mode 100644
index 00000000..c03cae4e
--- /dev/null
+++ b/rc/filetype/ini.kak
@@ -0,0 +1,15 @@
+hook global BufCreate .+\.(repo|ini|cfg|properties) %{
+ set-option buffer filetype 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 "^\h*\[[^\]]*\]" 0:title
+add-highlighter shared/ini/code/ regex "^\h*([^\[][^=\n]*)=([^\n]*)" 1:variable 2:value
+
+hook -group ini-highlight global WinSetOption filetype=ini %{
+ add-highlighter window/ini ref ini
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/ini }
+}
diff --git a/rc/filetype/java.kak b/rc/filetype/java.kak
new file mode 100644
index 00000000..7caa5aee
--- /dev/null
+++ b/rc/filetype/java.kak
@@ -0,0 +1,65 @@
+hook global BufCreate .*\.java %{
+ set-option buffer filetype 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/comment region /\* \*/ fill comment
+add-highlighter shared/java/line_comment region // $ fill comment
+
+add-highlighter shared/java/code/ regex %{\b(this|true|false|null)\b} 0:value
+add-highlighter shared/java/code/ regex "\b(void|int|char|unsigned|float|boolean|double)\b" 0:type
+add-highlighter shared/java/code/ regex "\b(while|for|if|else|do|static|switch|case|default|class|interface|enum|goto|break|continue|return|import|try|catch|throw|new|package|extends|implements|throws|instanceof)\b" 0:keyword
+add-highlighter shared/java/code/ regex "\b(final|public|protected|private|abstract|synchronized|native|transient|volatile)\b" 0:attribute
+add-highlighter shared/java/code/ regex "(?<!\w)@\w+\b" 0:meta
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+define-command -hidden java-indent-on-new-line %~
+ evaluate-commands -draft -itersel %=
+ # preserve previous line indent
+ try %{ execute-keys -draft \;K<a-&> }
+ # indent after lines ending with { or (
+ 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 }
+ # 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-;>' & }
+ # copy // comments prefix
+ try %{ execute-keys -draft \;<c-s>k<a-x> s ^\h*\K/{2,} <ret> y<c-o>P<esc> }
+ # indent after a switch's case/default statements
+ try %[ execute-keys -draft k<a-x> <a-k> ^\h*(case|default).*:$ <ret> j<a-gt> ]
+ # indent after keywords
+ try %[ execute-keys -draft \;<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> ]
+ =
+~
+
+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-&> ]
+]
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group java-highlight global WinSetOption filetype=java %{
+ add-highlighter window/java ref java
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/java }
+}
+
+hook global WinSetOption filetype=java %{
+ # cleanup trailing whitespaces when exiting insert mode
+ hook window ModeChange insert:.* -group java-trim-indent %{ try %{ execute-keys -draft <a-x>s^\h+$<ret>d } }
+ 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-.+ }
+}
diff --git a/rc/filetype/javascript.kak b/rc/filetype/javascript.kak
new file mode 100644
index 00000000..4d16ee68
--- /dev/null
+++ b/rc/filetype/javascript.kak
@@ -0,0 +1,117 @@
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](js)x? %{
+ set-option buffer filetype javascript
+}
+
+hook global BufCreate .*[.](ts)x? %{
+ set-option buffer filetype typescript
+}
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+define-command -hidden javascript-trim-indent %{
+ # remove trailing white spaces
+ try %{ execute-keys -draft -itersel <a-x> s \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-indent-on-new-line %<
+ evaluate-commands -draft -itersel %<
+ # copy // comments prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*\K#\h* <ret> y gh j P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; K <a-&> }
+ # filter previous line
+ try %{ execute-keys -draft k : javascript-trim-indent <ret> }
+ # indent after lines beginning / ending with opener token
+ try %_ execute-keys -draft k <a-x> <a-k> ^\h*[[{]|[[{]$ <ret> j <a-gt> _
+ >
+>
+
+# 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}/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
+ add-highlighter "shared/%arg{1}/division" region '[\w\)\]]\K(/|(\h+/\h+))' '(?=\w)' group # Help Kakoune to better detect /…/ literals
+
+ # 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
+ 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|if|import|in|instanceof|let|new|of|return|static|super|switch|throw|try|typeof|var|void|while|with|yield)\b 0:keyword
+
+ # Initialization
+ # ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+ hook -group "%arg{1}-highlight" global WinSetOption "filetype=%arg{1}" "
+ add-highlighter window/%arg{1} ref %arg{1}
+
+ hook -once -always window WinSetOption filetype=.* %%{ remove-highlighter window/%arg{1} }
+ "
+
+ hook global WinSetOption "filetype=%arg{1}" "
+ hook window ModeChange insert:.* -group %arg{1}-trim-indent javascript-trim-indent
+ hook window InsertChar .* -group %arg{1}-indent javascript-indent-on-char
+ hook window InsertChar \n -group %arg{1}-indent javascript-indent-on-new-line
+
+ hook -once -always window WinSetOption filetype=.* %%{ remove-hooks window %arg{1}-.+ }
+ "
+~
+
+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
diff --git a/rc/filetype/json.kak b/rc/filetype/json.kak
new file mode 100644
index 00000000..ae04c55a
--- /dev/null
+++ b/rc/filetype/json.kak
@@ -0,0 +1,60 @@
+# http://json.org
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](json) %{
+ set-option buffer filetype 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 <a-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 s \A|.\z <ret> 1<a-&> >
+ >
+>
+
+define-command -hidden json-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 : json-trim-indent <ret> }
+ # indent after lines beginning with opener token
+ try %< execute-keys -draft k <a-x> <a-k> ^\h*[[{] <ret> j <a-gt> >
+ >
+>
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group json-highlight global WinSetOption filetype=json %{
+ add-highlighter window/json ref json
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/json }
+}
+
+hook global WinSetOption filetype=json %{
+ hook window ModeChange 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-.+ }
+}
diff --git a/rc/filetype/julia.kak b/rc/filetype/julia.kak
new file mode 100644
index 00000000..abdf547a
--- /dev/null
+++ b/rc/filetype/julia.kak
@@ -0,0 +1,30 @@
+# http://julialang.org
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*\.(jl) %{
+ set-option buffer filetype 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 '#' '$' fill comment
+
+# taken from https://github.com/JuliaLang/julia/blob/master/contrib/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)\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|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
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group julia-highlight global WinSetOption filetype=julia %{
+ add-highlighter window/julia ref julia
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/julia }
+}
diff --git a/rc/filetype/just.kak b/rc/filetype/just.kak
new file mode 100644
index 00000000..201bfc3d
--- /dev/null
+++ b/rc/filetype/just.kak
@@ -0,0 +1,48 @@
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*/?[jJ]ustfile %{
+ set-option buffer filetype justfile
+}
+
+# Indentation
+# ‾‾‾‾‾‾‾‾‾‾‾
+
+define-command -hidden just-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # preserve previous line indent
+ try %{ execute-keys -draft \;K<a-&> }
+ # cleanup trailing white spaces on previous line
+ try %{ execute-keys -draft k<a-x> s \h+$ <ret>"_d }
+ # copy '#' comment prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*//\h* <ret> y jgh P }
+ }
+}
+
+# Highlighters
+# ‾‾‾‾‾‾‾‾‾‾‾‾
+
+add-highlighter shared/justfile regions
+add-highlighter shared/justfile/content default-region group
+add-highlighter shared/justfile/comment region '#' '$' fill comment
+add-highlighter shared/justfile/double_string region '"' (?<!\\)(\\\\)*" fill string
+add-highlighter shared/justfile/single_string region "'" (?<!\\)(\\\\)*' fill string
+add-highlighter shared/justfile/inline region '`' '`' ref sh
+
+add-highlighter shared/justfile/shell region '^\h+' '^[^\h]' group
+add-highlighter shared/justfile/shell/ ref sh
+add-highlighter shared/justfile/shell/ regex '(\{{2})([\w-]+)(\}{2})' 1:operator 2:variable 3:operator
+
+add-highlighter shared/justfile/content/ regex '^(@)?([\w-]+)(?:\s(.+))?\s?(:)(.+)?$' 1:operator 2:function 3:value 4:operator 5:type
+add-highlighter shared/justfile/content/ regex '([=+])' 1:operator
+add-highlighter shared/justfile/content/ regex '^([\w-]+)\s=' 1:value
+
+hook -group justfile-highlight global WinSetOption filetype=justfile %{
+ add-highlighter window/justfile ref justfile
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/justfile }
+}
+
+hook global WinSetOption filetype=justfile %{
+ hook window InsertChar \n -group justfile-indent just-indent-on-new-line
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window justfile-.+ }
+}
diff --git a/rc/filetype/kakrc.kak b/rc/filetype/kakrc.kak
new file mode 100644
index 00000000..7a9af989
--- /dev/null
+++ b/rc/filetype/kakrc.kak
@@ -0,0 +1,110 @@
+# http://kakoune.org
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate (.*/)?(kakrc|.*.kak) %{
+ set-option buffer filetype kak
+}
+
+# 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="edit write write-all kill quit write-quit write-all-quit map unmap alias unalias
+ buffer buffer-next buffer-previous delete-buffer add-highlighter remove-highlighter
+ hook remove-hooks define-command echo debug source try catch fail nop
+ set-option unset-option update-option declare-option execute-keys evaluate-commands
+ prompt menu on-key info set-face unset-face rename-client set-register select
+ change-directory rename-session colorscheme declare-user-mode enter-user-mode
+ edit! write! kill! quit! write-quit! delete-buffer!"
+ attributes="global buffer window current
+ normal insert menu 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"
+ 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' "hook global WinSetOption filetype=kak %{
+ set-option window static_words $(join "${keywords} ${attributes} ${types} ${values}" ' ')'
+ set-option -- window extra_word_chars '_' '-'
+ }"
+
+ # 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 \brgb:[0-9a-fA-F]{6}\b 0:value
+add-highlighter shared/kakrc/code/scopes regex \b(global|shared|buffer|window)(?:\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
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+define-command -hidden kak-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # copy '#' comment prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*#\h* <ret> y jgh P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; K <a-&> }
+ # cleanup trailing whitespaces from previous line
+ try %{ execute-keys -draft k <a-x> s \h+$ <ret> d }
+ # indent after line ending with %\w*[^\s\w]
+ try %{ execute-keys -draft k <a-x> <a-k> \%\w*[^\s\w]$ <ret> j <a-gt> }
+ }
+}
+
+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-&> }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group kak-highlight global WinSetOption filetype=kak %{
+ add-highlighter window/kakrc ref kakrc
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/kakrc }
+}
+
+hook global WinSetOption filetype=kak %~
+ 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 insert:.* -group kak-trim-indent %{ try %{ execute-keys -draft \; <a-x> s ^\h+$ <ret> d } }
+ set-option buffer extra_word_chars '_' '-'
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window kak-.+ }
+~
diff --git a/rc/filetype/kickstart.kak b/rc/filetype/kickstart.kak
new file mode 100644
index 00000000..6f30b4b8
--- /dev/null
+++ b/rc/filetype/kickstart.kak
@@ -0,0 +1,30 @@
+hook global BufCreate .*\.ks %{
+ set-option buffer filetype 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
+
+
+hook -group kickstart-highlight global WinSetOption filetype=kickstart %{
+ add-highlighter window/kickstart ref kickstart
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/kickstart }
+}
diff --git a/rc/filetype/latex.kak b/rc/filetype/latex.kak
new file mode 100644
index 00000000..acb5c1fc
--- /dev/null
+++ b/rc/filetype/latex.kak
@@ -0,0 +1,35 @@
+# https://www.latex-project.org/
+#
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*\.tex %{
+ set-option buffer filetype latex
+}
+
+# Highlighters
+# ‾‾‾‾‾‾‾‾‾‾‾‾
+
+add-highlighter shared/latex regions
+add-highlighter shared/latex/content default-region group
+add-highlighter shared/latex/comment region '(?<!\\)%' '\n' fill comment
+
+# Scopes, starting with a backslash
+add-highlighter shared/latex/content/ regex '\\(?!_)\w+\b' 0:keyword
+# Options passed to scopes, between brackets
+add-highlighter shared/latex/content/ regex '\\(?!_)\w+\b\[([^\]]+)\]' 1:value
+# Content between dollar signs/pairs
+add-highlighter shared/latex/content/ regex '(\$(\\\$|[^$])+\$)|(\$\$(\\\$|[^$])+\$\$)' 0:meta
+# Emphasized text
+add-highlighter shared/latex/content/ regex '\\(emph|textit)\{([^}]+)\}' 2:default+i
+# Bold text
+add-highlighter shared/latex/content/ regex '\\textbf\{([^}]+)\}' 1:default+b
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group latex-highlight global WinSetOption filetype=latex %{
+ add-highlighter window/latex ref latex
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/latex }
+}
diff --git a/rc/filetype/lisp.kak b/rc/filetype/lisp.kak
new file mode 100644
index 00000000..378bb3c5
--- /dev/null
+++ b/rc/filetype/lisp.kak
@@ -0,0 +1,74 @@
+# http://common-lisp.net
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](lisp) %{
+ set-option buffer filetype 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(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 (#?(['`:]|,@?))?\b[a-zA-Z][\w!$%&*+./:<=>?@^_~-]* 0:variable
+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 <a-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 '"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&<space>'
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group lisp-highlight global WinSetOption filetype=lisp %{
+ add-highlighter window/lisp ref lisp
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/lisp }
+}
+
+hook global WinSetOption filetype=lisp %{
+ hook window ModeChange insert:.* -group lisp-trim-indent lisp-trim-indent
+ hook window InsertChar \n -group lisp-indent lisp-indent-on-new-line
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window lisp-.+ }
+}
diff --git a/rc/filetype/lua.kak b/rc/filetype/lua.kak
new file mode 100644
index 00000000..605148e0
--- /dev/null
+++ b/rc/filetype/lua.kak
@@ -0,0 +1,103 @@
+# http://lua.org
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](lua) %{
+ set-option buffer filetype 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/ regex \b(and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b 0:keyword
+
+# 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 "echo -markup '{Error}implementation file not found'" && exit
+ ;;
+ *.lua)
+ 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 "echo -markup '{Error}spec/ not found'" && exit
+ ;;
+ *)
+ echo "echo -markup '{Error}alternative file not found'" && exit
+ ;;
+ esac
+ printf %s\\n "edit $altfile"
+}}
+
+define-command -hidden lua-indent-on-char %{
+ evaluate-commands -no-hooks -draft -itersel %{
+ # align middle and end structures to start and indent when necessary, elseif is already covered by else
+ try %{ execute-keys -draft <a-x><a-k>^\h*(else)$<ret><a-\;><a-?>^\h*(if)<ret>s\A|\z<ret>)<a-&> }
+ try %{ execute-keys -draft <a-x><a-k>^\h*(end)$<ret><a-\;><a-?>^\h*(for|function|if|while)<ret>s\A|\z<ret>)<a-&> }
+ }
+}
+
+define-command -hidden lua-indent-on-new-line %{
+ evaluate-commands -no-hooks -draft -itersel %{
+ # preserve previous line indent
+ try %{ execute-keys -draft <space>K<a-&> }
+ # remove trailing white spaces from previous line
+ try %{ execute-keys -draft k<a-x>s\h+$<ret>d }
+ # indent after start structure
+ try %{ execute-keys -draft k<a-x><a-k>^\h*(else|elseif|for|function|if|while)\b<ret>j<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 k<a-x>s^\h*\K--\h*<ret>yghjP }
+ # wisely add end structure
+ evaluate-commands -save-regs x %[
+ try %{ execute-keys -draft k<a-x>s^\h+<ret>"xy } catch %{ reg x '' } # Save previous line indent in register x
+ try %[ execute-keys -draft k<a-x> <a-k>^<c-r>x(for|function|if|while)<ret> J}iJ<a-x> <a-K>^<c-r>x(else|end|elseif)$<ret> # Validate previous line and that it is not closed yet
+ execute-keys -draft o<c-r>xend<esc> ] # auto insert end
+ ]
+ ]
+]
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group lua-highlight global WinSetOption filetype=lua %{
+ add-highlighter window/lua ref lua
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/lua }
+}
+
+hook global WinSetOption filetype=lua %{
+ 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
+ }
+}
diff --git a/rc/filetype/mail.kak b/rc/filetype/mail.kak
new file mode 100644
index 00000000..4323d28c
--- /dev/null
+++ b/rc/filetype/mail.kak
@@ -0,0 +1,13 @@
+hook global BufCreate .+\.eml %{
+ set-option buffer filetype mail
+}
+
+add-highlighter shared/mail group
+add-highlighter shared/mail/ regex ^(From|To|Cc|Bcc|Subject|Reply-To|In-Reply-To|Date):([^\n]*(?:\n\h+[^\n]+)*)$ 1:keyword 2:attribute
+add-highlighter shared/mail/ regex <[^@>]+@.*?> 0:string
+add-highlighter shared/mail/ regex ^>.*?$ 0:comment
+
+hook -group mail-highlight global WinSetOption filetype=mail %{
+ add-highlighter window/mail ref mail
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/mail }
+}
diff --git a/rc/filetype/makefile.kak b/rc/filetype/makefile.kak
new file mode 100644
index 00000000..569d51f9
--- /dev/null
+++ b/rc/filetype/makefile.kak
@@ -0,0 +1,60 @@
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*(/?[mM]akefile|\.mk) %{
+ set-option buffer filetype makefile
+}
+
+# Highlighters
+# ‾‾‾‾‾‾‾‾‾‾‾‾
+
+add-highlighter shared/makefile regions
+
+add-highlighter shared/makefile/content default-region group
+add-highlighter shared/makefile/comment region '#' '$' fill comment
+add-highlighter shared/makefile/evaluate-commands region -recurse '\(' '\$\(' '\)' fill value
+
+add-highlighter shared/makefile/content/ regex ^[\w.%-]+\h*:\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 "hook global WinSetOption filetype=makefile %{
+ set-option window static_words ${keywords}
+ }" | tr '|' ' '
+
+ # Highlight keywords
+ printf %s "add-highlighter shared/makefile/content/ regex \b(${keywords})\b 0:keyword"
+}
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+define-command -hidden makefile-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # preserve previous line indent
+ try %{ execute-keys -draft \;K<a-&> }
+ ## If the line above is a target indent with a tab
+ try %{ execute-keys -draft Z k<a-x> <a-k>^[^:]+:\s<ret> z i<tab> }
+ # cleanup trailing white space son previous line
+ try %{ execute-keys -draft k<a-x> s \h+$ <ret>d }
+ # indent after some keywords
+ try %{ execute-keys -draft Z k<a-x> <a-k> ^\h*(ifeq|ifneq|ifdef|ifndef|else|define)\b<ret> z <a-gt> }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group makefile-highlight global WinSetOption filetype=makefile %{
+ add-highlighter window/makefile ref makefile
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/makefile }
+}
+
+hook global WinSetOption filetype=makefile %{
+ hook window InsertChar \n -group makefile-indent makefile-indent-on-new-line
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window makefile-.+ }
+}
diff --git a/rc/filetype/markdown.kak b/rc/filetype/markdown.kak
new file mode 100644
index 00000000..18f3ccf6
--- /dev/null
+++ b/rc/filetype/markdown.kak
@@ -0,0 +1,85 @@
+# http://daringfireball.net/projects/markdown
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](markdown|md|mkd) %{
+ set-option buffer filetype markdown
+}
+
+# Highlighters
+# ‾‾‾‾‾‾‾‾‾‾‾‾
+
+add-highlighter shared/markdown regions
+add-highlighter shared/markdown/inline default-region regions
+add-highlighter shared/markdown/inline/text default-region group
+
+evaluate-commands %sh{
+ languages="
+ c cabal clojure coffee cpp css cucumber d diff dockerfile fish gas go
+ haml haskell html ini java javascript json julia kak kickstart latex
+ lisp lua makefile markdown moon objc perl pug python ragel ruby rust
+ sass scala scss sh swift toml tupfile typescript yaml sql
+ "
+ for lang in ${languages}; do
+ printf 'add-highlighter shared/markdown/%s region -match-capture ^(\h*)```\h*%s\\b ^(\h*)``` regions\n' "${lang}" "${lang}"
+ printf 'add-highlighter shared/markdown/%s/ default-region fill meta\n' "${lang}"
+ [ "${lang}" = kak ] && ref=kakrc || ref="${lang}"
+ printf 'add-highlighter shared/markdown/%s/inner region \A```[^\\n]*\K (?=```) ref %s\n' "${lang}" "${ref}"
+ done
+}
+
+add-highlighter shared/markdown/codeblock region -match-capture \
+ ^(\h*)```\h* \
+ ^(\h*)```\h*$ \
+ fill meta
+
+add-highlighter shared/markdown/listblock region ^\h*[-*]\s ^\h*((?=[-*])|$) regions
+add-highlighter shared/markdown/listblock/marker region \A [-*]\s fill bullet
+add-highlighter shared/markdown/listblock/content default-region ref markdown/inline
+
+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]+\n={2,}\h*\n\h*$ 0:title
+add-highlighter shared/markdown/inline/text/ regex (\A|\n\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:italic
+add-highlighter shared/markdown/inline/text/ regex (?<!_)(_([^\s_]|([^\s_](\n?[^\n_])*[^\s_]))_)(?!_) 1:italic
+add-highlighter shared/markdown/inline/text/ regex (?<!\*)(\*\*([^\s*]|([^\s*](\n?[^\n*])*[^\s*]))\*\*)(?!\*) 1:bold
+add-highlighter shared/markdown/inline/text/ regex (?<!_)(__([^\s_]|([^\s_](\n?[^\n_])*[^\s_]))__)(?!_) 1:bold
+add-highlighter shared/markdown/inline/text/ regex <(([a-z]+://.*?)|((mailto:)?[\w+-]+@[a-z]+[.][a-z]+))> 0:link
+add-highlighter shared/markdown/inline/text/ regex ^\[[^\]\n]*\]:\h*([^\n]*) 1:link
+add-highlighter shared/markdown/inline/text/ regex ^\h*(>\h*)+ 0:comment
+add-highlighter shared/markdown/inline/text/ regex \H\K\h\h$ 0:PrimarySelection
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+define-command -hidden markdown-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # copy block quote(s), list item prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*\K((>\h*)+([*+-]\h)?|(>\h*)*[*+-]\h)\h* <ret> y gh j P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; K <a-&> }
+ # remove trailing white spaces
+ try %{ execute-keys -draft -itersel %{ k<a-x> s \h+$ <ret> d } }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group markdown-highlight global WinSetOption filetype=markdown %{
+ add-highlighter window/markdown ref markdown
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/markdown }
+}
+
+hook global WinSetOption filetype=markdown %{
+ hook window InsertChar \n -group markdown-indent markdown-indent-on-new-line
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window markdown-.+ }
+}
diff --git a/rc/filetype/mercurial.kak b/rc/filetype/mercurial.kak
new file mode 100644
index 00000000..3f84eea2
--- /dev/null
+++ b/rc/filetype/mercurial.kak
@@ -0,0 +1,18 @@
+# https://www.mercurial-scm.org/
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*hg-editor-\w+\.txt$ %{
+ set-option buffer filetype hg-commit
+}
+
+# Highlighters
+# ‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group hg-commit-highlight global WinSetOption filetype=hg-commit %{
+ add-highlighter window/ group hg-commit-highlight
+ add-highlighter window/hg-commit-highlight regex '^HG:[^\n]*' 0:comment
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/hg-commit-highlight }
+}
diff --git a/rc/filetype/moon.kak b/rc/filetype/moon.kak
new file mode 100644
index 00000000..a1d2ecb8
--- /dev/null
+++ b/rc/filetype/moon.kak
@@ -0,0 +1,107 @@
+# http://moonscript.org
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](moon) %{
+ set-option buffer filetype 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 "echo -markup '{Error}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 "echo -markup '{Error}spec/ not found'" && exit
+ ;;
+ *)
+ echo "echo -markup '{Error}alternative file not found'" && exit
+ ;;
+ esac
+ printf %s\\n "edit $altfile"
+}}
+
+define-command -hidden moon-trim-indent %{
+ evaluate-commands -draft -itersel %{
+ execute-keys <a-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 <a-x> <a-k> ^ \h * (else(if)?) $ <ret> <a-\;> <a-?> ^ \h * (if|unless|when) <ret> s \A | \z <ret> ) <a-&> }
+ # align _when_ to _switch_ then indent
+ try %{ execute-keys -draft <a-x> <a-k> ^ \h * (when) $ <ret> <a-\;> <a-?> ^ \h * (switch) <ret> s \A | \z <ret> ) <a-&> ) <space> <gt> }
+ # align _catch_ and _finally_ to _try_
+ try %{ execute-keys -draft <a-x> <a-k> ^ \h * (catch|finally) $ <ret> <a-\;> <a-?> ^ \h * (try) <ret> s \A | \z <ret> ) <a-&> }
+ }
+}
+
+define-command -hidden moon-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # copy -- comment prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^ \h * \K -- \h * <ret> y gh j P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; K <a-&> }
+ # filter previous line
+ try %{ execute-keys -draft k : moon-trim-indent <ret> }
+ # indent after start structure
+ try %{ execute-keys -draft k <a-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 <a-x> <a-k> ^ \h * (break|return) \b <ret> j <a-lt> }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group moon-highlight global WinSetOption filetype=moon %{
+ add-highlighter window/moon ref moon
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/moon }
+}
+
+hook global WinSetOption filetype=moon %{
+ hook window ModeChange insert:.* -group moon-trim-indent moon-trim-indent
+ hook window InsertChar .* -group moon-indent moon-indent-on-char
+ 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
+ }
+}
diff --git a/rc/filetype/nim.kak b/rc/filetype/nim.kak
new file mode 100644
index 00000000..901ce68a
--- /dev/null
+++ b/rc/filetype/nim.kak
@@ -0,0 +1,112 @@
+# https://nim-lang.org/
+#
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*\.nim(s|ble)? %{
+ set-option buffer filetype 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 (?<!'\\)"(?!') (?<!\\)(\\\\)*" fill string
+add-highlighter shared/nim/comment region '#?#\[' '\]##?' fill comment
+
+evaluate-commands %sh{
+ # Grammar
+ opchars='[=+-/<>@$~&%|!?^.:\\*]'
+ opnocol='[=+-/<>@$~&%|!?^.\\*]'
+ suffix="('[iIuU](8|16|32|64)|'[fF](32|64)?|'[dDuU]|[fF])?"
+ floatsuffix="('[fF](32|64)?|'[dD]|[fF])?"
+ 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 as asm bind block break case cast concept const continue
+ converter defer discard distinct do elif else end enum except export
+ finally for from 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"
+ 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"
+
+ 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 "hook global WinSetOption filetype=nim %{
+ set-option window 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 '#[^\n]+' 0:comment
+add-highlighter shared/nim/code/ regex %{'(\\([rcnlftvabe\\"']|0*[12]?\d?\d|x[0-9a-fA-F]{2})|[^'\n])'} 0:string
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+def -hidden nim-indent-on-new-line %{
+ eval -draft -itersel %{
+ # copy '#' comment prefix and following white spaces
+ try %{ exec -draft k <a-x> s ^\h*#\h* <ret> y jgh P }
+ # preserve previous line indent
+ try %{ exec -draft \; K <a-&> }
+ # cleanup trailing whitespaces from previous line
+ try %{ exec -draft k <a-x> s \h+$ <ret> d }
+ # indent after line ending with type, import, export, const, let, var, ':' or '='
+ try %{ exec -draft <space> k x <a-k> (:|=|const|let|var|import|export|type)$ <ret> j <a-gt> }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group nim-highlight global WinSetOption filetype=nim %{
+ add-highlighter window/nim ref nim
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/nim }
+}
+
+hook global WinSetOption filetype=nim %{
+ hook window InsertChar \n -group nim-indent nim-indent-on-new-line
+ # cleanup trailing whitespaces on current line insert end
+ hook window ModeChange insert:.* -group nim-trim-indent %{ try %{ exec -draft \; <a-x> s ^\h+$ <ret> d } }
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window nim-.+ }
+}
diff --git a/rc/filetype/ocaml.kak b/rc/filetype/ocaml.kak
new file mode 100644
index 00000000..0a3d49bf
--- /dev/null
+++ b/rc/filetype/ocaml.kak
@@ -0,0 +1,38 @@
+# http://ocaml.org
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*\.mli? %{
+ set-option buffer filetype 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/comment region \Q(* \Q*) fill comment
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group ocaml-highlight global WinSetOption filetype=ocaml %{
+ add-highlighter window/ocaml ref ocaml
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/ocaml }
+}
+
+# Macro
+# ‾‾‾‾‾
+
+evaluate-commands %sh{
+ keywords=and:as:asr:assert:begin:class:constraint:do:done:downto:else:end:exception:external:false:for:fun:function:functor:if:in:include:inherit:initializer:land:lazy:let:lor:lsl:lsr:lxor:match:method:mod:module:mutable:new:nonrec:object:of:open:or:private:rec:sig:struct:then:to:true:try:type:val:virtual:when:while:with
+ echo "
+ add-highlighter shared/ocaml/code/ regex \b($(printf $keywords | tr : '|'))\b 0:keyword
+ hook global WinSetOption filetype=ocaml %{
+ set-option window static_words $keywords
+ }
+ "
+}
diff --git a/rc/filetype/perl.kak b/rc/filetype/perl.kak
new file mode 100644
index 00000000..e69058d3
--- /dev/null
+++ b/rc/filetype/perl.kak
@@ -0,0 +1,114 @@
+# https://www.perl.org/
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*\.(t|p[lm])$ %{
+ set-option buffer filetype 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
+
+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"
+ attributes="${attributes}|length|setpgrp|endgrent|link|setpriority|endhostent|listen|setprotoent|endnetent|local|setpwent"
+ attributes="${attributes}|endprotoent|localtime|setservent|endpwent|log|setsockopt|endservent|lstat|shift|eof|map|shmctl|eval|mkdir|shmget|exec|msgctl|shmread"
+ attributes="${attributes}|exists|msgget|shmwrite|msgrcv|shutdown|fcntl|msgsnd|sin|fileno|sleep|flock|next|socket|fork|socketpair|format|oct|sort"
+ attributes="${attributes}|formline|open|splice|getc|opendir|split|getgrent|ord|sprintf|getgrgid|our|sqrt|getgrnam|pack|srand|gethostbyaddr|pipe|stat|gethostbyname"
+ attributes="${attributes}|pop|state|gethostent|pos|study|getlogin|print|substr|getnetbyaddr|printf|symlink|abs|getnetbyname|prototype|syscall|accept|getnetent"
+ attributes="${attributes}|push|sysopen|alarm|getpeername|quotemeta|sysread|atan2|getpgrp|rand|sysseek|getppid|read|system|getpriority|readdir|syswrite|bind"
+ attributes="${attributes}|getprotobyname|readline|tell|binmode|getprotobynumber|readlink|telldir|bless|getprotoent|readpipe|tie|getpwent|recv|tied|caller"
+ attributes="${attributes}|getpwnam|redo|time|chdir|getpwuid|ref|times|getservbyname|rename|truncate|chmod|getservbyport|require|uc|chomp|getservent|reset|ucfirst"
+ attributes="${attributes}|chop|getsockname|umask|chown|getsockopt|reverse|undef|chr|glob|rewinddir|chroot|gmtime|rindex|unlink|close|rmdir|unpack"
+ attributes="${attributes}|closedir|grep|say|unshift|connect|hex|scalar|untie|cos|index|seek|use|crypt|seekdir|utime|dbmclose|int|select|values|dbmopen|ioctl|semctl"
+ attributes="${attributes}|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__"
+
+ # Add the language's grammar to the static completion list
+ printf %s\\n "hook global WinSetOption filetype=perl %{
+ set-option window static_words ${keywords} ${attributes} ${values}
+ }" | tr '|' ' '
+
+ # Highlight keywords
+ printf %s "
+ add-highlighter shared/perl/code/ regex \b(${keywords})\b 0:keyword
+ add-highlighter shared/perl/code/ regex \b(${attributes})\b 0:attribute
+ add-highlighter shared/perl/code/ regex \b(${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-indent-on-new-line %~
+ evaluate-commands -draft -itersel %=
+ # preserve previous line indent
+ try %{ execute-keys -draft \;K<a-&> }
+ # indent after lines ending with { or (
+ 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 }
+ # 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-;>' & }
+ # copy // comments prefix
+ try %{ execute-keys -draft \;<c-s>k<a-x> s ^\h*\K/{2,} <ret> y<c-o>P<esc> }
+ # indent after a switch's case/default statements
+ try %[ execute-keys -draft k<a-x> <a-k> ^\h*(case|default).*:$ <ret> j<a-gt> ]
+ # indent after if|else|while|for
+ try %[ execute-keys -draft \;<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-space><a-gt> ]
+ =
+~
+
+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-&> ]
+]
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group perl-highlight global WinSetOption filetype=perl %{
+ add-highlighter window/perl ref perl
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/perl }
+}
+
+hook global WinSetOption filetype=perl %{
+ # cleanup trailing whitespaces when exiting insert mode
+ hook window ModeChange insert:.* -group perl-trim-indent %{ try %{ execute-keys -draft <a-x>s^\h+$<ret>d } }
+ 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-.+ }
+}
diff --git a/rc/filetype/php.kak b/rc/filetype/php.kak
new file mode 100644
index 00000000..4acfde85
--- /dev/null
+++ b/rc/filetype/php.kak
@@ -0,0 +1,90 @@
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](php) %{
+ set-option buffer filetype php
+}
+
+# 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/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 <a-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-indent-on-new-line %<
+ evaluate-commands -draft -itersel %<
+ # copy // comments prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*\K#\h* <ret> y gh j P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; 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 <a-x> <a-k> ^\h*[[{]|[[{]$ <ret> j <a-gt> _
+ >
+>
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+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 }
+}
+
+hook global WinSetOption filetype=php %{
+ hook window ModeChange insert:.* -group php-trim-indent php-trim-indent
+ hook window InsertChar .* -group php-indent php-indent-on-char
+ hook window InsertChar \n -group php-indent php-indent-on-new-line
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window php-.+ }
+}
diff --git a/rc/filetype/pony.kak b/rc/filetype/pony.kak
new file mode 100644
index 00000000..713cc295
--- /dev/null
+++ b/rc/filetype/pony.kak
@@ -0,0 +1,92 @@
+# http://ponylang.org
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](pony) %{
+ set-option buffer filetype pony
+}
+
+# Highlighters & Completion
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+add-highlighter shared/pony regions
+add-highlighter shared/pony/code default-region group
+add-highlighter shared/pony/triple_string region '"""' '"""' fill string
+add-highlighter shared/pony/double_string region '"' (?<!\\)(\\\\)*" fill string
+add-highlighter shared/pony/comment region '/\*' '\*/' fill comment
+add-highlighter shared/pony/line_comment region '//' '$' fill comment
+
+evaluate-commands %sh{
+ # Grammar
+ values="true|false|None|this"
+ meta='use'
+ # Keyword list is collected using `keyword.kwlist` from `keyword`
+ keywords="and|as|or|break|match|continue|else|try|in|return|end|for|is"
+ keywords="${keywords}|recover|consume|error|do|then|if|while"
+ func_decl="new|fun|be|lambda"
+ capabilities="iso|ref|box|tag|val|trn"
+ struct="class|actor|interface|trait|primitive|type|var|let|embed"
+
+
+ # Add the language's grammar to the static completion list
+ static_words="${values} ${meta} ${keywords} ${types_decl} ${capabilities}"
+ static_words="${static_words} ${struct}"
+ printf %s\\n "hook global WinSetOption filetype=pony %{
+ set-option window static_words ${static_words}
+ }" | tr '|' ' '
+
+ # Highlight keywords
+ printf %s "
+ add-highlighter shared/pony/code/ regex '\b(${values})\b' 0:value
+ 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:type 3:builtin 4:builtin
+ add-highlighter shared/pony/code/ regex '\b(${func_decl})\b' 0:type
+ add-highlighter shared/pony/code/ regex '=>' 0:type
+ add-highlighter shared/pony/code/ regex '\b(${keywords})\b' 0:keyword
+ add-highlighter shared/pony/code/ regex ';' 0:keyword
+ add-highlighter shared/pony/code/ regex '^\s*|' 0:keyword
+ add-highlighter shared/pony/code/ regex '\b(${struct})\b' 0:variable
+ add-highlighter shared/pony/code/ regex '\b(${capabilities})\b(!|^)?' 1:builtin 2:builtin
+ "
+
+ # Highlight types and attributes
+ printf %s "
+ add-highlighter shared/pony/code/ regex '@[\w_]+\b' 0:attribute
+ "
+}
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+define-command -hidden pony-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # preserve previous line indent
+ try %{ execute-keys -draft <space> K <a-&> }
+ # cleanup trailing whitespaces from previous line
+ try %{ execute-keys -draft k <a-x> s \h+$ <ret> d }
+ # copy '//' comment prefix and following white spaces
+ # try %{ execute-keys -draft k x s ^\h*//\h* <ret> y jgh P }
+ # indent after line ending with :
+ try %{ execute-keys -draft <space> k x <a-k> (do|try|then|else|:|=>)$ <ret> j <a-gt> }
+ # else, end are always de-indented
+ try %{ execute-keys -draft <space> k x <a-k> (else|end):$ <ret> k x s ^\h* <ret> y j x <a-k> ^<c-r>" <ret> J <a-lt> }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group pony-highlight global WinSetOption filetype=pony %{
+ add-highlighter window/pony ref pony
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter pony }
+}
+
+hook global WinSetOption filetype=pony %{
+ hook window InsertChar \n -group pony-indent pony-indent-on-new-line
+ # cleanup trailing whitespaces on current line insert end
+ hook window ModeChange insert:.* -group pony-trim-indent %{ try %{ execute-keys -draft \; <a-x> s ^\h+$ <ret> d } }
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window pony-.+ }
+}
diff --git a/rc/filetype/protobuf.kak b/rc/filetype/protobuf.kak
new file mode 100644
index 00000000..2ef10480
--- /dev/null
+++ b/rc/filetype/protobuf.kak
@@ -0,0 +1,85 @@
+# https://developers.google.com/protocol-buffers/
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*\.proto$ %{
+ set-option buffer filetype 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"
+ keywords="${keywords}|package|service|syntax"
+ attributes="optional|repeated|required"
+ types="double|float|int32|int64|uint32|uint64|sint32|sint64|fixed32|fixed64"
+ types="${types}|sfixed32|sfixed64|bool|string|bytes|rpc"
+ values="false|true"
+
+ # Add the language's grammer to the static completion list
+ printf '%s\n' "hook global WinSetOption filetype=protobuf %{
+ set-option window static_words ${keywords} ${attributes} ${types} ${values}
+ }" | tr '|' ' '
+
+ # Highlight keywords
+ printf %s "
+ add-highlighter shared/protobuf/code/keywords regex \b(${keywords})\b 0:keyword
+ add-highlighter shared/protobuf/code/attributes regex \b(${attributes})\b 0:attribute
+ add-highlighter shared/protobuf/code/types regex \b(${types})\b 0:type
+ add-highlighter shared/protobuf/code/values regex \b(${values})\b 0:value
+ "
+}
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+
+define-command -hidden protobuf-indent-on-newline %~
+ evaluate-commands -draft -itersel %[
+ # preserve previous line indent
+ try %{ execute-keys -draft \;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 }
+ # copy // comments prefix
+ try %{ execute-keys -draft \;<c-s>k<a-x> s ^\h*\K/{2,}(\h*(?=\S))? <ret> y<c-o>P<esc> }
+ ]
+~
+
+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-&> ]
+]
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group protobuf-highlight global WinSetOption filetype=protobuf %{
+ add-highlighter window/protobuf ref protobuf
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/protobuf }
+}
+
+hook global WinSetOption filetype=protobuf %[
+ 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-.+ }
+]
diff --git a/rc/filetype/pug.kak b/rc/filetype/pug.kak
new file mode 100644
index 00000000..13aa839f
--- /dev/null
+++ b/rc/filetype/pug.kak
@@ -0,0 +1,74 @@
+# 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
+}
+
+# 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 <a-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 \; 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 <a-x> s ^\h*\K[/|!=-]{1,2}\h* <ret> y gh j P }
+ # indent unless we copied something above
+ try %{ execute-keys -draft <a-gt> <space> b s \S <ret> g l <a-lt> }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group pug-highlight global WinSetOption filetype=pug %{
+ add-highlighter window/pug ref pug
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/pug }
+}
+
+hook global WinSetOption filetype=pug %{
+ hook window ModeChange 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-.+ }
+}
diff --git a/rc/filetype/python.kak b/rc/filetype/python.kak
new file mode 100644
index 00000000..fb9477b9
--- /dev/null
+++ b/rc/filetype/python.kak
@@ -0,0 +1,148 @@
+# http://python.org
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](py) %{
+ set-option buffer filetype python
+}
+
+# Highlighters & Completion
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+add-highlighter shared/python regions
+add-highlighter shared/python/code default-region group
+add-highlighter shared/python/docstring region -match-capture ("""|''') ("""|''') regions
+add-highlighter shared/python/double_string region '"' (?<!\\)(\\\\)*" fill string
+add-highlighter shared/python/single_string region "'" (?<!\\)(\\\\)*' fill string
+add-highlighter shared/python/comment region '#' '$' fill comment
+
+# 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 string
+add-highlighter shared/python/docstring/ region '>>> \K' '\z' ref python
+add-highlighter shared/python/docstring/ region '\.\.\. \K' '\z' 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__"
+ attributes="${attributes}|__globals__|__kwdefaults__|__module__|__name__|__qualname__"
+ methods="__abs__|__add__|__aenter__|__aexit__|__aiter__|__and__|__anext__"
+ methods="${methods}|__await__|__bool__|__bytes__|__call__|__complex__|__contains__"
+ methods="${methods}|__del__|__delattr__|__delete__|__delitem__|__dir__|__divmod__"
+ methods="${methods}|__enter__|__eq__|__exit__|__float__|__floordiv__|__format__"
+ methods="${methods}|__ge__|__get__|__getattr__|__getattribute__|__getitem__"
+ methods="${methods}|__gt__|__hash__|__iadd__|__iand__|__ifloordiv__|__ilshift__"
+ methods="${methods}|__imatmul__|__imod__|__imul__|__index__|__init__"
+ methods="${methods}|__init_subclass__|__int__|__invert__|__ior__|__ipow__"
+ methods="${methods}|__irshift__|__isub__|__iter__|__itruediv__|__ixor__|__le__"
+ methods="${methods}|__len__|__length_hint__|__lshift__|__lt__|__matmul__"
+ methods="${methods}|__missing__|__mod__|__mul__|__ne__|__neg__|__new__|__or__"
+ methods="${methods}|__pos__|__pow__|__radd__|__rand__|__rdivmod__|__repr__"
+ methods="${methods}|__reversed__|__rfloordiv__|__rlshift__|__rmatmul__|__rmod__"
+ methods="${methods}|__rmul__|__ror__|__round__|__rpow__|__rrshift__|__rshift__"
+ methods="${methods}|__rsub__|__rtruediv__|__rxor__|__set__|__setattr__"
+ methods="${methods}|__setitem__|__set_name__|__slots__|__str__|__sub__"
+ methods="${methods}|__truediv__|__xor__"
+
+ # built-in exceptions https://docs.python.org/3/library/exceptions.html
+ exceptions="ArithmeticError|AssertionError|AttributeError|BaseException|BlockingIOError"
+ exceptions="${exceptions}|BrokenPipeError|BufferError|BytesWarning|ChildProcessError"
+ exceptions="${exceptions}|ConnectionAbortedError|ConnectionError|ConnectionRefusedError"
+ exceptions="${exceptions}|ConnectionResetError|DeprecationWarning|EOFError|Exception"
+ exceptions="${exceptions}|FileExistsError|FileNotFoundError|FloatingPointError|FutureWarning"
+ exceptions="${exceptions}|GeneratorExit|ImportError|ImportWarning|IndentationError"
+ exceptions="${exceptions}|IndexError|InterruptedError|IsADirectoryError|KeyboardInterrupt"
+ exceptions="${exceptions}|KeyError|LookupError|MemoryError|ModuleNotFoundError|NameError"
+ exceptions="${exceptions}|NotADirectoryError|NotImplementedError|OSError|OverflowError"
+ exceptions="${exceptions}|PendingDeprecationWarning|PermissionError|ProcessLookupError"
+ exceptions="${exceptions}|RecursionError|ReferenceError|ResourceWarning|RuntimeError"
+ exceptions="${exceptions}|RuntimeWarning|StopAsyncIteration|StopIteration|SyntaxError"
+ exceptions="${exceptions}|SyntaxWarning|SystemError|SystemExit|TabError|TimeoutError|TypeError"
+ exceptions="${exceptions}|UnboundLocalError|UnicodeDecodeError|UnicodeEncodeError|UnicodeError"
+ exceptions="${exceptions}|UnicodeTranslateError|UnicodeWarning|UserWarning|ValueError|Warning"
+ exceptions="${exceptions}|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"
+ keywords="${keywords}|finally|for|global|if|in|is|lambda|nonlocal|not|or|pass|print"
+ keywords="${keywords}|raise|return|try|while|with|yield"
+
+ types="bool|buffer|bytearray|bytes|complex|dict|file|float|frozenset|int"
+ types="${types}|list|long|memoryview|object|set|str|tuple|unicode|xrange"
+
+ functions="abs|all|any|ascii|bin|callable|chr|classmethod|compile|complex"
+ functions="${functions}|delattr|dict|dir|divmod|enumerate|eval|exec|filter"
+ functions="${functions}|format|frozenset|getattr|globals|hasattr|hash|help"
+ functions="${functions}|hex|id|__import__|input|isinstance|issubclass|iter"
+ functions="${functions}|len|locals|map|max|memoryview|min|next|oct|open|ord"
+ functions="${functions}|pow|print|property|range|repr|reversed|round"
+ functions="${functions}|setattr|slice|sorted|staticmethod|sum|super|type|vars|zip"
+
+ # Add the language's grammar to the static completion list
+ printf %s\\n "hook global WinSetOption filetype=python %{
+ set-option window static_words ${values} ${meta} ${attributes} ${methods} ${exceptions} ${keywords} ${types} ${functions}
+ }" | tr '|' ' '
+
+ # Highlight keywords
+ printf %s "
+ add-highlighter shared/python/code/ regex '\b(${values})\b' 0:value
+ add-highlighter shared/python/code/ regex '\b(${meta})\b' 0:meta
+ add-highlighter shared/python/code/ regex '\b(${attribute})\b' 0:attribute
+ add-highlighter shared/python/code/ regex '\bdef\s+(${methods})\b' 1:function
+ add-highlighter shared/python/code/ regex '\b(${exceptions})\b' 0:function
+ add-highlighter shared/python/code/ regex '\b(${keywords})\b' 0:keyword
+ add-highlighter shared/python/code/ regex '\b(${functions})\b\(' 1:builtin
+ add-highlighter shared/python/code/ regex '\b(${types})\b' 0:type
+ add-highlighter shared/python/code/ regex '@[\w_]+\b' 0:attribute
+ "
+}
+
+add-highlighter shared/python/code/ regex (?<=[\w\s\d'"_])(<=|<<|>>|>=|<>|<|>|!=|==|\||\^|&|\+|-|\*\*|\*|//|/|%|~) 0:operator
+add-highlighter shared/python/code/ regex (?<=[\w\s\d'"_])((?<![=<>!])=(?![=])|[+*-]=) 0:builtin
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+define-command -hidden python-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # copy '#' comment prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*#\h* <ret> y jgh P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; K <a-&> }
+ # cleanup trailing whitespaces from previous line
+ try %{ execute-keys -draft k <a-x> s \h+$ <ret> d }
+ # indent after line ending with :
+ try %{ execute-keys -draft <space> k <a-x> <a-k> :$ <ret> j <a-gt> }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group python-highlight global WinSetOption filetype=python %{
+ add-highlighter window/python ref python
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/python }
+}
+
+hook global WinSetOption filetype=python %{
+ hook window InsertChar \n -group python-indent python-indent-on-new-line
+ # cleanup trailing whitespaces on current line insert end
+ hook window ModeChange insert:.* -group python-trim-indent %{ try %{ execute-keys -draft \; <a-x> s ^\h+$ <ret> d } }
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window python-.+ }
+}
diff --git a/rc/filetype/ragel.kak b/rc/filetype/ragel.kak
new file mode 100644
index 00000000..b6e8dd4c
--- /dev/null
+++ b/rc/filetype/ragel.kak
@@ -0,0 +1,70 @@
+# http://complang.org/ragel
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# ragel.kak does not try to detect host language.
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](ragel|rl) %{
+ set-option buffer filetype 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 <a-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-indent-on-new-line %<
+ evaluate-commands -draft -itersel %<
+ # copy _#_ comment prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*\K#\h* <ret> y gh j P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; 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 <a-x> <a-k> [[{(*]$ <ret> j <a-gt> >
+ >
+>
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group ragel-highlight global WinSetOption filetype=ragel %{
+ add-highlighter window/ragel ref ragel
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/ragel }
+}
+
+hook global WinSetOption filetype=ragel %{
+ hook window ModeChange insert:.* -group ragel-trim-indent ragel-trim-indent
+ hook window InsertChar .* -group ragel-indent ragel-indent-on-char
+ hook window InsertChar \n -group ragel-indent ragel-indent-on-new-line
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window ragel-.+ }
+}
diff --git a/rc/filetype/restructuredtext.kak b/rc/filetype/restructuredtext.kak
new file mode 100644
index 00000000..1eaf4bfc
--- /dev/null
+++ b/rc/filetype/restructuredtext.kak
@@ -0,0 +1,74 @@
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](rst) %{
+ set-option buffer filetype 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
+
+evaluate-commands %sh{
+ for ft in c cabal clojure coffee cpp css cucumber ddiff dockerfile \
+ fish gas go haml haskell html ini java javascript json \
+ julia kak kickstart latex lisp lua makefile moon objc \
+ perl pug python ragel ruby rust sass scala scss sh swift \
+ tupfile yaml; do
+ if [ "$ft" = kak ]; then ref="kakrc"; else ref="$ft"; fi
+ printf 'add-highlighter shared/restructuredtext/%s region %s %s ref %s\n' "$ft" '\.\.\h*'$ft'::\h*c\h*\n' '^\S' "$ref"
+ done
+}
+
+# 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:bold
+add-highlighter shared/restructuredtext/content/ regex [^*](\*([^\s*]|([^\s*][^*]*[^\s*]))\*)[^*] 1:italic
+add-highlighter shared/restructuredtext/content/ regex [^`](``([^\s`]|([^\s`][^`]*[^\s`]))``)[^`] 1:mono
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group restructuredtext-highlight global WinSetOption filetype=restructuredtext %{
+ add-highlighter window/restructuredtext ref restructuredtext
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/restructuredtext }
+}
diff --git a/rc/filetype/ruby.kak b/rc/filetype/ruby.kak
new file mode 100644
index 00000000..3e5cfcfa
--- /dev/null
+++ b/rc/filetype/ruby.kak
@@ -0,0 +1,168 @@
+# 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
+}
+
+# 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 \( '%[iqrswxIQRSWX]\(' \) fill meta
+add-highlighter shared/ruby/ region -recurse \{ '%[iqrswxIQRSWX]\{' \} fill meta
+add-highlighter shared/ruby/ region -recurse \[ '%[iqrswxIQRSWX]\[' \] fill meta
+add-highlighter shared/ruby/ region -recurse < '%[iqrswxIQRSWX]<' > fill meta
+add-highlighter shared/ruby/heredoc region '<<[-~]?(?!self)(\w+)' '^\h*(\w+)$' fill string
+add-highlighter shared/ruby/division region '[\w\)\]](/|(\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|include|extend"
+
+ # Add the language's grammar to the static completion list
+ printf %s\\n "hook global WinSetOption filetype=ruby %{
+ set-option window static_words ${keywords} ${attributes} ${values} ${meta}
+ }" | tr '|' ' '
+
+ # Highlight keywords
+ printf %s "
+ add-highlighter shared/ruby/code/ regex \b(${keywords})\b 0: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 "echo -markup '{Error}implementation file not found'" && exit
+ ;;
+ *.rb)
+ path=$kak_buffile
+ dirs=$(while [ $path ]; do echo $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/.rb$/_spec.rb/)
+ break
+ fi
+ done
+ [ ! -d $altdir ] && echo "echo -markup '{Error}spec/ not found'" && exit
+ ;;
+ *)
+ echo "echo -markup '{Error}alternative file not found'" && exit
+ ;;
+ esac
+ echo "edit $altfile"
+}}
+
+define-command -hidden ruby-trim-indent %{
+ evaluate-commands -no-hooks -draft -itersel %{
+ execute-keys <a-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 <a-x> <a-k> ^ \h * (else|elsif) $ <ret> <a-\;> <a-?> ^ \h * (if) <ret> s \A | \z <ret> ) <a-&> }
+ try %{ execute-keys -draft <a-x> <a-k> ^ \h * (when) $ <ret> <a-\;> <a-?> ^ \h * (case) <ret> s \A | \z <ret> ) <a-&> }
+ try %{ execute-keys -draft <a-x> <a-k> ^ \h * (rescue) $ <ret> <a-\;> <a-?> ^ \h * (begin) <ret> s \A | \z <ret> ) <a-&> }
+ try %{ execute-keys -draft <a-x> <a-k> ^ \h * (end) $ <ret> <a-\;> <a-?> ^ \h * (begin|case|class|def|do|for|if|module|unless|until|while) <ret> s \A | \z <ret> ) <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 <a-x> <a-k> ^ \h * (begin|case|class|def|do|else|elsif|ensure|for|if|module|rescue|unless|until|when|while) \b <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 <a-x> s '^\h*\K#\h*' <ret> y gh j P }
+ # wisely add end structure
+ evaluate-commands -save-regs x %[
+ try %{ execute-keys -draft k <a-x> s ^ \h + <ret> \" x y } catch %{ reg x '' }
+ try %[
+ evaluate-commands -draft %[
+ execute-keys -draft k<a-x> <a-k>^<c-r>x(begin|case|class|def|do|for|if|module|unless|until|while)<ret> # Check if previous line opens a block
+ # Check that we do not already have an end for this indent level, or that we have another block opening at that indent level first
+ execute-keys -draft Ge <a-K>\A(^\n|^<c-r>x(?!begin)(?!case)(?!class)(?!def)(?!do)(?!for)(?!if)(?!module)(?!unless)(?!until)(?!while)[^\n]*\n)+<c-r>xend$<ret>
+ ]
+ execute-keys -draft o<c-r>xend<esc> # insert a new line with containing end
+ ]
+ ]
+ ]
+]
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group ruby-highlight global WinSetOption filetype=ruby %{
+ add-highlighter window/ruby ref ruby
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/ruby }
+}
+
+hook global WinSetOption filetype=ruby %{
+ hook window InsertChar .* -group ruby-indent ruby-indent-on-char
+ hook window InsertChar \n -group ruby-insert ruby-insert-on-new-line
+ hook window InsertChar \n -group ruby-indent ruby-indent-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
+ }
+}
diff --git a/rc/filetype/rust.kak b/rc/filetype/rust.kak
new file mode 100644
index 00000000..9cbca842
--- /dev/null
+++ b/rc/filetype/rust.kak
@@ -0,0 +1,88 @@
+# http://rust-lang.org
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](rust|rs) %{
+ set-option buffer filetype 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/comment region -recurse /\* /\* \*/ fill comment
+add-highlighter shared/rust/line_comment region // $ fill comment
+
+add-highlighter shared/rust/code/ regex \b[A-z0-9_]+! 0:meta
+# the number literals syntax is defined here:
+# https://doc.rust-lang.org/reference.html#number-literals
+add-highlighter shared/rust/code/ 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/ regex \b(?:&&|\|\|)\b 0:operator
+# the language keywords are defined here, but many of them are reserved and unused yet:
+# https://doc.rust-lang.org/grammar.html#keywords
+add-highlighter shared/rust/code/ regex (?:#!?\[.*?\]) 0:meta
+add-highlighter shared/rust/code/ regex \b(?:let|as|fn|return|match|if|else|loop|for|in|while|break|continue|move|box|where|impl|dyn|pub|unsafe)\b 0:keyword
+add-highlighter shared/rust/code/ regex \b(?:trait|struct|enum|type|mut|ref|static|const)\b 0:attribute
+add-highlighter shared/rust/code/ 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/ regex \b(?:mod|crate|use|extern)\b 0:module
+add-highlighter shared/rust/code/ regex \$\w+\b 0:variable
+add-highlighter shared/rust/code/ regex "'\\\\?.'" 0:value
+add-highlighter shared/rust/code/ regex "('\w+)[^']" 1:meta
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+define-command -hidden rust-trim-indent %{
+ # remove trailing white spaces
+ try %{ execute-keys -draft -itersel <a-x> s \h+$ <ret> d }
+}
+
+define-command -hidden rust-indent-on-new-line %~
+ evaluate-commands -draft -itersel %<
+ # copy // comments prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*\K//[!/]?\h* <ret> y gh j P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; K <a-&> }
+ # filter previous line
+ try %{ execute-keys -draft k : rust-trim-indent <ret> }
+ # indent after lines ending with { or (
+ try %[ execute-keys -draft k <a-x> <a-k> [{(]\h*$ <ret> j <a-gt> ]
+ # 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> & }
+ >
+~
+
+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-&> ]
+ _
+]
+
+define-command -hidden rust-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-&> ]
+ _
+]
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group rust-highlight global WinSetOption filetype=rust %{
+ add-highlighter window/rust ref rust
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/rust }
+}
+
+hook global WinSetOption filetype=rust %[
+ hook window ModeChange 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-curly-brace
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window rust-.+ }
+]
diff --git a/rc/filetype/sass.kak b/rc/filetype/sass.kak
new file mode 100644
index 00000000..d23a7b81
--- /dev/null
+++ b/rc/filetype/sass.kak
@@ -0,0 +1,62 @@
+# http://sass-lang.com
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](sass) %{
+ set-option buffer filetype 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/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 <a-x> s \h+$ <ret> d }
+}
+
+define-command -hidden sass-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # copy '/' comment prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*\K/\h* <ret> y gh j P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; 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 <a-x> <a-K> [:/] <ret> j <a-gt> }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group sass-highlight global WinSetOption filetype=sass %{
+ add-highlighter window/sass ref sass
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/sass }
+}
+
+hook global WinSetOption filetype=sass %{
+ hook window ModeChange insert:.* -group sass-trim-indent sass-trim-indent
+ 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-.+ }
+}
diff --git a/rc/filetype/scala.kak b/rc/filetype/scala.kak
new file mode 100644
index 00000000..1e62e2ad
--- /dev/null
+++ b/rc/filetype/scala.kak
@@ -0,0 +1,75 @@
+# http://scala-lang.org
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](scala) %{
+ set-option buffer filetype 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 <a-x> s \h+$ <ret> d }
+}
+
+define-command -hidden scala-indent-on-new-line %[
+ evaluate-commands -draft -itersel %[
+ # copy // comments prefix and following white spaces
+ try %[ execute-keys -draft k <a-x> s ^\h*\K#\h* <ret> y gh j P ]
+ # preserve previous line indent
+ try %[ execute-keys -draft \; K <a-&> ]
+ # filter previous line
+ try %[ execute-keys -draft k : scala-trim-indent <ret> ]
+ # indent after lines ending with {
+ try %[ execute-keys -draft k <a-x> <a-k> \{$ <ret> j <a-gt> ]
+ ]
+]
+
+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-&> ]
+ ]
+]
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group scala-highlight global WinSetOption filetype=scala %{
+ add-highlighter window/scala ref scala
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/scala }
+}
+
+hook global WinSetOption filetype=scala %[
+ hook window ModeChange insert:.* -group scala-trim-indent scala-trim-indent
+ 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-.+ }
+]
diff --git a/rc/filetype/scheme.kak b/rc/filetype/scheme.kak
new file mode 100644
index 00000000..ec86638b
--- /dev/null
+++ b/rc/filetype/scheme.kak
@@ -0,0 +1,133 @@
+# http://www.scheme-reports.org
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# require lisp.kak
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate (.*/)?(.*\.(scm|ss|sld)) %{
+ set-option buffer filetype scheme
+}
+
+# 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
+add-highlighter shared/scheme/code/ regex \b[0-9]+\.[0-9]*\b 0:value
+
+evaluate-commands %sh{ exec awk -f - <<'EOF'
+ BEGIN {
+ # Primitive expressions that cannot be derived.
+ split("define do let let* letrec if cond case and or begin lambda delay delay-force set!", keywords);
+
+ # Macro expressions.
+ split("define-syntax let-syntax letrec-syntax syntax-rules syntax-case", 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? input-port? "\
+ "null? number? output-port? procedure? symbol?", types);
+
+ # R5RS available procedures
+ split("abs acos angle append apply asin assoc assq assv atan "\
+ "caaaar caaadr caaar caadar caaddr caadr "\
+ "caar cadaar cadadr cadar caddar cadddr caddr cadr "\
+ "call-with-current-continuation 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-lower-case? char-numeric? char-ready? char-upcase "\
+ "char-upper-case? char-whitespace? char<=? char<? char=? "\
+ "char>=? char>? close-input-port close-output-port cons cos "\
+ "current-input-port current-output-port denominator display "\
+ "dynamic-wind else eq? equal? eqv? eval even? exact->inexact "\
+ "exact? exp expt floor for-each force gcd imag-part inexact->exact "\
+ "inexact? integer->char integer? interaction-environment lcm "\
+ "length list list->string list->vector list-ref list-tail load log "\
+ "magnitude make-polar make-rectangular make-string make-vector "\
+ "map max member memq memv min modulo negative? newline not "\
+ "null-environment number->string numerator odd? open-input-file "\
+ "open-output-file or peek-char positive? quasiquote quote quotient "\
+ "rational? rationalize read read-char real-part real? remainder "\
+ "reverse round scheme-report-environment set-car! set-cdr! sin "\
+ "sqrt string->list string->number string->symbol string-append "\
+ "string-ci<=? string-ci<? string-ci=? string-ci>=? "\
+ "string-ci>? string-copy string-fill! string-length string-ref "\
+ "string-set! string<=? string<? string=? string>=? string>? "\
+ "substring symbol->string tan truncate values vector "\
+ "vector->list vector-fill! vector-length vector-ref vector-set! "\
+ "with-input-from-file with-output-to-file write write-char zero?",
+ builtins);
+
+ non_word_chars="[\\s\\(\\)\\[\\]\\{\\};\\|]";
+
+ normal_identifiers="-!$%&\\*\\+\\./:<=>\\?\\^_~a-zA-Z0-9";
+ identifier_chars="[" normal_identifiers "][" normal_identifiers ",#]*";
+ }
+ function add_highlighter(regex, highlight) {
+ printf("add-highlighter shared/scheme/code/ regex \"%s\" %s\n", 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 = non_word_chars "+(" quoted_join(words) ")" non_word_chars
+ add_highlighter(regex, "1:" face)
+ }
+ function print_words(words) {
+ for (i in words) { printf(" %s", words[i]); }
+ }
+
+ BEGIN {
+ printf("hook global WinSetOption filetype=scheme %%{ set-option window 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, "builtin");
+ 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");
+ }
+EOF
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group scheme-highlight global WinSetOption filetype=scheme %{
+ add-highlighter window/scheme ref scheme
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/scheme }
+}
+
+
+hook global WinSetOption filetype=scheme %{
+ set-option buffer extra_word_chars '_' '-' '!' '%' '?' '<' '>' '='
+ hook window InsertEnd .* -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-.+ }
+}
diff --git a/rc/filetype/scss.kak b/rc/filetype/scss.kak
new file mode 100644
index 00000000..bb720db5
--- /dev/null
+++ b/rc/filetype/scss.kak
@@ -0,0 +1,45 @@
+# http://sass-lang.com
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# require css.kak
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](scss) %{
+ set-option buffer filetype scss
+}
+
+# Highlighters
+# ‾‾‾‾‾‾‾‾‾‾‾‾
+
+add-highlighter shared/scss regions
+add-highlighter shared/scss/core default-region group
+add-highlighter shared/scss/comment region // $ fill comment
+
+add-highlighter shared/scss/core/ ref css
+add-highlighter shared/scss/core/ regex @[A-Za-z][A-Za-z0-9_-]* 0:meta
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+define-command -hidden scss-trim-indent css-trim-indent
+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
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group scss-highlight global WinSetOption filetype=scss %{
+ add-highlighter window/scss ref scss
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/scss }
+}
+
+hook global WinSetOption filetype=scss %[
+ hook window ModeChange insert:.* -group scss-trim-indent scss-trim-indent
+ 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-.+ }
+]
diff --git a/rc/filetype/sh.kak b/rc/filetype/sh.kak
new file mode 100644
index 00000000..517f6a18
--- /dev/null
+++ b/rc/filetype/sh.kak
@@ -0,0 +1,43 @@
+hook global BufCreate .*\.(z|ba|c|k|mk)?sh(rc|_profile)? %{
+ set-option buffer filetype sh
+}
+
+add-highlighter shared/sh regions
+add-highlighter shared/sh/code default-region group
+add-highlighter shared/sh/double_string region %{(?<!\\)(?:\\\\)*\K"} %{(?<!\\)(?:\\\\)*"} group
+add-highlighter shared/sh/single_string region %{(?<!\\)(?:\\\\)*\K'} %{'} fill string
+add-highlighter shared/sh/comment region '(?<!\$)(?<!\$\{)#' '$' fill comment
+add-highlighter shared/sh/heredoc region -match-capture '<<-?''?(\w+)''?' '^\t*(\w+)$' fill string
+
+add-highlighter shared/sh/double_string/fill fill string
+
+evaluate-commands %sh{
+ # Grammar
+ keywords="alias bind builtin caller case cd command coproc declare do done
+ echo elif else enable esac exit fi for function help
+ if in let local logout mapfile printf read readarray
+ readonly return select set shift source test then
+ time type typeset ulimit unalias until while break continue"
+
+ 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=sh %{
+ set-option window static_words $(join "${keywords}" ' ')
+ }"
+
+ # Highlight keywords
+ printf %s "add-highlighter shared/sh/code/ regex \b($(join "${keywords}" '|'))\b 0:keyword"
+}
+
+add-highlighter shared/sh/code/operators regex [\[\]\(\)&|]{1,2} 0:operator
+add-highlighter shared/sh/code/variable regex (\w+)= 1:variable
+add-highlighter shared/sh/code/function regex ^\h*(\w+)\h*\(\) 1:function
+
+add-highlighter shared/sh/code/expansion regex \$(\w+|\{.+?\}|#|@|\?|\$|!|-|\*) 0:value
+add-highlighter shared/sh/double_string/expansion regex \$(\w+|\{.+?\}) 0:value
+
+hook -group sh-highlight global WinSetOption filetype=sh %{
+ add-highlighter window/sh ref sh
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/sh }
+}
diff --git a/rc/filetype/sql.kak b/rc/filetype/sql.kak
new file mode 100644
index 00000000..dbecea9c
--- /dev/null
+++ b/rc/filetype/sql.kak
@@ -0,0 +1,107 @@
+# https://www.w3schools.com/sql/default.asp
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*/?(?i)sql %{
+ set-option buffer filetype 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 "hook global WinSetOption filetype=sql %{
+ set-option window 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
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group sql-highlight global WinSetOption filetype=sql %{
+ add-highlighter window/sql ref sql
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/sql }
+}
diff --git a/rc/filetype/swift.kak b/rc/filetype/swift.kak
new file mode 100644
index 00000000..1526cadb
--- /dev/null
+++ b/rc/filetype/swift.kak
@@ -0,0 +1,28 @@
+hook global BufCreate .*\.(swift) %{
+ set-option buffer filetype swift
+}
+
+add-highlighter shared/swift regions
+add-highlighter shared/swift/code default-region group
+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/comment/ regex "\b(TODO|XXX|MARK)\b" 0:red
+
+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|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|public|protected|private|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
+
+hook -group swift-highlight global WinSetOption filetype=swift %{
+ add-highlighter window/swift ref swift
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/swift }
+}
diff --git a/rc/filetype/systemd.kak b/rc/filetype/systemd.kak
new file mode 100644
index 00000000..3810d005
--- /dev/null
+++ b/rc/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/rc/filetype/taskpaper.kak b/rc/filetype/taskpaper.kak
new file mode 100644
index 00000000..dca5de1e
--- /dev/null
+++ b/rc/filetype/taskpaper.kak
@@ -0,0 +1,47 @@
+# https://www.taskpaper.com
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*\.taskpaper %{
+ set-option buffer filetype 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 (([a-z]+://\S+)|((mailto:)[\w+-]+@\S+)) 0:link
+
+# Commands
+# ‾‾‾‾‾‾‾‾
+
+define-command -hidden taskpaper-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # preserve previous line indent
+ try %{ execute-keys -draft \;K<a-&> }
+ ## If the line above is a project indent with a tab
+ try %{ execute-keys -draft Z k<a-x> <a-k>^\h*([^:\n]+):<ret> z i<tab> }
+ # cleanup trailing white spaces on previous line
+ try %{ execute-keys -draft k<a-x> s \h+$ <ret>d }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group taskpaper-highlight global WinSetOption filetype=taskpaper %{
+ add-highlighter window/taskpaper ref taskpaper
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/taskpaper }
+}
+
+hook global WinSetOption filetype=taskpaper %{
+ hook window InsertChar \n -group taskpaper-indent taskpaper-indent-on-new-line
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window taskpaper-.+ }
+}
diff --git a/rc/filetype/toml.kak b/rc/filetype/toml.kak
new file mode 100644
index 00000000..f95fbb9d
--- /dev/null
+++ b/rc/filetype/toml.kak
@@ -0,0 +1,63 @@
+# https://github.com/toml-lang/toml/tree/v0.4.0
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*\.(toml) %{
+ set-option buffer filetype 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 <a-x> s \h+$ <ret> d }
+}
+
+define-command -hidden toml-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # copy comment prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*\K#\h* <ret> y gh j P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; K <a-&> }
+ # filter previous line
+ try %{ execute-keys -draft k : toml-trim-indent <ret> }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group toml-highlight global WinSetOption filetype=toml %{
+ add-highlighter window/toml ref toml
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/toml }
+}
+
+hook global WinSetOption filetype=toml %{
+ hook window ModeChange insert:.* -group toml-trim-indent toml-trim-indent
+ hook window InsertChar \n -group toml-indent toml-indent-on-new-line
+
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window toml-.+ }
+}
diff --git a/rc/filetype/troff.kak b/rc/filetype/troff.kak
new file mode 100644
index 00000000..072cc3d1
--- /dev/null
+++ b/rc/filetype/troff.kak
@@ -0,0 +1,30 @@
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*\.\d+ %{
+ set-option buffer filetype troff
+}
+
+# Highlighters
+# ‾‾‾‾‾‾‾‾‾‾‾‾
+
+add-highlighter shared/troff group
+add-highlighter shared/troff/ regex '\\f[A-Z]' 0:attribute
+add-highlighter shared/troff/ regex '\\fB(.+?)\\f[A-Z]' 1:+b
+add-highlighter shared/troff/ regex '\\fI(.+?)\\f[A-Z]' 1:+i
+
+add-highlighter shared/troff/ regex '^\.[a-zA-Z]{1,2}\b' 0:meta
+add-highlighter shared/troff/ regex '^\.TH\s+[^\n]+' 0:title
+add-highlighter shared/troff/ regex '^\.SH\s+[^\n]+' 0:header
+add-highlighter shared/troff/ regex '^\.IR\s+(\S+)' 1:+i
+add-highlighter shared/troff/ regex '^\.BR\s+(\S+)' 1:+b
+add-highlighter shared/troff/ regex '^\.I\s+([^\n]+)' 1:+i
+add-highlighter shared/troff/ regex '^\.B\s+([^\n]+)' 1:+b
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group troff-highlight global WinSetOption filetype=troff %{
+ add-highlighter window/troff ref troff
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/troff }
+}
diff --git a/rc/filetype/tupfile.kak b/rc/filetype/tupfile.kak
new file mode 100644
index 00000000..e7ba0d52
--- /dev/null
+++ b/rc/filetype/tupfile.kak
@@ -0,0 +1,33 @@
+# http://gittup.org/tup/
+#
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*/?Tup(file|rules)(\.\w+)?$ %{
+ set-option buffer filetype 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
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group tupfile-highlight global WinSetOption filetype=tupfile %{
+ add-highlighter window/tupfile ref tupfile
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/tupfile }
+}
diff --git a/rc/filetype/void-linux.kak b/rc/filetype/void-linux.kak
new file mode 100644
index 00000000..23a02061
--- /dev/null
+++ b/rc/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/rc/filetype/yaml.kak b/rc/filetype/yaml.kak
new file mode 100644
index 00000000..7076e13d
--- /dev/null
+++ b/rc/filetype/yaml.kak
@@ -0,0 +1,58 @@
+# http://yaml.org
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](ya?ml) %{
+ set-option buffer filetype 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 <a-x> s \h+$ <ret> d }
+}
+
+define-command -hidden yaml-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # copy '#' comment prefix and following white spaces
+ try %{ execute-keys -draft k <a-x> s ^\h*\K#\h* <ret> y gh j P }
+ # preserve previous line indent
+ try %{ execute-keys -draft \; K <a-&> }
+ # filter previous line
+ try %{ execute-keys -draft k : yaml-trim-indent <ret> }
+ # indent after :
+ try %{ execute-keys -draft <space> k x <a-k> :$ <ret> j <a-gt> }
+ }
+}
+
+# Initialization
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+hook -group yaml-highlight global WinSetOption filetype=yaml %{
+ add-highlighter window/yaml ref yaml
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/yaml }
+}
+
+hook global WinSetOption filetype=yaml %{
+ hook window ModeChange insert:.* -group yaml-trim-indent yaml-trim-indent
+ hook window InsertChar \n -group yaml-indent yaml-indent-on-new-line
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window yaml-.+ }
+}