]> git.eshelyaron.com Git - emacs.git/commitdiff
(kubed-command-line-completion-table): Elucidate, optimize
authorEshel Yaron <me@eshelyaron.com>
Thu, 25 Jul 2024 05:03:48 +0000 (07:03 +0200)
committerEshel Yaron <me@eshelyaron.com>
Thu, 25 Jul 2024 05:04:38 +0000 (07:04 +0200)
lisp/net/kubed.el

index e54f54d8fee71dc402bcbaf6a3a114e6b7e37d62..f90c481c1fc8ec81bc4e7b034ef1c93041b0385e 100644 (file)
@@ -1272,6 +1272,8 @@ Optional argument DEFAULT is the minibuffer default argument."
    (format-prompt prompt default) nil nil nil nil
    'kubed-container-images-history default))
 
+(defvar kubed-command-line-completion-cache nil)
+
 (defun kubed-command-line-completion-table (s p a)
   "Completion table for `kubectl' command lines.
 
@@ -1300,12 +1302,18 @@ Perform completion action A on string S with predicate P."
                         "")))
                    cands)))))
       (let* ((lines
-              (apply #'process-lines-ignore-status
-                     kubed-kubectl-executable "__complete"
-                     (let ((args (cdr (split-string-and-unquote s))))
-                       (if (string-suffix-p " " s)
-                           (nconc args '(""))
-                         args))))
+              (cdr
+               (if (string= s (car kubed-command-line-completion-cache))
+                   kubed-command-line-completion-cache
+                 (setq
+                  kubed-command-line-completion-cache
+                  (cons s
+                        (apply #'process-lines-ignore-status
+                               kubed-kubectl-executable "__complete"
+                               (let ((args (cdr (split-string-and-unquote s))))
+                                 (if (string-suffix-p " " s)
+                                     (nconc args '(""))
+                                   args))))))))
              (code nil)
              (comps (seq-take-while
                      (lambda (line)
@@ -1313,29 +1321,50 @@ Perform completion action A on string S with predicate P."
                                  (setq code (string-to-number
                                              (match-string 1 line))))))
                      lines)))
-        (when (and code (not (zerop code)))
-          (if (zerop (logand #b1001 code))
+        ;; `code' encodes "completion directives", as follows:
+        ;; #b000001: An error occurred, ignore completions.
+        ;; #b000010: Don't add space after completion.
+        ;; #b000100: Don't fall back to file completion.
+        ;; #b001000: Completions are really file extension filters.
+        ;; #b010000: Complete directory names.
+        ;; #b100000: Preserve completions order.
+        (when (and code (zerop (logand 1 code)))
+          ;; Error bit in unset, proceed.
+          (if (= #b100 (logand #b100 code))
+              ;; No file name completion.
               (if (eq (car-safe a) 'boundaries)
-                  `(boundaries ,start . ,(and (string-match "[[:space:]=]" (cdr a))
-                                              (match-beginning 0)))
-                (let ((table (mapcar
-                              (lambda (comp)
-                                (pcase (split-string comp "\t" t)
-                                  (`(,c ,a . ,_)
-                                   (propertize c 'kubed-command-line-argument-description
-                                               (car (split-string a "\\." t))))
-                                  (`(,c . ,_)  c)))
-                              comps)))
+                  `(boundaries
+                    ,start . ,(and (string-match "[[:space:]=]" (cdr a))
+                                   (match-beginning 0)))
+                (let ((table
+                       (mapcar
+                        ;; Annotate completion candidates.
+                        (lambda (comp)
+                          (pcase (split-string comp "\t" t)
+                            (`(,c ,d . ,_)
+                             (propertize
+                              c 'kubed-command-line-argument-description
+                              ;; Only keep first sentence.
+                              (car (split-string d "\\." t))))
+                            (`(,c . ,_)  c)))
+                        comps)))
                   (if a (complete-with-action a table (substring s start) p)
                     ;; `try-completion'.
                     (let ((comp (complete-with-action a table (substring s start) p)))
                       (if (stringp comp) (concat (substring s 0 start) comp) comp)))))
-            ;; File name completion.  `comps' are valid extensions.
-            (setq p (lambda (f)
+            ;; File name completion.
+            (setq p
+                  (cond
+                   ((= #b1000 (logand #b1000 code))
+                    ;; `comps' are valid extensions.
+                    (lambda (f)
                       (or (file-directory-p f)
                           (when (string-match "\\.[^.]*\\'" f)
                             (member (substring f (1+ (match-beginning 0)))
                                     comps)))))
+                   ((= #b10000 (logand #b10000 code))
+                    ;; Directory name completion.
+                    #'file-directory-p)))
             (if (eq (car-safe a) 'boundaries)
                 ;; Find nested boundaries.
                 (let* ((suf (cdr a))
@@ -1361,7 +1390,8 @@ This function calls `shell-command' (which see) to do the work.
 Interactively, prompt for COMMAND with completion for `kubectl' arguments."
   (interactive
    (list (completing-read "Command: " #'kubed-command-line-completion-table
-                          nil nil "kubectl " 'kubed-kubectl-command-history)))
+                          nil nil (concat kubed-kubectl-executable " ")
+                          'kubed-kubectl-command-history)))
   (shell-command command))
 
 ;;;###autoload (autoload 'kubed-prefix-map "kubed" nil t 'keymap)