python-voiceio 0.3.10__tar.gz → 0.3.11__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. {python_voiceio-0.3.10/python_voiceio.egg-info → python_voiceio-0.3.11}/PKG-INFO +16 -10
  2. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/README.md +14 -2
  3. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/pyproject.toml +3 -6
  4. {python_voiceio-0.3.10 → python_voiceio-0.3.11/python_voiceio.egg-info}/PKG-INFO +16 -10
  5. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/python_voiceio.egg-info/requires.txt +0 -10
  6. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_commands.py +21 -9
  7. python_voiceio-0.3.11/voiceio/__init__.py +1 -0
  8. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/app.py +19 -1
  9. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/commands.py +5 -2
  10. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/config.py +1 -0
  11. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/platform.py +4 -0
  12. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/typers/clipboard.py +1 -1
  13. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/wizard.py +15 -12
  14. python_voiceio-0.3.10/voiceio/__init__.py +0 -1
  15. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/LICENSE +0 -0
  16. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/python_voiceio.egg-info/SOURCES.txt +0 -0
  17. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/python_voiceio.egg-info/dependency_links.txt +0 -0
  18. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/python_voiceio.egg-info/entry_points.txt +0 -0
  19. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/python_voiceio.egg-info/top_level.txt +0 -0
  20. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/setup.cfg +0 -0
  21. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_app_wiring.py +0 -0
  22. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_autocorrect.py +0 -0
  23. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_backend_probes.py +0 -0
  24. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_clipboard_read.py +0 -0
  25. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_config.py +0 -0
  26. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_corrections.py +0 -0
  27. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_fallback.py +0 -0
  28. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_health.py +0 -0
  29. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_hints.py +0 -0
  30. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_history.py +0 -0
  31. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_ibus_typer.py +0 -0
  32. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_llm.py +0 -0
  33. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_llm_api.py +0 -0
  34. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_numbers.py +0 -0
  35. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_platform.py +0 -0
  36. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_postprocess.py +0 -0
  37. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_prebuffer.py +0 -0
  38. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_prompt.py +0 -0
  39. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_recorder_integration.py +0 -0
  40. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_robustness.py +0 -0
  41. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_streaming.py +0 -0
  42. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_transcriber.py +0 -0
  43. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_tts.py +0 -0
  44. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_vad.py +0 -0
  45. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_vocabulary.py +0 -0
  46. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/tests/test_wordfreq.py +0 -0
  47. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/__main__.py +0 -0
  48. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/autocorrect.py +0 -0
  49. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/backends.py +0 -0
  50. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/cli.py +0 -0
  51. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/clipboard_read.py +0 -0
  52. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/corrections.py +0 -0
  53. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/demo.py +0 -0
  54. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/feedback.py +0 -0
  55. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/health.py +0 -0
  56. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/hints.py +0 -0
  57. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/history.py +0 -0
  58. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/hotkeys/__init__.py +0 -0
  59. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/hotkeys/base.py +0 -0
  60. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/hotkeys/chain.py +0 -0
  61. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/hotkeys/evdev.py +0 -0
  62. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/hotkeys/pynput_backend.py +0 -0
  63. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/hotkeys/socket_backend.py +0 -0
  64. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/ibus/__init__.py +0 -0
  65. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/ibus/engine.py +0 -0
  66. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/llm.py +0 -0
  67. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/llm_api.py +0 -0
  68. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/models/__init__.py +0 -0
  69. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/models/silero_vad.onnx +0 -0
  70. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/numbers.py +0 -0
  71. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/pidlock.py +0 -0
  72. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/postprocess.py +0 -0
  73. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/prompt.py +0 -0
  74. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/recorder.py +0 -0
  75. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/service.py +0 -0
  76. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/sounds/__init__.py +0 -0
  77. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/sounds/commit.wav +0 -0
  78. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/sounds/start.wav +0 -0
  79. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/sounds/stop.wav +0 -0
  80. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/streaming.py +0 -0
  81. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/transcriber.py +0 -0
  82. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/tray/__init__.py +0 -0
  83. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/tray/_icons.py +0 -0
  84. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/tray/_indicator.py +0 -0
  85. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/tray/_pystray.py +0 -0
  86. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/tts/__init__.py +0 -0
  87. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/tts/base.py +0 -0
  88. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/tts/chain.py +0 -0
  89. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/tts/edge_engine.py +0 -0
  90. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/tts/espeak.py +0 -0
  91. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/tts/piper_engine.py +0 -0
  92. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/tts/player.py +0 -0
  93. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/typers/__init__.py +0 -0
  94. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/typers/base.py +0 -0
  95. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/typers/chain.py +0 -0
  96. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/typers/ibus.py +0 -0
  97. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/typers/pynput_type.py +0 -0
  98. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/typers/wtype.py +0 -0
  99. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/typers/xdotool.py +0 -0
  100. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/typers/ydotool.py +0 -0
  101. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/vad.py +0 -0
  102. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/vocabulary.py +0 -0
  103. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/wordfreq.py +0 -0
  104. {python_voiceio-0.3.10 → python_voiceio-0.3.11}/voiceio/worker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-voiceio
