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

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

[nongnu] elpa/bash-completion 4fcddf83c9 242/313: Make /etc/bash_complet


From: ELPA Syncer
Subject: [nongnu] elpa/bash-completion 4fcddf83c9 242/313: Make /etc/bash_completion scripts work with escaped spaces.
Date: Sat, 3 Dec 2022 10:59:34 -0500 (EST)

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

    Make /etc/bash_completion scripts work with escaped spaces.
    
    /etc/bash_completion uses dynamic completion for everything, instead
    of default completion. Completing files with escaped spaces didn't
    work with these scripts, because they rely on compgen -f, whose
    behavior is changes depending on whether readline is enabled - in a
    normal terminal - or not - in Emacs.
    
    This change works around the problem by feeding pre-unquoted strings
    to the scripts.
---
 Makefile                                 |  2 ++
 bash-completion.el                       | 25 +++++++++++++++------
 test/bash-completion-integration-test.el | 37 ++++++++++++++++++++++++++++++++
 test/bash-completion-test.el             | 16 +++++++-------
 4 files changed, 66 insertions(+), 14 deletions(-)

diff --git a/Makefile b/Makefile
index d704525a25..82c52eed57 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,7 @@
 CASK ?= cask
 EMACS ?= emacs
 BASH ?= bash
+BASH_COMPLETION ?= /etc/bash_completion
 
 setup_bash=test/.set-bash-prog.el
 
@@ -36,5 +37,6 @@ clean-elc:
 
 setup_bash:
        @echo '(setq bash-completion-prog "${BASH}")' >$(setup_bash)
+       @echo '(setq bash-completion_test-setup-completion 
"${BASH_COMPLETION}")' >>$(setup_bash)
 .PHONY: setup_bash
 
diff --git a/bash-completion.el b/bash-completion.el
index 0f862949a8..44ce408e9a 100644
--- a/bash-completion.el
+++ b/bash-completion.el
@@ -628,21 +628,34 @@ Returns a completion struct."
          (start (or (car (bash-completion-tokenize-get-range first-token)) 
comp-pos))
          (end (or (cdr (bash-completion-tokenize-get-range last-token)) 
comp-pos))
          (words (bash-completion-strings-from-tokens line-tokens))
