diff --git a/rc/filetype/fennel.kak b/rc/filetype/fennel.kak new file mode 100644 index 000000000..e6d604fe6 --- /dev/null +++ b/rc/filetype/fennel.kak @@ -0,0 +1,109 @@ +# http://fennel-lang.org +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.]fnl %{ + set-option buffer filetype fennel +} + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +hook global WinSetOption filetype=fennel %{ + require-module fennel + fennel-configure-window +} + +hook -group fennel-highlight global WinSetOption filetype=fennel %{ + add-highlighter window/fennel ref fennel + hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/fennel } +} + +provide-module fennel %{ + +require-module lisp + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +add-highlighter shared/fennel regions +add-highlighter shared/fennel/code default-region group +add-highlighter shared/fennel/comment region '(?]' '(?![-\w?\\^_!$%&*+./@|<=>])' fill keyword +add-highlighter shared/fennel/code/ regex \\(?:space|tab|newline|return|backspace|formfeed|u[0-9a-fA-F]{4}|o[0-3]?[0-7]{1,2}|.)\b 0:string + +evaluate-commands %sh{ + # Grammar + keywords="require-macros eval-compiler doc lua hashfn macro macros import-macros pick-args pick-values macroexpand macrodebug + do values if when each for fn lambda λ partial while set global var local let tset set-forcibly! doto match or and + not not= collect icollect rshift lshift bor band bnot bxor with-open" + re_keywords='\\$ \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9 \\$\\.\\.\\.' + builtins="_G _VERSION arg assert bit32 collectgarbage coroutine debug + dofile error getfenv getmetatable io ipairs length load + loadfile loadstring math next os package pairs pcall + print rawequal rawget rawlen rawset require select setfenv + setmetatable string table tonumber tostring type unpack xpcall" + + join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; } + +# Add the language's grammar to the static completion list + printf %s\\n "declare-option str-list fennel_static_words $(join "${keywords} ${builtins} false nil true" ' ')" + + # Highlight keywords + printf %s " + add-highlighter shared/fennel/code/keywords regex \b($(join "${keywords} ${re_keywords}" '|'))\b 0:keyword + add-highlighter shared/fennel/code/builtins regex \b($(join "${builtins}" '|'))\b 0:builtin + " +} + +add-highlighter shared/fennel/code/operator regex (\.|\?\.|\+|\.\.|\^|-|\*|%|/|>|<|>=|<=|=|\.\.\.|:|->|->>|-\?>|-\?>>) 0:operator +add-highlighter shared/fennel/code/value regex \b(false|nil|true|[0-9]+(:?\.[0-9])?(:?[eE]-?[0-9]+)?|0x[0-9a-fA-F])\b 0:value +add-highlighter shared/fennel/code/function_declaration regex \((?:fn|lambda|λ)\s+([\S]+) 1:function +add-highlighter shared/fennel/code/method_call regex (?:\w+|\$[0-9]{0,1}):(\S+)\b 1:function + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden fennel-configure-window %{ + set-option window static_words %opt{fennel_static_words} + + hook window ModeChange pop:insert:.* -group fennel-trim-indent fennel-trim-indent + hook window InsertChar \n -group fennel-indent fennel-indent-on-new-line + + set-option buffer extra_word_chars '_' . / * ? + - < > ! : "'" + hook -once -always window WinSetOption filetype=.* %{ remove-hooks window fennel-.+ } +} + +define-command -hidden fennel-trim-indent lisp-trim-indent + +declare-option \ + -docstring 'regex matching the head of forms which have options *and* indented bodies' \ + regex fennel_special_indent_forms \ + '(?:if|when|each|for|fn|lambda|λ|partial|while|local|var|doto|let)' + +define-command -hidden fennel-indent-on-new-line %{ + # registers: i = best align point so far; w = start of first word of form + evaluate-commands -draft -save-regs '/"|^@iw' -itersel %{ + execute-keys -draft 'gk"iZ' + try %{ + execute-keys -draft '[bl"i"wZ' + + try %{ + # If a special form, indent another (indentwidth - 1) spaces + execute-keys -draft '"wze[\s()\[\]\{\}]\A' %opt{fennel_special_indent_forms} '\z' + execute-keys -draft '"wzes.{' %sh{printf $(( kak_opt_indentwidth - 1 ))} '}\K.*;"i' + } catch %{ + # If not special and parameter appears on line 1, indent to parameter + execute-keys -draft '"wz[()[\]{}]e[\s()\[\]\{\}]s\h\K[^\s].*;"i' + } + } + try %{ execute-keys -draft '[rl"i' } + try %{ execute-keys -draft '[Bl"i' } + execute-keys -draft ';"ia&' + } +} + +}