3
- Version: 0.3.10
3
+ Version: 0.3.11
4
4
  Summary: Speak → text, locally, instantly.
5
5
  Author: Hugo Montenegro
6
6
  License-Expression: MIT
@@ -26,16 +26,10 @@ Requires-Dist: numpy>=1.24.0
26
26
  Requires-Dist: onnxruntime>=1.16.0
27
27
  Requires-Dist: wordfreq>=3.0
28
28
  Requires-Dist: evdev>=1.6.0; sys_platform == "linux"
29
- Requires-Dist: pynput>=1.7.6; sys_platform == "win32"
30
- Requires-Dist: pynput>=1.7.6; sys_platform == "darwin"
29
+ Requires-Dist: pynput>=1.7.6
31
30
  Requires-Dist: pyperclip>=1.8.0; sys_platform == "win32"
32
31
  Requires-Dist: win11toast>=0.36; sys_platform == "win32"
33
- Provides-Extra: x11
34
- Requires-Dist: pynput>=1.7.6; extra == "x11"
35
- Provides-Extra: mac
36
- Requires-Dist: pynput>=1.7.6; extra == "mac"
37
32
  Provides-Extra: win
38
- Requires-Dist: pynput>=1.7.6; extra == "win"
39
33
  Requires-Dist: pyperclip>=1.8.0; extra == "win"
40
34
  Requires-Dist: win11toast>=0.36; extra == "win"
41
35
  Provides-Extra: tray
@@ -52,6 +46,15 @@ Dynamic: license-file
52
46
 
53
47
  # voiceio
54
48
 
