branch: elpa/casual
commit d352a06c1b4181e65ee40f8ed39d65ffda7b9426
Merge: 6a7fa4a56e b32ba3bcfc
Author: Charles Choi <[email protected]>
Commit: GitHub <[email protected]>

    Merge pull request #147 from 
kickingvegas/141-add-wideningnarrowing-to-editkit
    
    Add support for narrow/widen in EditKit
---
 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
 lisp/casual-editkit-utils.el                     |  32 +++++++
 lisp/casual-editkit.el                           |   2 +
 tests/test-casual-editkit-utils.el               | 115 +++++++++++++++++++++++
 tests/test-casual-editkit.el                     |  16 +++-
 7 files changed, 214 insertions(+), 27 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/lisp/casual-editkit-utils.el b/lisp/casual-editkit-utils.el
index 1a08ee9337..8c4fa58937 100644
--- a/lisp/casual-editkit-utils.el
+++ b/lisp/casual-editkit-utils.el
@@ -780,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/tests/test-casual-editkit-utils.el 
b/tests/test-casual-editkit-utils.el
index 4de0c86515..18b89adcfe 100644
--- a/tests/test-casual-editkit-utils.el
+++ b/tests/test-casual-editkit-utils.el
@@ -665,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)

Reply via email to