userdiff: extend Bash pattern to cover more shell function forms

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@gmail.com>
Acked-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Moumita Dhar
2025-05-16 20:15:12 +05:30
committed by Junio C Hamano
parent cb96e1697a
commit ea8a71b40d
8 changed files with 128 additions and 8 deletions

View File

@@ -0,0 +1,4 @@
function myfunc # RIGHT
{
echo 'ChangeMe'
}

View File

@@ -0,0 +1,4 @@
func() { # RIGHT
ChangeMe
}

View File

@@ -0,0 +1,3 @@
RIGHT() echo "hello"
ChangeMe

View File

@@ -320,6 +320,7 @@ test_expect_success 'unset default driver' '
test_language_driver ada test_language_driver ada
test_language_driver bibtex test_language_driver bibtex
test_language_driver bash
test_language_driver cpp test_language_driver cpp
test_language_driver csharp test_language_driver csharp
test_language_driver css test_language_driver css

36
t/t4034/bash/expect Normal file
View File

@@ -0,0 +1,36 @@
<BOLD>diff --git a/pre b/post<RESET>
<BOLD>index 09ac008..60ba6a2 100644<RESET>
<BOLD>--- a/pre<RESET>
<BOLD>+++ b/post<RESET>
<CYAN>@@ -1,31 +1,31 @@<RESET>
<RED>my_var<RESET><GREEN>new_var<RESET>=10
x=<RED>123<RESET><GREEN>456<RESET>
echo <RED>$1<RESET><GREEN>$2<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>]}
ls <RED>-a<RESET><GREEN>-x<RESET>
ls <RED>--all<RESET><GREEN>--color<RESET>

31
t/t4034/bash/post Normal file
View File

@@ -0,0 +1,31 @@
new_var=10
x=456
echo $2
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[@]}
ls -x
ls --color

31
t/t4034/bash/pre Normal file
View File

@@ -0,0 +1,31 @@
my_var=10
x=123
echo $1
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[*]}
ls -a
ls --all

View File

@@ -59,20 +59,30 @@ PATTERNS("bash",
"(" "("
"(" "("
/* POSIX identifier with mandatory parentheses */ /* 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 */ /* 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 */ /* Everything after the function header is captured */
"[ \t]*" ".*$"
/* Compound command starting with `{`, `(`, `((` or `[[` */
"(\\{|\\(\\(?|\\[\\[)"
/* End of captured text */ /* End of captured text */
")", ")",
/* -- */ /* -- */
/* Characters not in the default $IFS value */ /* Identifiers: variable and function names */
"[^ \t]+"), "[a-zA-Z_][a-zA-Z0-9_]*"
/* Shell variables: $VAR, ${VAR} */
"|\\$[a-zA-Z0-9_]+|\\$\\{"
/*Command list separators and redirection operators */
"|\\|\\||&&|<<|>>"
/* Operators ending in '=' (comparison + compound assignment) */
"|==|!=|<=|>=|[-+*/%&|^]="
/* Additional parameter expansion operators */
"|:=|:-|:\\+|:\\?|##|%%|\\^\\^|,,"
/* Command-line options (to avoid splitting -option) */
"|[-a-zA-Z0-9_]+"
/* Brackets and grouping symbols */
"|\\(|\\)|\\{|\\}|\\[|\\]"),
PATTERNS("bibtex", PATTERNS("bibtex",
"(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$",
/* -- */ /* -- */