-- Groq Dictate: trigger по одиночному нажатию Fn (Globe) -- Fn нельзя биндить через hs.hotkey, поэтому слушаем flagsChanged local SCRIPT = os.getenv("HOME") .. "/bin/groq-dictate.sh" local function runScript() hs.task.new("/bin/bash", function(exitCode, stdOut, stdErr) local f = io.open("/tmp/groq-dictate.last", "r") if f then local text = f:read("*a") f:close() os.remove("/tmp/groq-dictate.last") if text and #text > 0 then hs.pasteboard.setContents(text) -- keycode 9 = физическая V, в обход keymap lookup чтобы не спамить warnings на ru-раскладке hs.eventtap.event.newKeyEvent({"cmd"}, 9, true):post() hs.eventtap.event.newKeyEvent({"cmd"}, 9, false):post() end end end, {SCRIPT}):start() end -- Отслеживаем Fn: keycode 63 — это physical Fn/Globe -- Триггер по press (а не по release), чтобы было снапи local fnPressed = false local fnTime = 0 fnTap = hs.eventtap.new({hs.eventtap.event.types.flagsChanged}, function(event) local kc = event:getKeyCode() if kc ~= 63 then return false end -- 63 = Fn/Globe local flags = event:getFlags() local now = hs.timer.absoluteTime() / 1e6 -- ms if flags.fn and not fnPressed then -- Fn pressed fnPressed = true fnTime = now elseif (not flags.fn) and fnPressed then -- Fn released fnPressed = false local elapsed = now - fnTime -- Только короткое нажатие (<400ms) триггерит — long-press для других целей if elapsed < 400 then runScript() end end return false -- не блокировать event для других слушателей end) fnTap:start() hs.alert.show("Groq Dictate: Fn (Globe) ready")