emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 6cc0ff1: Display some character widget values in a more user-frie


From: Lars Ingebrigtsen
Subject: master 6cc0ff1: Display some character widget values in a more user-friendly way
Date: Sat, 26 Sep 2020 11:09:35 -0400 (EDT)

branch: master
commit 6cc0ff19ddeadeb47d475da1c38490497488355b
Author: Mauro Aranda <maurooaranda@gmail.com>
Commit: Lars Ingebrigtsen <larsi@gnus.org>

    Display some character widget values in a more user-friendly way
    
    * lisp/wid-edit.el (widget-character--escape-sequences-alist): New
    variable.
    (widget-character--change-character-display): New function.  Use the new
    variable.
    (widget-character-notify): New function, to keep track of the changes
    in the character widget, and display characters like tab,
    newline and spaces better.
    (character widget): Use widget-character-notify as the notify
    function.  Use widget-character--change-character-display for the
    internal representation of value (bug#15925).
---
 lisp/wid-edit.el | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 62 insertions(+), 4 deletions(-)

diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index 8e2055f..0a2ddb0 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -1369,7 +1369,8 @@ Unlike (get-char-property POS \\='field), this works with 
empty fields too."
             (signal 'text-read-only
                     '("Attempt to change text outside editable field")))
            (widget-field-use-before-change
-            (widget-apply from-field :notify from-field))))))
+            (widget-apply from-field :notify
+                           from-field (list 'before-change from to)))))))
 
 (defun widget-add-change ()
   (remove-hook 'post-command-hook 'widget-add-change t)
@@ -1406,7 +1407,7 @@ Unlike (get-char-property POS \\='field), this works with 
empty fields too."
                                 (> (point) begin))
                       (delete-char -1)))))))
        (widget-specify-secret field))
-      (widget-apply field :notify field))))
+      (widget-apply field :notify field (list 'after-change from to)))))
 
 ;;; Widget Functions
 ;;
@@ -3532,13 +3533,70 @@ To use this type, you must define :match or 
:match-alternatives."
   :value-to-internal (lambda (_widget value)
                       (if (stringp value)
                           value
-                        (char-to-string value)))
+                         (let ((disp
+                                (widget-character--change-character-display
+                                 value)))
+                           (if disp
+                               (propertize (char-to-string value) 'display 
disp)
+                             (char-to-string value)))))
   :value-to-external (lambda (_widget value)
                       (if (stringp value)
                           (aref value 0)
                         value))
   :match (lambda (_widget value)
-          (characterp value)))
+          (characterp value))
+  :notify #'widget-character-notify)
+
+;; Only some escape sequences, not all of them.  (Bug#15925)
+(defvar widget-character--escape-sequences-alist
+  '((?\t . ?t)
+    (?\n . ?n)
+    (?\s . ?s))
+  "Alist that associates escape sequences to a character.
+Each element has the form (ESCAPE-SEQUENCE . CHARACTER).
+
+The character widget uses this alist to display the
+non-printable character represented by ESCAPE-SEQUENCE as \\CHARACTER,
+since that makes it easier to see what's in the widget.")
+
+(defun widget-character--change-character-display (c)
+  "Return a string to represent the character C, or nil.
+
+The character widget represents some characters (e.g., the newline character
+or the tab character) specially, to make it easier for the user to see what's
+in it.  For those characters, return a string to display that character in a
+more user-friendly way.
+
+For the caller, nil should mean that it is good enough to use the return value
+of `char-to-string' for the representation of C."
+  (let ((char (alist-get c widget-character--escape-sequences-alist)))
+    (and char (propertize (format "\\%c" char) 'face 'escape-glyph))))
+
+(defun widget-character-notify (widget child &optional event)
+  "Notify function for the character widget.
+
+This function allows the widget character to better display some characters,
+like the newline character or the tab character."
+  (when (eq (car-safe event) 'after-change)
+    (let* ((start (nth 1 event))
+           (end (nth 2 event))
+           str)
+      (if (eql start end)
+          (when (char-equal (widget-value widget) ?\s)
+            ;; The character widget is not really empty:
+            ;; its value is a single space character.
+            ;; We need to propertize it again, if it became empty for a while.
+            (let ((ov (widget-get widget :field-overlay)))
+              (put-text-property
+               (overlay-start ov) (overlay-end ov)
+               'display (widget-character--change-character-display ?\s))))
+        (setq str (buffer-substring-no-properties start end))
+        ;; This assumes the user enters one character at a time,
+        ;; and does nothing crazy, like yanking a long string.
+        (let ((disp (widget-character--change-character-display (aref str 0))))
+          (when disp
+            (put-text-property start end 'display disp))))))
+  (widget-default-notify widget child event))
 
 (define-widget 'list 'group
   "A Lisp list."



reply via email to

[Prev in Thread] Current Thread [Next in Thread]