commit d637a1cf0cad7e64140bfaaef0c2f071c672b88b
parent 1ff7225be540f6ae95db481660a1c3e2dc7f9fc2
Author: Yuval Langer <yuvallangerontheroad@gmail.com>
Date: Sat, 27 Nov 2021 03:35:56 +0200
Turn it a proper Python package.
Diffstat:
8 files changed, 160 insertions(+), 86 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
@@ -1,15 +1,23 @@
+## 2021-11-27
+
+Turn it into a Python package by adding a setup.py and sticking the files into
+a module.
+
## 2021-11-26
More Python script experimentations. I've started with a shell threeliner using
ready made packages and I ended up reimplementing them badly.
Something something UNIX philosophy.
-There is now a `~/.clipboard-speaker/words-per-minute` setting file for the Python version.
+There is now a `~/.clipboard-speaker/words-per-minute` setting file for the
+Python version.
Switched (again) to FIFO so you can:
- 10. Marking text and press the keybinding that runs clipboard-speaker as usual. While clipboard-speaker is running and speaking, you can
- 20. Mark more text and press the keybindings for it to feed more text into clipboard-speaker's text buffer, and if you wish
+ 10. Marking text and press the keybinding that runs clipboard-speaker as
+ usual. While clipboard-speaker is running and speaking, you can
+ 20. Mark more text and press the keybindings for it to feed more text into
+ clipboard-speaker's text buffer, and if you wish
30. GOTO 20.
## 2021-11-25
diff --git a/README.md b/README.md
@@ -18,13 +18,45 @@ Have a look at the <a href="CHANGELOG.md">CHANGELOG.md</a> file.
### Installation:
-1. Install the infrastructure:
- `apt install espeak-ng xsel python3`
-2. Copy the two executable scripts into your home bin directory:
- `cp clipboard-speaker clipboard-speaker-kill ~/bin/`
-3. Add the key bindings in (if you use Gnome. If you don't, look up how to
+#### Install the infrastructure:
+
+##### On Debian based systems:
+
+`apt install espeak-ng xsel python3`
+
+#### Install the script files:
+
+##### Manually:
+
+Copy the two executable scripts into your home bin directory:
+
+```
+cp clipboard_speaker/clipboard_speaker.py ~/bin/clipboard-speaker
+cp clipboard_speaker/clipboard_speaker_kill.py ~/bin/clipboard-speaker-kill
+```
+
+##### pip:
+
+```
+pip install --user .
+```
+
+After which the script files are located, at least here in my system, under
+`~/.local/bin/` as `~/.local/bin/clipboard-speak` and
+`~/.local/bin/clipboard-speak-kill`.
+
+#### Map your keybindings:
+
+##### On Gnome:
+
+Add the key bindings in (if you use Gnome. If you don't, look up how to
assign scripts to keybindings in your own window manager):
- `Gnome Settings → Keyboard Shortcuts → All the way down and press the + button`
+
+```
+Gnome Settings
+ → Keyboard Shortcuts
+ → All the way down and press the + button
+```
### Usage:
diff --git a/clipboard-speaker b/clipboard-speaker
@@ -1,63 +0,0 @@
-#!/usr/bin/env python3
-
-import os
-from pathlib import Path
-from subprocess import Popen, PIPE
-
-DEFAULT_WORDS_PER_MINUTE = "175"
-
-CLIPBOARD_SPEAKER_PATH = Path.home() / ".clipboard-speaker"
-PID_FILE_PATH = CLIPBOARD_SPEAKER_PATH / "pid"
-FIFO_FILE_PATH = CLIPBOARD_SPEAKER_PATH / "fifo"
-
-WORDS_PER_MINUTE_PATH = CLIPBOARD_SPEAKER_PATH / "words-per-minute"
-
-
-def get_words_per_minute() -> str:
- if not WORDS_PER_MINUTE_PATH.exists():
- with WORDS_PER_MINUTE_PATH.open("w") as words_per_minute_file:
- words_per_minute_file.write(DEFAULT_WORDS_PER_MINUTE)
- return DEFAULT_WORDS_PER_MINUTE
-
- with WORDS_PER_MINUTE_PATH.open("r") as words_per_minute_file:
- words_per_minute = words_per_minute_file.read().strip()
-
- return words_per_minute
-
-
-if __name__ == "__main__":
- words_per_minute = get_words_per_minute()
- try:
- os.mkfifo(FIFO_FILE_PATH, mode=0o600)
- except FileExistsError:
- pass
-
- # https://stackoverflow.com/questions/63132778/how-to-use-fifo-named-pipe-as-stdin-in-popen-python
- fifo_read_file = os.open(FIFO_FILE_PATH, os.O_RDONLY | os.O_NONBLOCK)
- fifo_write_file = os.open(FIFO_FILE_PATH, os.O_WRONLY)
-
- Popen(
- ["xsel", "-p"],
- stdout=fifo_write_file,
- )
- os.close(fifo_write_file)
-
- if not PID_FILE_PATH.exists():
- speak_ng_process = Popen(
- [
- "speak-ng",
- f"-s {words_per_minute}",
- ],
- stdin=fifo_read_file,
- )
- os.close(fifo_read_file)
-
- with PID_FILE_PATH.open("w") as pid_file:
- pid_file.write(str(speak_ng_process.pid))
-
- try:
- speak_ng_process.wait()
- except KeyboardInterrupt as e:
- os.remove(PID_FILE_PATH)
-
- os.remove(PID_FILE_PATH)
diff --git a/clipboard-speaker-kill b/clipboard-speaker-kill
@@ -1,14 +0,0 @@
-#!/usr/bin/env python3
-
-import os
-import pathlib
-import signal
-
-CLIPBOARD_SPEAKER_PATH = pathlib.Path.home() / ".clipboard-speaker"
-PID_FILE_PATH = CLIPBOARD_SPEAKER_PATH / "pid"
-
-if __name__ == "__main__":
- with PID_FILE_PATH.open("r") as pid_file:
- pid = int(pid_file.read())
- os.remove(PID_FILE_PATH)
- os.kill(pid, signal.SIGTERM)
diff --git a/clipboard_speaker/__init__.py b/clipboard_speaker/__init__.py
diff --git a/clipboard_speaker/clipboard_speaker.py b/clipboard_speaker/clipboard_speaker.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python3
+
+import os
+from pathlib import Path
+from subprocess import Popen, PIPE
+
+DEFAULT_WORDS_PER_MINUTE = "175"
+
+CLIPBOARD_SPEAKER_PATH = Path.home() / ".clipboard-speaker"
+PID_FILE_PATH = CLIPBOARD_SPEAKER_PATH / "pid"
+FIFO_FILE_PATH = CLIPBOARD_SPEAKER_PATH / "fifo"
+
+WORDS_PER_MINUTE_PATH = CLIPBOARD_SPEAKER_PATH / "words-per-minute"
+
+
+def get_words_per_minute() -> str:
+ if not WORDS_PER_MINUTE_PATH.exists():
+ with WORDS_PER_MINUTE_PATH.open("w") as words_per_minute_file:
+ words_per_minute_file.write(DEFAULT_WORDS_PER_MINUTE)
+ return DEFAULT_WORDS_PER_MINUTE
+
+ with WORDS_PER_MINUTE_PATH.open("r") as words_per_minute_file:
+ words_per_minute = words_per_minute_file.read().strip()
+
+ return words_per_minute
+
+
+def main() -> None:
+ words_per_minute = get_words_per_minute()
+ try:
+ os.mkfifo(FIFO_FILE_PATH, mode=0o600)
+ except FileExistsError:
+ pass
+
+ # https://stackoverflow.com/questions/63132778/how-to-use-fifo-named-pipe-as-stdin-in-popen-python
+ fifo_read_file = os.open(FIFO_FILE_PATH, os.O_RDONLY | os.O_NONBLOCK)
+ fifo_write_file = os.open(FIFO_FILE_PATH, os.O_WRONLY)
+
+ Popen(
+ ["xsel", "-p"],
+ stdout=fifo_write_file,
+ )
+ os.close(fifo_write_file)
+
+ if not PID_FILE_PATH.exists():
+ speak_ng_process = Popen(
+ [
+ "speak-ng",
+ f"-s {words_per_minute}",
+ ],
+ stdin=fifo_read_file,
+ )
+ os.close(fifo_read_file)
+
+ with PID_FILE_PATH.open("w") as pid_file:
+ pid_file.write(str(speak_ng_process.pid))
+
+ try:
+ speak_ng_process.wait()
+ except KeyboardInterrupt as e:
+ os.remove(PID_FILE_PATH)
+
+ os.remove(PID_FILE_PATH)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/clipboard_speaker/clipboard_speaker_kill.py b/clipboard_speaker/clipboard_speaker_kill.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python3
+
+import os
+import pathlib
+import signal
+
+CLIPBOARD_SPEAKER_PATH = pathlib.Path.home() / ".clipboard-speaker"
+PID_FILE_PATH = CLIPBOARD_SPEAKER_PATH / "pid"
+
+
+def main() -> None:
+ with PID_FILE_PATH.open("r") as pid_file:
+ pid = int(pid_file.read())
+ os.remove(PID_FILE_PATH)
+ os.kill(pid, signal.SIGTERM)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/setup.py b/setup.py
@@ -0,0 +1,25 @@
+from setuptools import setup, find_packages
+
+with open("README.md") as f:
+ readme = f.read()
+
+with open("LICENSE") as f:
+ license = f.read()
+
+setup(
+ name="clipboard-speaker",
+ version="1.0.0",
+ description="Read aloud selected text.",
+ long_description=readme,
+ author="Yuval Langer",
+ author_email="yuval.langer@gmail.com",
+ url="https://gitlab.com/yuvallangerontheroad/clipboard-speaker",
+ license=license,
+ entry_points={
+ "console_scripts": [
+ "clipboard-speaker=clipboard_speaker.clipboard_speaker:main",
+ "clipboard-speaker-kill=clipboard_speaker.clipboard_speaker_kill:main",
+ ],
+ },
+ packages=["clipboard_speaker"],
+)