Subject: bug#62709: 29.0.60; quail-minibuffer-message prevents set-mark-command from activating region in minibuffer

From: Visuwesh <[email-masked]>
Date: Fri, 07 Apr 2023 20:09:13 +0530

[வெள்ளி ஏப்ரல் 07, 2023] Visuwesh wrote:

>> I'd prefer to solve the problem that prevents the region from becoming
>> active, without changing how Quail shows its messages.  Can you try
>> finding such a solution, 
>
> One solution would be to use an overlay to show the guidance string,
> like what `minibuffer-depth-mode' does.

I came close to solving the issue with an overlay but I hit a roadblock
with the cursor property.
I currently create an overlay at minibuffer's point-max but the cursor
is shown _after_ the overlay string.  I tried to use the cursor text
property to move the cursor before the string but it does not do it if
the string contains a newline character _anywhere_, which is
contradictory to what the manual says

     One subtlety of this property is that it doesn’t work to put this
     property on a newline character that is part of a display or
              ^^^^^^^^^^^^^^^^^^^^^^
     overlay string.  That’s because the newline doesn’t have a graphic
     representation on the screen for Emacs to find when it looks for a
     character on display with that ‘cursor’ property.

but I do _not_ put the property on a newline character, I put it in on a
space character.

To spell things out, the overlay's after-string is something like
"  [none]
Guidance string here"

I put the cursor=t text-property on the first space character, but the
cursor is not displayed there.  If I remove the newline so the
after-string becomes

"  [none] Guidance string here"

then the cursor is just before the space character i.e., |  [none]...
where | is the cursor.

I'm attaching my work so far as a diff

diff --git a/lisp/international/quail.el b/lisp/international/quail.el
index 2ffe339233..20eba9c1d4 100644
--- a/lisp/international/quail.el
+++ b/lisp/international/quail.el
@@ -85,6 +85,9 @@ quail-overlay
 (defvar-local quail-conv-overlay nil
   "Overlay which covers the text to be converted in Quail mode.")
 
+(defvar-local quail-minibuf-guidance-overlay nil
+  "Overlay used to display the guidance string when in minibuffer.")
+
 (defvar-local quail-current-key nil
   "Current key for translation in Quail mode.")
 
@@ -571,18 +574,22 @@ quail-activate
     (setq deactivate-current-input-method-function #'quail-deactivate)
     (setq describe-current-input-method-function #'quail-help)
     (quail-delete-overlays)
-    (setq quail-guidance-str "")
-    (quail-show-guidance)
     ;; If we are in minibuffer, turn off the current input method
     ;; before exiting.
     (when (eq (selected-window) (minibuffer-window))
+      (quail-minibuf-setup-guidance-overlay)
       (add-hook 'minibuffer-exit-hook #'quail-exit-from-minibuffer)
       (add-hook 'post-command-hook #'quail-show-guidance nil t))
+    (setq quail-guidance-str "")
+    (quail-show-guidance)
     (run-hooks 'quail-activate-hook)
     (setq-local input-method-function #'quail-input-method)))
 
 (defun quail-exit-from-minibuffer ()
   (deactivate-input-method)
+  (when (and (overlayp quail-minibuf-guidance-overlay)
+             (overlay-start quail-minibuf-guidance-overlay))
+    (delete-overlay quail-minibuf-guidance-overlay))
   (if (<= (minibuffer-depth) 1)
       (remove-hook 'minibuffer-exit-hook 'quail-exit-from-minibuffer)))
 
@@ -1993,17 +2000,33 @@ quail-require-guidance-buf
 ;; with timeout 1000000 seconds instead of two seconds.
 
 (defun quail-minibuffer-message (string)
-  (message nil)
-  (let ((point-max (point-max))
-	(inhibit-quit t))
-    (save-excursion
-      (goto-char point-max)
-      (insert string))
-    (sit-for 1000000)
-    (delete-region point-max (point-max))
-    (when quit-flag
-      (setq quit-flag nil)
-      (quail-add-unread-command-events 7 t))))
+  (put-text-property 0 1 'cursor t string)
+  (overlay-put quail-minibuf-guidance-overlay
+               'after-string string))
+
+;; (defun quail-minibuffer-message (string)
+;;   (message nil)
+;;   (let ((point-max (point-max))
+;; 	(inhibit-quit t))
+;;     (save-excursion
+;;       (goto-char point-max)
+;;       (insert string))
+;;     (sit-for 1000000)
+;;     (delete-region point-max (point-max))
+;;     (when quit-flag
+;;       (setq quit-flag nil)
+;;       (quail-add-unread-command-events 7 t))))
+
+(defun quail-minibuf-move-guidance-overlay (ov afterp &rest _)
+  (when afterp
+    (move-overlay ov (point-max) (point-max))))
+
+(defun quail-minibuf-setup-guidance-overlay ()
+  (setq quail-minibuf-guidance-overlay
+        (make-overlay (point-max) (point-max)))
+  (overlay-put quail-minibuf-guidance-overlay 'insert-behind-hooks
+               '(quail-minibuf-move-guidance-overlay)))
+
 
 (defun quail-show-guidance ()
   "Display a guidance for Quail input method in some window.