From: Moumita Dhar <dhar61595@xxxxxxxxx> The previous function regex required explicit matching of function bodies using `{`, `(`, `((`, or `[[`, which caused several issues: - It failed to capture valid functions where `{` was on the next line due to line continuation (`\`). - It did not recognize functions with single command body, such as `x () echo hello`. Replacing the function body matching logic with `.*$`, ensures that everything on the function definition line is captured. Additionally, the word regex is refined to better recognize shell syntax, including additional parameter expansion operators and command-line options. Signed-off-by: Moumita Dhar <dhar61595@xxxxxxxxx> --- t/t4018/bash-bashism-style-multiline-function | 4 ++ .../bash-hunk-header-complete-line-capture | 4 ++ t/t4018/bash-posix-style-multiline-function | 4 ++ .../bash-posix-style-single-command-function | 3 ++ t/t4034-diff-words.sh | 1 + t/t4034/bash/expect | 38 +++++++++++++++++++ t/t4034/bash/post | 33 ++++++++++++++++ t/t4034/bash/pre | 33 ++++++++++++++++ userdiff.c | 28 ++++++++++---- 9 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 t/t4018/bash-bashism-style-multiline-function create mode 100644 t/t4018/bash-hunk-header-complete-line-capture create mode 100644 t/t4018/bash-posix-style-multiline-function create mode 100644 t/t4018/bash-posix-style-single-command-function create mode 100644 t/t4034/bash/expect create mode 100644 t/t4034/bash/post create mode 100644 t/t4034/bash/pre diff --git a/t/t4018/bash-bashism-style-multiline-function b/t/t4018/bash-bashism-style-multiline-function new file mode 100644 index 0000000000..284d50dd99 --- /dev/null +++ b/t/t4018/bash-bashism-style-multiline-function @@ -0,0 +1,4 @@ +function RIGHT \ +{ + echo 'ChangeMe' +} diff --git a/t/t4018/bash-hunk-header-complete-line-capture b/t/t4018/bash-hunk-header-complete-line-capture new file mode 100644 index 0000000000..818c8c5a5f --- /dev/null +++ b/t/t4018/bash-hunk-header-complete-line-capture @@ -0,0 +1,4 @@ +func() { # RIGHT + + ChangeMe +} \ No newline at end of file diff --git a/t/t4018/bash-posix-style-multiline-function b/t/t4018/bash-posix-style-multiline-function new file mode 100644 index 0000000000..cc8727cbcd --- /dev/null +++ b/t/t4018/bash-posix-style-multiline-function @@ -0,0 +1,4 @@ +RIGHT() \ +{ + ChangeMe +} diff --git a/t/t4018/bash-posix-style-single-command-function b/t/t4018/bash-posix-style-single-command-function new file mode 100644 index 0000000000..398ae1c5d2 --- /dev/null +++ b/t/t4018/bash-posix-style-single-command-function @@ -0,0 +1,3 @@ +RIGHT() echo "hello" + + ChangeMe diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh index f51d3557f1..0be647c2fb 100755 --- a/t/t4034-diff-words.sh +++ b/t/t4034-diff-words.sh @@ -320,6 +320,7 @@ test_expect_success 'unset default driver' ' test_language_driver ada test_language_driver bibtex +test_language_driver bash test_language_driver cpp test_language_driver csharp test_language_driver css diff --git a/t/t4034/bash/expect b/t/t4034/bash/expect new file mode 100644 index 0000000000..17755e455f --- /dev/null +++ b/t/t4034/bash/expect @@ -0,0 +1,38 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index 09ac008..60ba6a2 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -1,33 +1,33 @@<RESET> +<RED>my_var<RESET><GREEN>new_var<RESET>=10 +x=<RED>123<RESET><GREEN>456<RESET> +y=<RED>3.14<RESET><GREEN>2.71<RESET> +z=<RED>.5<RESET><GREEN>.75<RESET> +echo <RED>$USER<RESET><GREEN>$USERNAME<RESET> +${<RED>HOME<RESET><GREEN>HOMEDIR<RESET>} +((a<RED>+<RESET><GREEN>+=<RESET>b)) +((a<RED>*<RESET><GREEN>*=<RESET>b)) +((a<RED>/<RESET><GREEN>/=<RESET>b)) +((a<RED>%<RESET><GREEN>%=<RESET>b)) +((a<RED>|<RESET><GREEN>|=<RESET>b)) +((a<RED>^<RESET><GREEN>^=<RESET>b)) +((a<RED>=<RESET><GREEN>==<RESET>b)) +((a<RED>!<RESET><GREEN>!=<RESET>b)) +((a<RED><<RESET><GREEN><=<RESET>b)) +((a<RED>><RESET><GREEN>>=<RESET>b)) +$((a<RED><<RESET><GREEN><<<RESET>b)) +$((a<RED>><RESET><GREEN>>><RESET>b)) +$((a<RED>&<RESET><GREEN>&&<RESET>b)) +$((a<RED>|<RESET><GREEN>||<RESET>b)) +${a<RED>:<RESET><GREEN>:-<RESET>b} +${a<RED>:<RESET><GREEN>:=<RESET>b} +${a<RED>:<RESET><GREEN>:+<RESET>b} +${a<RED>:<RESET><GREEN>:?<RESET>b} +${a<RED>#<RESET><GREEN>##<RESET>*/} +${a<RED>%<RESET><GREEN>%%<RESET>.*} +${a<RED>^<RESET><GREEN>^^<RESET>} +${a<RED>,<RESET><GREEN>,,<RESET>} +${<GREEN>!<RESET>a} +${a[<RED>*<RESET><GREEN>@<RESET>]} +${a<RED>:2:3<RESET><GREEN>:4:6<RESET>} +ls <RED>-a<RESET><GREEN>-x<RESET> +ls <RED>--a<RESET><GREEN>--x<RESET> diff --git a/t/t4034/bash/post b/t/t4034/bash/post new file mode 100644 index 0000000000..669e218c30 --- /dev/null +++ b/t/t4034/bash/post @@ -0,0 +1,33 @@ +new_var=10 +x=456 +y=2.71 +z=.75 +echo $USERNAME +${HOMEDIR} +((a+=b)) +((a*=b)) +((a/=b)) +((a%=b)) +((a|=b)) +((a^=b)) +((a==b)) +((a!=b)) +((a<=b)) +((a>=b)) +$((a<<b)) +$((a>>b)) +$((a&&b)) +$((a||b)) +${a:-b} +${a:=b} +${a:+b} +${a:?b} +${a##*/} +${a%%.*} +${a^^} +${a,,} +${!a} +${a[@]} +${a:4:6} +ls -x +ls --x diff --git a/t/t4034/bash/pre b/t/t4034/bash/pre new file mode 100644 index 0000000000..ada8470bac --- /dev/null +++ b/t/t4034/bash/pre @@ -0,0 +1,33 @@ +my_var=10 +x=123 +y=3.14 +z=.5 +echo $USER +${HOME} +((a+b)) +((a*b)) +((a/b)) +((a%b)) +((a|b)) +((a^b)) +((a=b)) +((a!b)) +((a<b)) +((a>b)) +$((a<b)) +$((a>b)) +$((a&b)) +$((a|b)) +${a:b} +${a:b} +${a:b} +${a:b} +${a#*/} +${a%.*} +${a^} +${a,} +${a} +${a[*]} +${a:2:3} +ls -a +ls --a diff --git a/userdiff.c b/userdiff.c index 340c4eb4f7..655c8fe0b1 100644 --- a/userdiff.c +++ b/userdiff.c @@ -59,20 +59,32 @@ PATTERNS("bash", "(" "(" /* POSIX identifier with mandatory parentheses */ - "[a-zA-Z_][a-zA-Z0-9_]*[ \t]*\\([ \t]*\\))" + "([a-zA-Z_][a-zA-Z0-9_]*[ \t]*\\([ \t]*\\))" "|" /* Bashism identifier with optional parentheses */ - "(function[ \t]+[a-zA-Z_][a-zA-Z0-9_]*(([ \t]*\\([ \t]*\\))|([ \t]+))" + "(function[ \t]+[a-zA-Z_][a-zA-Z0-9_]*(([ \t]*\\([ \t]*\\))|([ \t]+)))" ")" - /* Optional whitespace */ - "[ \t]*" - /* Compound command starting with `{`, `(`, `((` or `[[` */ - "(\\{|\\(\\(?|\\[\\[)" + /* Everything after the function header is captured */ + ".*$" /* End of captured text */ ")", /* -- */ - /* Characters not in the default $IFS value */ - "[^ \t]+"), + /* Identifiers: variable and function names */ + "[a-zA-Z_][a-zA-Z0-9_]*" + /* Numeric constants: integers and decimals */ + "|[0-9]+(\\.[0-9]*)?|[-+]?\\.[0-9]+" + /* Shell variables: $VAR, ${VAR} */ + "|\\$[a-zA-Z_][a-zA-Z0-9_]*|\\$\\{" + /* Logical and comparison operators */ + "|\\|\\||&&|<<|>>|==|!=|<=|>=" + /* Assignment and arithmetic operators */ + "|[-+*/%&|^!=<>]=?" + /* Additional parameter expansion operators */ + "|:?=|:-|:\\+|:\\?|:|#|##|%|%%|\\^\\^?|,|,,?|!|@|:[0-9]+(:[0-9]+)?" + /* Command-line options (to avoid splitting -option) */ + "|--?[a-zA-Z0-9_-]+" + /* Brackets and grouping symbols */ + "|\\(|\\)|\\{|\\}|\\[|\\]"), PATTERNS("bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$", /* -- */ -- 2.48.0