[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/pcmpl-args 36139ba64f 20/33: Added pass completion
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/pcmpl-args 36139ba64f 20/33: Added pass completion |
Date: |
Mon, 31 Jan 2022 11:59:24 -0500 (EST) |
branch: elpa/pcmpl-args
commit 36139ba64f43a3d3f4090ef0118bcebfef7e20c9
Author: Valeriy Litkovskyy <vlr.ltkvsk@protonmail.com>
Commit: Troy Hinckley <t.macman@gmail.com>
Added pass completion
2021-07-21 Valeriy Litkovskyy <vlr.ltkvsk@protonmail.com>
* pcmpl-args.el (pcmpl-args-pass-subcommands): Added a completion
table with annotations for password-store subcommands.
(pcmpl-args-pass-prefix): Added a function that returns
password-store directory.
(pcmpl-args-pass-find): Added a function that returns a list of
password-store entries.
(pcmpl-args-pass-keys): Added a function that returns a list of
gpg secret keys.
(pcmpl-args-pass-subcommand-specs): Added a function that returns
specs for password-store subcommands.
(pcomplete/pass): Added an autoloaded password-store completion
function.
---
pcmpl-args.el | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 149 insertions(+), 1 deletion(-)
diff --git a/pcmpl-args.el b/pcmpl-args.el
index 7f26edd996..a0cc5bae57 100644
--- a/pcmpl-args.el
+++ b/pcmpl-args.el
@@ -98,6 +98,7 @@
(require 'pcmpl-unix)
(require 'pcmpl-linux)
(require 'pcmpl-gnu)
+(require 'cl-seq)
(defgroup pcmpl-args nil
"Refined argument completion for use with pcomplete."
@@ -3400,6 +3401,153 @@ options found in its man page."
(defalias 'pcomplete/wget 'pcmpl-args-pcomplete-on-man)
+;; Pass completion
+
+(defalias 'pcmpl-args-pass-subcommands
+ (pcmpl-args-completion-table-with-annotations
+ '(("cp" "Copy password or directory")
+ ("edit" "Insert a new password or edit an existing password")
+ ("find" "List names of passwords inside the tree that match patterns")
+ ("generate" "Generate new password")
+ ("git" "Execute git commands")
+ ("grep" "Searches inside each decrypted password file")
+ ("help" "Show usage message")
+ ("init" "Initialize new password storage")
+ ("insert" "Insert a new password into the password store")
+ ("ls" "List names of passwords")
+ ("mv" "Move password or directory")
+ ("rm" "Remove password or directory")
+ ("show" "Decrypt and print a password")
+ ("version" "Show version information"))))
+
+(defun pcmpl-args-pass-prefix ()
+ "Return password-store directory.
+It is suffixed with a slash."
+ (let ((directory (or (getenv "PASSWORD_STORE_DIR")
+ (expand-file-name "~/.password-store"))))
+ (concat directory "/")))
+
+(defun pcmpl-args-pass-find (&rest find-args)
+ "Return a list of password-store entries.
+By default, return all directories and files in password-store.
+These can be limited by `FIND-ARGS'.
+
+`FIND-ARGS' is a list of find (GNU/findutils) arguments. For
+example, to get only directories:
+
+\(pcmpl-args-pass-find \"-type\" \"d\")"
+ (let* ((prefix (pcmpl-args-pass-prefix))
+ (args `("find" "-L" ,prefix
+ "(" "-name" ".git*" "-o" "-name" ".gpg-id" ")" "-prune"
+ "-o" ,@find-args "-print"))
+ (rx (concat "^" (regexp-quote prefix) "\\(.+?\\)\\(?:\\.gpg\\)?$")))
+ (with-temp-buffer
+ (apply #'pcmpl-args-process-file args)
+ (goto-char (point-min))
+ (save-match-data
+ (while (search-forward-regexp rx nil t)
+ (replace-match "\\1")))
+ (beginning-of-line)
+ (let (lines)
+ (while (progn (push (string-trim-right (thing-at-point 'line t)) lines)
+ (forward-line -1)
+ (not (bobp))))
+ lines))))
+
+(defun pcmpl-args-pass-keys (args)
+ "Return a list of gpg secret keys.
+This list is filtered based on `ARGS', which is an alist with
+inserted command line argument. If some gpg key was already
+entered, it will be removed from returned list."
+ ;; Should we use epg-list-keys to get keys?
+ (let ((rx "^\\(?:[^:]*:\\)\\{9\\}\\([^:]*\\).*?$"))
+ (with-temp-buffer
+ (pcmpl-args-process-file "gpg2" "--list-secret-keys" "--with-colons")
+ (goto-char (point-min))
+ (save-match-data
+ (while (search-forward-regexp rx nil t)
+ (replace-match "\\1")))
+ (forward-line 1)
+ (let (lines)
+ (while (progn (forward-line -1)
+ (push (string-trim-right (thing-at-point 'line t)) lines)
+ (not (bobp))))
+ (cl-set-difference lines (cadr (assq '* args)) :test #'string=)))))
+
+(defun pcmpl-args-pass-subcommand-specs (subcommand)
+ "Return specs for pass `SUBCOMMAND'."
+ (pcase subcommand
+ ("edit"
+ '((argument 0 (("PASSNAME" (:eval (pcmpl-args-pass-find "-type" "f")))))))
+
+ ("find"
+ '((argument * (("PATTERN" none)))))
+
+ ("generate"
+ '((option "-n, --no-symbols" :help "Use only alphanumeric characters")
+ (option "-c, --clip" :help "Copy the password to the clipboard")
+ (option "-i, --in-place" :help "Only replace the first line of the
password file")
+ (option "-f, --force" :help "Don't prompt before overwriting an
existing password")
+ (argument 0 (("PASSNAME" (:eval (pcmpl-args-pass-find)))))
+ (argument 1 (("PASSLENGTH" none)))))
+
+ ((or "git" "grep")
+ '((argument 0 (("CMDOPTS" none))
+ :subparser
+ (lambda (args specs seen)
+ (push (plist-get (pop seen) :stub) args)
+ (pcmpl-args-command-subparser args specs seen)))))
+
+ ("init"
+ '((option "-p, --path=SUBFOLDER" (("SUBFOLDER" (:eval
(pcmpl-args-pass-find "-type" "d"))))
+ :help "GPGIDs are assigned for that specific SUBFOLDER of the
store")
+ (argument * (("GPGID" (:lambda pcmpl-args-pass-keys))))))
+
+ ("insert"
+ '((option "-e, --echo" :help "Enable keyboard echo and don't confirm the
password")
+ (option "-m, --multiline" :help "Read lines until EOF or Ctrl+D is
reached")
+ (option "-f, --force" :help "Don't prompt before overwriting an
existing password")
+ (argument 0 (("PASSNAME" (:eval (pcmpl-args-pass-find)))))))
+
+ ("ls"
+ '((argument 0 (("SUBFOLDER" (:eval (pcmpl-args-pass-find "-type"
"d")))))))
+
+ ("rm"
+ '((option "-r, --recursive" :help "Delete PASSNAME recursively if it is a
directory")
+ (option "-f, --force" :help "Do not interactively prompt before
removal")
+ (argument 0 (("PASSNAME" (:eval (pcmpl-args-pass-find)))))))
+
+ ("show"
+ '((option "-c[LINENUMBER], --clip[=LINENUMBER]" (("LINENUMBER" none))
+ :help "Copy the first (or specified) line to the clipboard")
+ (option "-q[LINENUMBER], --qrcode[=LINENUMBER]" (("LINENUMBER" none))
+ :help "Display a QR code of the first (or specified) line")
+ (argument 0 (("PASSNAME" (:eval (pcmpl-args-pass-find "-type" "f")))))))
+
+ ((or "cp" "mv")
+ '((option "-f, --force" :help "Silently overwrite NEWPATH if it exists")
+ (argument 0 (("OLDPATH" (:eval (pcmpl-args-pass-find)))))
+ (argument 1 (("NEWPATH" (:eval (pcmpl-args-pass-find)))))))))
+
+(defun pcomplete/pass ()
+ "Pass completion."
+ (pcmpl-args-pcomplete
+ (pcmpl-args-make-argspecs
+ '((argument 0 (("OPTIONS" nil))
+ :subparser
+ (lambda (arguments argspecs seen)
+ (let ((command (pop arguments)))
+ (push (list :name 0
+ :stub command
+ :values (list command)
+ :action '("COMMAND"
pcmpl-args-pass-subcommands))
+ seen)
+ (when arguments
+ (let ((specs (pcmpl-args-pass-subcommand-specs command)))
+ (setq argspecs (pcmpl-args-make-argspecs specs)))))
+ (list arguments argspecs seen)))))))
+
+
;;; Testing
(defun pcmpl-args--debug-parse-help-buffer ()
@@ -3683,7 +3831,7 @@ will print completions for `ls -'."
;; (insert (format "\n\n;;;###autoload (dolist (func '(%s)) (autoload func
\"pcmpl-args\"))\n"
;; (mapconcat 'identity accum " "))))
-;;;###autoload (dolist (func '(pcomplete/chgrp pcomplete/chmod pcomplete/chown
pcomplete/chroot pcomplete/cp pcomplete/date pcomplete/dd pcomplete/dir
pcomplete/echo pcomplete/env pcomplete/false pcomplete/groups pcomplete/id
pcomplete/ln pcomplete/ls pcomplete/mv pcomplete/nice pcomplete/nohup
pcomplete/printenv pcomplete/printf pcomplete/rm pcomplete/rmdir pcomplete/sort
pcomplete/stat pcomplete/test pcomplete/true pcomplete/vdir pcomplete/basename
pcomplete/cat pcomplete/cksum pcomple [...]
+;;;###autoload (dolist (func '(pcomplete/chgrp pcomplete/chmod pcomplete/chown
pcomplete/chroot pcomplete/cp pcomplete/date pcomplete/dd pcomplete/dir
pcomplete/echo pcomplete/env pcomplete/false pcomplete/groups pcomplete/id
pcomplete/ln pcomplete/ls pcomplete/mv pcomplete/nice pcomplete/nohup
pcomplete/printenv pcomplete/printf pcomplete/rm pcomplete/rmdir pcomplete/sort
pcomplete/stat pcomplete/test pcomplete/true pcomplete/vdir pcomplete/basename
pcomplete/cat pcomplete/cksum pcomple [...]
(provide 'pcmpl-args)
;;; pcmpl-args.el ends here
- [nongnu] branch elpa/pcmpl-args created (now 02ae18bda3), ELPA Syncer, 2022/01/31
- [nongnu] elpa/pcmpl-args 4d74a0d768 11/33: Move README to README.org, ELPA Syncer, 2022/01/31
- [nongnu] elpa/pcmpl-args 690360006d 21/33: Fixed backspaces in man and git completion, ELPA Syncer, 2022/01/31
- [nongnu] elpa/pcmpl-args 36139ba64f 20/33: Added pass completion,
ELPA Syncer <=
- [nongnu] elpa/pcmpl-args 66276289e9 24/33: Fixed useless regexp, ELPA Syncer, 2022/01/31
- [nongnu] elpa/pcmpl-args 3e479c852b 03/33: Add link to github repo, ELPA Syncer, 2022/01/31
- [nongnu] elpa/pcmpl-args 886f0c4967 02/33: Add autoloads and packaging support, ELPA Syncer, 2022/01/31
- [nongnu] elpa/pcmpl-args 2ba03b3125 06/33: Add README and more documentation, ELPA Syncer, 2022/01/31
- [nongnu] elpa/pcmpl-args f06b973c67 08/33: Merge pull request #1 from kozikow/master, ELPA Syncer, 2022/01/31
- [nongnu] elpa/pcmpl-args c124d44bf4 09/33: Use cache for git completions, ELPA Syncer, 2022/01/31
- [nongnu] elpa/pcmpl-args 43f3daada7 19/33: Fix return outside of the block, ELPA Syncer, 2022/01/31
- [nongnu] elpa/pcmpl-args 7d444d5793 22/33: Update minor version, ELPA Syncer, 2022/01/31
- [nongnu] elpa/pcmpl-args 910f42cdbd 31/33: Fix package-lint warnings, ELPA Syncer, 2022/01/31
- [nongnu] elpa/pcmpl-args 1a1f5f5eab 05/33: Fix annotation display width on ttys, ELPA Syncer, 2022/01/31