diff --git a/config.el b/config.el index f885a5f..ddf0694 100644 --- a/config.el +++ b/config.el @@ -69,6 +69,7 @@ Funguje v libovolném textu, včetně Markdown linků (např. [x](./...))." ;; -------------------------------------------------- ;; Org ;; -------------------------------------------------- + (setq org-directory "~/org/") (after! org @@ -396,3 +397,87 @@ Funguje v libovolném textu, včetně Markdown linků (např. [x](./...))." :localleader "l l" #'org-store-link "l i" #'org-insert-link) + + + +;;; ================================ +;;; Emacspeak robust ON/OFF for Doom +;;; Default: OFF (won't auto-restart) +;;; Keys: +;;; SPC t s -> Speech ON +;;; SPC t S -> Speech OFF +;;; ================================ + +(defconst my/emacspeak-dir (expand-file-name "~/.emacspeak")) +(defconst my/emacspeak-wrapper (expand-file-name "~/.local/bin/emacspeak-mac")) + +;; Emacspeak uses this to start the speech server. +(setq dtk-program my/emacspeak-wrapper) + +;; State flags +(defvar my/emacspeak-loaded nil) +(defvar my/emacspeak-enabled nil) + +;; Hard inhibit: when non-nil, Emacspeak is NOT allowed to start/restart the server. +(defvar my/emacspeak-inhibit-server t) + +(defun my/emacspeak--ensure-loaded () + "Load Emacspeak once, safely, without breaking Doom startup." + (unless my/emacspeak-loaded + (setq my/emacspeak-loaded t) + (setq emacspeak-directory my/emacspeak-dir) + ;; Load late-ish (but still inside the command that enables it) + (load-file (expand-file-name "lisp/emacspeak-setup.el" emacspeak-directory)) + + ;; After Emacspeak is present, install inhibition advices. + ;; These prevent the common 'it restarts by itself' problem. + (with-eval-after-load 'dtk-speak + (dolist (fn '(dtk-initialize dtk-start-process dtk-speak)) + (when (fboundp fn) + (advice-add + fn :around + (lambda (orig &rest args) + (if my/emacspeak-inhibit-server + ;; OFF mode: do nothing (and crucially: don't restart speaker) + nil + (apply orig args))))))))) + +(defun my/emacspeak-on () + "Enable speech (and allow server start)." + (interactive) + (setq my/emacspeak-inhibit-server nil) + (my/emacspeak--ensure-loaded) + (setq my/emacspeak-enabled t) + (when (fboundp 'dtk-restart) + (ignore-errors (dtk-restart))) + (when (fboundp 'dtk-speak) + (ignore-errors (dtk-speak "Emacspeak on."))) + (message "Emacspeak ON")) + +(defun my/emacspeak-off () + "Disable speech robustly (stop + prevent auto-restart)." + (interactive) + ;; First: inhibit any future attempts to start/restart. + (setq my/emacspeak-enabled nil) + (setq my/emacspeak-inhibit-server t) + + ;; Stop current speech if any. + (when (fboundp 'dtk-stop) + (ignore-errors (dtk-stop))) + + ;; Kill the server process hard (if it exists). + (when (boundp 'dtk-speaker-process) + (let ((p dtk-speaker-process)) + (when (processp p) + (ignore-errors (set-process-sentinel p nil)) + (ignore-errors (delete-process p)))) + (setq dtk-speaker-process nil)) + + (message "Emacspeak OFF (server restart inhibited)")) + +;; Doom leader keys +(map! :leader + (:prefix ("t" . "toggle") + :desc "Speech ON" "s" #'my/emacspeak-on + :desc "Speech OFF" "S" #'my/emacspeak-off)) +