keypad.el 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. ;;; keypad.el --- simplified keypad bindings
  2. ;; Copyright (C) 2002-2012 Free Software Foundation, Inc.
  3. ;; Author: Kim F. Storm <storm@cua.dk>
  4. ;; Keywords: keyboard convenience
  5. ;; This file is part of GNU Emacs.
  6. ;; GNU Emacs is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; GNU Emacs is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;; The keypad package allows easy binding of the keypad keys to
  18. ;; various commonly used sets of commands.
  19. ;;
  20. ;; With the following setup, the keypad can be used for numeric data
  21. ;; entry when NumLock is off, and to give numeric prefix arguments to
  22. ;; emacs commands, when NumLock is on.
  23. ;;
  24. ;; keypad-setup => Plain Numeric Keypad
  25. ;; keypad-numlock-setup => Prefix numeric args
  26. ;;
  27. ;; +--------+--------+--------+
  28. ;; | M-7 | M-8 | M-9 | <- numlock on
  29. ;; | 7 | 8 | 9 | <- numlock off
  30. ;; +--------+--------+--------+
  31. ;; | M-4 | M-5 | M-6 |
  32. ;; | 4 | 5 | 6 |
  33. ;; +--------+--------+--------+
  34. ;; | M-1 | M-2 | M-3 |
  35. ;; | 1 | 2 | 3 |
  36. ;; +--------+--------+--------+
  37. ;; | M-0 | M-- |
  38. ;; | 0 | . |
  39. ;; +-----------------+--------+
  40. ;; The following keypad setup is used for navigation together with
  41. ;; modes like cua-mode which uses shifted movement keys to extend the
  42. ;; region.
  43. ;;
  44. ;; keypad-setup => Cursor keys
  45. ;; keypad-shifted-setup => Shifted cursor keys
  46. ;;
  47. ;; +--------+--------+--------+
  48. ;; | S-home | S-up | S-PgUp | <- shifted, numlock off
  49. ;; | Home | up | PgUp | <- unshifted, numlock off
  50. ;; +--------+--------+--------+
  51. ;; | S-left |S-space |S-right |
  52. ;; | left | space | right |
  53. ;; +--------+--------+--------+
  54. ;; | S-end | S-down | S-PgDn |
  55. ;; | end | down | PgDn |
  56. ;; +--------+--------+--------+
  57. ;; | S-insert |S-delete|
  58. ;; | insert | delete |
  59. ;; +-----------------+--------+
  60. ;; The following setup binds the unshifted keypad keys to plain
  61. ;; numeric keys when NumLock is either on or off, but the decimal key
  62. ;; produces either a . (NumLock off) or a , (NumLock on). This is
  63. ;; useful for e.g. Danish users where the decimal separator is a
  64. ;; comma.
  65. ;;
  66. ;; keypad-setup => Plain Numeric Keypad
  67. ;; keypad-numlock-setup => Numeric Keypad with Decimal key: ,
  68. ;;
  69. ;; +--------+--------+--------+
  70. ;; | 7 | 8 | 9 | <- numlock on
  71. ;; | 7 | 8 | 9 | <- numlock off
  72. ;; +--------+--------+--------+
  73. ;; | 4 | 5 | 6 |
  74. ;; | 4 | 5 | 6 |
  75. ;; +--------+--------+--------+
  76. ;; | 1 | 2 | 3 |
  77. ;; | 1 | 2 | 3 |
  78. ;; +--------+--------+--------+
  79. ;; | 0 | , |
  80. ;; | 0 | . |
  81. ;; +-----------------+--------+
  82. ;;; Code:
  83. (provide 'keypad)
  84. ;;; Customization
  85. ;;;###autoload
  86. (defcustom keypad-setup nil
  87. "Specifies the keypad setup for unshifted keypad keys when NumLock is off.
  88. When selecting the plain numeric keypad setup, the character returned by the
  89. decimal key must be specified."
  90. :set (lambda (symbol value)
  91. (if value
  92. (keypad-setup value nil nil value)))
  93. :initialize 'custom-initialize-default
  94. :link '(emacs-commentary-link "keypad.el")
  95. :version "22.1"
  96. :type '(choice (const :tag "Plain numeric keypad" numeric)
  97. (character :tag "Numeric Keypad with Decimal Key"
  98. :match (lambda (widget value) (integerp value))
  99. :value ?.)
  100. (const :tag "Numeric prefix arguments" prefix)
  101. (const :tag "Cursor keys" cursor)
  102. (const :tag "Shifted cursor keys" S-cursor)
  103. (const :tag "Unspecified/User-defined" none)
  104. (other :tag "Keep existing bindings" nil))
  105. :require 'keypad
  106. :group 'keyboard)
  107. ;;;###autoload
  108. (defcustom keypad-numlock-setup nil
  109. "Specifies the keypad setup for unshifted keypad keys when NumLock is on.
  110. When selecting the plain numeric keypad setup, the character returned by the
  111. decimal key must be specified."
  112. :set (lambda (symbol value)
  113. (if value
  114. (keypad-setup value t nil value)))
  115. :initialize 'custom-initialize-default
  116. :link '(emacs-commentary-link "keypad.el")
  117. :version "22.1"
  118. :type '(choice (const :tag "Plain numeric keypad" numeric)
  119. (character :tag "Numeric Keypad with Decimal Key"
  120. :match (lambda (widget value) (integerp value))
  121. :value ?.)
  122. (const :tag "Numeric prefix arguments" prefix)
  123. (const :tag "Cursor keys" cursor)
  124. (const :tag "Shifted cursor keys" S-cursor)
  125. (const :tag "Unspecified/User-defined" none)
  126. (other :tag "Keep existing bindings" nil))
  127. :require 'keypad
  128. :group 'keyboard)
  129. ;;;###autoload
  130. (defcustom keypad-shifted-setup nil
  131. "Specifies the keypad setup for shifted keypad keys when NumLock is off.
  132. When selecting the plain numeric keypad setup, the character returned by the
  133. decimal key must be specified."
  134. :set (lambda (symbol value)
  135. (if value
  136. (keypad-setup value nil t value)))
  137. :initialize 'custom-initialize-default
  138. :link '(emacs-commentary-link "keypad.el")
  139. :version "22.1"
  140. :type '(choice (const :tag "Plain numeric keypad" numeric)
  141. (character :tag "Numeric Keypad with Decimal Key"
  142. :match (lambda (widget value) (integerp value))
  143. :value ?.)
  144. (const :tag "Numeric prefix arguments" prefix)
  145. (const :tag "Cursor keys" cursor)
  146. (const :tag "Shifted cursor keys" S-cursor)
  147. (const :tag "Unspecified/User-defined" none)
  148. (other :tag "Keep existing bindings" nil))
  149. :require 'keypad
  150. :group 'keyboard)
  151. ;;;###autoload
  152. (defcustom keypad-numlock-shifted-setup nil
  153. "Specifies the keypad setup for shifted keypad keys when NumLock is off.
  154. When selecting the plain numeric keypad setup, the character returned by the
  155. decimal key must be specified."
  156. :set (lambda (symbol value)
  157. (if value
  158. (keypad-setup value t t value)))
  159. :initialize 'custom-initialize-default
  160. :link '(emacs-commentary-link "keypad.el")
  161. :version "22.1"
  162. :type '(choice (const :tag "Plain numeric keypad" numeric)
  163. (character :tag "Numeric Keypad with Decimal Key"
  164. :match (lambda (widget value) (integerp value))
  165. :value ?.)
  166. (const :tag "Numeric prefix arguments" prefix)
  167. (const :tag "Cursor keys" cursor)
  168. (const :tag "Shifted cursor keys" S-cursor)
  169. (const :tag "Unspecified/User-defined" none)
  170. (other :tag "Keep existing bindings" nil))
  171. :require 'keypad
  172. :group 'keyboard)
  173. ;;;###autoload
  174. (defun keypad-setup (setup &optional numlock shift decimal)
  175. "Set keypad bindings in `function-key-map' according to SETUP.
  176. If optional second argument NUMLOCK is non-nil, the NumLock On bindings
  177. are changed. Otherwise, the NumLock Off bindings are changed.
  178. If optional third argument SHIFT is non-nil, the shifted keypad
  179. keys are bound.
  180. Setup Binding
  181. -------------------------------------------------------------
  182. 'prefix Command prefix argument, i.e. M-0 .. M-9 and M--
  183. 'S-cursor Bind shifted keypad keys to the shifted cursor movement keys.
  184. 'cursor Bind keypad keys to the cursor movement keys.
  185. 'numeric Plain numeric keypad, i.e. 0 .. 9 and . (or DECIMAL arg)
  186. 'none Removes all bindings for keypad keys in function-key-map;
  187. this enables any user-defined bindings for the keypad keys
  188. in the global and local keymaps.
  189. If SETUP is 'numeric and the optional fourth argument DECIMAL is non-nil,
  190. the decimal key on the keypad is mapped to DECIMAL instead of `.'"
  191. (let* ((i 0)
  192. (var (cond
  193. ((and (not numlock) (not shift)) 'keypad-setup)
  194. ((and (not numlock) shift) 'keypad-shifted-setup)
  195. ((and numlock (not shift)) 'keypad-numlock-setup)
  196. ((and numlock shift) 'keypad-numlock-shifted-setup)))
  197. (kp (cond
  198. ((eq var 'keypad-setup)
  199. [kp-delete kp-insert kp-end kp-down kp-next kp-left
  200. kp-space kp-right kp-home kp-up kp-prior])
  201. ((eq var 'keypad-shifted-setup)
  202. [S-kp-decimal S-kp-0 S-kp-1 S-kp-2 S-kp-3 S-kp-4
  203. S-kp-5 S-kp-6 S-kp-7 S-kp-8 S-kp-9])
  204. ((eq var 'keypad-numlock-setup)
  205. [kp-decimal kp-0 kp-1 kp-2 kp-3 kp-4
  206. kp-5 kp-6 kp-7 kp-8 kp-9])
  207. ((eq var 'keypad-numlock-shifted-setup)
  208. [S-kp-delete S-kp-insert S-kp-end S-kp-down S-kp-next S-kp-left
  209. S-kp-space S-kp-right S-kp-home S-kp-up S-kp-prior])))
  210. (bind
  211. (cond
  212. ((or (eq setup 'numeric)
  213. (characterp setup))
  214. (if (eq decimal 'numeric)
  215. (setq decimal nil))
  216. (vector (or decimal ?.) ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9))
  217. ((eq setup 'prefix)
  218. [?\M-- ?\M-0 ?\M-1 ?\M-2 ?\M-3 ?\M-4
  219. ?\M-5 ?\M-6 ?\M-7 ?\M-8 ?\M-9])
  220. ((eq setup 'cursor)
  221. [delete insert end down next left
  222. space right home up prior])
  223. ((eq setup 'S-cursor)
  224. [S-delete S-insert S-end S-down S-next S-left
  225. S-space S-right S-home S-up S-prior])
  226. ((eq setup 'none)
  227. nil)
  228. (t
  229. (signal 'error (list "Unknown keypad setup: " setup))))))
  230. (set var setup)
  231. ;; Bind the keys in KP list to BIND list in function-key-map.
  232. ;; If BIND is nil, all bindings for the keys are removed.
  233. (if (not (boundp 'function-key-map))
  234. (setq function-key-map (make-sparse-keymap)))
  235. (while (< i 11)
  236. (define-key function-key-map (vector (aref kp i))
  237. (if bind (vector (aref bind i))))
  238. (if (= i 6)
  239. (cond ((eq (aref kp i) 'kp-space)
  240. (define-key function-key-map [kp-begin]
  241. (if bind (vector (aref bind i)))))
  242. ((eq (aref kp i) 'S-kp-space)
  243. (define-key function-key-map [S-kp-begin]
  244. (if bind (vector (aref bind i)))))))
  245. (setq i (1+ i)))))
  246. ;;; keypad.el ends here