diff options
| author | Stephen Berman | 2013-12-20 18:21:12 +0100 |
|---|---|---|
| committer | Stephen Berman | 2013-12-20 18:21:12 +0100 |
| commit | f3a66082f986c33df1c72b0ab2b77195cdd8b435 (patch) | |
| tree | 3ec14c9da30b1d0aacd5a1954116e4ea23804630 | |
| parent | 2f99433b944d602c382bfa87c8e3e27b1eaaed3b (diff) | |
| download | emacs-f3a66082f986c33df1c72b0ab2b77195cdd8b435.tar.gz emacs-f3a66082f986c33df1c72b0ab2b77195cdd8b435.zip | |
New implementation of Todo item insertion commands and key bindings.
* calendar/todo-mode.el: New implementation of item insertion
commands and key bindings.
(todo-key-prompt): New face.
(todo-insert-item): New command.
(todo-insert-item--parameters): New defconst, replacing defvar
todo-insertion-commands-args-genlist.
(todo-insert-item--param-key-alist): New defconst, replacing
defvar todo-insertion-commands-arg-key-list.
(todo-insert-item--keyof, todo-insert-item--this-key): New defsubsts.
(todo-insert-item--argsleft, todo-insert-item--apply-args)
(todo-insert-item--next-param): New functions.
(todo-insert-item--args, todo-insert-item--argleft)
(todo-insert-item--argsleft, todo-insert-item--newargsleft):
New variables.
(todo-key-bindings-t): Change binding of "i" from
todo-insertion-map to todo-insert-item.
(todo-powerset, todo-gen-arglists, todo-insertion-commands-args)
(todo-insertion-command-name, todo-insertion-commands-names)
(todo-define-insertion-command, todo-insertion-commands)
(todo-insertion-key-bindings, todo-insertion-map): Remove.
| -rw-r--r-- | lisp/ChangeLog | 23 | ||||
| -rw-r--r-- | lisp/calendar/todo-mode.el | 330 |
2 files changed, 220 insertions, 133 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index e367749fb39..3286c90caed 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,5 +1,28 @@ | |||
| 1 | 2013-12-20 Stephen Berman <stephen.berman@gmx.net> | 1 | 2013-12-20 Stephen Berman <stephen.berman@gmx.net> |
| 2 | 2 | ||
| 3 | * calendar/todo-mode.el: New implementation of item insertion | ||
| 4 | commands and key bindings. | ||
| 5 | (todo-key-prompt): New face. | ||
| 6 | (todo-insert-item): New command. | ||
| 7 | (todo-insert-item--parameters): New defconst, replacing defvar | ||
| 8 | todo-insertion-commands-args-genlist. | ||
| 9 | (todo-insert-item--param-key-alist): New defconst, replacing | ||
| 10 | defvar todo-insertion-commands-arg-key-list. | ||
| 11 | (todo-insert-item--keyof, todo-insert-item--this-key): New defsubsts. | ||
| 12 | (todo-insert-item--argsleft, todo-insert-item--apply-args) | ||
| 13 | (todo-insert-item--next-param): New functions. | ||
| 14 | (todo-insert-item--args, todo-insert-item--argleft) | ||
| 15 | (todo-insert-item--argsleft, todo-insert-item--newargsleft): | ||
| 16 | New variables. | ||
| 17 | (todo-key-bindings-t): Change binding of "i" from | ||
| 18 | todo-insertion-map to todo-insert-item. | ||
| 19 | (todo-powerset, todo-gen-arglists, todo-insertion-commands-args) | ||
| 20 | (todo-insertion-command-name, todo-insertion-commands-names) | ||
| 21 | (todo-define-insertion-command, todo-insertion-commands) | ||
| 22 | (todo-insertion-key-bindings, todo-insertion-map): Remove. | ||
| 23 | |||
| 24 | 2013-12-20 Stephen Berman <stephen.berman@gmx.net> | ||
| 25 | |||
| 3 | * calendar/todo-mode.el: Bug fixes and new features (bug#15225). | 26 | * calendar/todo-mode.el: Bug fixes and new features (bug#15225). |
| 4 | (todo-toggle-item-highlighting): Use eval-and-compile instead of | 27 | (todo-toggle-item-highlighting): Use eval-and-compile instead of |
| 5 | eval-when-compile. | 28 | eval-when-compile. |
diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el index 3dcb305f05a..055c97972a8 100644 --- a/lisp/calendar/todo-mode.el +++ b/lisp/calendar/todo-mode.el | |||
| @@ -330,6 +330,11 @@ shown in the Fancy Diary display." | |||
| 330 | ;;; Faces | 330 | ;;; Faces |
| 331 | ;; ----------------------------------------------------------------------------- | 331 | ;; ----------------------------------------------------------------------------- |
| 332 | 332 | ||
| 333 | (defface todo-key-prompt | ||
| 334 | '((t (:weight bold))) | ||
| 335 | "Face for making keys in item insertion prompt stand out." | ||
| 336 | :group 'todo-faces) | ||
| 337 | |||
| 333 | (defface todo-mark | 338 | (defface todo-mark |
| 334 | ;; '((t :inherit font-lock-warning-face)) | 339 | ;; '((t :inherit font-lock-warning-face)) |
| 335 | '((((class color) | 340 | '((((class color) |
| @@ -1743,6 +1748,30 @@ marking of the next N items." | |||
| 1743 | (defvar todo-date-from-calendar nil | 1748 | (defvar todo-date-from-calendar nil |
| 1744 | "Helper variable for setting item date from the Emacs Calendar.") | 1749 | "Helper variable for setting item date from the Emacs Calendar.") |
| 1745 | 1750 | ||
| 1751 | (defvar todo-insert-item--keys-so-far) | ||
| 1752 | (defvar todo-insert-item--parameters) | ||
| 1753 | |||
| 1754 | (defun todo-insert-item (&optional arg) | ||
| 1755 | "Insert a new todo item into a category. | ||
| 1756 | |||
| 1757 | With no prefix argument ARG, add the item to the current | ||
| 1758 | category; with one prefix argument (`C-u'), prompt for a category | ||
| 1759 | from the current todo file; with two prefix arguments (`C-u | ||
| 1760 | C-u'), first prompt for a todo file, then a category in that | ||
| 1761 | file. If a non-existing category is entered, ask whether to add | ||
| 1762 | it to the todo file; if answered affirmatively, add the category | ||
| 1763 | and insert the item there. | ||
| 1764 | |||
| 1765 | There are a number of item insertion parameters which can be | ||
| 1766 | combined by entering specific keys to produce different insertion | ||
| 1767 | commands. After entering each key, a message shows which have | ||
| 1768 | already been entered and which remain available. See | ||
| 1769 | `todo-basic-insert-item' for details of the parameters and their | ||
| 1770 | effects." | ||
| 1771 | (interactive "P") | ||
| 1772 | (setq todo-insert-item--keys-so-far "i") | ||
| 1773 | (todo-insert-item--next-param nil (list arg) todo-insert-item--parameters)) | ||
| 1774 | |||
| 1746 | (defun todo-basic-insert-item (&optional arg diary nonmarking date-type time | 1775 | (defun todo-basic-insert-item (&optional arg diary nonmarking date-type time |
| 1747 | region-or-here) | 1776 | region-or-here) |
| 1748 | "Insert a new todo item into a category. | 1777 | "Insert a new todo item into a category. |
| @@ -5425,131 +5454,173 @@ of each other." | |||
| 5425 | ;;; Utilities for generating item insertion commands and key bindings | 5454 | ;;; Utilities for generating item insertion commands and key bindings |
| 5426 | ;; ----------------------------------------------------------------------------- | 5455 | ;; ----------------------------------------------------------------------------- |
| 5427 | 5456 | ||
| 5428 | ;; Wolfgang Jenkner posted this powerset definition to emacs-devel | 5457 | ;; Thanks to Stefan Monnier for suggesting dynamically generating item |
| 5429 | ;; (http://lists.gnu.org/archive/html/emacs-devel/2013-06/msg00423.html) | 5458 | ;; insertion commands and their key bindings, and offering an elegant |
| 5430 | ;; and kindly gave me permission to use it. | 5459 | ;; implementation, which, however, relies on lexical scoping and so |
| 5431 | 5460 | ;; cannot be used here until the Calendar code used by todo-mode.el is | |
| 5432 | (defun todo-powerset (list) | 5461 | ;; converted to lexical binding. Hence, the following implementation |
| 5433 | "Return the powerset of LIST." | 5462 | ;; uses dynamic binding. |
| 5434 | (let ((powerset (list nil))) | 5463 | |
| 5435 | (dolist (elt list (mapcar 'reverse powerset)) | 5464 | (defconst todo-insert-item--parameters |
| 5436 | (nconc powerset (mapcar (apply-partially 'cons elt) powerset))))) | 5465 | '((default copy) diary nonmarking (calendar date dayname) time (here region)) |
| 5437 | 5466 | "List of all item insertion parameters. | |
| 5438 | (defun todo-gen-arglists (arglist) | 5467 | Passed by `todo-insert-item' to `todo-insert-item--next-param' to |
| 5439 | "Return list of lists of non-nil atoms produced from ARGLIST. | 5468 | dynamically create item insertion commands.") |
| 5440 | The elements of ARGLIST may be atoms or lists." | 5469 | |
| 5441 | (let (arglists) | 5470 | (defconst todo-insert-item--param-key-alist |
| 5442 | (while arglist | 5471 | '((default . "i") |
| 5443 | (let ((arg (pop arglist))) | 5472 | (copy . "p") |
| 5444 | (cond ((symbolp arg) | 5473 | (diary . "y") |
| 5445 | (setq arglists (if arglists | 5474 | (nonmarking . "k") |
| 5446 | (mapcar (lambda (l) (push arg l)) arglists) | 5475 | (calendar . "c") |
| 5447 | (list (push arg arglists))))) | 5476 | (date . "d") |
| 5448 | ((listp arg) | 5477 | (dayname . "n") |
| 5449 | (setq arglists | 5478 | (time . "t") |
| 5450 | (mapcar (lambda (a) | 5479 | (here . "h") |
| 5451 | (if (= 1 (length arglists)) | 5480 | (region . "r")) |
| 5452 | (apply (lambda (l) (push a l)) arglists) | 5481 | "List pairing item insertion parameters with their completion keys.") |
| 5453 | (mapcar (lambda (l) (push a l)) arglists))) | 5482 | |
| 5454 | arg)))))) | 5483 | (defsubst todo-insert-item--keyof (param) |
| 5455 | (setq arglists (mapcar 'reverse (apply 'append (mapc 'car arglists)))))) | 5484 | "Return key paired with item insertion PARAM." |
| 5456 | 5485 | (cdr (assoc param todo-insert-item--param-key-alist))) | |
| 5457 | (defvar todo-insertion-commands-args-genlist | 5486 | |
| 5458 | '(diary nonmarking (calendar date dayname) time (here region)) | 5487 | (defun todo-insert-item--argsleft (key list) |
| 5459 | "Generator list for argument lists of item insertion commands.") | 5488 | "Return sublist of LIST whose first member corresponds to KEY." |
| 5460 | 5489 | (let (l sym) | |
| 5461 | (defvar todo-insertion-commands-args | 5490 | (mapc (lambda (m) |
| 5462 | (let ((arglist (todo-gen-arglists todo-insertion-commands-args-genlist)) | 5491 | (when (consp m) |
| 5463 | res new) | 5492 | (catch 'found1 |
| 5464 | (setq res (cl-remove-duplicates | 5493 | (dolist (s m) |
| 5465 | (apply 'append (mapcar 'todo-powerset arglist)) :test 'equal)) | 5494 | (when (equal key (todo-insert-item--keyof s)) |
| 5466 | (dolist (l res) | 5495 | (throw 'found1 (setq sym s)))))) |
| 5467 | (unless (= 5 (length l)) | 5496 | (if sym |
| 5468 | (let ((v (make-vector 5 nil)) elt) | 5497 | (progn |
| 5469 | (while l | 5498 | (push sym l) |
| 5470 | (setq elt (pop l)) | 5499 | (setq sym nil)) |
| 5471 | (cond ((eq elt 'diary) | 5500 | (push m l))) |
| 5472 | (aset v 0 elt)) | 5501 | list) |
| 5473 | ((eq elt 'nonmarking) | 5502 | (setq list (reverse l))) |
| 5474 | (aset v 1 elt)) | 5503 | (memq (catch 'found2 |
| 5475 | ((or (eq elt 'calendar) | 5504 | (dolist (e todo-insert-item--param-key-alist) |
| 5476 | (eq elt 'date) | 5505 | (when (equal key (cdr e)) |
| 5477 | (eq elt 'dayname)) | 5506 | (throw 'found2 (car e))))) |
| 5478 | (aset v 2 elt)) | 5507 | list)) |
| 5479 | ((eq elt 'time) | 5508 | |
| 5480 | (aset v 3 elt)) | 5509 | (defsubst todo-insert-item--this-key () (char-to-string last-command-event)) |
| 5481 | ((or (eq elt 'here) | 5510 | |
| 5482 | (eq elt 'region)) | 5511 | (defvar todo-insert-item--keys-so-far "" |
| 5483 | (aset v 4 elt)))) | 5512 | "String of item insertion keys so far entered for this command.") |
| 5484 | (setq l (append v nil)))) | 5513 | |
| 5485 | (setq new (append new (list l)))) | 5514 | (defvar todo-insert-item--args nil) |
| 5486 | new) | 5515 | (defvar todo-insert-item--argleft nil) |
| 5487 | "List of all argument lists for Todo mode item insertion commands.") | 5516 | (defvar todo-insert-item--argsleft nil) |
| 5488 | 5517 | (defvar todo-insert-item--newargsleft nil) | |
| 5489 | (defun todo-insertion-command-name (arglist) | 5518 | |
| 5490 | "Generate Todo mode item insertion command name from ARGLIST." | 5519 | (defun todo-insert-item--apply-args () |
| 5491 | (replace-regexp-in-string | 5520 | "Build list of arguments for item insertion and apply them. |
| 5492 | "-\\_>" "" | 5521 | The list consists of item insertion parameters that can be passed |
| 5493 | (replace-regexp-in-string | 5522 | as insertion command arguments in fixed positions. If a position |
| 5494 | "-+" "-" | 5523 | in the list is not occupied by the corresponding parameter, it is |
| 5495 | (concat "todo-insert-item-" | 5524 | occupied by `nil'." |
| 5496 | (mapconcat (lambda (e) (if e (symbol-name e))) arglist "-"))))) | 5525 | (let* ((arg (list (car todo-insert-item--args))) |
| 5497 | 5526 | (args (nconc (cdr todo-insert-item--args) | |
| 5498 | (defvar todo-insertion-commands-names | 5527 | (list (car (todo-insert-item--argsleft |
| 5499 | (mapcar (lambda (l) | 5528 | (todo-insert-item--this-key) |
| 5500 | (todo-insertion-command-name l)) | 5529 | todo-insert-item--argsleft))))) |
| 5501 | todo-insertion-commands-args) | 5530 | (arglist (unless (= 5 (length args)) |
| 5502 | "List of names of Todo mode item insertion commands.") | 5531 | (let ((v (make-vector 5 nil)) elt) |
| 5503 | 5532 | (while args | |
| 5504 | (defmacro todo-define-insertion-command (&rest args) | 5533 | (setq elt (pop args)) |
| 5505 | "Generate Todo mode item insertion command definitions from ARGS." | 5534 | (cond ((eq elt 'diary) |
| 5506 | (let ((name (intern (todo-insertion-command-name args))) | 5535 | (aset v 0 elt)) |
| 5507 | (arg0 (nth 0 args)) | 5536 | ((eq elt 'nonmarking) |
| 5508 | (arg1 (nth 1 args)) | 5537 | (aset v 1 elt)) |
| 5509 | (arg2 (nth 2 args)) | 5538 | ((or (eq elt 'calendar) |
| 5510 | (arg3 (nth 3 args)) | 5539 | (eq elt 'date) |
| 5511 | (arg4 (nth 4 args))) | 5540 | (eq elt 'dayname)) |
| 5512 | `(defun ,name (&optional arg &rest args) | 5541 | (aset v 2 elt)) |
| 5513 | "Todo mode item insertion command generated from ARGS. | 5542 | ((eq elt 'time) |
| 5514 | For descriptions of the individual arguments, their values, and | 5543 | (aset v 3 elt)) |
| 5515 | their relation to key bindings, see `todo-basic-insert-item'." | 5544 | ((or (eq elt 'here) |
| 5516 | (interactive (list current-prefix-arg)) | 5545 | (eq elt 'region)) |
| 5517 | (todo-basic-insert-item arg ',arg0 ',arg1 ',arg2 ',arg3 ',arg4)))) | 5546 | (aset v 4 elt)))) |
| 5518 | 5547 | (append v nil))))) | |
| 5519 | (defvar todo-insertion-commands | 5548 | (apply #'todo-basic-insert-item (nconc arg arglist)))) |
| 5520 | (mapcar (lambda (c) | 5549 | |
| 5521 | (eval `(todo-define-insertion-command ,@c))) | 5550 | (defun todo-insert-item--next-param (last args argsleft) |
| 5522 | todo-insertion-commands-args) | 5551 | "Build item insertion command from LAST, ARGS and ARGSLEFT and call it. |
| 5523 | "List of Todo mode item insertion commands.") | 5552 | Dynamically generate key bindings, prompting with the keys |
| 5524 | 5553 | already entered and those still available." | |
| 5525 | (defvar todo-insertion-commands-arg-key-list | 5554 | (cl-assert argsleft) |
| 5526 | '(("diary" "y" "yy") | 5555 | (let* ((map (make-sparse-keymap)) |
| 5527 | ("nonmarking" "k" "kk") | 5556 | (prompt nil) |
| 5528 | ("calendar" "c" "cc") | 5557 | (addprompt (lambda (k name) |
| 5529 | ("date" "d" "dd") | 5558 | (setq prompt (concat prompt |
| 5530 | ("dayname" "n" "nn") | 5559 | (format (concat |
| 5531 | ("time" "t" "tt") | 5560 | (if (or (eq name 'default) |
| 5532 | ("here" "h" "h") | 5561 | (eq name 'calendar) |
| 5533 | ("region" "r" "r")) | 5562 | (eq name 'here)) |
| 5534 | "List of mappings of item insertion command arguments to key sequences.") | 5563 | " { " " ") |
| 5535 | 5564 | "%s=>%s" | |
| 5536 | (defun todo-insertion-key-bindings (map) | 5565 | (when (or (eq name 'copy) |
| 5537 | "Generate key binding definitions for item insertion keymap MAP." | 5566 | (eq name 'dayname) |
| 5538 | (dolist (c todo-insertion-commands) | 5567 | (eq name 'region)) |
| 5539 | (let* ((key "") | 5568 | " }")) |
| 5540 | (cname (symbol-name c))) | 5569 | (propertize k 'face |
| 5541 | (mapc (lambda (l) | 5570 | 'todo-key-prompt) |
| 5542 | (let ((arg (nth 0 l)) | 5571 | name)))))) |
| 5543 | (key1 (nth 1 l)) | 5572 | (setq todo-insert-item--args args) |
| 5544 | (key2 (nth 2 l))) | 5573 | (setq todo-insert-item--argsleft argsleft) |
| 5545 | (if (string-match (concat (regexp-quote arg) "\\_>") cname) | 5574 | (when last |
| 5546 | (setq key (concat key key2))) | 5575 | (cond ((eq last 'default) |
| 5547 | (if (string-match (concat (regexp-quote arg) ".+") cname) | 5576 | (apply #'todo-basic-insert-item (car todo-insert-item--args)) |
| 5548 | (setq key (concat key key1))))) | 5577 | (setq todo-insert-item--argsleft nil)) |
| 5549 | todo-insertion-commands-arg-key-list) | 5578 | ((eq last 'copy) |
| 5550 | (if (string-match (concat (regexp-quote "todo-insert-item") "\\_>") cname) | 5579 | (todo-copy-item) |
| 5551 | (setq key (concat key "i"))) | 5580 | (setq todo-insert-item--argsleft nil)) |
| 5552 | (define-key map key c)))) | 5581 | (t (let ((k (todo-insert-item--keyof last))) |
| 5582 | (funcall addprompt k 'GO!) | ||
| 5583 | (define-key map (todo-insert-item--keyof last) | ||
| 5584 | (lambda () (interactive) | ||
| 5585 | (todo-insert-item--apply-args))))))) | ||
| 5586 | (while todo-insert-item--argsleft | ||
| 5587 | (let ((x (car todo-insert-item--argsleft))) | ||
| 5588 | (setq todo-insert-item--newargsleft (cdr todo-insert-item--argsleft)) | ||
| 5589 | (dolist (argleft (if (consp x) x (list x))) | ||
| 5590 | (let ((k (todo-insert-item--keyof argleft))) | ||
| 5591 | (funcall addprompt k argleft) | ||
| 5592 | (define-key map k | ||
| 5593 | (if (null todo-insert-item--newargsleft) | ||
| 5594 | (lambda () (interactive) | ||
| 5595 | (todo-insert-item--apply-args)) | ||
| 5596 | (lambda () (interactive) | ||
| 5597 | (when (equal "k" (todo-insert-item--this-key)) | ||
| 5598 | (unless (string-match "y" todo-insert-item--keys-so-far) | ||
| 5599 | (when (y-or-n-p (concat "`k' only takes effect with `y';" | ||
| 5600 | " add `y'? ")) | ||
| 5601 | (setq todo-insert-item--keys-so-far | ||
| 5602 | (concat todo-insert-item--keys-so-far " y")) | ||
| 5603 | (setq todo-insert-item--args | ||
| 5604 | (nconc todo-insert-item--args (list 'diary)))))) | ||
| 5605 | (setq todo-insert-item--keys-so-far | ||
| 5606 | (concat todo-insert-item--keys-so-far " " | ||
| 5607 | (todo-insert-item--this-key))) | ||
| 5608 | (todo-insert-item--next-param | ||
| 5609 | (car (todo-insert-item--argsleft | ||
| 5610 | (todo-insert-item--this-key) | ||
| 5611 | todo-insert-item--argsleft)) | ||
| 5612 | (nconc todo-insert-item--args | ||
| 5613 | (list (car (todo-insert-item--argsleft | ||
| 5614 | (todo-insert-item--this-key) | ||
| 5615 | todo-insert-item--argsleft)))) | ||
| 5616 | (cdr (todo-insert-item--argsleft | ||
| 5617 | (todo-insert-item--this-key) | ||
| 5618 | todo-insert-item--argsleft))))))))) | ||
| 5619 | (setq todo-insert-item--argsleft todo-insert-item--newargsleft)) | ||
| 5620 | (when prompt (message "Enter a key (so far `%s'): %s" | ||
| 5621 | todo-insert-item--keys-so-far prompt)) | ||
| 5622 | (set-temporary-overlay-map map) | ||
| 5623 | (setq todo-insert-item--argsleft argsleft))) | ||
| 5553 | 5624 | ||
| 5554 | ;; ----------------------------------------------------------------------------- | 5625 | ;; ----------------------------------------------------------------------------- |
| 5555 | ;;; Todo minibuffer utilities | 5626 | ;;; Todo minibuffer utilities |
| @@ -6224,13 +6295,6 @@ Filtered Items mode following todo (not done) items." | |||
| 6224 | ;;; Key binding | 6295 | ;;; Key binding |
| 6225 | ;; ----------------------------------------------------------------------------- | 6296 | ;; ----------------------------------------------------------------------------- |
| 6226 | 6297 | ||
| 6227 | (defvar todo-insertion-map | ||
| 6228 | (let ((map (make-keymap))) | ||
| 6229 | (todo-insertion-key-bindings map) | ||
| 6230 | (define-key map "p" 'todo-copy-item) | ||
| 6231 | map) | ||
| 6232 | "Keymap for Todo mode item insertion commands.") | ||
| 6233 | |||
| 6234 | (defvar todo-key-bindings-t | 6298 | (defvar todo-key-bindings-t |
| 6235 | `( | 6299 | `( |
| 6236 | ("Af" todo-find-archive) | 6300 | ("Af" todo-find-archive) |
| @@ -6272,7 +6336,7 @@ Filtered Items mode following todo (not done) items." | |||
| 6272 | ("eyk" todo-edit-item-diary-nonmarking) | 6336 | ("eyk" todo-edit-item-diary-nonmarking) |
| 6273 | ("ec" todo-edit-done-item-comment) | 6337 | ("ec" todo-edit-done-item-comment) |
| 6274 | ("d" todo-item-done) | 6338 | ("d" todo-item-done) |
| 6275 | ("i" ,todo-insertion-map) | 6339 | ("i" todo-insert-item) |
| 6276 | ("k" todo-delete-item) | 6340 | ("k" todo-delete-item) |
| 6277 | ("m" todo-move-item) | 6341 | ("m" todo-move-item) |
| 6278 | ("u" todo-item-undone) | 6342 | ("u" todo-item-undone) |