-         (stub-start) (unparsed-stub) (parsed-stub))
+         (rebuilt-line) (stub-start) (unparsed-stub) (parsed-stub))
+    ;; Note about rebuilt-line: When using readline, line and words
+    ;; would be passed unquoted to the functions. This doesn't work,
+    ;; however, when called from Emacs as when readline 'compgen -f'
+    ;; behaves differently and does not unquote the string it's
+    ;; passed. This is why words and the last word of the line are
+    ;; passed unquoted. This makes the standard bash completion
+    ;; scripts work - possibly at the cost of more inconsistencies
+    ;; with other scripts.
     (if (or (> comp-pos end) (= start end))
         (setq stub-start comp-pos
               unparsed-stub ""
               parsed-stub ""
-              words (append words '("")))
+              words (append words '(""))
+              rebuilt-line (buffer-substring-no-properties start comp-pos))
       (if (< bash-major-version 4)
           (setq last-token (car (last (bash-completion-tokenize
-                                       comp-start comp-pos wordbreaks)))))
+                                       start comp-pos wordbreaks)))))
       (setq stub-start (car (bash-completion-tokenize-get-range last-token))
             parsed-stub (bash-completion-tokenize-get-str last-token)
-            unparsed-stub (buffer-substring-no-properties stub-start 
comp-pos)))
+            unparsed-stub (buffer-substring-no-properties stub-start comp-pos)
+            rebuilt-line (concat
+                          (buffer-substring-no-properties
+                           start (car (cdr (assq 'range (car (last 
line-tokens))))))
+                          (cdr (assq 'str (car (last line-tokens)))))))
     (bash-completion--make
-     :line (buffer-substring-no-properties start comp-pos)
-     :point (- comp-pos start)
+     :line rebuilt-line
+     :point (length rebuilt-line)
      :cword (- (length words) 1)
      :words words
      :stub-start stub-start
diff --git a/test/bash-completion-integration-test.el 
b/test/bash-completion-integration-test.el
index 40d154633c..8cf504d946 100644
--- a/test/bash-completion-integration-test.el
+++ b/test/bash-completion-integration-test.el
@@ -33,6 +33,8 @@
 (require 'dired)
 (require 'ert)
 
+(defvar bash-completion_test-setup-completion "/etc/bash_completion")
+
 (defmacro bash-completion_test-harness (bashrc use-separate-process &rest body)
   `(let ((test-env-dir (bash-completion_test-setup-env ,bashrc)))
      (let ((bash-completion-processes nil)
@@ -207,6 +209,41 @@ for testing completion."
       ;; actually bash, the test could otherwise work just fine.
       (should (not (null (cdr (assq nil bash-completion-processes)))))))))
 
+(ert-deftest bash-completion-integration-space ()
+  (bash-completion_test-with-shell-harness
+   ""
+   nil
+   (bash-completion_test-test-spaces)))
+
+(ert-deftest bash-completion-integration-space-and-prog-completion ()
+  ;; Recent version of bash completion define a completion for ls. This
+  ;; test makes sure that it works.
+  (when (and bash-completion_test-setup-completion
+             (not (zerop (length bash-completion_test-setup-completion))))
+    (bash-completion_test-with-shell-harness
+     (concat "source " bash-completion_test-setup-completion "\n")
+     nil
+     (bash-completion_test-test-spaces))))
+  
+(defun bash-completion_test-test-spaces ()
+   (make-directory "my dir1/my dir2" 'parents)
+   (with-temp-buffer (write-file "my dir1/other"))
+
+   (should (equal "ls my\\ dir1/" (bash-completion_test-complete "ls my")))
+   (should (equal "ls my\\ dir1/my\\ dir2/" (bash-completion_test-complete "ls 
my\\ dir1/my")))
+   (should (equal "ls my\\ dir1/other " (bash-completion_test-complete "ls 
my\\ dir1/o")))
+   (should (equal "cp my\\ dir1/a my\\ dir1/" (bash-completion_test-complete 
"cp my\\ dir1/a my\\ dir")))
+
+   (should (equal "ls \"my dir1/" (bash-completion_test-complete "ls \"my")))
+   (should (equal "ls \"my dir1/my dir2/" (bash-completion_test-complete "ls 
\"my dir1/my")))
+   (should (equal "ls \"my dir1/other\" " (bash-completion_test-complete "ls 
\"my dir1/o")))
+   (should (equal "cp \"my dir1/a\" \"my dir1/" (bash-completion_test-complete 
"cp \"my dir1/a\" \"my dir")))
+
+   (should (equal "ls 'my dir1/" (bash-completion_test-complete "ls 'my")))
+   (should (equal "ls 'my dir1/my dir2/" (bash-completion_test-complete "ls 
'my dir1/my")))
+   (should (equal "ls 'my dir1/other' " (bash-completion_test-complete "ls 'my 
dir1/o")))
+   (should (equal "cp 'my dir1/a' 'my dir1/" (bash-completion_test-complete 
"cp 'my dir1/a' 'my dir"))))
+
 (ert-deftest bash-completion-integration-bash-4-default-completion ()
   (bash-completion_test-with-shell-harness
    (concat ; .bashrc
diff --git a/test/bash-completion-test.el b/test/bash-completion-test.el
index 2d080f2699..4f0d8c06c9 100644
--- a/test/bash-completion-test.el
+++ b/test/bash-completion-test.el
@@ -264,8 +264,8 @@ The return value is the one returned by BODY."
   ;; with escaped quote
   (should (equal
            (bash-completion--make
-            :line "cd /vcr/shows/Dexter\\'s"
-            :point 23
+            :line "cd /vcr/shows/Dexter's"
+            :point 22
             :cword 1
             :words '("cd" "/vcr/shows/Dexter's")
             :stub-start 4
@@ -279,8 +279,8 @@ The return value is the one returned by BODY."
   ;; with escaped quote, bash 4
   (should (equal
            (bash-completion--make
-            :line "cd /vcr/shows/Dexter\\'s"
-            :point 23
+            :line "cd /vcr/shows/Dexter's"
+            :point 22
             :cword 1
             :words '("cd" "/vcr/shows/Dexter's")
             :stub-start 4
@@ -294,8 +294,8 @@ The return value is the one returned by BODY."
   ;; with double quote
   (should (equal
            (bash-completion--make
-            :line "cd \"/vcr/shows/Dexter's"
-            :point 23
+            :line "cd /vcr/shows/Dexter's"
+            :point 22
             :cword 1
             :words '("cd" "/vcr/shows/Dexter's")
             :stub-start 4
@@ -310,8 +310,8 @@ The return value is the one returned by BODY."
   ;; with single quote
   (should (equal
            (bash-completion--make
-            :line "cd '/vcr/shows/Dexter'\\''s"
-            :point 26
+            :line "cd /vcr/shows/Dexter's"
+            :point 22
             :cword 1
             :words '("cd" "/vcr/shows/Dexter's")
             :stub-start 4



reply via email to

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