(root)/Scribbles/Vim regex within globs.md 🍁

|wildcard| expansion, gen_expand_wildcards() in filepath.c, can be coerced into calling into the regex engine.

when a |wildcard| path doesn't contain unescaped {`' (otherwise it'd be caught by has_special_wildchar() in filepath.c) and contains at least one unescaped *?[{ (so it's accepted by mch_has_exp_wildcard() in os_unix.c), then gen_expand_wildcards() will call into mch_expandpath() in os_unix.c aka unix_expandpath() in filepath.c, which will parse each component of the path as a |file-pattern| (file patterns are converted to regexes by file_pat_to_reg_pat() in fileio.c). if your path doesn't happen to contain unescaped *?[{, just throw [\= (optional opening square bracket) or ?\\\{0\} (zero times any single character) or similar at the end of the path.

here is an equivalence table. |wildcard| paths, once they contain *?[{, are pretty similar to |file-pattern|s, up to workarounds for {`'.

∣pattern∣ ∣file-pattern∣ ∣wildcard∣
. ? ?
\+ \+ \+
* \\\{\} \\\{\}
\? \= \=
.* * *
\d \d \d
\a \a \a
[abc] [abc] [abc]
r\∣s {r,s}, r\\∣s r\\∣s
\(r\) {r}, \(r\) \(r\)
{ \{ \{
} \} \}
? \? \?
\. . .
\~ ~ ~

experimentation:

ar []\\|\u\+
ar []\@<!\u\+
ar [x]\@<!\u\+
ar [x]\@!\u\+
tab h pattern
ar [x]\&\u\+
ar [x]\\|\u\+
ar [[]\\|\u\+
ar [[]\?\u\+
ar [[]\\?\u\+
ar [x]\\?\u\+
ar \[\u\+
ar \\\[\u\+
ar \\[\u\+
ar []\u\+
ar [.]\\|\u\+
ar [.]\u\+
ar [.]\@=\u\+
ar [.]\@!\u\+
ar [.]=\u\+
ar [.]\=\u\+
ar [\ ]\=\u\+
ar [=]\=\u?
ar [=]\=\u\?
ar [=]\=\u\\?
ar [=]\=\u\\\?
ar [=]\=\u\=
ar [=]\=\u\+
ar [=]\=\u*
ar [=]\=\u\*
ar [=]\=\u\\*
ar [=]\=\u\\\{\}
ar [/]\=\u\\\{\}
ar [\\]\=\u\\\{\}
ar [\/]\=\u\\\{\}
ar **/[\/]\=\u\\\{\}
ar [\/]\=**/\u\\\{\}
ar ar **/\u\+[=]\=
ar **/[=]\=\u\+
argd *
ar **/\u\+[=]\=
ar **/\u\+[\n]\=
ar **/\u\+\\ze[]
ar **/\u\+\ze[]
ar **/\u\+\ze[x]
ar **/\u\+[]\=
ar **/\u\+[x]\=
ar **/\u\+[\\\{\}
ar **/\l\+]\=
ar **/\l\+[\=
ar **/\l\+[\\\{0\}
vim/foo/a\|b
vim/foo/a\|b[\=
vim/foo/a\\|b[\=
vim/foo/README.md\\|b[\=
$\\|^
vim/foo/README.md\$\\|\^b[\=
vim/foo/README.md$\\|^b[\=
vim/foo/README.md\$\\|^b[\=
vim/foo/\(README.md\\|b[\=\)
vim/vim/\(README.md\\|LICENSE[\=\)
cope
vim/vim/\(README.md\|LICENSE\)[\=
vim/vim/\(README.md\\|LICENSE\)[\=
ar **/\u\+
ar **/\u\+[
ar **/\u\+
ar \.\+[\=
ar \\.\+[\=
tab h file-pattern
ar .\+[\=
ar ?\+[\=
ar \(*/\u\+\)[\=
ar \(*/\u\+[\=\)
ar */\u\+[\=
ar \*/\u\+[\=
ar *[\=
ar \*[\=
ar \*\u\+[\=
ar \u*
ar *\u
ar \u*\u
ar \u\+\*
ar \u\+\\*
ar \u\+
ar \u\+*$
ar \u\+*\$
ar \u\+*
ar \u\+*\
ar \u\+*
ar \u\+
ar \u\+?\=
ar \u\+[\=
ar \v\u\+\[=
ar \v\u\+[=
ar \v\u+[=
argd
ar **/\u\+
ar **/\u\+[\=
ar **/\l\+/\l\+[\=
ar **/\l\+[\=/\l\+[\=
ar \l\+\[=/\l\+[\=
ar \l\+[\=/\u\+[\=
ar a\\|b[\=
ar *.\(txt\\|??x\)
ar *.\(??x\)[\=
ar \l\+/\l\+[\=
ar ?/\l\+/\l\+
ar ?/\l\+/\l\+[\=
ar \l\+[\=/\l\+[\=
ar

for debugging:

diff --git src/filepath.c src/filepath.c
index 91423d9dc..60e48adcd 100644
--- src/filepath.c
+++ src/filepath.c
@@ -3871,6 +3871,8 @@ unix_expandpath(
        vim_free(buf);
        return 0;
     }
+    emsg(pat);
+    emsg("");

     // compile the regexp into a program
     if (flags & EW_ICASE)
@@ -4103,8 +4105,10 @@ gen_expand_wildcards(
     {
        if (has_special_wildchar(pat[i])
                && !(vim_backtick(pat[i]) && pat[i][1] == '=')
-          )
+          ) {
+           emsg("has_special_wildchar");
            return mch_expand_wildcards(num_pat, pat, num_file, file, flags);
+       }
     }
 #endif

@@ -4179,6 +4183,8 @@ gen_expand_wildcards(
                }
                else
                    add_pat = mch_expandpath(&ga, p, flags);
+           } else {
+               emsg("!mch_has_exp_wildcard");
            }
        }