給xbindkeys添加key sequence支持

xbindkeys不支持emacs風格的key sequence,不過由於它可以調用guile來支持scheme的配置文件。xbindkeystarball裏有一個配置文件,支持key sequence的特殊形式:兩個鍵的序列。

最近正好學了些scheme,就好好折騰了一把,寫了一份配置文件,可以支持任意長的key sequence(當然太長的一般用不到)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
(define (delete-duplicates l)
(cond ((null? l) '())
((memq (car l) (cdr l)) (delete-duplicates (cdr l)))
(else (cons (car l) (delete-duplicates (cdr l))))
)
)

(define global-map '())

(define (register keys action)
(define (loop getmap setmap keys)
(if (null? keys)
(setmap action)
(let ((k (car keys)))
(if (eq? #f (assoc k (getmap)))
(setmap (assoc-set! (getmap) k '())))
(loop (lambda () (cdr (assoc k (getmap))))
(lambda (m) (setmap (assoc-set! (getmap) k m)))
(cdr keys))
)
)
)
(loop (lambda () global-map) (lambda (m) (set! global-map m)) keys)
)

(define (grab keymap)
(define (proc k)
(define action (cdr (assoc k keymap)))
(ungrab-all-keys)
(remove-all-keys)
(if (string? action)
(begin
(run-command action)
(reset-first-binding)
)
(grab action)
)
(grab-all-keys)
)
(map (lambda (k)
(xbindkey-function k (lambda () (proc k)))
) (delete-duplicates (map car keymap)))
(if (not (eq? global-map keymap))
(xbindkey-function '(control g) (lambda () (reset-first-binding)))
)
)

(define (first-binding)
(grab global-map)
)

(define (reset-first-binding)
(ungrab-all-keys)
(remove-all-keys)
(first-binding)
(grab-all-keys))

(define (simple s)
(string-concatenate `("wmctrl -xa " ,s "||" ,s))
)

(register '((control semicolon) x) (simple "xterm"))
(register '((control semicolon) u) "wmctrl tmux || -T tmux -e tmux attach -t default")
(register '((control semicolon) e) "wmctrl -xa Emacs || emacsclient -c -n")
(register '((control semicolon) v) "wmctrl -xa Vim || gvim")
(register '((control semicolon) f) (simple "firefox"))
(register '((control semicolon) i) (simple "evince"))
(register '((control semicolon) (control semicolon)) "xdotool send ctrl+semicolon")

(first-binding)

用法很簡單,模仿代碼中的(register ...),在這串鍵綁定裏添刪你自己的。xbindkeys還支持shift mod3 release等修飾符。release指的是鍵釋放時而不是press時執行動作。xbindkeys -d還有其他一些關於修飾符的例子。

我的鍵綁定中wmctrl -xa是一個用外部命令搭建的簡易jump-or-execwmctrl會檢查窗口titleclass,如果不存在則執行,否則給相應窗口焦點。(simple ...)針對的是titleclass相同的情況。

兩次control semicolon被我映射爲產生一個control semicolonkey sequence按到一半時按control g是取消。