branch: elpa/casual
commit e1151a66838acfb58b74d9892ab93108f0761c91
Merge: 2d1cfd6fe4 d352a06c1b
Author: Charles Choi <[email protected]>
Commit: GitHub <[email protected]>
Merge pull request #148 from
kickingvegas/merge-development-to-main-20250128_114420
Merge development to main 20250128_114420
---
docs/editkit.org | 76 ++++++++-----
docs/images/casual-editkit-main-screenshot.png | Bin 317764 -> 242099 bytes
docs/images/casual-editkit-narrow-screenshot.png | Bin 0 -> 97375 bytes
.../images/casual-editkit-transform-screenshot.png | Bin 154973 -> 127099 bytes
docs/images/casual-info-screenshot.png | Bin 344749 -> 447998 bytes
lisp/casual-editkit-utils.el | 40 ++++++-
lisp/casual-editkit.el | 2 +
lisp/casual-info.el | 3 +-
lisp/casual.el | 2 +-
tests/test-casual-editkit-utils.el | 118 +++++++++++++++++++++
tests/test-casual-editkit.el | 16 ++-
tests/test-casual-info.el | 2 +
12 files changed, 228 insertions(+), 31 deletions(-)
diff --git a/docs/editkit.org b/docs/editkit.org
index 4bf04b9a1f..675f5fad33 100644
--- a/docs/editkit.org
+++ b/docs/editkit.org
@@ -5,32 +5,40 @@ An opinionated
[[https://github.com/magit/transient][Transient]]-based user inte
[[file:images/casual-editkit-main-screenshot.png]]
-Casual EditKit endeavors to surface the many different editing commands
offered by Emacs via Transient menus. Included in this library are menus for:
-
-- Register commands
-- Rectangle commands
-- Editing commands for words, sentences, paragraphs, and balanced expressions
(sexps), and functions (defuns).
- - Marking
- - Copying
- - Killing
- - Moving
- - Transposing
- - Transforming
- - Deleting
- - Sorting
-- Window management
- - Creating
- - Moving
- - Deleting
-- Search & Replace commands
-- Open commands
-- Project commands
-- Bookmark commands
-- Emoji & Symbol Insertion (including smart quotes)
-- Tool commands
-- Macro commands
-
-A main menu (~casual-editkit-main-tmenu~) demonstrating all of the above is
provided as a reference model. This reference model can be used as is. More
motivated users can use the reference model as a template to build their own
customized menus.
+Casual EditKit endeavors to surface the many different editing commands
offered by Emacs via Transient menus. The main menu
(~casual-editkit-main-tmenu~) both demonstrates and provides a reference to all
EditKit menus. Motivated users can customize this menu to their taste.
+
+* Table of Contents :TOC_3:
+- [[#casual-editkit][Casual EditKit]]
+- [[#motivation][Motivation]]
+ - [[#goals][Goals]]
+ - [[#non-goals][Non-Goals]]
+- [[#install][Install]]
+- [[#library-overview][Library Overview]]
+ - [[#register-commands-casual-editkit-registers-tmenu][Register commands
(~casual-editkit-registers-tmenu~)]]
+ - [[#rectangle-commands-casual-editkit-rectangle-tmenu][Rectangle commands
(~casual-editkit-rectangle-tmenu~)]]
+ - [[#edit-commands-casual-editkit-edit-tmenu][Edit commands
(~casual-editkit-edit-tmenu~)]]
+ - [[#mark-casual-editkit-mark-tmenu][Mark (~casual-editkit-mark-tmenu~)]]
+ - [[#copy-casual-editkit-copy-tmenu][Copy (~casual-editkit-copy-tmenu~)]]
+ - [[#kill-cut-casual-editkit-kill-tmenu][Kill (Cut)
(~casual-editkit-kill-tmenu~)]]
+ - [[#move-casual-editkit-move-tmenu][Move (~casual-editkit-move-tmenu~)]]
+ - [[#transpose-casual-editkit-transpose-tmenu][Transpose
(~casual-editkit-transpose-tmenu~)]]
+ - [[#transform-casual-editkit-transform-tmenu][Transform
(~casual-editkit-transform-tmenu~)]]
+ - [[#delete-casual-editkit-delete-tmenu][Delete
(~casual-editkit-delete-tmenu~)]]
+ - [[#sort-casual-editkit-sort-tmenu][Sort (~casual-editkit-sort-tmenu~)]]
+ - [[#reformat-casual-editkit-reformat-tmenu][Reformat
(~casual-editkit-reformat-tmenu~)]]
+ - [[#window-management-casual-editkit-window-tmenu][Window management
(~casual-editkit-window-tmenu~)]]
+ - [[#deletion-casual-editkit-window-delete-tmenu][Deletion
(~casual-editkit-window-delete-tmenu~)]]
+ - [[#search--replace-commands-casual-editkit-search-tmenu][Search & Replace
commands (~casual-editkit-search-tmenu~)]]
+ - [[#open-commands-casual-editkit-open-tmenu][Open commands
(~casual-editkit-open-tmenu~)]]
+ - [[#project-commands-casual-editkit-project-tmenu][Project commands
(~casual-editkit-project-tmenu~)]]
+ - [[#bookmark-commands-casual-editkit-bookmarks-tmenu][Bookmark commands
(~casual-editkit-bookmarks-tmenu~)]]
+ - [[#emoji--symbol-insertion-casual-editkit-emoji-symbol-tmenu][Emoji &
Symbol Insertion (~casual-editkit-emoji-symbol-tmenu~)]]
+ - [[#tool-commands-casual-editkit-tools-tmenu][Tool commands
(~casual-editkit-tools-tmenu~)]]
+ - [[#narrowwiden-commands-casual-editkit-narrow-tmenu][Narrow/Widen Commands
(~casual-editkit-narrow-tmenu~)]]
+ - [[#macro-casual-editkit-macro-tmenu][Macro (~casual-editkit-macro-tmenu~)]]
+ - [[#settings-casual-editkit-settings-tmenu][Settings
(~casual-editkit-settings-tmenu~)]]
+- [[#sponsorship][Sponsorship]]
+- [[#see-also][See Also]]
* Motivation
Emacs has many commands that are easy to forget if not used frequently. Menus
are a user interface (UI) affordance that offers discoverability and
recognition that can lower its learning curve. While menus are commonly
associated with mouse-driven UI, the inclusion of Transient in Emacs core
allows for building a keyboard-driven menu UI. Casual EditKit endeavors to
offer this as many Emacs users prefer keyboard-driven workflows.
@@ -159,6 +167,22 @@ This menu holds an assorted collection of different
tools/utilities provided by
[[file:images/casual-editkit-tools-screenshot.png]]
+** Narrow/Widen Commands (~casual-editkit-narrow-tmenu~)
+Support for
[[https://www.gnu.org/software/emacs/manual/html_node/emacs/Narrowing.html][narrowing
and widening]] a buffer is supported. Mode specific narrowing behavior is
supported for Org and ~prog-mode~ derived buffers.
+
+[[file:images/casual-editkit-narrow-screenshot.png]]
+
+This menu can be
[[https://www.gnu.org/software/emacs/manual/html_mono/transient.html#Modifying-Existing-Transients][modified]]
to support narrowing in other modes, particularly those that are packaged with
Emacs. For example, if one wanted narrowing support for Markdown
([[https://jblevins.org/projects/markdown-mode/][markdown-mode]]), the
following initialization code can be used.
+
+#+begin_src elisp :lexical no
+ (transient-append-suffix 'casual-editkit-narrow-tmenu '(0 0)
+ ["Markdown"
+ :if (lambda () (derived-mode-p 'markdown-mode))
+ ("s" "Subtree" markdown-narrow-to-subtree)
+ ("b" "Block" markdown-narrow-to-block)
+ ("p" "Page" markdown-narrow-to-page)])
+#+end_src
+
** Macro (~casual-editkit-macro-tmenu~)
Commands for managing macros are provided for by this menu. Note that macro
creation commands are /not/ supported as they are tightly-bound to keybindings.
diff --git a/docs/images/casual-editkit-main-screenshot.png
b/docs/images/casual-editkit-main-screenshot.png
index 694b7e1b53..a169d9d26a 100644
Binary files a/docs/images/casual-editkit-main-screenshot.png and
b/docs/images/casual-editkit-main-screenshot.png differ
diff --git a/docs/images/casual-editkit-narrow-screenshot.png
b/docs/images/casual-editkit-narrow-screenshot.png
new file mode 100644
index 0000000000..6b250444ba
Binary files /dev/null and b/docs/images/casual-editkit-narrow-screenshot.png
differ
diff --git a/docs/images/casual-editkit-transform-screenshot.png
b/docs/images/casual-editkit-transform-screenshot.png
index 6afcb98823..225eca9bff 100644
Binary files a/docs/images/casual-editkit-transform-screenshot.png and
b/docs/images/casual-editkit-transform-screenshot.png differ
diff --git a/docs/images/casual-info-screenshot.png
b/docs/images/casual-info-screenshot.png
index 8de71f8727..cfeb019e29 100644
Binary files a/docs/images/casual-info-screenshot.png and
b/docs/images/casual-info-screenshot.png differ
diff --git a/lisp/casual-editkit-utils.el b/lisp/casual-editkit-utils.el
index eb4e1ff13e..8c4fa58937 100644
--- a/lisp/casual-editkit-utils.el
+++ b/lisp/casual-editkit-utils.el
@@ -702,8 +702,12 @@ Commands pertaining to rectangle operations can be
accessed here."
Commands pertaining to transformation operations can be accessed here."
["Transform"
- [("c" "Capitialize" capitalize-dwim :transient t)
- ("l" "Make Lower Case" downcase-dwim :transient t)
+ [("c" "Capitalize" capitalize-dwim :transient t)
+ ("t" "Title Region (Upcase Initials)" upcase-initials-region
+ :transient t
+ :inapt-if-not use-region-p)]
+
+ [("l" "Make Lower Case" downcase-dwim :transient t)
("u" "Make Upper Case" upcase-dwim :transient t)]
[("RET" "Done" transient-quit-all)]]
@@ -776,6 +780,38 @@ accessed here."
(format "Fill Column (%d)" fill-column)))]
casual-editkit-navigation-group)
+;;;###autoload (autoload 'casual-editkit-narrow-tmenu "casual-editkit-utils"
nil t)
+(transient-define-prefix casual-editkit-narrow-tmenu ()
+ "Menu for narrow commands."
+
+ ["Narrow"
+ ["Programming"
+ ("d" "Defun" narrow-to-defun
+ :if (lambda () (derived-mode-p 'prog-mode)))]
+
+ ["Org"
+ :if (lambda () (derived-mode-p 'org-mode))
+ ("s" "Subtree" org-narrow-to-subtree)
+ ("b" "Block" org-narrow-to-block)
+ ("e" "Element" org-narrow-to-element)]
+
+ ["Region"
+ ("r" "Region" narrow-to-region
+ :inapt-if-not use-region-p)]]
+
+ casual-editkit-navigation-group)
+
+;; !!!
+;; If markdown-mode is installed, then this will add markdown-mode specific
+;; narrowing commands to casual-editkit-narrow-tmenu.
+;;
+;; (transient-append-suffix 'casual-editkit-narrow-tmenu '(0 0)
+;; ["Markdown"
+;; :if (lambda () (derived-mode-p 'markdown-mode))
+;; ("s" "Subtree" markdown-narrow-to-subtree)
+;; ("b" "Block" markdown-narrow-to-block)
+;; ("p" "Page" markdown-narrow-to-page)])
+
;;; Functions
(defun casual-editkit-macro-info ()
"Get Info for syntax of regexps."
diff --git a/lisp/casual-editkit.el b/lisp/casual-editkit.el
index cffa1f80b7..76934e2501 100644
--- a/lisp/casual-editkit.el
+++ b/lisp/casual-editkit.el
@@ -70,6 +70,8 @@ user-customized menu."
("C-o" "Open line" open-line
:transient t
:if-not casual-editkit-buffer-read-only-p)
+ ("N" "Narrow›" casual-editkit-narrow-tmenu :if-not buffer-narrowed-p)
+ ("W" "Widen" widen :if buffer-narrowed-p)
("E" "Emoji & Symbols›" casual-editkit-emoji-symbols-tmenu
:if-not casual-editkit-buffer-read-only-p)]
diff --git a/lisp/casual-info.el b/lisp/casual-info.el
index 610feb4fe1..4a81ed2c1e 100644
--- a/lisp/casual-info.el
+++ b/lisp/casual-info.el
@@ -48,7 +48,8 @@
"CC Info Transient menu."
[["Overview"
- ("d" "Directory" Info-directory :transient nil)
+ ("d" "Directory" Info-directory)
+ ("M" "Manual…" info-display-manual)
("t" "Top" Info-top-node)
("T" "ToC" Info-toc :transient nil)]
diff --git a/lisp/casual.el b/lisp/casual.el
index 40496288b0..11f705d99e 100644
--- a/lisp/casual.el
+++ b/lisp/casual.el
@@ -5,7 +5,7 @@
;; Author: Charles Choi <[email protected]>
;; URL: https://github.com/kickingvegas/casual
;; Keywords: tools, wp
-;; Version: 2.2.8
+;; Version: 2.2.9-rc.1
;; Package-Requires: ((emacs "29.1") (transient "0.6.0"))
;; This program is free software; you can redistribute it and/or modify
diff --git a/tests/test-casual-editkit-utils.el
b/tests/test-casual-editkit-utils.el
index 4e3cead7ff..18b89adcfe 100644
--- a/tests/test-casual-editkit-utils.el
+++ b/tests/test-casual-editkit-utils.el
@@ -608,15 +608,18 @@
(let ((tmpfile "casual-editkit-transform-text-tmenu.txt"))
(casualt-editkit-setup tmpfile)
(cl-letf ((casualt-mock #'capitalize-dwim)
+ (casualt-mock #'upcase-initials-region)
(casualt-mock #'downcase-dwim)
(casualt-mock #'upcase-dwim))
(let ((test-vectors
'((:binding "c" :command capitalize-dwim)
+ (:binding "t" :command upcase-initials-region)
(:binding "l" :command downcase-dwim)
(:binding "u" :command upcase-dwim)
(:binding "RET" :command transient-quit-all))))
+ (casualt-mock-active-region)
(casualt-suffix-testcase-runner test-vectors
#'casual-editkit-transform-text-tmenu
'(lambda () (random 5000)))))
@@ -662,6 +665,121 @@
'(lambda () (random 5000)))))
(casualt-editkit-breakdown tmpfile)))
+
+(ert-deftest test-casual-editkit-narrow-tmenu ()
+ ;; TODO: need to test for region.
+ (let ((tmpfile "casual-editkit-narrow-tmenu.el"))
+ (casualt-editkit-setup tmpfile)
+ (cl-letf ((casualt-mock #'narrow-to-defun))
+ (let ((test-vectors
+ '((:binding "d" :command narrow-to-defun))))
+
+ (emacs-lisp-mode)
+ (insert "(defun foo() (message \"hi.\"))")
+ (goto-char (point-min))
+ (save-buffer)
+
+ (casualt-suffix-testcase-runner test-vectors
+ #'casual-editkit-narrow-tmenu
+ '(lambda () (random 5000)))))
+
+ (casualt-editkit-breakdown tmpfile))
+
+ (let ((tmpfile "casual-editkit-narrow-tmenu.org"))
+ (casualt-editkit-setup tmpfile)
+ (cl-letf ((casualt-mock #'org-narrow-to-subtree)
+ (casualt-mock #'org-narrow-to-block)
+ (casualt-mock #'org-narrow-to-element))
+
+ (let ((test-vectors
+ '((:binding "s" :command org-narrow-to-subtree)
+ ;; (:binding "e" :command org-narrow-to-element)
+ )))
+
+ (org-mode)
+ (insert "* Header 1\n")
+
+ (casualt-suffix-testcase-runner test-vectors
+ #'casual-editkit-narrow-tmenu
+ '(lambda () (random 5000))))
+ (widen)
+ (let ((test-vectors
+ '((:binding "b" :command org-narrow-to-block)
+ ;; (:binding "e" :command org-narrow-to-element)
+ )))
+
+ (insert "#+begin_src elisp\n")
+ (insert "hi there\n")
+ (insert "#+end_src\n")
+ (previous-line 2)
+
+ (casualt-suffix-testcase-runner test-vectors
+ #'casual-editkit-narrow-tmenu
+ '(lambda () (random 5000))))
+ (widen)
+ (let ((test-vectors
+ '((:binding "e" :command org-narrow-to-element))))
+
+ (insert "This is a bogus sentence.")
+ (beginning-of-line)
+
+ (casualt-suffix-testcase-runner test-vectors
+ #'casual-editkit-narrow-tmenu
+ '(lambda () (random 5000))))
+ (widen)
+ (save-buffer)
+ (casualt-editkit-breakdown tmpfile)))
+
+
+ ;; (let ((tmpfile "casual-editkit-narrow-tmenu.md"))
+ ;; (casualt-editkit-setup tmpfile)
+ ;; (cl-letf ((casualt-mock #'markdown-narrow-to-subtree)
+ ;; (casualt-mock #'markdown-narrow-to-block)
+ ;; (casualt-mock #'markdown-narrow-to-page))
+
+ ;; (let ((test-vectors
+ ;; '((:binding "s" :command markdown-narrow-to-subtree)
+
+ ;; )))
+
+ ;; (markdown-mode)
+ ;; (insert "# Header 1\n")
+
+ ;; (casualt-suffix-testcase-runner test-vectors
+ ;; #'casual-editkit-narrow-tmenu
+ ;; '(lambda () (random 5000))))
+
+ ;; (widen)
+ ;; (let ((test-vectors
+ ;; '((:binding "b" :command markdown-narrow-to-block)
+ ;; ;; (:binding "e" :command org-narrow-to-element)
+ ;; )))
+
+ ;; (insert " #!python\n")
+ ;; (insert " def foo(a):\n")
+ ;; (insert " return a + 2\n")
+ ;; (previous-line 2)
+
+ ;; (casualt-suffix-testcase-runner test-vectors
+ ;; #'casual-editkit-narrow-tmenu
+ ;; '(lambda () (random 5000))))
+
+ ;; (widen)
+
+ ;; (let ((test-vectors
+ ;; '((:binding "p" :command markdown-narrow-to-page))))
+
+ ;; (insert "This is a bogus sentence.")
+ ;; (beginning-of-line)
+
+ ;; (casualt-suffix-testcase-runner test-vectors
+ ;; #'casual-editkit-narrow-tmenu
+ ;; '(lambda () (random 5000))))
+ ;; (widen)
+ ;; (save-buffer)
+ ;; (casualt-editkit-breakdown tmpfile)))
+ )
+
;; -------
(provide 'test-casual-editkit-utils)
;;; test-casual-editkit-utils.el ends here
diff --git a/tests/test-casual-editkit.el b/tests/test-casual-editkit.el
index fe410d8d22..1dab805df3 100644
--- a/tests/test-casual-editkit.el
+++ b/tests/test-casual-editkit.el
@@ -40,6 +40,7 @@
(casualt-mock #'recentf-open-files)
(casualt-mock #'revert-buffer)
(casualt-mock #'save-buffer)
+ (casualt-mock #'widen)
(casualt-mock #'insert-char)
(casualt-mock #'fill-paragraph)
@@ -71,6 +72,9 @@
(:binding "p" :command fill-paragraph)
(:binding "l" :command join-line)
(:binding "C-o" :command open-line)
+ (:binding "N" :command casual-editkit-narrow-tmenu)
+ ;; (:binding "W" :command widen)
+
(:binding "E" :command casual-editkit-emoji-symbols-tmenu)
(:binding "m" :command mark-sexp)
@@ -100,13 +104,23 @@
(:binding "," :command casual-editkit-settings-tmenu)
(:binding "x" :command save-buffers-kill-emacs))))
-
(insert "hello")
(casualt-suffix-testcase-runner test-vectors
#'casual-editkit-main-tmenu
'(lambda () (random 5000)))
(save-buffer)))
+ (cl-letf (((symbol-function #'buffer-narrowed-p) (lambda () t))
+ (casualt-mock #'widen))
+
+ (let ((test-vectors
+ '((:binding "W" :command widen))))
+
+ (insert "hello")
+ (casualt-suffix-testcase-runner test-vectors
+ #'casual-editkit-main-tmenu
+ '(lambda () (random 5000)))
+ (save-buffer)))
(casualt-editkit-breakdown tmpfile)))
(provide 'test-casual-editkit)
diff --git a/tests/test-casual-info.el b/tests/test-casual-info.el
index 47d5e32262..9a557d0082 100644
--- a/tests/test-casual-info.el
+++ b/tests/test-casual-info.el
@@ -33,6 +33,7 @@
(casualt-info-setup)
(cl-letf (
(casualt-mock #'Info-directory)
+ (casualt-mock #'info-display-manual)
(casualt-mock #'Info-top-node)
(casualt-mock #'Info-toc)
(casualt-mock #'Info-menu)
@@ -69,6 +70,7 @@
(let ((test-vectors
'(;; Overview
(:binding "d" :command Info-directory)
+ (:binding "M" :command info-display-manual)
(:binding "t" :command Info-top-node)
(:binding "T" :command Info-toc)