Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

373 lines
15 KiB

4 years ago
  1. ;;; key-chord.el --- map pairs of simultaneously pressed keys to commands
  2. ;;-------------------------------------------------------------------
  3. ;;
  4. ;; Copyright (C) 2003,2005,2008,2012 David Andersson
  5. ;;
  6. ;; This file is NOT part of Emacs.
  7. ;;
  8. ;; This program is free software; you can redistribute it and/or
  9. ;; modify it under the terms of the GNU General Public License as
  10. ;; published by the Free Software Foundation; either version 2 of
  11. ;; the License, or (at your option) any later version.
  12. ;;
  13. ;; This program is distributed in the hope that it will be
  14. ;; useful, but WITHOUT ANY WARRANTY; without even the implied
  15. ;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  16. ;; PURPOSE. See the GNU General Public License for more details.
  17. ;;
  18. ;; You should have received a copy of the GNU General Public
  19. ;; License along with this program; if not, write to the Free
  20. ;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. ;; MA 02111-1307 USA
  22. ;;
  23. ;;-------------------------------------------------------------------
  24. ;; Author: David Andersson <l.david.andersson(at)sverige.nu>
  25. ;; Created: 27 April 2003
  26. ;; Version: 0.6 (2012-10-23)
  27. ;; Package-Version: 20160227.1238
  28. ;; Keywords: keyboard chord input
  29. ;;; Commentary:
  30. ;; ######## Compatibility ########################################
  31. ;;
  32. ;; Works with Emacs-20.3, 20.6, 20.7, 21.2, 21.4, 22.1 and 23.1
  33. ;; Does not work with Emacs-19.31 nor XEmacs-20.4 and 21.4.
  34. ;; ######## Quick start ########################################
  35. ;;
  36. ;; Add to your ~/.emacs
  37. ;;
  38. ;; (require 'key-chord)
  39. ;; (key-chord-mode 1)
  40. ;;
  41. ;; and some chords, for example
  42. ;;
  43. ;; (key-chord-define-global "hj" 'undo)
  44. ;; (key-chord-define-global ",." "<>\C-b")
  45. ;; ######## Terminology ########################################
  46. ;;
  47. ;; In this package, a "key chord" is two keys pressed simultaneously,
  48. ;; or a single key quickly pressed twice.
  49. ;;
  50. ;; (Sometimes pressing SHIFT and/or META plus another key is call a chord,
  51. ;; but not here. However SHIFT plus two normal keys can be a "key chord".)
  52. ;; ######## Description ########################################
  53. ;;
  54. ;; Key chord mode acts like a global minor mode controlled by the function
  55. ;; `key-chord-mode'.
  56. ;;
  57. ;; Key chord definitions are stored in ordinary key-maps.
  58. ;; The function `key-chord-define-global' defines a chord in the global
  59. ;; key-map and `key-chord-define' defines a chord in a specified key-map,
  60. ;; for example for a specific mode.
  61. ;;
  62. ;; A TWO-key chord is two distinct keys pressed simultaneously (within
  63. ;; one tenth of a second, or so).
  64. ;;
  65. ;; Examples:
  66. ;;
  67. ;; (key-chord-define-global ",." "<>\C-b")
  68. ;; (key-chord-define-global "hj" 'undo)
  69. ;; (key-chord-define-global [?h ?j] 'undo) ; the same
  70. ;; (key-chord-define-global "jk" 'dabbrev-expand)
  71. ;; (key-chord-define-global "cv" 'reindent-then-newline-and-indent)
  72. ;; (key-chord-define-global "4r" "$")
  73. ;;
  74. ;; Comma and dot pressed together insert a pair of angle brackets.
  75. ;; `h' and `j' pressed together invoke the undo command.
  76. ;; `j' and `k' pressed together invoke the dabbrev-expand command.
  77. ;; 'c' and 'v' pressed together insert a newline.
  78. ;; `4' and `r' pressed together insert a dollar sign.
  79. ;;
  80. ;; A ONE-key chord is a single key quickly pressed twice (within one third
  81. ;; of a second or so).
  82. ;;
  83. ;; Examples:
  84. ;;
  85. ;; (key-chord-define-global "''" "`'\C-b")
  86. ;; (key-chord-define-global ",," 'indent-for-comment)
  87. ;; (key-chord-define-global "qq" "the ")
  88. ;; (key-chord-define-global "QQ" "The ")
  89. ;;
  90. ;; Tick (') pressed twice inserts a back-tick and a tick (`').
  91. ;; Comma (,) pressed twice indents for and/or inserts a comment.
  92. ;; `q' pressed twice inserts the word "the ".
  93. ;;
  94. ;; Examples: Mode specific chords
  95. ;;
  96. ;; (key-chord-define c++-mode-map ";;" "\C-e;")
  97. ;; (key-chord-define c++-mode-map "{}" "{\n\n}\C-p\t")
  98. ;;
  99. ;; The command `key-chord-describe' lists currently defined key chords.
  100. ;; The standard command `describe-bindings' (C-h b) will also show key chords.
  101. ;;
  102. ;; The standard command `describe-key' (C-h k) will accept a key chord and
  103. ;; show its definition. (Isn't that amazing. There is no explicit code to
  104. ;; carry out this functionality.)
  105. ;; ######## Tips ########################################
  106. ;;
  107. ;; Don't chord key combinations that exists in the languages you typically
  108. ;; write. Otherwise, if you are typing fast, two key intended to be separate
  109. ;; letters might instead trig a chord.
  110. ;; E.g. "uu" would be a good chord in spanish but not in finnish, and
  111. ;; "hj" would be a good chord in english but not in swedish.
  112. ;;
  113. ;; Don't rely solely on /usr/dict/words to find unusual combination.
  114. ;; For example "cv" or "fg" can be quite common in certain kinds of
  115. ;; programming. Grep your own texts to verify that a combination is unusual.
  116. ;; And don't forget to check both permutations: "fg" and "gf".
  117. ;;
  118. ;; Choose two keys that are close to each other on the keyboard, so they
  119. ;; can be quickly typed without effort. Chords involving two hands (as
  120. ;; opposed to two fingers on one hand) are harder to type (quickly).
  121. ;; The idea is that key chords are to replace function keys for functions
  122. ;; that are frequently performed while the hands are in writing position.
  123. ;;
  124. ;; Key chords might not work well over a slow network.
  125. ;; ######## Limitations ########################################
  126. ;;
  127. ;; When recording keyboard macros, the time between keyboard inputs are not
  128. ;; recorded. Thus, the key-chord-input-method cannot know for sure if two keys
  129. ;; in a macro was a chord or not. The current solution remembers the first key
  130. ;; of the chords typed during macro recording, and keys that match those (and
  131. ;; are defined as chords) are considered key-chords during macro execution.
  132. ;; This knowledge is not saved with `name-last-kbd-macro', so they may
  133. ;; execute wrong if they contain pair of keys that match defined chords.
  134. ;;
  135. ;; Emacs will not call input-method-function for keys that have non numeric
  136. ;; codes or whos code is outside the range 32..126. Thus you cannot define
  137. ;; key chords involving function keys, control keys, or even your non-english
  138. ;; letters (on national keyboards) that otherwise are well positioned for
  139. ;; chording on your keyboard.
  140. ;; (I think chording left and right arrow keys would be useful, but cannot do.
  141. ;; I consider this a bug in Emacs. Input methods could happily return
  142. ;; unmodified *any* key they don't know about.)
  143. ;;
  144. ;; Key chords longer that 2 keys are not supported. It could be done, but I
  145. ;; don't think it is worth the trubbel since most keyboards will not reliably
  146. ;; send all key codes when 3 or more keys are pressed simultaneously.
  147. ;; It might also be a bit trickier to maintain performance.
  148. ;;
  149. ;; Key chord mode uses input-method-function. And so do internationalisation
  150. ;; packages (mule, quail, etc). Do not expect them to work well together.
  151. ;; The last one that gets the input-method-function rules.
  152. ;; ######## Implementation ########################################
  153. ;;
  154. ;; Key chords piggy back in ordinary key maps, so they can be defined
  155. ;; per mode without having to add hooks to all modes.
  156. ;;
  157. ;; Key chord key codes are vectors beginning with the atom `key-chord'.
  158. ;; A two key chord, e.g. "hj", will add two entries in the key-map.
  159. ;; E.g. [key-chord ?h ?j] and [key-chord ?j ?h].
  160. ;;
  161. ;; When key-chord-mode is enabled input-method-function is set to
  162. ;; key-chord-input-method.
  163. ;; ######## To do ########################################
  164. ;;
  165. ;; * Find a way to save key-chord info in keyboard macros.
  166. ;;
  167. ;; * Save previous value of input-method-function? And call it?
  168. ;;
  169. ;; * input-method-function is reset in *info* buffers! What to do?
  170. ;;
  171. ;; * How to enter interactively command OR string in key-chord-define-global?
  172. ;;
  173. ;; * Customize public vars (defcustom).
  174. ;; ######## History ########################################
  175. ;;
  176. ;; 0.6 (2012-10-23) l.david.andersson(at)sverige.nu
  177. ;; Add key-chord-define-local, key-chord-unset-local, key-chord-unset-global
  178. ;; 0.5 (2008-09-15) david(at)symsoft.se
  179. ;; Bugfix sit-for; Improved examples; New E-mail in comment
  180. ;; 0.4 (2005-05-07) david(at)symsoft.se
  181. ;; Slightly better macro heuristics; Added option key-chord-in-macros
  182. ;; 0.3 (2005-04-14) david(at)symsoft.se
  183. ;; Require advice; More examples
  184. ;; 0.2 (2003-09-13) david(at)symsoft.se
  185. ;; Quick and dirty fix for keyboard macros
  186. ;; 0.1 (2003-04-27) david(at)symsoft.se
  187. ;; First release
  188. ;;; Code:
  189. (defvar key-chord-two-keys-delay 0.1 ; 0.05 or 0.1
  190. "Max time delay between two key press to be considered a key chord.")
  191. (defvar key-chord-one-key-delay 0.2 ; 0.2 or 0.3 to avoid first autorepeat
  192. "Max time delay between two press of the same key to be considered a key chord.
  193. This should normally be a little longer than `key-chord-two-keys-delay'.")
  194. (defvar key-chord-in-macros t
  195. "If nil, don't expand key chords when executing keyboard macros.
  196. If non-nil, expand chord sequenses in macros, but only if a similar chord was
  197. entered during the last interactive macro recording. (This carries a bit of
  198. guesswork. We can't know for sure when executing whether two keys were
  199. typed quickly or slowly when recorded.)")
  200. ;; Internal vars
  201. (defvar key-chord-mode nil)
  202. ;; Shortcut for key-chord-input-method: no need to test a key again if it
  203. ;; didn't matched a chord the last time. Improves feedback during autorepeat.
  204. (defvar key-chord-last-unmatched nil)
  205. ;; Macro heuristics: Keep track of which chords was used when the last macro
  206. ;; was defined. Or rather, only the first-char of the chords. Only expand
  207. ;; matching chords during macro execution.
  208. (defvar key-chord-in-last-kbd-macro nil)
  209. (defvar key-chord-defining-kbd-macro nil)
  210. ;;;###autoload
  211. (defun key-chord-mode (arg)
  212. "Toggle key chord mode.
  213. With positive ARG enable the mode. With zero or negative arg disable the mode.
  214. A key chord is two keys that are pressed simultaneously, or one key quickly
  215. pressed twice.
  216. \nSee functions `key-chord-define-global', `key-chord-define-local', and
  217. `key-chord-define' and variables `key-chord-two-keys-delay' and
  218. `key-chord-one-key-delay'."
  219. (interactive "P")
  220. (setq key-chord-mode (if arg
  221. (> (prefix-numeric-value arg) 0)
  222. (not key-chord-mode)))
  223. (cond (key-chord-mode
  224. (setq input-method-function 'key-chord-input-method)
  225. (message "Key Chord mode on"))
  226. (t
  227. (setq input-method-function nil)
  228. (message "Key Chord mode off"))))
  229. ;;;###autoload
  230. (defun key-chord-define-global (keys command)
  231. "Define a key-chord of the two keys in KEYS starting a COMMAND.
  232. \nKEYS can be a string or a vector of two elements. Currently only elements
  233. that corresponds to ascii codes in the range 32 to 126 can be used.
  234. \nCOMMAND can be an interactive function, a string, or nil.
  235. If COMMAND is nil, the key-chord is removed.
  236. \nNote that KEYS defined locally in the current buffer will have precedence."
  237. (interactive "sSet key chord globally (2 keys): \nCSet chord \"%s\" to command: ")
  238. (key-chord-define (current-global-map) keys command))
  239. ;;;###autoload
  240. (defun key-chord-define-local (keys command)
  241. "Locally define a key-chord of the two keys in KEYS starting a COMMAND.
  242. \nKEYS can be a string or a vector of two elements. Currently only elements
  243. that corresponds to ascii codes in the range 32 to 126 can be used.
  244. \nCOMMAND can be an interactive function, a string, or nil.
  245. If COMMAND is nil, the key-chord is removed.
  246. \nThe binding goes in the current buffer's local map,
  247. which in most cases is shared with all other buffers in the same major mode."
  248. (interactive "sSet key chord locally (2 keys): \nCSet chord \"%s\" to command: ")
  249. (key-chord-define (current-local-map) keys command))
  250. (defun key-chord-unset-global (keys)
  251. "Remove global key-chord of the two keys in KEYS."
  252. (interactive "sUnset key chord globally (2 keys): ")
  253. (key-chord-define (current-global-map) keys nil))
  254. (defun key-chord-unset-local (keys)
  255. "Remove local key-chord of the two keys in KEYS."
  256. (interactive "sUnset key chord locally (2 keys): ")
  257. (key-chord-define (current-local-map) keys nil))
  258. ;;;###autoload
  259. (defun key-chord-define (keymap keys command)
  260. "Define in KEYMAP, a key-chord of the two keys in KEYS starting a COMMAND.
  261. \nKEYS can be a string or a vector of two elements. Currently only elements
  262. that corresponds to ascii codes in the range 32 to 126 can be used.
  263. \nCOMMAND can be an interactive function, a string, or nil.
  264. If COMMAND is nil, the key-chord is removed."
  265. (if (/= 2 (length keys))
  266. (error "Key-chord keys must have two elements"))
  267. ;; Exotic chars in a string are >255 but define-key wants 128..255 for those
  268. (let ((key1 (logand 255 (aref keys 0)))
  269. (key2 (logand 255 (aref keys 1))))
  270. (if (eq key1 key2)
  271. (define-key keymap (vector 'key-chord key1 key2) command)
  272. ;; else
  273. (define-key keymap (vector 'key-chord key1 key2) command)
  274. (define-key keymap (vector 'key-chord key2 key1) command))))
  275. (defun key-chord-lookup-key1 (keymap key)
  276. "Like lookup-key but no third arg and no numeric return value."
  277. (let ((res (lookup-key keymap key)))
  278. (if (numberp res)
  279. nil
  280. ;; else
  281. res)))
  282. (defun key-chord-lookup-key (key)
  283. "Lookup KEY in all current key maps."
  284. (let ((maps (current-minor-mode-maps))
  285. res)
  286. (while (and maps (not res))
  287. (setq res (key-chord-lookup-key1 (car maps) key)
  288. maps (cdr maps)))
  289. (or res
  290. (if (current-local-map)
  291. (key-chord-lookup-key1 (current-local-map) key))
  292. (key-chord-lookup-key1 (current-global-map) key))))
  293. (defun key-chord-describe ()
  294. "List key chord bindings in a help buffer.
  295. \nTwo key chords will be listed twice and there will be Prefix Commands.
  296. Please ignore that."
  297. (interactive)
  298. (describe-bindings [key-chord]))
  299. (defun key-chord-input-method (first-char)
  300. "Input method controlled by key bindings with the prefix `key-chord'."
  301. (if (and (not (eq first-char key-chord-last-unmatched))
  302. (key-chord-lookup-key (vector 'key-chord first-char)))
  303. (let ((delay (if (key-chord-lookup-key (vector 'key-chord first-char first-char))
  304. key-chord-one-key-delay
  305. ;; else
  306. key-chord-two-keys-delay)))
  307. (if (if executing-kbd-macro
  308. (not (memq first-char key-chord-in-last-kbd-macro))
  309. (when (bound-and-true-p eldoc-mode)
  310. (eldoc-pre-command-refresh-echo-area))
  311. (sit-for delay 0 'no-redisplay))
  312. (progn
  313. (setq key-chord-last-unmatched nil)
  314. (list first-char))
  315. ;; else input-pending-p
  316. (let* ((input-method-function nil)
  317. (next-char (read-event))
  318. (res (vector 'key-chord first-char next-char)))
  319. (if (key-chord-lookup-key res)
  320. (progn
  321. (setq key-chord-defining-kbd-macro
  322. (cons first-char key-chord-defining-kbd-macro))
  323. (list 'key-chord first-char next-char))
  324. ;; else put back next-char and return first-char
  325. (setq unread-command-events (cons next-char unread-command-events))
  326. (if (eq first-char next-char)
  327. (setq key-chord-last-unmatched first-char))
  328. (list first-char)))))
  329. ;; else no key-chord keymap
  330. (setq key-chord-last-unmatched first-char)
  331. (list first-char)))
  332. (require 'advice)
  333. (defadvice start-kbd-macro (after key-chord activate)
  334. (setq key-chord-defining-kbd-macro nil))
  335. (defadvice end-kbd-macro (after key-chord activate)
  336. (setq key-chord-in-last-kbd-macro key-chord-defining-kbd-macro))
  337. (provide 'key-chord)
  338. ;;; key-chord.el ends here