refactor: rename to password-store-ivy

This commit is contained in:
Pavel Korytov 2022-02-13 13:02:37 +03:00
parent 3a2794b63a
commit f8bb907a5b
4 changed files with 91 additions and 91 deletions

View file

@ -24,7 +24,7 @@ jobs:
env: env:
LOCAL_REPO: ${{ github.workspace }} LOCAL_REPO: ${{ github.workspace }}
# RECIPE is your recipe as written for MELPA: # RECIPE is your recipe as written for MELPA:
RECIPE: (ivy-pass :repo "SqrtMinusOne/ivy-pass" :fetcher github) RECIPE: (password-store-ivy :repo "SqrtMinusOne/password-store-ivy" :fetcher github)
# set this to false (or remove it) if the package isn't on MELPA: # set this to false (or remove it) if the package isn't on MELPA:
EXIST_OK: false EXIST_OK: false
run: echo $GITHUB_REF && make -C ~/melpazoid run: echo $GITHUB_REF && make -C ~/melpazoid

2
Cask
View file

@ -1,4 +1,4 @@
(source gnu) (source gnu)
(source melpa) (source melpa)
(package-file "ivy-pass.el") (package-file "password-store-ivy.el")

View file

@ -1,8 +1,8 @@
#+TITLE: ivy-pass #+TITLE: password-store-ivy
A [[https://www.passwordstore.org/][pass]] frontend based on [[https://github.com/abo-abo/swiper#ivy][Ivy]], made primarily to use with [[https://github.com/ch11ng/exwm][EXWM]] and [[https://github.com/tumashu/ivy-posframe][ivy-posframe]]. Types fields from entries. A [[https://www.passwordstore.org/][pass]] frontend based on [[https://github.com/abo-abo/swiper#ivy][Ivy]], made primarily to use with [[https://github.com/ch11ng/exwm][EXWM]] and [[https://github.com/tumashu/ivy-posframe][ivy-posframe]]. Types fields from entries.
Also take a look at Nicolas Petton's [[https://github.com/NicolasPetton/pass][pass]], =ivy-pass= is designed as complementary to the Nicolas' package. Also take a look at Nicolas Petton's [[https://github.com/NicolasPetton/pass][pass]], =password-store-ivy= is designed as complementary to the Nicolas' package.
This package is made with Ivy because I need some fine-tuning like actions and turning off the sort in some completions, and Ivy happens to be the competing system I'm using now. This package is made with Ivy because I need some fine-tuning like actions and turning off the sort in some completions, and Ivy happens to be the competing system I'm using now.
@ -10,8 +10,8 @@ This package is made with Ivy because I need some fine-tuning like actions and t
As the package isnt yet available anywhere but in this repository, you can clone the repository, add it to the load-path and require the package. My preferred way is =use-package= with =straight=: As the package isnt yet available anywhere but in this repository, you can clone the repository, add it to the load-path and require the package. My preferred way is =use-package= with =straight=:
#+begin_src emacs-lisp #+begin_src emacs-lisp
(use-package ivy-pass (use-package password-store-ivy
:straight (:host github :repo "SqrtMinusOne/ivy-pass") :straight (:host github :repo "SqrtMinusOne/password-store-ivy")
:after (exwm)) :after (exwm))
#+end_src #+end_src
@ -19,7 +19,7 @@ This package types stuff with =xdotool=, so you need to have that available in y
* Usage * Usage
Emacs' built-in [[https://www.gnu.org/software/emacs/manual/html_node/auth/The-Unix-password-store.html][password store]] integration has to be set up. Emacs' built-in [[https://www.gnu.org/software/emacs/manual/html_node/auth/The-Unix-password-store.html][password store]] integration has to be set up.
The only command is =M-x ivy-pass=, which invokes Ivy to select an entry from the pass database. Available commands in the selection buffer: The only command is =M-x password-store-ivy=, which invokes Ivy to select an entry from the pass database. Available commands in the selection buffer:
- =M-a=. Perform autotype - =M-a=. Perform autotype
- =M-p=. Type password - =M-p=. Type password
- =M-u=. Type username - =M-u=. Type username
@ -28,10 +28,10 @@ The only command is =M-x ivy-pass=, which invokes Ivy to select an entry from th
* Customization * Customization
There are a few parameters that control delays: There are a few parameters that control delays:
- =ivy-pass-initial-wait= controls the initial delay before starting to type a sequence (in milliseconds) - =password-store-ivy-initial-wait= controls the initial delay before starting to type a sequence (in milliseconds)
- =ivy-pass-delay= controls the delay between typing characters (in milliseconds) - =password-store-ivy-delay= controls the delay between typing characters (in milliseconds)
There is also =ivy-pass-sequences= that determines the sequence of actions =ivy-pass= performs. There is also =password-store-ivy-sequences= that determines the sequence of actions =password-store-ivy= performs.
It is an alist with the following required keys (corresponding to the basic actions): It is an alist with the following required keys (corresponding to the basic actions):
- =autotype= - =autotype=
@ -40,7 +40,7 @@ It is an alist with the following required keys (corresponding to the basic acti
- =url= - =url=
The values are lists of the following elements: The values are lists of the following elements:
- =wait=. Wait for =ivy-pass-initial-wait= milliseconds - =wait=. Wait for =password-store-ivy-initial-wait= milliseconds
- =(wait <milliseconds>)=. Wait for =<milliseconds>=. - =(wait <milliseconds>)=. Wait for =<milliseconds>=.
- =(key <key>)=. Type =<key>=. - =(key <key>)=. Type =<key>=.
- =(field <field>)=. Type =<field>= of entry. - =(field <field>)=. Type =<field>= of entry.
@ -57,7 +57,7 @@ For example, the starting values:
(url . (wait (field . "url")))) (url . (wait (field . "url"))))
#+end_src #+end_src
In addition to the global override, sequences can be overriden per-entry with a field called =sequence-<name>=, where =<name>= is a key of =ivy-pass-sequences=. In addition to the global override, sequences can be overriden per-entry with a field called =sequence-<name>=, where =<name>= is a key of =password-store-ivy-sequences=.
For example, here is an override to press =Tab= twice: For example, here is an override to press =Tab= twice:
#+begin_example #+begin_example

View file

@ -1,4 +1,4 @@
;;; ivy-pass.el --- A simple pass frontend for Ivy -*- lexical-binding: t -*- ;;; password-store-ivy --- A simple pass frontend for Ivy -*- lexical-binding: t -*-
;; Copyright (C) 2022 Korytov Pavel ;; Copyright (C) 2022 Korytov Pavel
@ -31,12 +31,12 @@
;; This package types stuff with xdotool, so you need to have that ;; This package types stuff with xdotool, so you need to have that
;; available in your $PATH. ;; available in your $PATH.
;; ;;
;; The only command is `ivy-pass', which presents an Ivy buffer to ;; The only command is `password-store-ivy', which presents an Ivy buffer to
;; select some entry from the pass database. Take a look at its ;; select some entry from the pass database. Take a look at its
;; docstring for mode detail. ;; docstring for mode detail.
;; ;;
;; Also take a look at the package README at ;; Also take a look at the package README at
;; <https://github.com/SqrtMinusOne/ivy-pass>. ;; <https://github.com/SqrtMinusOne/password-store-ivy>.
;;; Code: ;;; Code:
(require 'ivy) (require 'ivy)
@ -44,21 +44,21 @@
(require 'auth-source-pass) (require 'auth-source-pass)
(require 'password-store) (require 'password-store)
(defgroup ivy-pass () (defgroup password-store-ivy ()
"An ivy-based pass frontend." "An ivy-based pass frontend."
:group 'password-store) :group 'password-store)
(defcustom ivy-pass-initial-wait 250 (defcustom password-store-ivy-initial-wait 250
"How much milliseconds to wait before typing characters." "How much milliseconds to wait before typing characters."
:type 'integer :type 'integer
:group 'ivy-pass) :group 'password-store-ivy)
(defcustom ivy-pass-delay 50 (defcustom password-store-ivy-delay 50
"Delay between typing characters." "Delay between typing characters."
:type 'integer :type 'integer
:group 'ivy-pass) :group 'password-store-ivy)
(defcustom ivy-pass-sequences (defcustom password-store-ivy-sequences
'((autotype . (wait '((autotype . (wait
(field . "username") (field . "username")
(key . "Tab") (key . "Tab")
@ -67,7 +67,7 @@
(password . (wait (field . secret))) (password . (wait (field . secret)))
(username . (wait (field . "username"))) (username . (wait (field . "username")))
(url . (wait (field . "url")))) (url . (wait (field . "url"))))
"Sequences to execute by `ivy-pass'. "Sequences to execute by `password-store-ivy'.
It is an alist with the following required keys (corresponding to the It is an alist with the following required keys (corresponding to the
basic actions): basic actions):
@ -77,14 +77,14 @@ basic actions):
- url - url
Values are lists of symbols that determine action. Take a look at Values are lists of symbols that determine action. Take a look at
`ivy-pass--get-commands' for available options." `password-store-ivy--get-commands' for available options."
:group 'ivy-pass :group 'password-store-ivy
:options '(autotype password username url) :options '(autotype password username url)
:type '(alist :key-type (symbol :tag "Sequence name") :type '(alist :key-type (symbol :tag "Sequence name")
:value-type (repeat :value-type (repeat
:tag "Sequence contents" :tag "Sequence contents"
(choice (choice
(const :tag "Wait for `ivy-pass-initial-wait'" wait) (const :tag "Wait for `password-store-ivy-initial-wait'" wait)
(cons (cons
:tag "Wait for milliseconds" :tag "Wait for milliseconds"
(const :tag "Wait for milliseconds" wait) (const :tag "Wait for milliseconds" wait)
@ -105,7 +105,7 @@ Values are lists of symbols that determine action. Take a look at
(const "Return") (const "Return")
(string :tag "Other key"))))))) (string :tag "Other key")))))))
(defun ivy-pass--async-command (command callback) (defun password-store-ivy--async-command (command callback)
"Run COMMAND in shell asyncronously. "Run COMMAND in shell asyncronously.
Call CALLBACK when the command in finished." Call CALLBACK when the command in finished."
@ -118,49 +118,49 @@ Call CALLBACK when the command in finished."
('exit (funcall callback)) ('exit (funcall callback))
('fatal (error "Error in running %s" command))))))) ('fatal (error "Error in running %s" command)))))))
(defun ivy-pass--async-commands (commands &optional callback) (defun password-store-ivy--async-commands (commands &optional callback)
"Run COMMANDS asyncronously. "Run COMMANDS asyncronously.
Call CALLBACK when the last command is executed." Call CALLBACK when the last command is executed."
(if (seq-empty-p commands) (if (seq-empty-p commands)
(when callback (funcall callback)) (when callback (funcall callback))
(ivy-pass--async-command (password-store-ivy--async-command
(car commands) (car commands)
(lambda () (lambda ()
(ivy-pass--async-commands (password-store-ivy--async-commands
(cdr commands) (cdr commands)
callback))))) callback)))))
(defun ivy-pass--get-type-command (str) (defun password-store-ivy--get-type-command (str)
"Return a command to type STR." "Return a command to type STR."
(concat (concat
"printf " "printf "
(shell-quote-argument str) (shell-quote-argument str)
"| xdotool type --clearmodifiers --file - --delay " "| xdotool type --clearmodifiers --file - --delay "
(number-to-string ivy-pass-delay))) (number-to-string password-store-ivy-delay)))
(defun ivy-pass--get-wait-command (&optional milliseconds) (defun password-store-ivy--get-wait-command (&optional milliseconds)
"Return a command to sleep for MILLISECONDS. "Return a command to sleep for MILLISECONDS.
If MILLISECONDS is nil, default to `ivy-pass-initial-wait'." If MILLISECONDS is nil, default to `password-store-ivy-initial-wait'."
(format "sleep %f" (/ (float (or milliseconds ivy-pass-initial-wait)) 1000))) (format "sleep %f" (/ (float (or milliseconds password-store-ivy-initial-wait)) 1000)))
(defun ivy-pass--get-key-command (key) (defun password-store-ivy--get-key-command (key)
"Get a command that presses KEY." "Get a command that presses KEY."
(format "xdotool key %s" key)) (format "xdotool key %s" key))
(defun ivy-pass--get-entry-command (entry field) (defun password-store-ivy--get-entry-command (entry field)
"Get a command to type FIELD of ENTRY. "Get a command to type FIELD of ENTRY.
ENTRY is an alist, FIELD is a symbol or string that can be a key of alist" ENTRY is an alist, FIELD is a symbol or string that can be a key of alist"
(when-let ((contents (alist-get field entry nil nil #'equal))) (when-let ((contents (alist-get field entry nil nil #'equal)))
(ivy-pass--get-type-command contents))) (password-store-ivy--get-type-command contents)))
(defun ivy-pass--get-commands (entry sequence) (defun password-store-ivy--get-commands (entry sequence)
"Get a list of commands to execute for ENTRY. "Get a list of commands to execute for ENTRY.
SEQUENCE is a list of the following elements: SEQUENCE is a list of the following elements:
- `wait'. Wait for `ivy-pass-initial-wait' milliseconds. - `wait'. Wait for `password-store-ivy-initial-wait' milliseconds.
- `(wait <milliseconds>)'. Wait for <milliseconds>. - `(wait <milliseconds>)'. Wait for <milliseconds>.
- `(key <key>)'. Type <key>. - `(key <key>)'. Type <key>.
- `(field <field>)'. Type <field> of entry." - `(field <field>)'. Type <field> of entry."
@ -171,36 +171,36 @@ SEQUENCE is a list of the following elements:
(unless (sequencep elem) (unless (sequencep elem)
(setq elem (list elem))) (setq elem (list elem)))
(pcase (car elem) (pcase (car elem)
('wait (ivy-pass--get-wait-command (cdr elem))) ('wait (password-store-ivy--get-wait-command (cdr elem)))
('key (ivy-pass--get-key-command (cdr elem))) ('key (password-store-ivy--get-key-command (cdr elem)))
('field (ivy-pass--get-entry-command entry (cdr elem))) ('field (password-store-ivy--get-entry-command entry (cdr elem)))
(_ (error "Wrong field: %s" (prin1-to-string elem))))) (_ (error "Wrong field: %s" (prin1-to-string elem)))))
sequence))) sequence)))
(defun ivy-pass--get-entry (entry-name) (defun password-store-ivy--get-entry (entry-name)
"Get a pass entry by ENTRY-NAME." "Get a pass entry by ENTRY-NAME."
(let ((entry (auth-source-pass-parse-entry entry-name))) (let ((entry (auth-source-pass-parse-entry entry-name)))
(unless entry (unless entry
(user-error "The entry is empty. Perhaps password was incorrect?")) (user-error "The entry is empty. Perhaps password was incorrect?"))
entry)) entry))
(defun ivy-pass--get-sequence (entry sequence-name) (defun password-store-ivy--get-sequence (entry sequence-name)
"Get a sequence from an ENTRY. "Get a sequence from an ENTRY.
SEQUENCE-NAME is a key of `ivy-pass-sequences'." SEQUENCE-NAME is a key of `password-store-ivy-sequences'."
(or (when-let ((str (alist-get (or (when-let ((str (alist-get
(format "sequence-%s" (symbol-name sequence-name)) (format "sequence-%s" (symbol-name sequence-name))
entry nil nil #'equal))) entry nil nil #'equal)))
(condition-case err (condition-case err
(car (read-from-string str)) (car (read-from-string str))
(error (error "Error in %s: %s" str (prin1-to-string err))))) (error (error "Error in %s: %s" str (prin1-to-string err)))))
(alist-get sequence-name ivy-pass-sequences))) (alist-get sequence-name password-store-ivy-sequences)))
(defmacro ivy-pass--def-command (name &rest body) (defmacro password-store-ivy--def-command (name &rest body)
"Create functions to be invoked from `ivy-pass'. "Create functions to be invoked from `password-store-ivy'.
NAME is the base name. The first function created, NAME-command, NAME is the base name. The first function created, NAME-command,
can be executed inside the `ivy-pass' completion interface. can be executed inside the `password-store-ivy' completion interface.
The second function, NAME-action, can be registered as an action, The second function, NAME-action, can be registered as an action,
e.g. with `ivy-set-actions'. e.g. with `ivy-set-actions'.
@ -213,33 +213,33 @@ the current entry available via the `entry' variable."
(interactive) (interactive)
(ivy-exit-with-action (ivy-exit-with-action
(lambda (entry-name) (lambda (entry-name)
(let ((entry (ivy-pass--get-entry entry-name))) (let ((entry (password-store-ivy--get-entry entry-name)))
,@body)))) ,@body))))
(defun ,(intern (format "%s-action" name)) (entry-name) (defun ,(intern (format "%s-action" name)) (entry-name)
(let ((entry (ivy-pass--get-entry entry-name))) (let ((entry (password-store-ivy--get-entry entry-name)))
,@body)))) ,@body))))
(ivy-pass--def-command ivy-pass--autotype (password-store-ivy--def-command password-store-ivy--autotype
(ivy-pass--async-commands (password-store-ivy--async-commands
(ivy-pass--get-commands (password-store-ivy--get-commands
entry (ivy-pass--get-sequence entry 'autotype)))) entry (password-store-ivy--get-sequence entry 'autotype))))
(ivy-pass--def-command ivy-pass--password (password-store-ivy--def-command password-store-ivy--password
(ivy-pass--async-commands (password-store-ivy--async-commands
(ivy-pass--get-commands (password-store-ivy--get-commands
entry (ivy-pass--get-sequence entry 'password)))) entry (password-store-ivy--get-sequence entry 'password))))
(ivy-pass--def-command ivy-pass--username (password-store-ivy--def-command password-store-ivy--username
(ivy-pass--async-commands (password-store-ivy--async-commands
(ivy-pass--get-commands (password-store-ivy--get-commands
entry (ivy-pass--get-sequence entry 'username)))) entry (password-store-ivy--get-sequence entry 'username))))
(ivy-pass--def-command ivy-pass--url (password-store-ivy--def-command password-store-ivy--url
(ivy-pass--async-commands (password-store-ivy--async-commands
(ivy-pass--get-commands (password-store-ivy--get-commands
entry (ivy-pass--get-sequence entry 'url)))) entry (password-store-ivy--get-sequence entry 'url))))
(ivy-pass--def-command ivy-pass--fields (password-store-ivy--def-command password-store-ivy--fields
(let ((sequences (let ((sequences
(mapcar (mapcar
(lambda (item) (lambda (item)
@ -258,46 +258,46 @@ the current entry available via the `entry' variable."
:require-match t :require-match t
:sort nil :sort nil
:action (lambda (data) :action (lambda (data)
(ivy-pass--async-commands (password-store-ivy--async-commands
(ivy-pass--get-commands (password-store-ivy--get-commands
entry entry
(cdr data))))))) (cdr data)))))))
(defvar ivy-pass-map (defvar password-store-ivy-map
(let ((map (make-sparse-keymap))) (let ((map (make-sparse-keymap)))
(define-key map (kbd "M-a") #'ivy-pass--autotype-command) (define-key map (kbd "M-a") #'password-store-ivy--autotype-command)
(define-key map (kbd "M-p") #'ivy-pass--password-command) (define-key map (kbd "M-p") #'password-store-ivy--password-command)
(define-key map (kbd "M-u") #'ivy-pass--username-command) (define-key map (kbd "M-u") #'password-store-ivy--username-command)
(define-key map (kbd "M-U") #'ivy-pass--url-command) (define-key map (kbd "M-U") #'password-store-ivy--url-command)
(define-key map (kbd "M-f") #'ivy-pass--fields-command) (define-key map (kbd "M-f") #'password-store-ivy--fields-command)
map) map)
"A keymap for `ivy-pass'.") "A keymap for `password-store-ivy'.")
(defvar ivy-pass-history nil (defvar password-store-ivy-history nil
"History for `ivy-pass'.") "History for `password-store-ivy'.")
;;;###autoload ;;;###autoload
(defun ivy-pass () (defun password-store-ivy ()
"A frontend for pass. "A frontend for pass.
The command invokes Ivy to select an entry from the pass The command invokes Ivy to select an entry from the pass
database (with `password-store-list'). database (with `password-store-list').
Available commands: Available commands:
\\{ivy-pass-map}" \\{password-store-ivy-map}"
(interactive) (interactive)
(ivy-read "Pass entry: " (ivy-read "Pass entry: "
(password-store-list) (password-store-list)
:require-match t :require-match t
:history 'ivy-pass-history :history 'password-store-ivy-history
:keymap ivy-pass-map :keymap password-store-ivy-map
:action '(1 :action '(1
("p" ivy-pass--password-action "password") ("p" password-store-ivy--password-action "password")
("a" ivy-pass--autotype-action "autotype") ("a" password-store-ivy--autotype-action "autotype")
("f" ivy-pass--fields-action "fields") ("f" password-store-ivy--fields-action "fields")
("u" ivy-pass--username-action "username") ("u" password-store-ivy--username-action "username")
("U" ivy-pass--url-action "url")) ("U" password-store-ivy--url-action "url"))
:caller #'ivy-pass)) :caller #'password-store-ivy))
(provide 'ivy-pass) (provide 'password-store-ivy)
;;; ivy-pass.el ends here ;;; password-store-ivy.el ends here