[Top][All Lists]

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

Re: defcustom :type to use for a key sequence?

From: Kim F. Storm
Subject: Re: defcustom :type to use for a key sequence?
Date: Tue, 20 Dec 2005 15:53:06 +0100
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux)

"Richard M. Stallman" <address@hidden> writes:

>     I still think it would make a lot of sense to make :type key-sequence
>     edit a string rather than a sexp.
>     The actual value would still be a vector or string, but before editing
>     it would be passed through "key-description" to give the string to
>     edit, and after editing the string would be passed through "kbd" (aka
>     "read-kbd-macro") to make the value to save in the variable.
> That could be a big improvement.  Would you like to do it?

Patch included below.  Works like a charm :-)

Would some "widget expert" please take a look at the two "what is this
good for" questions...

> This is a new feature (isn't it? please correct me if I'm wrong),
> so fixing it now to work well when first released is appropriate.

Right!  The key-sequence widget was added quite recently, and
only mouse-region-delete-keys uses it.

>     It would be great if there was some way to actually press the keys
>     to insert, rather than to have to spell them out -- is there some
>     way to bind a key to have a special meaning while editing such a string?
>     E.g. to add C-M-S-$ to the string, one could press e.g. C-u C-M-S-$
> That could also be a big improvement, but how to reconcile these two
> features?  It could appear as a string, with a box which you click on
> to enter a new key by typing it.

Easy :-)

With the code below, C-q followed by KEY or EVENT simply inserts the
string representation of the key or event "at point".

This seems logical as meaning "quote next key chord".

Well, it steals the binding which allowed you to enter arbitrary
numeric values, but I don't see the purpose of that! Why would anyone
want to create a binding for a key they cannot type?

The help-echo is changed accordingly.

Index: wid-edit.el
RCS file: /cvsroot/emacs/emacs/lisp/wid-edit.el,v
retrieving revision 1.157
diff -c -r1.157 wid-edit.el
*** wid-edit.el 17 Dec 2005 08:52:54 -0000      1.157
--- wid-edit.el 20 Dec 2005 14:41:54 -0000
*** 3161,3188 ****
      (widget-apply widget :notify widget event)
  (defvar widget-key-sequence-prompt-value-history nil
    "History of input to `widget-key-sequence-prompt-value'.")
! ;; This mostly works, but I am pretty sure it needs more change
! ;; to be 100% correct.  I don't know what the change should be -- rms.
  (define-widget 'key-sequence 'restricted-sexp
!   "A Lisp function."
    :prompt-value 'widget-field-prompt-value
    :prompt-internal 'widget-symbol-prompt-internal
!   :prompt-match 'fboundp
    :prompt-history 'widget-key-sequence-prompt-value-history
    :action 'widget-field-action
    :match-alternatives '(stringp vectorp)
!   :validate (lambda (widget)
!             (unless (or (stringp (widget-value widget))
!                         (vectorp (widget-value widget)))
!               (widget-put widget :error (format "Invalid key sequence: %S"
!                                                 (widget-value widget)))
!               widget))
!   :value 'ignore
    :tag "Key sequence")
  (define-widget 'sexp 'editable-field
    "An arbitrary Lisp expression."
--- 3161,3224 ----
      (widget-apply widget :notify widget event)
+ ;;; I'm not sure about what this is good for?  KFS.
  (defvar widget-key-sequence-prompt-value-history nil
    "History of input to `widget-key-sequence-prompt-value'.")
! (defvar widget-key-sequence-default-value [ignore]
!   "Default value for an empty key sequence.")
! (defvar widget-key-sequence-map
!   (let ((map (make-sparse-keymap)))
!     (set-keymap-parent map widget-field-keymap)
!     (define-key map [(control ?q)] 'widget-key-sequence-read-event)
!     map))
  (define-widget 'key-sequence 'restricted-sexp
!   "A key sequence."
    :prompt-value 'widget-field-prompt-value
    :prompt-internal 'widget-symbol-prompt-internal
! ; :prompt-match 'fboundp   ;; What was this good for?  KFS
    :prompt-history 'widget-key-sequence-prompt-value-history
    :action 'widget-field-action
    :match-alternatives '(stringp vectorp)
!   :format "%{%t%}: %v"
!   :validate 'widget-key-sequence-validate
!   :value-to-internal 'widget-key-sequence-value-to-internal
!   :value-to-external 'widget-key-sequence-value-to-external
!   :value widget-key-sequence-default-value
!   :keymap widget-key-sequence-map
!   :help-echo "C-q: insert KEY or EVENT; RET: enter value"
    :tag "Key sequence")
+ (defun widget-key-sequence-read-event (ev)
+   (interactive (list (read-event "Insert KEY or EVENT: ")))
+   (if (/= (char-before) ?\s) (insert " "))
+   (insert (key-description (list ev)))
+   (if (memq 'down (event-modifiers ev))
+       (insert " " (key-description (list (read-event))))))
+ (defun widget-key-sequence-validate (widget)
+   (unless (or (stringp (widget-value widget))
+             (vectorp (widget-value widget)))
+     (widget-put widget :error (format "Invalid key sequence: %S"
+                                     (widget-value widget)))
+     widget))
+ (defun widget-key-sequence-value-to-internal (widget value)
+   (if (widget-apply widget :match value)
+       (if (equal value widget-key-sequence-default-value)
+         ""
+       (key-description value))
+     value))
+ (defun widget-key-sequence-value-to-external (widget value)
+   (if (stringp value)
+       (if (string-match "\\`[[:space:]]*\\'" value)
+         widget-key-sequence-default-value
+       (read-kbd-macro value))
+     value))
  (define-widget 'sexp 'editable-field
    "An arbitrary Lisp expression."

Kim F. Storm <address@hidden> http://www.cua.dk

reply via email to

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