From: Eshel Yaron Date: Thu, 25 Jul 2024 05:03:48 +0000 (+0200) Subject: (kubed-command-line-completion-table): Elucidate, optimize X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=c7681742b286bdfce3b755b9388f997baf61c65a;p=emacs.git (kubed-command-line-completion-table): Elucidate, optimize --- diff --git a/lisp/net/kubed.el b/lisp/net/kubed.el index e54f54d8fee..f90c481c1fc 100644 --- a/lisp/net/kubed.el +++ b/lisp/net/kubed.el @@ -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)