feat - tag prompt using choice.el

This commit is contained in:
contrapunctus 2021-02-10 12:52:19 +05:30
parent b219876378
commit c27ac66a30
2 changed files with 31 additions and 85 deletions

3
Cask
View File

@ -6,12 +6,13 @@
"0.6.4"
"A time tracker for Emacs with a nice interface")
(depends-on "cl")
(depends-on "cl-lib")
(depends-on "dash" "2.16.0")
(depends-on "seq" "2.20")
(depends-on "s" "1.12.0")
(depends-on "ts" "0.2")
(depends-on "anaphora" "1.0.4")
(depends-on "choice" "0.1.0")
(files "elisp/*.el")

View File

@ -5,6 +5,7 @@
(require 'dash)
(require 'seq)
(require 'anaphora)
(require 'choice)
(require 'chronometrist-migrate)
(require 'chronometrist-events)
@ -488,98 +489,42 @@ This function always returns t, so it can be used in `chronometrist-before-out-f
;; [x] we want C-g to quit, and universal arg to work...
;; Subsume `chronometrist-choice/body' into `chronometrist-choice-define-commands'? Or we'll have
;; to pass suggestions twice...
;; FIXME - incorrect tags added to file
;; defchoice expands to...
;; define a global var for state ("key", form, "hint")
;; (another macro?) define commands using FORM in state
;; define keymap, use state to bind commands to given keys
;; define a foo/function to (analogous to Hydra's foo/body)
;; we make a macro to generate choice prompts at runtime
(defun chronometrist-defchoice (mode key table)
"MODE ::= :tag
| :key
| :value
(defmacro defchoice (name &rest choices)
`(progn
(defvar ,(intern (format "%s-state")) choices)
(defun ,(intern (format "%s-prompt" name)) nil)))
(defun chronometrist-choice-command-name (i)
(intern (format "chronometrist-choice-%s" i)))
(defvar chronometrist-tag-choice/state nil)
(defmacro chronometrist-choice-define-commands (type)
"TYPE can be one of :tag, :key, or :value."
(cl-loop with seq = chronometrist-tag-choice/state
with num = 0
for elt in seq do (incf num)
KEY ::= \"task\" (if MODE is :tags or :keys)
| \"key\" (if MODE is :values)"
(cl-loop with num = 0
for comb in (-take 10 (gethash key table))
do (incf num)
if (= num 10) do (setq num 0)
collect
`(defun ,(chronometrist-choice-command-name num) (&optional arg)
(interactive "P")
(chronometrist-sexp-replace-last
(chronometrist-plist-update
(chronometrist-sexp-last)
(quote ,(case type
(:tag (list :tags elt))
(t elt)))))) into forms
finally
(cl-return
`(progn ,@forms
(defun chronometrist-choice-skip () (interactive))))))
(list (format "%s" num)
`(chronometrist-sexp-replace-last
(chronometrist-plist-update (chronometrist-sexp-last) ',(list :tags comb)))
(format "%s" comb))
into numeric-commands
finally do
(eval `(defchoice ,(intern
(format
"chronometrist-%s" (s-chop-prefix ":" (symbol-name mode))))
,@numeric-commands
("s" nil "skip")))))
(defun chronometrist-choice/body (prompt choices)
"Query user with PROMPT to choose an element of SEQ.
Each element corresponds to a numeric key (0-9). See
`chronometrist-choice-define-commands' for creating the commands
called by this function."
(let* (text
(map (aprog1 (make-sparse-keymap)
(set-keymap-parent it (current-global-map))
(cl-loop with sep = ", "
for choice in choices
do (incf num)
if (= num 10) do (setq num 0 sep ".")
collect
(-let [(key form hint) choice]
(define-key it (kbd key)
(chronometrist-choice-command-name num))
(format "[%s]: %s%s" num hint sep)) into hints
finally do
(setq text
(propertize (apply #'concat prompt ": " hints)
'face 'minibuffer-prompt)))))
(key (read-key-sequence text))
(cmd (lookup-key map key)))
(command-execute cmd)
;; cmd
))
(defun chronometrist-tags-choice (task)
(defun chronometrist-tag-choice (task)
"Query user for tags to be added to TASK.
Return t, to permit use in `chronometrist-before-out-functions'."
(chronometrist-tags-history-populate task chronometrist-tags-history chronometrist-file)
(if (hash-table-empty-p chronometrist-tags-history)
(chronometrist-tags-add)
(cl-loop with num = 0
for comb in (-take 10 (gethash task chronometrist-tags-history))
do (incf num)
if (= num 10) do (setq num 0)
collect
(list (format "%s" num)
`(chronometrist-sexp-replace-last
(chronometrist-plist-update (chronometrist-sexp-last) (quote ,(list :tags comb))))
(format "%s" comb))
into numeric-commands
finally do
(setq chronometrist-tag-choice/state
(append numeric-commands
'(("s" (defun chronometrist-choice-skip () (interactive)) "skip")))))
(chronometrist-choice-define-commands :tag)
(chronometrist-choice/body "Which tags?" chronometrist-tag-choice/state))
t)
(let ((table chronometrist-tags-history))
(chronometrist-tags-history-populate task table chronometrist-file)
(if (hash-table-empty-p table)
(chronometrist-tags-add)
(chronometrist-defchoice :tag task table)
(chronometrist-tag-choice-prompt "Which tags?"))
t))
(provide 'chronometrist-key-values)