emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/bash-completion 2378b04eeb 140/313: More easily call bash-


From: ELPA Syncer
Subject: [nongnu] elpa/bash-completion 2378b04eeb 140/313: More easily call bash-completion-dynamic-complete-nocomint, faking bash
Date: Sat, 3 Dec 2022 10:59:24 -0500 (EST)

branch: elpa/bash-completion
commit 2378b04eeb4338a8268072d7eda7820dba390ccd
Author: Stephane Zermatten <szermatt@gmx.net>
Commit: Stephane Zermatten <szermatt@gmx.net>

    More easily call bash-completion-dynamic-complete-nocomint, faking bash
    calls.
    
    This commit extends the test to better test the functionality introduced
    in f3b11e1, at a higher level than previously possible. This uncovered
    an issue with directory expansion not caught by 319886f when quoting
    with a single quote, so this commit fixes that, too.
---
 bash-completion-test.el | 113 +++++++++++++++++++++++++++++++++++++++++++++---
 bash-completion.el      |  15 +++++--
 2 files changed, 119 insertions(+), 9 deletions(-)

diff --git a/bash-completion-test.el b/bash-completion-test.el
index 0bb63c73b3..95dd55c80d 100644
--- a/bash-completion-test.el
+++ b/bash-completion-test.el
@@ -414,20 +414,32 @@ garbage
 (ert-deftest bash-completion-addsuffix-test ()
   (cl-letf (((symbol-function 'file-accessible-directory-p)
             (lambda (a) (error "unexpected"))))
-    (should (equal "hello/" (bash-completion-addsuffix "hello/")))
+    (should (equal "hello/" (bash-completion-addsuffix nil "hello/")))
     ;; ends with space"
-    (should (equal "hello " (bash-completion-addsuffix "hello ")))
+    (should (equal "hello " (bash-completion-addsuffix nil "hello ")))
     ;; ends with separator"
-    (should (equal "hello:" (bash-completion-addsuffix "hello:"))))
+    (should (equal "hello:" (bash-completion-addsuffix nil "hello:"))))
   ;; check directory"
   (cl-letf (((symbol-function 'file-accessible-directory-p)
             (lambda (a) (equal a "/tmp/hello")))
            (default-directory "/tmp"))
-    (should (equal "hello/" (bash-completion-addsuffix "hello"))))
+    (should (equal "hello/" (bash-completion-addsuffix nil "hello"))))
+  (cl-letf (((symbol-function 'file-accessible-directory-p)
+            (lambda (a) (equal a "/tmp/hello world")))
+           (default-directory "/tmp"))
+    (should (equal "hello\\ world/" (bash-completion-addsuffix nil "hello\\ 
world"))))
+  (cl-letf (((symbol-function 'file-accessible-directory-p)
+            (lambda (a) (equal a "/tmp/hello \"world\"")))
+           (default-directory "/tmp"))
+    (should (equal "hello \\\"world\\\"/" (bash-completion-addsuffix ?\" 
"hello \\\"world\\\""))))
+  (cl-letf (((symbol-function 'file-accessible-directory-p)
+            (lambda (a) (equal a "/tmp/d'uh")))
+           (default-directory "/tmp"))
+    (should (equal "d'\\''uh/" (bash-completion-addsuffix ?' "d'\\''uh"))))
   (cl-letf (((symbol-function 'file-accessible-directory-p)
             (lambda (a) (equal a (concat (expand-file-name "y" "~/x")))))
            (default-directory "~/x"))
-    (should (equal "y/" (bash-completion-addsuffix "y")))))
+    (should (equal "y/" (bash-completion-addsuffix nil "y")))))
 
 (ert-deftest bash-completion-starts-with-test ()
   (should (equal nil (bash-completion-starts-with "" "hello ")))
@@ -669,4 +681,95 @@ garbage
   (should (equal "export PATH=/sbin:/bin/"
                 (bash-completion_test-with-shell "export PATH=/sbin:/bi"))))
 
+(defmacro --with-fake-bash-completion-send (&rest body)
+  "Runs the body in an environment that fakes `bash-completion-send'.
+
+When `bash-completion-send' is called, it pops the result from
+--send-results and captures the command-line it was given into
+--captured-commands.
+
+Directories in --directories get a / appended to them. Note that
+the current directory in this environemnt is /tmp/test.
+
+The body is run with a test buffer as current buffer. Fill it with the 
command-line
+before calling `bash-completion-dynamic-complete-nocomint'.
+"
+  `(let ((default-directory "/tmp/test")
+         (bash-completion-alist '()))
+     (lexical-let ((--process-buffer) (--test-buffer) (--send-results) 
(--captured-commands (list))
+                   (--directories (list)))
+       (with-temp-buffer
+         (setq --process-buffer (current-buffer))
+         (with-temp-buffer
+           (setq --test-buffer (current-buffer))
+           (cl-letf (((symbol-function 'bash-completion-require-process) 
(lambda () 'process))
+                     ((symbol-function 'bash-completion-buffer) (lambda () 
--process-buffer))
+                     ((symbol-function 'process-buffer) (lambda (p) 
--process-buffer))
+                     ((symbol-function 'file-accessible-directory-p)
+                      (lambda (d) (member d --directories)))
+                     ((symbol-function 'bash-completion-send)
+                      (lambda (commandline &optional process timeout)
+                        (with-current-buffer --process-buffer
+                          (delete-region (point-min) (point-max))
+                          (insert (pop --send-results))
+                          (push commandline --captured-commands)
+                          0))))
+             (progn ,@body)))))))
+
+(ert-deftest bash-completion-simple-complete-test ()
+  (--with-fake-bash-completion-send
+   (push "hell\nhello1\nhello2\n" --send-results)
+   (insert "$ cat he")
+   (should (equal
+            (list 7 9 '("hell" "hello1" "hello2"))
+            (bash-completion-dynamic-complete-nocomint 3 (point))))
+   (should (equal "cd >/dev/null 2>&1 /tmp/test ; compgen -o default he 
2>/dev/null"
+                  (pop --captured-commands)))))
+
+(ert-deftest bash-completion-complete-dir-with-spaces-test ()
+  (--with-fake-bash-completion-send
+   (push "/tmp/test/Documents" --directories)
+   (push "/tmp/test/Documents/Modes d'emplois" --directories)
+   (push "/tmp/test/Documents\n" --send-results)
+   (push "Documents\n" --send-results)
+   (insert "$ cat Doc")
+   (should (equal
+            '(7 10 ("Documents/"))
+            (bash-completion-dynamic-complete-nocomint 3 (point))))
+   (insert "uments/")
+   (push "Documents/Modes d'emplois\n" --send-results)
+   (should (equal
+            '("Documents/Modes\\ d\\'emplois/")
+            (nth 2(bash-completion-dynamic-complete-nocomint 3 (point)))))
+   (insert "Modes\\ d\\'emplois/")
+   (push "Documents/Modes d'emplois/KAR 1.pdf\nDocuments/Modes d'emplois/KAR 
2.pdf\n"
+         --send-results)
+   (should (equal
+            '("Documents/Modes\\ d\\'emplois/KAR\\ 1.pdf"
+              "Documents/Modes\\ d\\'emplois/KAR\\ 2.pdf")
+            (nth 2(bash-completion-dynamic-complete-nocomint 3 (point)))))))
+
+(ert-deftest bash-completion-complete-single-quoted-dir ()
+  (--with-fake-bash-completion-send
+   (push "/tmp/test/Documents" --directories)
+   (push "/tmp/test/Documents/Modes d'emplois" --directories)
+   (push "/tmp/test/Documents\n" --send-results)
+   (push "Documents\n" --send-results)
+   (insert "$ cat 'Doc")
+   (should (equal
+            '(8 11 ("Documents/"))
+            (bash-completion-dynamic-complete-nocomint 3 (point))))
+   (insert "uments/")
+   (push "Documents/Modes d'emplois\n" --send-results)
+   (should (equal
+            '("Documents/Modes d'\\''emplois/")
+            (nth 2(bash-completion-dynamic-complete-nocomint 3 (point)))))
+   (insert "Modes d'\\''emplois/")
+   (push "Documents/Modes d'emplois/KAR 1.pdf\nDocuments/Modes d'emplois/KAR 
2.pdf\n"
+         --send-results)
+   (should (equal
+            '("Documents/Modes d'\\''emplois/KAR 1.pdf"
+              "Documents/Modes d'\\''emplois/KAR 2.pdf")
+            (nth 2 (bash-completion-dynamic-complete-nocomint 3 (point)))))))
+
 ;;; bash-completion_test.el ends here
diff --git a/bash-completion.el b/bash-completion.el
index 383392d29a..ea2f173c23 100644
--- a/bash-completion.el
+++ b/bash-completion.el
@@ -380,7 +380,7 @@ This function is not meant to be called outside of
          ;; was used for the split in unparsed-stub.
          (separator-pos-in-unparsed
           (- (length unparsed-stub)
-             (seq-position (reverse unparsed-stub) separator)))
+             (or (seq-position (reverse unparsed-stub) separator) 0)))
          (unparsed-after-wordbreak
           (substring unparsed-stub
                      separator-pos-in-unparsed
@@ -758,6 +758,7 @@ for directory name detection to work."
        (open-quote (or open-quote (and bash-completion-open-quote)))
        (suffix ""))
     (bash-completion-addsuffix
+     open-quote
      (let* (rebuilt
            (rest (cond
                   ((bash-completion-starts-with str parsed-prefix)
@@ -821,12 +822,18 @@ Return a possibly escaped version of 
COMPLETION-CANDIDATE."
    (t
     completion-candidate)))
 
+(defun bash-completion-unescape (open-quote string)
+  "Unescapes a possibly QUOTE'ed STRING."
+  (if (eq ?' open-quote)
+      (replace-regexp-in-string "'\\\\''" "'" string)
+    (replace-regexp-in-string "\\(\\\\\\)\\(.\\)" "\\2" string)))
+
 (defconst bash-completion-known-suffixes-regexp
   (concat "[" (regexp-quote bash-completion-wordbreaks-str) "/ ]$")
   "Regexp matching known suffixes for `bash-completion-addsuffix'.")
 
-(defun bash-completion-addsuffix (str)
-  "Add a directory suffix to STR if it looks like a directory.
+(defun bash-completion-addsuffix (open-quote str)
+  "Add a directory suffix to OPEN-QUOTE'd STR if it looks like a directory.
 
 This function looks for a directory called STR relative to the
 buffer-local variable default-directory. If it exists, it returns
@@ -834,7 +841,7 @@ buffer-local variable default-directory. If it exists, it 
returns
   (if (and (null (string-match bash-completion-known-suffixes-regexp str))
           (file-accessible-directory-p
             (expand-file-name
-             (replace-regexp-in-string "\\(\\\\\\)\\(.\\)" "\\2" str)
+             (bash-completion-unescape open-quote str)
              default-directory)))
        (concat str "/")
     str))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]