-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdictate-editor
More file actions
executable file
·87 lines (74 loc) · 2.42 KB
/
dictate-editor
File metadata and controls
executable file
·87 lines (74 loc) · 2.42 KB
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#!/bin/bash
# Voice-to-editor: opens nvim with dictation keybindings
# Used as $EDITOR with Claude Code's Ctrl+G (chat:externalEditor)
# F5 = start dictation, F6 = stop recording & transcribe now
FILE="$1"
REAL_EDITOR="${DICTATE_EDITOR:-/usr/bin/nvim}"
NVIM_INIT=$(mktemp /tmp/dictate-nvim-XXXXXX.lua)
cat > "$NVIM_INIT" << 'LUA'
local dictate_job = nil
local dictate_output = ''
local function show(msg, hl)
vim.cmd('echohl ' .. (hl or 'Normal'))
vim.cmd('echon ' .. vim.fn.string(msg))
vim.cmd('echohl None')
end
local function on_dictate_done()
local result = dictate_output:gsub('%s+$', '')
dictate_job = nil
dictate_output = ''
if result ~= '' then
local words = #vim.split(result, '%s+', {trimempty = true})
show('Inserted ' .. words .. ' words', 'String')
local lines = vim.split(result, '\n')
vim.api.nvim_put(lines, 'c', true, true)
else
show('(no speech detected)', 'Comment')
end
vim.cmd('startinsert!')
end
-- F5: start dictation (async)
vim.keymap.set({'n', 'i'}, '<F5>', function()
if dictate_job then
show('Already recording... press F6 to stop', 'ErrorMsg')
return
end
if vim.fn.mode() == 'i' then vim.cmd('stopinsert') end
dictate_output = ''
dictate_job = vim.fn.jobstart('dictate --once 2>/dev/null', {
stdout_buffered = true,
on_stdout = function(_, data, _)
if data then
dictate_output = dictate_output .. table.concat(data, '\n')
end
end,
on_exit = function(_, _, _)
vim.schedule(on_dictate_done)
end,
})
-- Show message after mode change settles
vim.defer_fn(function()
show('● Recording... [F6 = stop, or 3s silence]', 'WarningMsg')
end, 50)
end, { desc = 'Start dictation' })
-- F6: stop recording immediately
vim.keymap.set({'n', 'i'}, '<F6>', function()
if dictate_job then
vim.fn.system('dictate --stop-recording')
show('⏹ Stopping... transcribing', 'WarningMsg')
else
show('Not recording', 'Comment')
end
end, { desc = 'Stop recording & transcribe' })
-- F7: toggle spell checker
vim.keymap.set({'n', 'i'}, '<F7>', function()
vim.wo.spell = not vim.wo.spell
if vim.wo.spell then
show('Spell ON — ]s/[s = next/prev, z= = suggest, zg = add word', 'WarningMsg')
else
show('Spell OFF', 'Comment')
end
end, { desc = 'Toggle spell check' })
show('[dictate-editor] F5 = dictate, F6 = stop, F7 = spell. :wq when done.', 'Title')
LUA
exec "$REAL_EDITOR" -c "luafile $NVIM_INIT" "$FILE"