unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Nicholas Vollmer <nv@parenthetic.dev>
To: 71404@debbugs.gnu.org
Subject: bug#71404: 30.0.50; [WISHLIST] string-edit-mode should allow changing major mode
Date: Fri, 07 Jun 2024 22:27:58 -0400	[thread overview]
Message-ID: <877cf0f9sh.fsf@parenthetic.dev> (raw)
In-Reply-To: <87bk4cf9yx.fsf@parenthetic.dev> (Nicholas Vollmer's message of "Fri, 07 Jun 2024 22:24:06 -0400")

[-- Attachment #1: Type: text/plain, Size: 692 bytes --]

Nicholas Vollmer <nv@parenthetic.dev> writes:

> Nicholas Vollmer <nv@parenthetic.dev> writes:
>
> Attached is a proof-of-concept patch which addresses bugs 
> #71404, #71405, and
> #71406 I'll take care of that if/when the design is agreed upon.
>
> The patch rewrites string-edit-mode as a minor mode.
> It utilizes an overlay for the edit prompt (to persist across 
> major mode
> changes) and prevents the prompt separator from being deleted.
> It persists the buffer-local editing data so that the major mode 
> can be changed
> and the edit can still be completed.
> It uses #'ignore as the default abort function if none is 
> provided.

Sorry. Forgot to attach patch.
Attached here.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-lisp-textmodes-string-edit.el-refactor-as-minor-mode.patch --]
[-- Type: text/x-patch, Size: 5458 bytes --]

From 10ae067b0590884c7df6854ca04a1863782c368c Mon Sep 17 00:00:00 2001
From: Nicholas Vollmer <iarchivedmywholelife@gmail.com>
Date: Fri, 7 Jun 2024 22:11:16 -0400
Subject: [PATCH] lisp/textmodes/string-edit.el: refactor as minor mode

---
 lisp/textmodes/string-edit.el | 82 +++++++++++++++++++----------------
 1 file changed, 45 insertions(+), 37 deletions(-)

diff --git a/lisp/textmodes/string-edit.el b/lisp/textmodes/string-edit.el
index 03be426ac25..0eeba50b8ed 100644
--- a/lisp/textmodes/string-edit.el
+++ b/lisp/textmodes/string-edit.el
@@ -23,20 +23,22 @@
 
 ;;; Code:
 
-(require 'cl-lib)
-
 (defface string-edit-prompt
   '((t (:inherit font-lock-comment-face)))
   "Face used on `string-edit' help text."
   :group 'text
   :version "29.1")
 
-(defvar string-edit--success-callback)
-(defvar string-edit--abort-callback)
+(defvar-local string-edit--success-callback nil)
+(put 'string-edit--success-callback 'permanent-local t)
+(defvar-local string-edit--abort-callback nil)
+(put 'string-edit--abort-callback 'permanent-local t)
+(defvar-local string-edit--prompt nil)
+(put 'string-edit--prompt 'permanent-local t)
+
 
 ;;;###autoload
-(cl-defun string-edit (prompt string success-callback
-                              &key abort-callback)
+(defun string-edit (prompt string success-callback &optional abort-callback)
   "Switch to a new buffer to edit STRING.
 When the user finishes editing (with \\<string-edit-mode-map>\\[string-edit-done]), SUCCESS-CALLBACK
 is called with the resulting string.
@@ -50,36 +52,16 @@ string-edit
 
 Also see `read-string-from-buffer'."
   (with-current-buffer (generate-new-buffer "*edit string*")
-    (when prompt
-      (let ((inhibit-read-only t))
-        (insert prompt)
-        (ensure-empty-lines 0)
-        (add-text-properties (point-min) (point)
-                             (list 'intangible t
-                                   'face 'string-edit-prompt
-                                   'read-only t))
-        (insert (propertize (make-separator-line) 'rear-nonsticky t))
-        (add-text-properties (point-min) (point)
-                             (list 'string-edit--prompt t))))
-    (let ((start (point)))
-      (insert string)
-      (goto-char start))
-
+    (setq string-edit--prompt prompt
+          string-edit--success-callback success-callback
+          string-edit--abort-callback (or abort-callback #'ignore))
+    (string-edit-mode)
+    (save-excursion (insert string))
     ;; Use `fit-window-to-buffer' after the buffer is filled with text.
     (pop-to-buffer (current-buffer)
                    '(display-buffer-below-selected
                      (window-height . (lambda (window)
                                         (fit-window-to-buffer window nil 10)))))
-
-    (set-buffer-modified-p nil)
-    (setq buffer-undo-list nil)
-    (string-edit-mode)
-    (setq-local string-edit--success-callback success-callback)
-    (when abort-callback
-      (setq-local string-edit--abort-callback abort-callback))
-    (setq-local header-line-format
-                (substitute-command-keys
-                 "Type \\<string-edit-mode-map>\\[string-edit-done] when you've finished editing or \\[string-edit-abort] to abort"))
     (message "%s" (substitute-command-keys
                    "Type \\<string-edit-mode-map>\\[string-edit-done] when you've finished editing"))))
 
@@ -99,9 +81,9 @@ read-string-from-buffer
    (lambda (edited)
      (setq string edited)
      (exit-recursive-edit))
-   :abort-callback (lambda ()
-                     (exit-recursive-edit)
-                     (error "Aborted edit")))
+   (lambda ()
+     (exit-recursive-edit)
+     (error "Aborted edit")))
   (recursive-edit)
   string)
 
