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

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

[elpa] externals/company e8a9d38e53 3/3: Merge pull request #1497 from c


From: ELPA Syncer
Subject: [elpa] externals/company e8a9d38e53 3/3: Merge pull request #1497 from company-mode/completion_restart_in_new_field
Date: Tue, 5 Nov 2024 12:57:43 -0500 (EST)

branch: externals/company
commit e8a9d38e5332912433712947bab28af5adb27d7c
Merge: 9c273fc7c1 c625b2ccc7
Author: Dmitry Gutov <dmitry@gutov.dev>
Commit: GitHub <noreply@github.com>

    Merge pull request #1497 from company-mode/completion_restart_in_new_field
    
    company-finish: Restart completion if entered a new field
---
 NEWS.md            |  7 +++++++
 company-capf.el    |  5 ++---
 company-files.el   | 14 -------------
 company.el         | 25 ++++++++++++++++++----
 doc/company.texi   |  1 +
 test/core-tests.el | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 92 insertions(+), 21 deletions(-)

diff --git a/NEWS.md b/NEWS.md
index d1e28f99dd..e19eebbb5d 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -2,6 +2,13 @@
 
 # Next
 
+* Completion is restarted if it enters a new "field" at the end, as indicated 
by
+  the `adjust-boundaries` backend action
+  (#[1497](https://github.com/company-mode/company-mode/pull/1497)). This
+  benefits file name (and directory) completion.  The user option
+  `company-files-chop-trailing-slash` has been removed, and the
+  `post-completion` handler in `company-files` has been removed as well.
+
 * Handle the case when the current c-a-p-f function changes mid-session
   (#[1494](https://github.com/company-mode/company-mode/pull/1494)).
 
diff --git a/company-capf.el b/company-capf.el
index 5295ecdd80..baeacaa283 100644
--- a/company-capf.el
+++ b/company-capf.el
@@ -240,8 +240,7 @@ so we can't just use the preceding variable instead.")
          (exit-function (plist-get (nthcdr 4 res) :exit-function))
          (table (nth 3 res)))
     (if exit-function
-        ;; We can more or less know when the user is done with completion,
-        ;; so we do something different than `completion--done'.
+        ;; Follow the example of `completion--done'.
         (funcall exit-function arg
                  ;; FIXME: Should probably use an additional heuristic:
                  ;; completion-at-point doesn't know when the user picked a
@@ -250,7 +249,7 @@ so we can't just use the preceding variable instead.")
                  ;; RET (or use implicit completion with company-tng).
                  (if (= (car (completion-boundaries arg table nil ""))
                         (length arg))
-                     'sole
+                     'exact
                    'finished)))))
 
 (provide 'company-capf)
diff --git a/company-files.el b/company-files.el
index 61e8490467..738809606b 100644
--- a/company-files.el
+++ b/company-files.el
@@ -38,14 +38,6 @@ The values should use the same format as 
`completion-ignored-extensions'."
   :type '(repeat (string :tag "File extension or directory name"))
   :package-version '(company . "0.9.1"))
 
-(defcustom company-files-chop-trailing-slash t
-  "Non-nil to remove the trailing slash after inserting directory name.
-
-This way it's easy to continue completion by typing `/' again.
-
-Set this to nil to disable that behavior."
-  :type 'boolean)
-
 (defun company-files--directory-files (dir prefix)
   ;; Don't use directory-files. It produces directories without trailing /.
   (condition-case _err
@@ -137,11 +129,6 @@ Set this to nil to disable that behavior."
   (and (equal (cdr old) (cdr new))
        (string-prefix-p (car old) (car new))))
 
-(defun company-files--post-completion (arg)
-  (when (and company-files-chop-trailing-slash
-             (company-files--trailing-slash-p arg))
-    (delete-char -1)))
-
 (defun company-files--adjust-boundaries (_file prefix suffix)
   (cons
    (file-name-nondirectory prefix)
@@ -162,7 +149,6 @@ File paths with spaces are only supported inside strings."
      (company-files--adjust-boundaries arg (nth 0 rest) (nth 1 rest)))
     (location (cons (dired-noselect
                      (file-name-directory (directory-file-name arg))) 1))
-    (post-completion (company-files--post-completion arg))
     (kind (if (string-suffix-p "/" arg) 'folder 'file))
     (sorted t)
     (no-cache t)))
diff --git a/company.el b/company.el
index a579a1de46..3023da6068 100644
--- a/company.el
+++ b/company.el
@@ -2491,7 +2491,6 @@ For more details see `company-insertion-on-trigger' and
 (defun company--begin-new ()
   (let ((min-prefix (company--prefix-min-length))
         entity c)
-    (company-cache-expire)
     (cl-dolist (backend (if company-backend
                             ;; prefer manual override
                             (list company-backend)
@@ -2545,6 +2544,7 @@ For more details see `company-insertion-on-trigger' and
    (company-candidates
     (company--continue))
    ((company--should-complete)
+    (company-cache-expire)
     (company--begin-new)))
   (if (not company-candidates)
       (setq company-backend nil)
@@ -2595,8 +2595,21 @@ For more details see `company-insertion-on-trigger' and
   (pcase-let ((`(,prefix . ,suffix) (company--boundaries result)))
     (company--insert-candidate result (or prefix company-prefix))
     (and (> (length suffix) 0)
-         (delete-region (point) (+ (point) (length suffix)))))
-  (company-cancel result))
+         (delete-region (point) (+ (point) (length suffix))))
+    (let ((tick (buffer-chars-modified-tick))
+          (backend company-backend))
+      ;; Call backend's `post-completion' and run other hooks, then exit.
+      (company-cancel result)
+      ;; Try restarting completion, to see if we moved into a new field.
+      ;; Most commonly, this would be after entering a dir in file completion.
+      (when (= (buffer-chars-modified-tick) tick)
+        (let (company-require-match)
+          (setq company-backend backend
+                company--manual-prefix 0)
+          (company--begin-new))
+        (unless (and company-candidates
+                     (equal (company--boundaries) '("" . "")))
+          (company-cancel))))))
 
 (defsubst company-keep (command)
   (and (symbolp command) (get command 'company-keep)))
@@ -3075,7 +3088,11 @@ For use in the `select-mouse' frontend action.  
`let'-bound.")
     (company-complete-selection)))
 
 (defun company-complete-selection ()
-  "Insert the selected candidate."
+  "Insert the selected candidate.
+
+Restart completion if a new field is entered. A field is indicated by
+`adjust-boundaries' as implemented in the backend. If both adjusted prefix
+and adjusted suffix are empty strings, that means a new field."
   (interactive)
   (when (and (company-manual-begin) company-selection)
     (let ((result (nth company-selection company-candidates)))
diff --git a/doc/company.texi b/doc/company.texi
index 020075a173..9b9eb02397 100644
--- a/doc/company.texi
+++ b/doc/company.texi
@@ -332,6 +332,7 @@ Select the previous candidate
 @cindex complete
 @findex company-complete-selection
 Insert the selected candidate (@code{company-complete-selection}).
+Restart completion if a new field is entered.
 
 @item TAB
 @itemx <tab>
diff --git a/test/core-tests.el b/test/core-tests.el
index 152e94c5a2..c33eb3b79c 100644
--- a/test/core-tests.el
+++ b/test/core-tests.el
@@ -706,6 +706,67 @@
       (company-complete-selection)
       (should (string= "tea-cup" (buffer-string))))))
 
+(ert-deftest company-complete-restarts-in-new-field ()
+  (with-temp-buffer
+    (insert "foo")
+    (company-mode)
+    (let (company-frontends
+          (company-backends
+           (list (lambda (command &optional _arg &rest rest)
+                   (cl-case command
+                     (prefix (buffer-substring (point-min) (point)))
+                     (adjust-boundaries
+                      (if (string-suffix-p "/" (car rest))
+                          (cons "" (nth 1 rest))
+                        (cons (car rest) (nth 1 rest))))
+                     (candidates '("cc/" "aa1" "bb2"))
+                     (sorted t))))))
+      (let (this-command)
+        (company-complete))
+      (should (string= "foo" (buffer-string)))
+      (company-complete-selection)
+      (should (string= "cc/" (buffer-string)))
+      (should (equal company-candidates '("cc/" "aa1" "bb2"))))))
+
+(ert-deftest company-complete-no-restart-in-old-field ()
+  (with-temp-buffer
+    (insert "foo")
+    (company-mode)
+    (let (company-frontends
+          (company-backends
+           (list (lambda (command &rest _rest)
+                   (cl-case command
+                     (prefix (buffer-substring (point-min) (point)))
+                     (candidates '("cc/" "aa1" "bb2"))
+                     (sorted t))))))
+      (let (this-command)
+        (company-complete))
+      (company-complete-selection)
+      (should (string= "cc/" (buffer-string)))
+      (should (null company-candidates)))))
+
+(ert-deftest company-complete-no-restart-after-post-completion-change ()
+  (with-temp-buffer
+    (insert "foo")
+    (company-mode)
+    (let (company-frontends
+          (company-backends
+           (list (lambda (command &optional _arg &rest rest)
+                   (cl-case command
+                     (prefix (buffer-substring (point-min) (point)))
+                     (candidates '("cc/" "aa1" "bb2"))
+                     (adjust-boundaries
+                      (if (string-suffix-p "/" (car rest))
+                          (cons "" (nth 1 rest))
+                        (cons (car rest) (nth 1 rest))))
+                     (post-completion (insert "bar/"))
+                     (sorted t))))))
+      (let (this-command)
+        (company-complete))
+      (company-complete-selection)
+      (should (string= "cc/bar/" (buffer-string)))
+      (should (null company-candidates)))))
+
 (defvar ct-sorted nil)
 
 ;; FIXME: When Emacs 29+ only: just replace with equal-including-properties.



reply via email to

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