49
+ ```
50
+ ██╗ ██╗ ██████╗ ██╗ ██████╗███████╗██╗ ██████╗
51
+ ██║ ██║██╔═══██╗██║██╔════╝██╔════╝██║██╔═══██╗
52
+ ██║ ██║██║ ██║██║██║ █████╗ ██║██║ ██║
53
+ ╚██╗ ██╔╝██║ ██║██║██║ ██╔══╝ ██║██║ ██║
54
+ ╚████╔╝ ╚██████╔╝██║╚██████╗███████╗██║╚██████╔╝
55
+ ╚═══╝ ╚═════╝ ╚═╝ ╚═════╝╚══════╝╚═╝ ╚═════╝
56
+ ```
57
+
55
58
  [![CI](https://github.com/Hugo0/voiceio/actions/workflows/ci.yml/badge.svg)](https://github.com/Hugo0/voiceio/actions/workflows/ci.yml)
56
59
  [![PyPI](https://img.shields.io/pypi/v/python-voiceio)](https://pypi.org/project/python-voiceio/)
57
60
  [![Python](https://img.shields.io/pypi/pyversions/python-voiceio)](https://pypi.org/project/python-voiceio/)
@@ -60,11 +63,13 @@ Dynamic: license-file
60
63
 
61
64
  Speak → text, locally, instantly.
62
65
 
66
+ https://github.com/user-attachments/assets/9cf5d1ac-b4bb-4cf8-b775-7a66dc16b376
67
+
63
68
  ## Quick start
64
69
 
65
70
  ```bash
66
71
  # 1. Install system dependencies (Ubuntu/Debian)
67
- sudo apt install pipx ibus gir1.2-ibus-1.0 python3-gi portaudio19-dev
72
+ sudo apt install pipx ibus gir1.2-ibus-1.0 python3-gi python3-dev portaudio19-dev
68
73
 
69
74
  # 2. Install voiceio
70
75
  pipx install python-voiceio
@@ -79,7 +84,7 @@ That's it. Press **Ctrl+Alt+V** (or your chosen hotkey) to start dictating.
79
84
  <summary><strong>Fedora</strong></summary>
80
85
 
81
86
  ```bash
82
- sudo dnf install pipx ibus python3-gobject portaudio-devel
87
+ sudo dnf install pipx ibus python3-gobject python3-devel portaudio-devel
83
88
  pipx install python-voiceio
84
89
  voiceio setup
85
90
  ```
@@ -90,6 +95,7 @@ voiceio setup
90
95
 
91
96
  ```bash
92
97
  sudo pacman -S python-pipx ibus python-gobject portaudio
98
+ # Note: Arch includes Python headers by default with the python package
93
99
  pipx install python-voiceio
94
100
  voiceio setup
95
101
  ```
@@ -1,5 +1,14 @@
1
1
  # voiceio
2
2
 
3
+ ```
4
+ ██╗ ██╗ ██████╗ ██╗ ██████╗███████╗██╗ ██████╗
5
+ ██║ ██║██╔═══██╗██║██╔════╝██╔════╝██║██╔═══██╗
6
+ ██║ ██║██║ ██║██║██║ █████╗ ██║██║ ██║
7
+ ╚██╗ ██╔╝██║ ██║██║██║ ██╔══╝ ██║██║ ██║
8
+ ╚████╔╝ ╚██████╔╝██║╚██████╗███████╗██║╚██████╔╝
9
+ ╚═══╝ ╚═════╝ ╚═╝ ╚═════╝╚══════╝╚═╝ ╚═════╝
10
+ ```
11
+
3
12
  [![CI](https://github.com/Hugo0/voiceio/actions/workflows/ci.yml/badge.svg)](https://github.com/Hugo0/voiceio/actions/workflows/ci.yml)
4
13
  [![PyPI](https://img.shields.io/pypi/v/python-voiceio)](https://pypi.org/project/python-voiceio/)
5
14
  [![Python](https://img.shields.io/pypi/pyversions/python-voiceio)](https://pypi.org/project/python-voiceio/)
@@ -8,11 +17,13 @@
8
17
 
9
18
  Speak → text, locally, instantly.
10
19
 
20
+ https://github.com/user-attachments/assets/9cf5d1ac-b4bb-4cf8-b775-7a66dc16b376
21
+
11
22
  ## Quick start
12
23
 
13
24
  ```bash
14
25
  # 1. Install system dependencies (Ubuntu/Debian)
15
- sudo apt install pipx ibus gir1.2-ibus-1.0 python3-gi portaudio19-dev
26
+ sudo apt install pipx ibus gir1.2-ibus-1.0 python3-gi python3-dev portaudio19-dev
16
27
 
17
28
  # 2. Install voiceio
18
29
  pipx install python-voiceio
@@ -27,7 +38,7 @@ That's it. Press **Ctrl+Alt+V** (or your chosen hotkey) to start dictating.
27
38
  <summary><strong>Fedora</strong></summary>
28
39
 
29
40
  ```bash
30
- sudo dnf install pipx ibus python3-gobject portaudio-devel
41
+ sudo dnf install pipx ibus python3-gobject python3-devel portaudio-devel
31
42
  pipx install python-voiceio
32
43
  voiceio setup
33
44
  ```
@@ -38,6 +49,7 @@ voiceio setup
38
49
 
39
50
  ```bash
40
51
  sudo pacman -S python-pipx ibus python-gobject portaudio
52
+ # Note: Arch includes Python headers by default with the python package
41
53
  pipx install python-voiceio
42
54
  voiceio setup
43
55
  ```
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-voiceio"
7
- version = "0.3.10"
7
+ version = "0.3.11"
8
8
  description = "Speak → text, locally, instantly."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -28,16 +28,13 @@ dependencies = [
28
28
  "onnxruntime>=1.16.0",
29
29
  "wordfreq>=3.0",
30
30
  "evdev>=1.6.0; sys_platform == 'linux'",
31
- "pynput>=1.7.6; sys_platform == 'win32'",
32
- "pynput>=1.7.6; sys_platform == 'darwin'",
31
+ "pynput>=1.7.6",
33
32
  "pyperclip>=1.8.0; sys_platform == 'win32'",
34
33
  "win11toast>=0.36; sys_platform == 'win32'",
35
34
  ]
36
35
 
37
36
  [project.optional-dependencies]
38
- x11 = ["pynput>=1.7.6"]
39
- mac = ["pynput>=1.7.6"]
40
- win = ["pynput>=1.7.6", "pyperclip>=1.8.0", "win11toast>=0.36"]
37
+ win = ["pyperclip>=1.8.0", "win11toast>=0.36"]
41
38
  tray = ["pystray>=0.19", "Pillow>=10.0"]
42
39
  tts = ["piper-tts>=1.2.0"]
43
40
  tts-cloud = ["edge-tts>=6.1.0"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-voiceio
3
- Version: 0.3.10
3
+ Version: 0.3.11
4
4
  Summary: Speak → text, locally, instantly.
5
5
  Author: Hugo Montenegro
6
6
  License-Expression: MIT
@@ -26,16 +26,10 @@ Requires-Dist: numpy>=1.24.0
26
26
  Requires-Dist: onnxruntime>=1.16.0
27
27
  Requires-Dist: wordfreq>=3.0
28
28
  Requires-Dist: evdev>=1.6.0; sys_platform == "linux"
29
- Requires-Dist: pynput>=1.7.6; sys_platform == "win32"
30
- Requires-Dist: pynput>=1.7.6; sys_platform == "darwin"
29
+ Requires-Dist: pynput>=1.7.6
31
30
  Requires-Dist: pyperclip>=1.8.0; sys_platform == "win32"
32
31
  Requires-Dist: win11toast>=0.36; sys_platform == "win32"
33
- Provides-Extra: x11
34
- Requires-Dist: pynput>=1.7.6; extra == "x11"
35
- Provides-Extra: mac
36
- Requires-Dist: pynput>=1.7.6; extra == "mac"
37
32
  Provides-Extra: win
38
- Requires-Dist: pynput>=1.7.6; extra == "win"
39
33
  Requires-Dist: pyperclip>=1.8.0; extra == "win"
40
34
  Requires-Dist: win11toast>=0.36; extra == "win"
41
35
  Provides-Extra: tray
@@ -52,6 +46,15 @@ Dynamic: license-file
52
46
 
53
47
  # voiceio
54
48
 
49
+ ```
50
+ ██╗ ██╗ ██████╗ ██╗ ██████╗███████╗██╗ ██████╗
51
+ ██║ ██║██╔═══██╗██║██╔════╝██╔════╝██║██╔═══██╗
52
+ ██║ ██║██║ ██║██║██║ █████╗ ██║██║ ██║
53
+ ╚██╗ ██╔╝██║ ██║██║██║ ██╔══╝ ██║██║ ██║
54
+ ╚████╔╝ ╚██████╔╝██║╚██████╗███████╗██║╚██████╔╝
55
+ ╚═══╝ ╚═════╝ ╚═╝ ╚═════╝╚══════╝╚═╝ ╚═════╝
56
+ ```
57
+
55
58
  [![CI](https://github.com/Hugo0/voiceio/actions/workflows/ci.yml/badge.svg)](https://github.com/Hugo0/voiceio/actions/workflows/ci.yml)
56
59
  [![PyPI](https://img.shields.io/pypi/v/python-voiceio)](https://pypi.org/project/python-voiceio/)
57
60
  [![Python](https://img.shields.io/pypi/pyversions/python-voiceio)](https://pypi.org/project/python-voiceio/)
@@ -60,11 +63,13 @@ Dynamic: license-file
60
63
 
61
64
  Speak → text, locally, instantly.
62
65
 
66
+ https://github.com/user-attachments/assets/9cf5d1ac-b4bb-4cf8-b775-7a66dc16b376
67
+
63
68
  ## Quick start
64
69
 
65
70
  ```bash
66
71
  # 1. Install system dependencies (Ubuntu/Debian)
67
- sudo apt install pipx ibus gir1.2-ibus-1.0 python3-gi portaudio19-dev
72
+ sudo apt install pipx ibus gir1.2-ibus-1.0 python3-gi python3-dev portaudio19-dev
68
73
 
69
74
  # 2. Install voiceio
70
75
  pipx install python-voiceio
@@ -79,7 +84,7 @@ That's it. Press **Ctrl+Alt+V** (or your chosen hotkey) to start dictating.
79
84
  <summary><strong>Fedora</strong></summary>
80
85
 
81
86
  ```bash
82
- sudo dnf install pipx ibus python3-gobject portaudio-devel
87
+ sudo dnf install pipx ibus python3-gobject python3-devel portaudio-devel
83
88
  pipx install python-voiceio
84
89
  voiceio setup
85
90
  ```
@@ -90,6 +95,7 @@ voiceio setup
90
95
 
91
96
  ```bash
92
97
  sudo pacman -S python-pipx ibus python-gobject portaudio
98
+ # Note: Arch includes Python headers by default with the python package
93
99
  pipx install python-voiceio
94
100
  voiceio setup
95
101
  ```
@@ -3,15 +3,12 @@ sounddevice>=0.4.6
3
3
  numpy>=1.24.0
4
4
  onnxruntime>=1.16.0
5
5
  wordfreq>=3.0
6
-
7
- [:sys_platform == "darwin"]
8
6
  pynput>=1.7.6
9
7
 
10
8
  [:sys_platform == "linux"]
11
9
  evdev>=1.6.0
12
10
 
13
11
  [:sys_platform == "win32"]
14
- pynput>=1.7.6
15
12
  pyperclip>=1.8.0
16
13
  win11toast>=0.36
17
14
 
@@ -19,9 +16,6 @@ win11toast>=0.36
19
16
  pytest>=7.0
20
17
  pytest-mock
21
18
 
22
- [mac]
23
- pynput>=1.7.6
24
-
25
19
  [tray]
26
20
  pystray>=0.19
27
21
  Pillow>=10.0
@@ -33,9 +27,5 @@ piper-tts>=1.2.0
33
27
  edge-tts>=6.1.0
34
28
 
35
29
  [win]
36
- pynput>=1.7.6
37
30
  pyperclip>=1.8.0
38
31
  win11toast>=0.36
39
-
40
- [x11]
41
- pynput>=1.7.6
@@ -59,30 +59,36 @@ class TestFormatting:
59
59
 
60
60
  class TestUndo:
61
61
  def test_scratch_that(self):
62
- cp = CommandProcessor()
62
+ cp = CommandProcessor(editing=True)
63
63
  result = cp.process("hello world scratch that")
64
64
  assert result == "hello world"
65
65
  assert cp.undo_requested is True
66
66
 
67
67
  def test_undo_that(self):
68
- cp = CommandProcessor()
68
+ cp = CommandProcessor(editing=True)
69
69
  result = cp.process("hello world undo that")
70
70
  assert result == "hello world"
71
71
  assert cp.undo_requested is True
72
72
 
73
73
  def test_scratch_that_only(self):
74
- cp = CommandProcessor()
74
+ cp = CommandProcessor(editing=True)
75
75
  result = cp.process("scratch that")
76
76
  assert result == ""
77
77
  assert cp.undo_requested is True
78
78
 
79
79
  def test_undo_resets_between_calls(self):
80
- cp = CommandProcessor()
80
+ cp = CommandProcessor(editing=True)
81
81
  cp.process("scratch that")
82
82
  assert cp.undo_requested is True
83
83
  cp.process("hello world")
84
84
  assert cp.undo_requested is False
85
85
 
86
+ def test_editing_off_ignores_scratch(self):
87
+ cp = CommandProcessor(editing=False)
88
+ result = cp.process("hello world scratch that")
89
+ assert result == "hello world scratch that"
90
+ assert cp.undo_requested is False
91
+
86
92
 
87
93
  class TestEdgeCases:
88
94
  def test_no_commands(self):
@@ -127,27 +133,27 @@ class TestEdgeCases:
127
133
 
128
134
  class TestCorrectThat:
129
135
  def test_correct_that_sets_flag(self):
130
- cp = CommandProcessor()
136
+ cp = CommandProcessor(editing=True)
131
137
  result = cp.process("hello world correct that")
132
138
  assert cp.flag_requested is True
133
139
  assert cp.flagged_word == "world"
134
140
  assert result == "hello"
135
141
 
136
142
  def test_correct_that_no_preceding_word(self):
137
- cp = CommandProcessor()
143
+ cp = CommandProcessor(editing=True)
138
144
  result = cp.process("correct that")
139
145
  assert cp.flag_requested is True
140
146
  assert cp.flagged_word == ""
141
147
  assert result == ""
142
148
 
143
149
  def test_correct_that_returns_text_before(self):
144
- cp = CommandProcessor()
150
+ cp = CommandProcessor(editing=True)
145
151
  result = cp.process("one two three correct that")
146
152
  assert result == "one two"
147
153
  assert cp.flagged_word == "three"
148
154
 
149
155
  def test_flag_resets_between_calls(self):
150
- cp = CommandProcessor()
156
+ cp = CommandProcessor(editing=True)
151
157
  cp.process("hello correct that")
152
158
  assert cp.flag_requested is True
153
159
  cp.process("hello world")
@@ -155,11 +161,17 @@ class TestCorrectThat:
155
161
  assert cp.flagged_word == ""
156
162
 
157
163
  def test_undo_not_set_on_flag(self):
158
- cp = CommandProcessor()
164
+ cp = CommandProcessor(editing=True)
159
165
  cp.process("hello correct that")
160
166
  assert cp.flag_requested is True
161
167
  assert cp.undo_requested is False
162
168
 
169
+ def test_editing_off_ignores_correct(self):
170
+ cp = CommandProcessor(editing=False)
171
+ result = cp.process("hello world correct that")
172
+ assert result == "hello world correct that"
173
+ assert cp.flag_requested is False
174
+
163
175
 
164
176
  class TestSpacing:
165
177
  def test_no_double_spaces(self):
@@ -0,0 +1 @@
1
+ __version__ = "0.3.11"
@@ -126,6 +126,24 @@ class VoiceIO:
126
126
  self._socket: SocketHotkey | None = None
127
127
  if self._hotkey.name != "socket":
128
128
  self._socket = SocketHotkey()
129
+ elif self.platform.desktop not in ("GNOME", "KDE"):
130
+ # Socket backend has no physical hotkey listener — user must bind
131
+ # `voiceio toggle` to a key in their WM config.
132
+ log.warning(
133
+ "Hotkey backend is 'socket' on desktop '%s'. "
134
+ "Physical hotkey capture is not available. "
135
+ "Bind 'voiceio toggle' to a key in your window manager config "
136
+ "(e.g. i3: bindsym Ctrl+Alt+v exec voiceio toggle). "
137
+ "Or: sudo usermod -aG input $USER && log out/in to enable evdev.",
138
+ self.platform.desktop,
139
+ )
140
+ print(
141
+ f"\n NOTE: No physical hotkey listener available on '{self.platform.desktop}'.\n"
142
+ f" Bind 'voiceio toggle' to a key in your WM config, e.g.:\n"
143
+ f" i3/sway: bindsym Ctrl+Alt+v exec voiceio toggle\n"
144
+ f" hyprland: bind = CTRL ALT, V, exec, voiceio toggle\n"
145
+ f" Or fix evdev: sudo usermod -aG input $USER (then log out/in)\n",
146
+ )
129
147
 
130
148
  print(f"Loading model '{cfg.model.name}'...", end="", flush=True)
131
149
  t0 = time.monotonic()
@@ -146,7 +164,7 @@ class VoiceIO:
146
164
  if vocab:
147
165
  self.transcriber.set_initial_prompt(vocab)
148
166
 
149
- self._command_processor = CommandProcessor(enabled=cfg.commands.enabled)
167
+ self._command_processor = CommandProcessor(enabled=cfg.commands.enabled, editing=cfg.commands.editing)
150
168
  self._cleanup = cfg.output.punctuation_cleanup
151
169
  self._number_conversion = cfg.output.number_conversion
152
170
  self._streaming = cfg.output.streaming
@@ -83,9 +83,12 @@ def _normalize_spacing(text: str) -> str:
83
83
  class CommandProcessor:
84
84
  """Detects and replaces voice commands in transcribed text."""
85
85
 
86
- def __init__(self, enabled: bool = True):
86
+ def __init__(self, enabled: bool = True, editing: bool = False):
87
87
  self._enabled = enabled
88
- self._commands = DEFAULT_COMMANDS
88
+ self._commands = {
89
+ k: v for k, v in DEFAULT_COMMANDS.items()
90
+ if editing or v not in (_UNDO_SENTINEL, _FLAG_SENTINEL)
91
+ }
89
92
  self._max_words = max(len(k) for k in self._commands) if self._commands else 1
90
93
  self.undo_requested = False
91
94
  self.flag_requested = False
@@ -85,6 +85,7 @@ class DaemonConfig:
85
85
  @dataclass
86
86
  class CommandsConfig:
87
87
  enabled: bool = True
88
+ editing: bool = False
88
89
 
89
90
 
90
91
  @dataclass
@@ -234,6 +234,10 @@ def open_in_terminal(cmd: list[str]) -> bool:
234
234
  _TERMINALS = [
235
235
  (["gnome-terminal", "--"], "gnome-terminal"),
236
236
  (["konsole", "-e"], "konsole"),
237
+ (["alacritty", "-e"], "alacritty"),
238
+ (["kitty", "--"], "kitty"),
239
+ (["foot", "--"], "foot"),
240
+ (["wezterm", "start", "--"], "wezterm"),
237
241
  (["xfce4-terminal", "-e"], "xfce4-terminal"),
238
242
  (["xterm", "-e"], "xterm"),
239
243
  ]
@@ -80,7 +80,7 @@ class ClipboardTyper:
80
80
  return ProbeResult(
81
81
  ok=False,
82
82
  reason="No clipboard tool found",
83
- fix_hint="Install xclip (X11), wl-copy (Wayland), or pbcopy (macOS).",
83
+ fix_hint="Install xclip + xdotool (X11), wl-copy + ydotool/wtype (Wayland), or pbcopy (macOS).",
84
84
  )
85
85
  if sys.platform == "win32":
86
86
  try:
@@ -945,10 +945,11 @@ def run_wizard() -> None:
945
945
  "will use GPU" if checks["cuda"] else "will use CPU (still fast)",
946
946
  optional=True)
947
947
 
948
- if checks["display"] == "wayland":
948
+ if checks["is_linux"]:
949
949
  _print_check("Input group (evdev)", checks["input_group"],
950
- "" if checks["input_group"] else "optional: sudo usermod -aG input $USER",
951
- optional=True)
950
+ "evdev hotkeys available" if checks["input_group"]
951
+ else "sudo usermod -aG input $USER (then log out/in)",
952
+ optional=checks["input_group"])
952
953
 
953
954
  # Tray icon
954
955
  from voiceio.tray import probe_availability
@@ -1067,13 +1068,12 @@ def run_wizard() -> None:
1067
1068
  else:
1068
1069
  print(f" {YELLOW}⚠{RESET} {DIM}Could not install IBus component, will use fallback{RESET}")
1069
1070
 
1070
- if checks["display"] == "wayland":
1071
- if checks["input_group"]:
1072
- backend = "evdev"
1073
- else:
1074
- backend = "socket"
1071
+ if checks["input_group"]:
1072
+ backend = "evdev"
1073
+ elif checks["pynput"] and checks["display"] != "wayland":
1074
+ backend = "auto" # pynput works on X11
1075
1075
  else:
1076
- backend = "auto"
1076
+ backend = "socket"
1077
1077
 
1078
1078
  # ── Defaults for optional settings ──────────────────────────────────
1079
1079
  sound_enabled = True
@@ -1286,9 +1286,12 @@ def run_wizard() -> None:
1286
1286
  print(f" {YELLOW}⚠{RESET} Auto-setup failed. Add manually in Settings → Keyboard → Shortcuts:")
1287
1287
  print(" Command: voiceio-toggle")
1288
1288
  elif backend == "socket":
1289
- print(f"\n {YELLOW}ℹ{RESET} Add a keyboard shortcut manually in your DE settings:")
1290
- print(f" Shortcut: {BOLD}{hotkey}{RESET}")
1291
- print(f" Command: {BOLD}voiceio-toggle{RESET}")
1289
+ print(f"\n {YELLOW}ℹ{RESET} Add a keyboard shortcut in your window manager config:")
1290
+ print(f" {DIM}i3/sway:{RESET} bindsym Ctrl+Alt+v exec voiceio toggle")
1291
+ print(f" {DIM}hyprland:{RESET} bind = CTRL ALT, V, exec, voiceio toggle")
1292
+ print(f" {DIM}other:{RESET} bind {BOLD}{hotkey}{RESET} → {BOLD}voiceio toggle{RESET}")
1293
+ print(f"\n {DIM}Or enable evdev (no WM config needed):{RESET}")
1294
+ print(f" sudo usermod -aG input $USER {DIM}(then log out and back in){RESET}")
1292
1295
 
1293
1296
  # Autostart
1294
1297
  from voiceio.service import install_service
@@ -1 +0,0 @@
1
- __version__ = "0.3.10"
File without changes