From 83277d5545463aa1af37bb3de5221fe28dec5eae Mon Sep 17 00:00:00 2001 From: Simon Fowler Date: Sat, 26 Sep 2020 19:17:59 +1000 Subject: [PATCH] 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. --- rc/filetype/sh.kak | 37 ++++++++++++++--------- test/indent/sh/no-deindent-after-else/cmd | 1 + test/indent/sh/no-deindent-after-else/in | 7 +++++ test/indent/sh/no-deindent-after-else/out | 8 +++++ test/indent/sh/no-deindent-after-else/rc | 3 ++ test/indent/sh/no-deindent-after-fi/cmd | 1 + test/indent/sh/no-deindent-after-fi/in | 7 +++++ test/indent/sh/no-deindent-after-fi/out | 8 +++++ test/indent/sh/no-deindent-after-fi/rc | 3 ++ 9 files changed, 60 insertions(+), 15 deletions(-) create mode 100644 test/indent/sh/no-deindent-after-else/cmd create mode 100644 test/indent/sh/no-deindent-after-else/in create mode 100644 test/indent/sh/no-deindent-after-else/out create mode 100644 test/indent/sh/no-deindent-after-else/rc create mode 100644 test/indent/sh/no-deindent-after-fi/cmd create mode 100644 test/indent/sh/no-deindent-after-fi/in create mode 100644 test/indent/sh/no-deindent-after-fi/out create mode 100644 test/indent/sh/no-deindent-after-fi/rc diff --git a/rc/filetype/sh.kak b/rc/filetype/sh.kak index d2ee6efb..e087d8fb 100644 --- a/rc/filetype/sh.kak +++ b/rc/filetype/sh.kak @@ -17,7 +17,8 @@ hook -group sh-highlight global WinSetOption filetype=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/code default-region group @@ -86,8 +87,13 @@ define-command -hidden sh-insert-on-new-line %[ ] ] -define-command -hidden sh-indent-on-new-line %[ - evaluate-commands -draft -itersel %[ +# 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 %@ # preserve previous line indent try %{ execute-keys -draft K } # filter previous line @@ -113,8 +119,10 @@ define-command -hidden sh-indent-on-new-line %[ # # indent after do try %{ execute-keys -draft k \bdo$ j } - # deindent after done - try %{ execute-keys -draft k \bdone$ K j j K } + # 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 k \bdone$ gh [c\bdo\b,\bdone\b 1 j K } # Indent if/then/else syntax, e.g.: # if [ $foo = $bar ]; then @@ -133,11 +141,10 @@ define-command -hidden sh-indent-on-new-line %[ # # indent after then try %{ execute-keys -draft k \bthen$ j } - # deindent after fi - try %{ execute-keys -draft k \bfi$ K j j K } - # deindent and reindent after else - deindent the else, then back - # down and return to the previous indent level. - try %{ execute-keys -draft k \belse$ j } + # copy the indentation of the matching if + try %{ execute-keys -draft k \bfi$ gh [c\bif\b,\bfi\b 1 j K } + # copy the indentation of the matching if, and then re-indent afterwards + try %{ execute-keys -draft k \belse$ gh [c\bif\b,\bfi\b 1 j K j } # Indent case syntax, e.g.: # case "$foo" in @@ -158,8 +165,8 @@ define-command -hidden sh-indent-on-new-line %[ # # indent after in try %{ execute-keys -draft k \bin$ j } - # deindent after esac - try %{ execute-keys -draft k \besac$ j K } + # copy the indentation of the matching case + try %{ execute-keys -draft k \besac$ gh [c\bcase\b,\besac\b 1 j K } # indent after ) try %{ execute-keys -draft k ^\s*\(?[^(]+[^)]\)$ j } # deindent after ;; @@ -191,7 +198,7 @@ define-command -hidden sh-indent-on-new-line %[ # deindent closing } when after cursor try %= execute-keys -draft ^\h*\} gh / \} m 1 = - ] -] + @ +¶ -] +§ diff --git a/test/indent/sh/no-deindent-after-else/cmd b/test/indent/sh/no-deindent-after-else/cmd new file mode 100644 index 00000000..6e489622 --- /dev/null +++ b/test/indent/sh/no-deindent-after-else/cmd @@ -0,0 +1 @@ +gk3jobaz diff --git a/test/indent/sh/no-deindent-after-else/in b/test/indent/sh/no-deindent-after-else/in new file mode 100644 index 00000000..89687e31 --- /dev/null +++ b/test/indent/sh/no-deindent-after-else/in @@ -0,0 +1,7 @@ +if [ $foo ]; then + if [ $bar ]; then + foobar + else + qux + fi +fi diff --git a/test/indent/sh/no-deindent-after-else/out b/test/indent/sh/no-deindent-after-else/out new file mode 100644 index 00000000..3849d90a --- /dev/null +++ b/test/indent/sh/no-deindent-after-else/out @@ -0,0 +1,8 @@ +if [ $foo ]; then + if [ $bar ]; then + foobar + else + baz + qux + fi +fi diff --git a/test/indent/sh/no-deindent-after-else/rc b/test/indent/sh/no-deindent-after-else/rc new file mode 100644 index 00000000..4795bd80 --- /dev/null +++ b/test/indent/sh/no-deindent-after-else/rc @@ -0,0 +1,3 @@ +source "%val{runtime}/colors/default.kak" +source "%val{runtime}/rc/filetype/sh.kak" +set buffer filetype sh diff --git a/test/indent/sh/no-deindent-after-fi/cmd b/test/indent/sh/no-deindent-after-fi/cmd new file mode 100644 index 00000000..89b4b7a9 --- /dev/null +++ b/test/indent/sh/no-deindent-after-fi/cmd @@ -0,0 +1 @@ +gk5jobaz diff --git a/test/indent/sh/no-deindent-after-fi/in b/test/indent/sh/no-deindent-after-fi/in new file mode 100644 index 00000000..89687e31 --- /dev/null +++ b/test/indent/sh/no-deindent-after-fi/in @@ -0,0 +1,7 @@ +if [ $foo ]; then + if [ $bar ]; then + foobar + else + qux + fi +fi diff --git a/test/indent/sh/no-deindent-after-fi/out b/test/indent/sh/no-deindent-after-fi/out new file mode 100644 index 00000000..14b78e6f --- /dev/null +++ b/test/indent/sh/no-deindent-after-fi/out @@ -0,0 +1,8 @@ +if [ $foo ]; then + if [ $bar ]; then + foobar + else + qux + fi + baz +fi diff --git a/test/indent/sh/no-deindent-after-fi/rc b/test/indent/sh/no-deindent-after-fi/rc new file mode 100644 index 00000000..4795bd80 --- /dev/null +++ b/test/indent/sh/no-deindent-after-fi/rc @@ -0,0 +1,3 @@ +source "%val{runtime}/colors/default.kak" +source "%val{runtime}/rc/filetype/sh.kak" +set buffer filetype sh