From c0dccdd90dd615cf663d95fd94fbdbdf2a88b165 Mon Sep 17 00:00:00 2001 From: Alex Leferry 2 Date: Mon, 18 Mar 2019 19:56:34 +0100 Subject: Add categories in rc/ Closes #2783 --- rc/filetype/ruby.kak | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 rc/filetype/ruby.kak (limited to 'rc/filetype/ruby.kak') 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 ':"' (? 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 + # remove trailing white spaces + try %{ execute-keys -draft s \h + $ 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 ^ \h * (else|elsif) $ ^ \h * (if) s \A | \z ) } + try %{ execute-keys -draft ^ \h * (when) $ ^ \h * (case) s \A | \z ) } + try %{ execute-keys -draft ^ \h * (rescue) $ ^ \h * (begin) s \A | \z ) } + try %{ execute-keys -draft ^ \h * (end) $ ^ \h * (begin|case|class|def|do|for|if|module|unless|until|while) s \A | \z ) } + } +} + +define-command -hidden ruby-indent-on-new-line %{ + evaluate-commands -no-hooks -draft -itersel %{ + # preserve previous line indent + try %{ execute-keys -draft K } + # filter previous line + try %{ execute-keys -draft k : ruby-trim-indent } + # indent after start structure + try %{ execute-keys -draft k ^ \h * (begin|case|class|def|do|else|elsif|ensure|for|if|module|rescue|unless|until|when|while) \b j } + } +} + +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 s '^\h*\K#\h*' y gh j P } + # wisely add end structure + evaluate-commands -save-regs x %[ + try %{ execute-keys -draft k s ^ \h + \" x y } catch %{ reg x '' } + try %[ + evaluate-commands -draft %[ + execute-keys -draft k ^x(begin|case|class|def|do|for|if|module|unless|until|while) # 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(^\n|^x(?!begin)(?!case)(?!class)(?!def)(?!do)(?!for)(?!if)(?!module)(?!unless)(?!until)(?!while)[^\n]*\n)+xend$ + ] + execute-keys -draft oxend # 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 + } +} -- cgit v1.2.3