Clojureでキーボード操作をエミュレートするにはjava.awt.Robot
を使えばできます。
awtbotというjava.awt.Robot
をラップしたライブラリもありますが、基本的な関数しかないのでもっと簡単に使える関数を作ってみます。
robot.clj
(ns robot.sample
(:import [java.awt Robot]
[java.awt.event KeyEvent]
[javax.swing KeyStroke]))
(defn static-fields [^Class class fields]
(map #(load-string (str (.getName class) "/" %)) fields))
(defn modifiers->vks [modifiers]
(->> (map #(when (pos? (bit-and modifiers %1)) %2)
(static-fields KeyEvent '[SHIFT_DOWN_MASK CTRL_DOWN_MASK ALT_DOWN_MASK ALT_GRAPH_DOWN_MASK META_DOWN_MASK])
(static-fields KeyEvent '[VK_SHIFT VK_CONTROL VK_ALT VK_ALT_GRAPH VK_META]))
(filter identity)))
(defn stroke->vks [^String stroke]
(let [^KeyStroke ks (KeyStroke/getKeyStroke stroke)
vks (modifiers->vks (.getModifiers ks))]
(concat vks [(.getKeyCode ks)])))
(def ^:dynamic *sleep-time* 100)
(defn emulate-stroke [^Robot robot ^String stroke]
(Thread/sleep *sleep-time*)
(let [vks (stroke->vks stroke)]
(doseq [vk vks]
(.keyPress robot vk))
(doseq [vk (reverse vks)]
(.keyRelease robot vk))))
(defn emulate-strokes [^Robot robot & strokes]
(doseq [stroke strokes]
(emulate-stroke robot stroke)))
これを以下のように使います。
キーの文字列はjavax.swing KeyStroke/getKeyStroke
で指定できるものが使えます。
use_robot.clj
(def bot (Robot.))
(emulate-strokes bot "P" "shift T" "B" "shift A" "TAB")
ctrlとshiftを同時押しするキーの場合、環境によってはNumLockが有効だとshiftが有効にならないという問題があるようです。
また、java.awt.ToolkitのsetLockingKeyStateやgetLockingKeyStateでNUM_LOCKの状態の設定と参照ができそうですが、バグっててうまく働かないようです。残念