Improve shell indentation implementation.

Use the custom object match command for copying indentation of blocks,
rather than simply increasing/decreasing indentation when start and end
statements are encountered.

This fixes an issue where a newline added after an already correctly
placed `else` or `fi` would trigger an unnecessary deindent. Tests have
been added to ensure no regression in this behaviour.
This commit is contained in:
Simon Fowler 2020-09-26 19:17:59 +10:00
parent dd1a582b30
commit 83277d5545
9 changed files with 60 additions and 15 deletions

View File

@ -17,7 +17,8 @@ hook -group sh-highlight global WinSetOption filetype=sh %{
hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/sh } hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/sh }
} }
provide-module sh %[ # using non-ascii characters here so that we can use the '[' command
provide-module sh %§
add-highlighter shared/sh regions add-highlighter shared/sh regions
add-highlighter shared/sh/code default-region group add-highlighter shared/sh/code default-region group
@ -86,8 +87,13 @@ define-command -hidden sh-insert-on-new-line %[
] ]
] ]
define-command -hidden sh-indent-on-new-line %[ # Use custom object matching to copy indentation for the various logical
evaluate-commands -draft -itersel %[ # 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 %@
# preserve previous line indent # preserve previous line indent
try %{ execute-keys -draft <semicolon> K <a-&> } try %{ execute-keys -draft <semicolon> K <a-&> }
# filter previous line # filter previous line
@ -113,8 +119,10 @@ define-command -hidden sh-indent-on-new-line %[
# #
# indent after do # indent after do
try %{ execute-keys -draft <space> k <a-x> <a-k> \bdo$ <ret> j <a-gt> } try %{ execute-keys -draft <space> k <a-x> <a-k> \bdo$ <ret> j <a-gt> }
# deindent after done # copy the indentation of the matching for/when - matching on the do
try %{ execute-keys -draft <space> k <a-x> <a-k> \bdone$ <ret> K <a-&> j <a-lt> j K <a-&> } # 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-&> }
# Indent if/then/else syntax, e.g.: # Indent if/then/else syntax, e.g.:
# if [ $foo = $bar ]; then # if [ $foo = $bar ]; then
@ -133,11 +141,10 @@ define-command -hidden sh-indent-on-new-line %[
# #
# indent after then # indent after then
try %{ execute-keys -draft <space> k <a-x> <a-k> \bthen$ <ret> j <a-gt> } try %{ execute-keys -draft <space> k <a-x> <a-k> \bthen$ <ret> j <a-gt> }
# deindent after fi # copy the indentation of the matching if
try %{ execute-keys -draft <space> k <a-x> <a-k> \bfi$ <ret> K <a-&> j <a-lt> j K <a-&> } 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-&> }
# deindent and reindent after else - deindent the else, then back # copy the indentation of the matching if, and then re-indent afterwards
# down and return to the previous indent level. 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> }
try %{ execute-keys -draft <space> k <a-x> <a-k> \belse$ <ret> <a-lt> j }
# Indent case syntax, e.g.: # Indent case syntax, e.g.:
# case "$foo" in # case "$foo" in
@ -158,8 +165,8 @@ define-command -hidden sh-indent-on-new-line %[
# #
# indent after in # indent after in
try %{ execute-keys -draft <space> k <a-x> <a-k> \bin$ <ret> j <a-gt> } try %{ execute-keys -draft <space> k <a-x> <a-k> \bin$ <ret> j <a-gt> }
# deindent after esac # copy the indentation of the matching case
try %{ execute-keys -draft <space> k <a-x> <a-k> \besac$ <ret> <a-lt> j K <a-&> } 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-&> }
# indent after ) # indent after )
try %{ execute-keys -draft <space> k <a-x> <a-k> ^\s*\(?[^(]+[^)]\)$ <ret> j <a-gt> } try %{ execute-keys -draft <space> k <a-x> <a-k> ^\s*\(?[^(]+[^)]\)$ <ret> j <a-gt> }
# deindent after ;; # deindent after ;;
@ -191,7 +198,7 @@ define-command -hidden sh-indent-on-new-line %[
# deindent closing } when after cursor # deindent closing } when after cursor
try %= execute-keys -draft <a-x> <a-k> ^\h*\} <ret> gh / \} <ret> m <a-S> 1<a-&> = try %= execute-keys -draft <a-x> <a-k> ^\h*\} <ret> gh / \} <ret> m <a-S> 1<a-&> =
] @
]
] §

View File

@ -0,0 +1 @@
gk3jobaz

View File

@ -0,0 +1,7 @@
if [ $foo ]; then
if [ $bar ]; then
foobar
else
qux
fi
fi

View File

@ -0,0 +1,8 @@
if [ $foo ]; then
if [ $bar ]; then
foobar
else
baz
qux
fi
fi

View File

@ -0,0 +1,3 @@
source "%val{runtime}/colors/default.kak"
source "%val{runtime}/rc/filetype/sh.kak"
set buffer filetype sh

View File

@ -0,0 +1 @@
gk5jobaz

View File

@ -0,0 +1,7 @@
if [ $foo ]; then
if [ $bar ]; then
foobar
else
qux
fi
fi

View File

@ -0,0 +1,8 @@
if [ $foo ]; then
if [ $bar ]; then
foobar
else
qux
fi
baz
fi

View File

@ -0,0 +1,3 @@
source "%val{runtime}/colors/default.kak"
source "%val{runtime}/rc/filetype/sh.kak"
set buffer filetype sh