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).
This commit is contained in:
parent
9b6f564227
commit
6cc0ff19dd
1 changed files with 62 additions and 4 deletions
|
@ -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."
|
||||
|
|
Loading…
Add table
Reference in a new issue