Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

[RFC PATCH] _path_files: teach zsh_directory_name



Signed-off-by: Takeshi Banse <thb@xxxxxxxxx>
---

Hi, I want this feature, too. It is necessary to tweak _path_files function
as far as I can tell. So, I wrote a patch.

To zsh-workers:
This `elif` clause could be merged with the following `elif` clause because
it starts with \~, too. But it may break something, so I did prepend the
separate `elif` clause for \~\[*.

 Completion/Unix/Type/_path_files | 70 ++++++++++++++++++++++++++++++++++++++++
 Test/Y01completion.ztst          | 30 +++++++++++++++++
 2 files changed, 100 insertions(+)

diff --git a/Completion/Unix/Type/_path_files b/Completion/Unix/Type/_path_files
index 9fa6ae9fc..8fbc21ffa 100644
--- a/Completion/Unix/Type/_path_files
+++ b/Completion/Unix/Type/_path_files
@@ -274,6 +274,76 @@ if [[ "$pre" = [^][*?#^\|\<\>\\]#(\`[^\`]#\`|\$)*/* && "$compstate[quote]" != \'
   orig="${orig[1,(in:i:)/][1,-2]}"
   donepath=
   prepaths=( '' )
+elif [[ "$pre" = \~\[* && "$compstate[quote]" = (|\`) ]]; then
+  (($+functions[zsh_directory_name] || $+zsh_directory_name_functions)) &&
+  () {
+    # It begins with `~[', so the characters from `$pre[3]' to before the
+    # first `]' represent the dynamic directory name. Otherwise, it may fall
+    # through to the following elif/else clauses.
+
+    local name=
+    () {
+      local -i i=3 n=$#pre sq=0 dq=0
+      local c=
+      while ((i<=n)); do
+        c=$pre[i++]
+        case $c in
+          (\')
+            if ((sq)); then
+              ((sq=0))
+            elif ((dq==0)); then
+              ((sq=1))
+            fi
+          ;;
+          (\")
+            if [[ "$name[-1]" != '\' ]]; then
+              if ((dq)); then
+                ((dq=0))
+              elif ((sq==0)); then
+                ((dq=1))
+              fi
+            fi
+          ;;
+          (\;) ;&
+          (])
+            repeat 1; do
+              ((sq || dq)) && break
+              [[ "$name[-1]" == '\' ]] && break
+              [[ "$c" == ';' ]] && return 1
+              return 0
+            done
+          ;;
+        esac
+        name+="$c"
+      done
+      return 1
+    } &&
+    () {
+      local -a reply
+      local -i ret=1
+      if (($+functions[zsh_directory_name])); then
+        zsh_directory_name n "$name"
+        ret=$?
+      fi
+      if ((ret != 0)); then
+        local func=
+        for func in "${zsh_directory_name_functions[@]-}"; do
+          "$func" n "$name"
+          ret=$?
+          ((ret == 0)) && break
+        done
+      fi
+      if ((ret == 0)); then
+        realpath="$reply[1]/"
+        linepath="$pre[1,$#name+2+1]/"
+      fi
+      return ret
+    }
+  } then
+  pre="${pre#${linepath}}"
+  orig="${orig#${linepath}}"
+  donepath=
+  prepaths=( '' )
 elif [[ "$pre[1]" = \~ && "$compstate[quote]" = (|\`) ]]; then
 
   # It begins with `~', so remember anything before the first slash to be able
diff --git a/Test/Y01completion.ztst b/Test/Y01completion.ztst
index b1c0e40e5..cbfbb75d7 100644
--- a/Test/Y01completion.ztst
+++ b/Test/Y01completion.ztst
@@ -36,6 +36,36 @@
 >line: {: dir1/}{}
 >line: {: dir2/}{}
 
+  comptesteval 'zsh_directory_name () {
+    case "$1" in
+      (d)
+        return 1
+      ;;
+      (n)
+        reply=("$2")
+      ;;
+      (c)
+        local expl
+        _wanted dynamic-dirs expl dynamic compadd -S\] -Q -- ./
+      ;;
+    esac
+  }'
+  comptest $': ~[\t/\t\t\t\t\t\t\t'
+0:tilde with zsh_directory_name
+>line: {: ~[./]}{}
+>line: {: ~[./]/}{}
+>DESCRIPTION:{file}
+>DI:{dir1}
+>DI:{dir2}
+>FI:{file1}
+>FI:{file2}
+>line: {: ~[./]/dir1/}{}
+>line: {: ~[./]/dir2/}{}
+>line: {: ~[./]/file1}{}
+>line: {: ~[./]/file2}{}
+>line: {: ~[./]/dir1/}{}
+>line: {: ~[./]/dir2/}{}
+
   comptesteval '_users () { compadd user1 user2 }'
   comptest $': ~\t\t\t\t\t'
 0:tilde
-- 
2.16.1



Messages sorted by: Reverse Date, Date, Thread, Author