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
(local {: eventtap : execute : logger : pasteboard : uielement} hs)
(local log (logger.new :utils :info))
(fn chomp [s]
"Returns the input without a trailing newline"
(if (= (s:sub -1) "\n")
(s:sub 1 -2)
s))
;; paste content, preserving the previous pasteboard
(fn paste [content]
(let [prev-pasteboard (pasteboard.getContents)]
(pasteboard.setContents content)
(eventtap.keyStroke [:cmd] :v)
(pasteboard.setContents prev-pasteboard)))
(fn replace-selection [cb]
"Replaces the current selection with the return value of the callback"
(let [prev-pasteboard (pasteboard.getContents)
e (uielement.focusedElement)
text (if e (e:selectedText)
(do
(eventtap.keyStroke [:cmd] :c)
(pasteboard.getContents)))
content (cb text prev-pasteboard)]
(paste content)
(pasteboard.setContents prev-pasteboard)))
(fn run [...]
"Executes a list of commands"
(each [_ cmd (ipairs [...])]
(execute cmd)))
; https://github.com/Hammerspoon/hammerspoon/issues/3224#issuecomment-1294359070
(λ with-ax-hotfix [win cb]
(let [app (win:application)
ax-app (hs.axuielement.applicationElement app)
prev-val ax-app.AXEnhancedUserInterface]
(set ax-app.AXEnhancedUserInterface false)
(cb)
(set ax-app.AXEnhancedUserInterface prev-val)))
(fn debounce [delay f]
(var timer nil)
(fn []
(when timer
(timer:stop))
(set timer (hs.timer.doAfter delay f))))
{: chomp : debounce : paste : replace-selection : run : with-ax-hotfix}