@@ -109,9 +91,35 @@ string-edit-mode-map
   "C-c C-c" #'string-edit-done
   "C-c C-k" #'string-edit-abort)
 
-(define-derived-mode string-edit-mode text-mode "String"
-  "Mode for editing strings."
-  :interactive nil)
+(defun string-edit--prepare-buffer ()
+  "Prepare `string-edit-mode' buffer."
+  (with-silent-modifications
+    (when string-edit--prompt
+      (insert (propertize " " 'intangible t 'read-only t))
+      (let ((o (make-overlay (point-min) (point-max))))
+        (overlay-put o 'display
+                     (concat (propertize string-edit--prompt 'face 'string-edit-prompt)
+                             "\n"
+                             (propertize "\n" 0 1 'face '(:inherit separator-line :extend t))))
+        (overlay-put o 'evaporate nil)
+        (insert (propertize "\n" 'string-edit--prompt t 'read-only t 'rear-nonsticky t 'intangible t 'front-sticky t)))
+      (setq string-edit--prompt nil))
+    (setq header-line-format
+          (substitute-command-keys
+           "Type \\<string-edit-mode-map>\\[string-edit-done] when you've finished editing or \\[string-edit-abort] to abort"))
+    (setq buffer-undo-list nil)))
+
+(define-minor-mode string-edit-mode
+  "Minor mode for editing strings in a dedicated buffer."
+  :lighter " string-edit"
+  (cond
+   (string-edit-mode
+    (add-hook 'after-change-major-mode-hook #'string-edit-mode nil t)
+    (put 'after-change-major-mode-hook 'permanent-local t)
+    (string-edit--prepare-buffer))
+   (t
+    (remove-hook 'after-change-major-mode-hook #'string-edit-mode t)
+    (put 'after-change-major-mode-hook 'permanent-local nil))))
 
 (defun string-edit-done ()
   "Finish editing the string and call the callback function.
-- 
2.45.1


  reply	other threads:[~2024-06-08  2:27 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-06 15:50 bug#71404: 30.0.50; [WISHLIST] string-edit-mode should allow changing major mode Nicholas Vollmer
2024-06-07  6:35 ` Eli Zaretskii
2024-06-07 23:37   ` Nicholas Vollmer
2024-06-08  2:24 ` Nicholas Vollmer
2024-06-08  2:27   ` Nicholas Vollmer [this message]
2024-06-10 20:53     ` Nicholas Vollmer
2024-06-11  6:21       ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=877cf0f9sh.fsf@parenthetic.dev \
    --to=nv@parenthetic.dev \
    --cc=71404@debbugs.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).