Subject: [PATCH v2 1/1] userdiff: extend Bash pattern to cover more shell function forms

From: Moumita <[email-masked]>
Date: Tue, 18 Feb 2025 21:05:27 +0530

From: Moumita Dhar <[email-masked]>

The existing Bash userdiff pattern misses some shell function forms, such as
`function foo()`, multi-line definitions, and extra whitespace.

Extend the pattern to:
- Support `function foo()` syntax.
- Allow spaces in `foo ( )` definitions.
- Recognize multi-line definitions with backslashes.
- Broaden function body detection.

Signed-off-by: Moumita Dhar <[email-masked]>
---
 userdiff.c | 34 +++++++++++++++++++++++-----------
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/userdiff.c b/userdiff.c
index 340c4eb4f7..194e28883d 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -53,26 +53,38 @@ IPATTERN("ada",
 	 "|[-+]?[0-9][0-9#_.aAbBcCdDeEfF]*([eE][+-]?[0-9_]+)?"
 	 "|=>|\\.\\.|\\*\\*|:=|/=|>=|<=|<<|>>|<>"),
 PATTERNS("bash",
-	 /* Optional leading indentation */
+     /* Optional leading indentation */
 	 "^[ \t]*"
-	 /* Start of captured text */
+	 /* Start of captured function name */
 	 "("
 	 "("
-	     /* POSIX identifier with mandatory parentheses */
-	     "[a-zA-Z_][a-zA-Z0-9_]*[ \t]*\\([ \t]*\\))"
+		 /* POSIX identifier with mandatory parentheses (allow spaces inside) */
+		 "[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]+))"
+		 /* Bash-style function definitions, allowing optional `function` keyword */
+		 "(?:function[ \t]+(?=[a-zA-Z_]))?[a-zA-Z_][a-zA-Z0-9_]*(([ \t]*\\([ \t]*\\))|([ \t]+))?"
 	 ")"
 	 /* Optional whitespace */
 	 "[ \t]*"
-	 /* Compound command starting with `{`, `(`, `((` or `[[` */
-	 "(\\{|\\(\\(?|\\[\\[)"
-	 /* End of captured text */
+	 /* Allow function body to start with `{`, `(` (subshell), `[[` */
+	 "(\\{|\\(|\\[\\[)"
+	 /* End of captured function name */
 	 ")",
 	 /* -- */
-	 /* 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 */
+	 "|[-+*/%&|^!=<>]=?"
+	 /* 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