diff options
| author | Mauro Aranda | 2020-09-26 17:09:22 +0200 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2020-09-26 17:09:22 +0200 |
| commit | 6cc0ff19ddeadeb47d475da1c38490497488355b (patch) | |
| tree | 92ce3b883e060d3dfa6cff51b444f11c3cee189a | |
| parent | 9b6f5642274b5b9ca0ad1b2e0e673d92b01fab6e (diff) | |
| download | emacs-6cc0ff19ddeadeb47d475da1c38490497488355b.tar.gz emacs-6cc0ff19ddeadeb47d475da1c38490497488355b.zip | |
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).
| -rw-r--r-- | lisp/wid-edit.el | 66 |
1 files changed, 62 insertions, 4 deletions
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el index 8e2055f9185..0a2ddb0ea1d 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." | |||
| 1369 | (signal 'text-read-only | 1369 | (signal 'text-read-only |
| 1370 | '("Attempt to change text outside editable field"))) | 1370 | '("Attempt to change text outside editable field"))) |
| 1371 | (widget-field-use-before-change | 1371 | (widget-field-use-before-change |
| 1372 | (widget-apply from-field :notify from-field)))))) | 1372 | (widget-apply from-field :notify |
| 1373 | from-field (list 'before-change from to))))))) | ||
| 1373 | 1374 | ||
| 1374 | (defun widget-add-change () | 1375 | (defun widget-add-change () |
| 1375 | (remove-hook 'post-command-hook 'widget-add-change t) | 1376 | (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." | |||
| 1406 | (> (point) begin)) | 1407 | (> (point) begin)) |
| 1407 | (delete-char -1))))))) | 1408 | (delete-char -1))))))) |
| 1408 | (widget-specify-secret field)) | 1409 | (widget-specify-secret field)) |
| 1409 | (widget-apply field :notify field)))) | 1410 | (widget-apply field :notify field (list 'after-change from to))))) |
| 1410 | 1411 | ||
| 1411 | ;;; Widget Functions | 1412 | ;;; Widget Functions |
| 1412 | ;; | 1413 | ;; |
| @@ -3532,13 +3533,70 @@ To use this type, you must define :match or :match-alternatives." | |||
| 3532 | :value-to-internal (lambda (_widget value) | 3533 | :value-to-internal (lambda (_widget value) |
| 3533 | (if (stringp value) | 3534 | (if (stringp value) |
| 3534 | value | 3535 | value |
| 3535 | (char-to-string value))) | 3536 | (let ((disp |
| 3537 | (widget-character--change-character-display | ||
| 3538 | value))) | ||
| 3539 | (if disp | ||
| 3540 | (propertize (char-to-string value) 'display disp) | ||
| 3541 | (char-to-string value))))) | ||
| 3536 | :value-to-external (lambda (_widget value) | 3542 | :value-to-external (lambda (_widget value) |
| 3537 | (if (stringp value) | 3543 | (if (stringp value) |
| 3538 | (aref value 0) | 3544 | (aref value 0) |
| 3539 | value)) | 3545 | value)) |
| 3540 | :match (lambda (_widget value) | 3546 | :match (lambda (_widget value) |
| 3541 | (characterp value))) | 3547 | (characterp value)) |
| 3548 | :notify #'widget-character-notify) | ||
| 3549 | |||
| 3550 | ;; Only some escape sequences, not all of them. (Bug#15925) | ||
| 3551 | (defvar widget-character--escape-sequences-alist | ||
| 3552 | '((?\t . ?t) | ||
| 3553 | (?\n . ?n) | ||
| 3554 | (?\s . ?s)) | ||
| 3555 | "Alist that associates escape sequences to a character. | ||
| 3556 | Each element has the form (ESCAPE-SEQUENCE . CHARACTER). | ||
| 3557 | |||
| 3558 | The character widget uses this alist to display the | ||
| 3559 | non-printable character represented by ESCAPE-SEQUENCE as \\CHARACTER, | ||
| 3560 | since that makes it easier to see what's in the widget.") | ||
| 3561 | |||
| 3562 | (defun widget-character--change-character-display (c) | ||
| 3563 | "Return a string to represent the character C, or nil. | ||
| 3564 | |||
| 3565 | The character widget represents some characters (e.g., the newline character | ||
| 3566 | or the tab character) specially, to make it easier for the user to see what's | ||
| 3567 | in it. For those characters, return a string to display that character in a | ||
| 3568 | more user-friendly way. | ||
| 3569 | |||
| 3570 | For the caller, nil should mean that it is good enough to use the return value | ||
| 3571 | of `char-to-string' for the representation of C." | ||
| 3572 | (let ((char (alist-get c widget-character--escape-sequences-alist))) | ||
| 3573 | (and char (propertize (format "\\%c" char) 'face 'escape-glyph)))) | ||
| 3574 | |||
| 3575 | (defun widget-character-notify (widget child &optional event) | ||
| 3576 | "Notify function for the character widget. | ||
| 3577 | |||
| 3578 | This function allows the widget character to better display some characters, | ||
| 3579 | like the newline character or the tab character." | ||
| 3580 | (when (eq (car-safe event) 'after-change) | ||
| 3581 | (let* ((start (nth 1 event)) | ||
| 3582 | (end (nth 2 event)) | ||
| 3583 | str) | ||
| 3584 | (if (eql start end) | ||
| 3585 | (when (char-equal (widget-value widget) ?\s) | ||
| 3586 | ;; The character widget is not really empty: | ||
| 3587 | ;; its value is a single space character. | ||
| 3588 | ;; We need to propertize it again, if it became empty for a while. | ||
| 3589 | (let ((ov (widget-get widget :field-overlay))) | ||
| 3590 | (put-text-property | ||
| 3591 | (overlay-start ov) (overlay-end ov) | ||
| 3592 | 'display (widget-character--change-character-display ?\s)))) | ||
| 3593 | (setq str (buffer-substring-no-properties start end)) | ||
| 3594 | ;; This assumes the user enters one character at a time, | ||
| 3595 | ;; and does nothing crazy, like yanking a long string. | ||
| 3596 | (let ((disp (widget-character--change-character-display (aref str 0)))) | ||
| 3597 | (when disp | ||
| 3598 | (put-text-property start end 'display disp)))))) | ||
| 3599 | (widget-default-notify widget child event)) | ||
| 3542 | 3600 | ||
| 3543 | (define-widget 'list 'group | 3601 | (define-widget 'list 'group |
| 3544 | "A Lisp list." | 3602 | "A Lisp list." |