2020-11-01 09:59:55 +01:00
|
|
|
hook global BufCreate .*\.((z|ba|c|k|mk)?sh(rc|_profile)?|profile) %{
|
2017-11-03 08:34:41 +01:00
|
|
|
set-option buffer filetype sh
|
2013-01-08 14:01:22 +01:00
|
|
|
}
|
|
|
|
|
2019-04-10 05:54:19 +02:00
|
|
|
hook global WinSetOption filetype=sh %{
|
2019-03-13 06:24:33 +01:00
|
|
|
require-module sh
|
2019-04-10 05:54:19 +02:00
|
|
|
set-option window static_words %opt{sh_static_words}
|
2019-06-20 03:19:39 +02:00
|
|
|
|
2019-10-16 11:19:43 +02:00
|
|
|
hook window ModeChange pop:insert:.* -group sh-trim-indent sh-trim-indent
|
2020-08-15 05:42:52 +02:00
|
|
|
hook window InsertChar \n -group sh-insert sh-insert-on-new-line
|
2019-06-29 04:34:14 +02:00
|
|
|
hook window InsertChar \n -group sh-indent sh-indent-on-new-line
|
2019-06-20 03:19:39 +02:00
|
|
|
hook -once -always window WinSetOption filetype=.* %{ remove-hooks window sh-.+ }
|
2019-04-10 05:54:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
hook -group sh-highlight global WinSetOption filetype=sh %{
|
|
|
|
add-highlighter window/sh ref sh
|
|
|
|
hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/sh }
|
2019-03-13 06:24:33 +01:00
|
|
|
}
|
|
|
|
|
2020-09-26 11:17:59 +02:00
|
|
|
# using non-ascii characters here so that we can use the '[' command
|
|
|
|
provide-module sh %§
|
2019-03-13 06:24:33 +01:00
|
|
|
|
2018-06-28 11:50:23 +02:00
|
|
|
add-highlighter shared/sh regions
|
|
|
|
add-highlighter shared/sh/code default-region group
|
2020-11-14 09:54:25 +01:00
|
|
|
add-highlighter shared/sh/arithmetic region -recurse \(.*?\( (\$|(?<=for)\h*)\(\( \)\) group
|
2018-07-02 12:59:12 +02:00
|
|
|
add-highlighter shared/sh/double_string region %{(?<!\\)(?:\\\\)*\K"} %{(?<!\\)(?:\\\\)*"} group
|
|
|
|
add-highlighter shared/sh/single_string region %{(?<!\\)(?:\\\\)*\K'} %{'} fill string
|
2020-09-05 07:36:31 +02:00
|
|
|
add-highlighter shared/sh/expansion region -recurse (?<!\\)(?:\\\\)*\K\$\{ (?<!\\)(?:\\\\)*\K\$\{ \}|\n fill value
|
2020-07-18 23:18:07 +02:00
|
|
|
add-highlighter shared/sh/comment region (?<!\\)(?:\\\\)*(?:^|\h)\K# '$' fill comment
|
2020-05-16 22:07:29 +02:00
|
|
|
add-highlighter shared/sh/heredoc region -match-capture '<<-?\h*''?(\w+)''?' '^\t*(\w+)$' fill string
|
2014-06-12 22:52:23 +02:00
|
|
|
|
2020-11-14 09:54:25 +01:00
|
|
|
add-highlighter shared/sh/arithmetic/expansion ref sh/double_string/expansion
|
2018-06-25 14:04:33 +02:00
|
|
|
add-highlighter shared/sh/double_string/fill fill string
|
2014-06-12 22:52:23 +02:00
|
|
|
|
2018-05-06 23:29:52 +02:00
|
|
|
evaluate-commands %sh{
|
2016-03-14 13:08:51 +01:00
|
|
|
# Grammar
|
2020-01-12 11:35:56 +01:00
|
|
|
# Generated with `compgen -k` in bash
|
|
|
|
keywords="if then else elif fi case esac for select while until do done in
|
|
|
|
function time coproc"
|
2018-06-28 11:50:23 +02:00
|
|
|
|
2020-01-12 11:35:56 +01:00
|
|
|
# Generated with `compgen -b` in bash
|
|
|
|
builtins="alias bg bind break builtin caller cd command compgen complete
|
|
|
|
compopt continue declare dirs disown echo enable eval exec
|
|
|
|
exit export false fc fg getopts hash help history jobs kill
|
|
|
|
let local logout mapfile popd printf pushd pwd read readarray
|
|
|
|
readonly return set shift shopt source suspend test times trap
|
|
|
|
true type typeset ulimit umask unalias unset wait"
|
|
|
|
|
2020-01-13 17:51:18 +01:00
|
|
|
join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; }
|
2020-01-12 11:35:56 +01:00
|
|
|
|
|
|
|
# Add the language's grammar to the static completion list
|
2020-01-13 17:51:18 +01:00
|
|
|
printf %s\\n "declare-option str-list sh_static_words $(join "${keywords}" ' ') $(join "${builtins}" ' ')"
|
|
|
|
|
|
|
|
# Highlight keywords
|
2020-02-03 21:34:36 +01:00
|
|
|
printf %s\\n "add-highlighter shared/sh/code/ regex (?<!-)\b($(join "${keywords}" '|'))\b(?!-) 0:keyword"
|
2020-01-12 11:35:56 +01:00
|
|
|
|
|
|
|
# Highlight builtins
|
2020-02-03 21:34:36 +01:00
|
|
|
printf %s "add-highlighter shared/sh/code/builtin regex (?<!-)\b($(join "${builtins}" '|'))\b(?!-) 0:builtin"
|
2016-03-14 13:08:51 +01:00
|
|
|
}
|
|
|
|
|
2018-06-25 14:04:33 +02:00
|
|
|
add-highlighter shared/sh/code/operators regex [\[\]\(\)&|]{1,2} 0:operator
|
2020-02-03 19:33:27 +01:00
|
|
|
add-highlighter shared/sh/code/variable regex ((?<![-:])\b\w+)= 1:variable
|
2020-02-03 19:59:46 +01:00
|
|
|
add-highlighter shared/sh/code/alias regex \balias(\h+[-+]\w)*\h+([\w-.]+)= 2:variable
|
2021-11-18 17:51:53 +01:00
|
|
|
add-highlighter shared/sh/code/function regex ^\h*(\S+(?<!=))\h*\(\) 1:function
|
2014-06-12 22:52:23 +02:00
|
|
|
|
2020-09-05 07:36:31 +02:00
|
|
|
add-highlighter shared/sh/code/unscoped_expansion regex (?<!\\)(?:\\\\)*\K\$(\w+|#|@|\?|\$|!|-|\*) 0:value
|
2020-11-14 09:57:23 +01:00
|
|
|
add-highlighter shared/sh/double_string/expansion regex (?<!\\)(?:\\\\)*\K\$(\w+|#|@|\?|\$|!|-|\*|\{.+?\}) 0:value
|
2013-01-08 14:01:22 +01:00
|
|
|
|
2019-06-20 03:19:39 +02:00
|
|
|
# Commands
|
|
|
|
# ‾‾‾‾‾‾‾‾
|
|
|
|
|
|
|
|
define-command -hidden sh-trim-indent %{
|
|
|
|
# remove trailing white spaces
|
|
|
|
try %{ execute-keys -draft -itersel <a-x> s \h+$ <ret> d }
|
|
|
|
}
|
|
|
|
|
|
|
|
# This is at best an approximation, since shell syntax is very complex.
|
|
|
|
# Also note that this targets plain sh syntax, not bash - bash adds a whole
|
|
|
|
# other level of complexity. If your bash code is fairly portable this will
|
|
|
|
# probably work.
|
|
|
|
#
|
|
|
|
# Of necessity, this is also fairly opinionated about indentation styles.
|
|
|
|
# Doing it "properly" would require far more context awareness than we can
|
|
|
|
# bring to this kind of thing.
|
2020-08-15 05:42:52 +02:00
|
|
|
define-command -hidden sh-insert-on-new-line %[
|
2019-06-20 03:19:39 +02:00
|
|
|
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 }
|
2020-08-15 05:42:52 +02:00
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2020-09-26 11:17:59 +02:00
|
|
|
# Use custom object matching to copy indentation for the various logical
|
|
|
|
# blocks.
|
|
|
|
#
|
|
|
|
# Note that we're using a weird non-ascii character instead of [ or { here
|
|
|
|
# because the '[' and '{' characters need to be available for the commands.
|
|
|
|
define-command -hidden sh-indent-on-new-line %¶
|
|
|
|
evaluate-commands -draft -itersel %@
|
2019-06-20 03:19:39 +02:00
|
|
|
# preserve previous line indent
|
2019-10-22 11:02:06 +02:00
|
|
|
try %{ execute-keys -draft <semicolon> K <a-&> }
|
2019-06-20 03:19:39 +02:00
|
|
|
# filter previous line
|
|
|
|
try %{ execute-keys -draft k : sh-trim-indent <ret> }
|
|
|
|
|
|
|
|
# Indent loop syntax, e.g.:
|
|
|
|
# for foo in bar; do
|
|
|
|
# things
|
|
|
|
# done
|
|
|
|
#
|
|
|
|
# or:
|
|
|
|
#
|
|
|
|
# while foo; do
|
|
|
|
# things
|
|
|
|
# done
|
|
|
|
#
|
|
|
|
# or equivalently:
|
|
|
|
#
|
|
|
|
# while foo
|
|
|
|
# do
|
|
|
|
# things
|
|
|
|
# done
|
|
|
|
#
|
|
|
|
# indent after do
|
2020-08-12 00:30:01 +02:00
|
|
|
try %{ execute-keys -draft <space> k <a-x> <a-k> \bdo$ <ret> j <a-gt> }
|
2020-09-26 11:17:59 +02:00
|
|
|
# copy the indentation of the matching for/when - matching on the do
|
|
|
|
# statement, so we don't need to duplicate this for the two loop
|
|
|
|
# structures.
|
|
|
|
try %{ execute-keys -draft <space> k <a-x> <a-k> \bdone$ <ret> gh [c\bdo\b,\bdone\b <ret> <a-x> <a-S> 1<a-&> <space> j K <a-&> }
|
2019-06-20 03:19:39 +02:00
|
|
|
|
|
|
|
# Indent if/then/else syntax, e.g.:
|
|
|
|
# if [ $foo = $bar ]; then
|
|
|
|
# things
|
|
|
|
# else
|
|
|
|
# other_things
|
|
|
|
# fi
|
|
|
|
#
|
|
|
|
# or equivalently:
|
|
|
|
# if [ $foo = $bar ]
|
|
|
|
# then
|
|
|
|
# things
|
|
|
|
# else
|
|
|
|
# other_things
|
|
|
|
# fi
|
|
|
|
#
|
|
|
|
# indent after then
|
2020-08-12 00:30:01 +02:00
|
|
|
try %{ execute-keys -draft <space> k <a-x> <a-k> \bthen$ <ret> j <a-gt> }
|
2020-09-26 11:17:59 +02:00
|
|
|
# copy the indentation of the matching if
|
|
|
|
try %{ execute-keys -draft <space> k <a-x> <a-k> \bfi$ <ret> gh [c\bif\b,\bfi\b <ret> <a-x> <a-S> 1<a-&> <space> j K <a-&> }
|
|
|
|
# copy the indentation of the matching if, and then re-indent afterwards
|
|
|
|
try %{ execute-keys -draft <space> k <a-x> <a-k> \belse$ <ret> gh [c\bif\b,\bfi\b <ret> <a-x> <a-S> 1<a-&> <space> j K <a-&> j <a-gt> }
|
2019-06-20 03:19:39 +02:00
|
|
|
|
|
|
|
# Indent case syntax, e.g.:
|
|
|
|
# case "$foo" in
|
|
|
|
# bar) thing1;;
|
|
|
|
# baz)
|
|
|
|
# things
|
|
|
|
# ;;
|
|
|
|
# *)
|
|
|
|
# default_things
|
|
|
|
# ;;
|
|
|
|
# esac
|
|
|
|
#
|
|
|
|
# or equivalently:
|
|
|
|
# case "$foo"
|
|
|
|
# in
|
|
|
|
# bar) thing1;;
|
|
|
|
# esac
|
|
|
|
#
|
|
|
|
# indent after in
|
2020-08-12 00:30:01 +02:00
|
|
|
try %{ execute-keys -draft <space> k <a-x> <a-k> \bin$ <ret> j <a-gt> }
|
2020-09-26 11:17:59 +02:00
|
|
|
# copy the indentation of the matching case
|
|
|
|
try %{ execute-keys -draft <space> k <a-x> <a-k> \besac$ <ret> gh [c\bcase\b,\besac\b <ret> <a-x> <a-S> 1<a-&> <space> j K <a-&> }
|
2019-06-20 03:19:39 +02:00
|
|
|
# indent after )
|
|
|
|
try %{ execute-keys -draft <space> k <a-x> <a-k> ^\s*\(?[^(]+[^)]\)$ <ret> j <a-gt> }
|
|
|
|
# deindent after ;;
|
|
|
|
try %{ execute-keys -draft <space> k <a-x> <a-k> ^\s*\;\;$ <ret> j <a-lt> }
|
|
|
|
|
|
|
|
# Indent compound commands as logical blocks, e.g.:
|
|
|
|
# {
|
|
|
|
# thing1
|
|
|
|
# thing2
|
|
|
|
# }
|
|
|
|
#
|
|
|
|
# or in a function definition:
|
|
|
|
# foo () {
|
|
|
|
# thing1
|
|
|
|
# thing2
|
|
|
|
# }
|
|
|
|
#
|
|
|
|
# We don't handle () delimited compond commands - these are technically very
|
|
|
|
# similar, but the use cases are quite different and much less common.
|
|
|
|
#
|
|
|
|
# Note that in this context the '{' and '}' characters are reserved
|
|
|
|
# words, and hence must be surrounded by a token separator - typically
|
|
|
|
# white space (including a newline), though technically it can also be
|
|
|
|
# ';'. Only vertical white space makes sense in this context, though,
|
|
|
|
# since the syntax denotes a logical block, not a simple compound command.
|
|
|
|
try %= execute-keys -draft <space> k <a-x> <a-k> (\s|^)\{$ <ret> j <a-gt> =
|
|
|
|
# deindent closing }
|
|
|
|
try %= execute-keys -draft <space> k <a-x> <a-k> ^\s*\}$ <ret> <a-lt> j K <a-&> =
|
2020-07-30 05:31:21 +02:00
|
|
|
# deindent closing } when after cursor
|
|
|
|
try %= execute-keys -draft <a-x> <a-k> ^\h*\} <ret> gh / \} <ret> m <a-S> 1<a-&> =
|
2019-06-20 03:19:39 +02:00
|
|
|
|
2020-09-26 11:17:59 +02:00
|
|
|
@
|
|
|
|
¶
|
2019-06-20 03:19:39 +02:00
|
|
|
|
2020-09-26 11:17:59 +02:00
|
|
|
§
|