1 ;;; hib-kbd.el --- Implicit button type for key sequences delimited with {}.
3 ;; Copyright (C) 1991-1995, 2008 Free Software Foundation, Inc.
4 ;; Developed with support from Motorola Inc.
6 ;; Author: Bob Weiner, Brown U.
7 ;; Maintainer: Mats Lidell <matsl@contactor.se>
8 ;; Keywords: extensions, hypermedia
10 ;; This file is part of GNU Hyperbole.
12 ;; GNU Hyperbole is free software; you can redistribute it and/or
13 ;; modify it under the terms of the GNU General Public License as
14 ;; published by the Free Software Foundation; either version 3, or (at
15 ;; your option) any later version.
17 ;; GNU Hyperbole is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 ;; General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
29 ;; A click of the Hyperbole execution key on a key sequence executes its
32 ;; A click of the Hyperbole help key on a key sequence displays the
33 ;; documentation for its command binding.
35 ;; Key sequences should be in human readable form, e.g. {C-b}.
36 ;; Forms such as {\C-b}, {\^b}, and {^b} will not be recognized.
42 ;;; Public implicit button types
45 (defact kbd-key (key-sequence)
46 "Executes the function binding for KEY-SEQUENCE, delimited by {}.
47 Returns t if a KEY-SEQUENCE has a binding, else nil."
48 (interactive "kKeyboard key to execute (no {}): ")
49 (kbd-key:act key-sequence))
52 "Executes a key sequence delimited by curly braces.
53 Key sequences should be in human readable form, e.g. {C-b}.
54 Forms such as {\C-b}, {\^b}, and {^b} will not be recognized."
57 (let* ((seq-and-pos (or (hbut:label-p t "{`" "'}" t)
58 (hbut:label-p t "{" "}" t)))
59 (key-sequence (car seq-and-pos))
60 (binding (and (stringp key-sequence)
61 (key-binding (kbd-key:normalize key-sequence)))))
62 (and binding (not (integerp binding))
63 (ibut:label-set seq-and-pos)
64 (hact 'kbd-key key-sequence)))))
70 (defun kbd-key:act (key-sequence)
71 "Executes the command binding for KEY-SEQUENCE.
72 Returns t if KEY-SEQUENCE has a binding, else nil."
73 (interactive "kKeyboard key to execute (no {}): ")
74 (setq current-prefix-arg nil) ;; kbd-key:normalize below sets it.
75 (let ((binding (key-binding (kbd-key:normalize key-sequence))))
76 (cond ((null binding) nil)
77 ((memq binding '(action-key action-mouse-key hkey-either))
79 (message "(kbd-key:act): This key does what the Action Key does.")
81 (t (call-interactively binding) t))))
83 (defun kbd-key:doc (key &optional full)
84 "Shows first line of doc for binding of keyboard KEY in minibuffer.
85 With optional FULL, displays full documentation for command."
86 (interactive "kKey sequence: \nP")
87 (let* ((cmd (let ((cmd (key-binding (kbd-key:normalize key))))
88 (if (not (integerp cmd)) cmd)))
89 (doc (and cmd (documentation cmd)))
93 (setq end-line (string-match "[\n]" doc)
94 doc (substitute-command-keys (substring doc 0 end-line))))
95 (setq doc (format "No documentation for {%s} %s" key (or cmd ""))))
98 (describe-function cmd)
101 (defun kbd-key:help (but)
102 "Display documentation for binding of keyboard key given by BUT's label."
103 (let ((kbd-key (hbut:key-to-label (hattr:get but 'lbl-key))))
104 (and kbd-key (kbd-key:doc kbd-key 'full))))
106 (defun kbd-key:normalize (key-sequence)
107 "Returns KEY-SEQUENCE normalized into a form that can be parsed by commands."
108 (interactive "kKeyboard key sequence to normalize (no {}): ")
109 (let ((norm-key-seq (copy-sequence key-sequence))
110 (case-fold-search nil) (case-replace t))
111 ;; Quote Control and Meta key names
112 (setq norm-key-seq (hypb:replace-match-string
113 "[ \t\n\^M]+" norm-key-seq "" t)
114 norm-key-seq (hypb:replace-match-string
115 "@key{SPC}\\|SPC" norm-key-seq "\040" t)
116 norm-key-seq (hypb:replace-match-string
117 "@key{DEL}\\|DEL" norm-key-seq "\177" t)
118 norm-key-seq (hypb:replace-match-string
119 "@key{RET}\\|@key{RTN}\\|RET\\|RTN"
120 norm-key-seq "\015" t)
121 norm-key-seq (hypb:replace-match-string
122 "ESCESC" norm-key-seq "\233" t)
123 norm-key-seq (hypb:replace-match-string
124 "@key{ESC}\\|ESC" norm-key-seq "M-" t)
125 ;; Unqote special {} chars.
126 norm-key-seq (hypb:replace-match-string "\\\\\\([{}]\\)"
129 (while (string-match "\\`\\(C-u\\|M-\\)\\(-?[0-9]+\\)" norm-key-seq)
130 (setq current-prefix-arg
131 (string-to-number (substring norm-key-seq (match-beginning 2)
133 norm-key-seq (substring norm-key-seq (match-end 0))))
135 (while (string-match "\\`C-u" norm-key-seq)
136 (if (or (not (listp current-prefix-arg))
137 (not (integerp (setq arg-val (car current-prefix-arg)))))
138 (setq current-prefix-arg '(1)
140 (setq arg-val (* arg-val 4)
141 current-prefix-arg (cons arg-val nil)
142 norm-key-seq (substring norm-key-seq (match-end 0)))))
143 (setq norm-key-seq (hypb:replace-match-string
144 "C-\\(.\\)" norm-key-seq
150 (substring str (match-beginning 1)
151 (1+ (match-beginning 1)))))
153 (hypb:replace-match-string
154 "M-\\(.\\)" norm-key-seq
157 (char-to-string (+ (downcase (string-to-char
158 (substring str (match-beginning 1)
159 (1+ (match-beginning 1)))))
164 ;;; hib-kbd.el ends here