branch: scratch/greader commit 6fe3129a11f32078f5622e1321e9e5021eb0f5cc Author: Stefan Monnier <monn...@iro.umontreal.ca> Commit: Stefan Monnier <monn...@iro.umontreal.ca>
Miscellanous simplifications and "tightening" Many of the simplifications result from hoisting `setq` out of ifs or avoiding `setq` altogether. Among the tightening, don't treat hooks as mere "variables holding a list of functions", since they're a bit more complex than that (e.g. can contain a function rather than a list, can have both global and buffer-local functions at the same time, ...). * greader.el (greader--call-functions-after-get-of-sentence): Use `run-hook-wrapped` and simplify. (greader--call-before-finish-functions): Use `run-hook-with-args-until-success`. (greader-change-backend): Consolidate the `seq-local`s outside of the ifs. Use (cadr (memq ...)) to find the "next" item instead of going through index numbers. (greader-read-asynchronous): Simplify the computation of `txt` and `backend` by avoiding `setq`. (greader-action): Assume `greader-backend-action` is non-nil. Use `ignore` rather than `nil` if you want a backend that does nothing :-) (greader-set-language): Simplify by avoiding `setq`. (greader-timer-flag-p, greader-sentence-needs-dehyphenation): η-reduce. (greader-compile-mode): Don't trust the `member` test since hooks aren't just "normal var holding a list". * greader-speechd.el (greader-speechd-set-punctuation): Simplify. Signal an error when `punct` is nil instead of returning `greader-speechd-punctuation` without a preceding "-m". * greader-mac.el: Add missing `Code:` header. (greader-mac-set-voice): Simplify. (greader-mac-forward-sentence): Use `move` arg of `re-search-forward`. (greader-mac-get-sentence): Use `greader-mac-forward-sentence` and eliminate dummy initialization of `sentence-start` that's immediately overwritten by something else. (greader--mac-get-voices): `beginning-of-buffer` is "interactive-only". --- greader-mac.el | 45 +++++++------------ greader-speechd.el | 29 ++++-------- greader.el | 127 +++++++++++++++++++++++------------------------------ 3 files changed, 80 insertions(+), 121 deletions(-) diff --git a/greader-mac.el b/greader-mac.el index 067a19caa6..2577af3875 100644 --- a/greader-mac.el +++ b/greader-mac.el @@ -1,6 +1,10 @@ ;;; greader.el --- gnamù reader, send buffer contents to a speech engine. -*- lexical-binding: t; -*- +;; FIXME: The above line is not right for this file :-( ;; Copyright (C) 2017-2023 Free Software Foundation, Inc. + +;;; Code: + (defgroup greader-mac nil "Back-end of mac for greader." @@ -37,27 +41,14 @@ nil means to use the system voice." (defun greader-mac-set-voice (voice) "Set specified VOICE for `say'. -When called interactively, this function reads a string from the minibuffer providing completion." +When called interactively, this function reads a string from the minibuffer +providing completion." (interactive - (list (read-string "voice: " nil nil (greader--mac-get-voices)))) - (let (result) - (if (called-interactively-p 'any) - (progn - (if (string-equal "system" voice) - (setq-local greader-mac-voice nil) - (setq-local greader-mac-voice voice))) - (when voice - (if (string-equal voice "system") - (progn - (setq result nil) - (setq-local greader-mac-voice nil)) - (setq result (concat "-v" voice)) - (setq-local greader-mac-voice voice))) - (unless voice - (if greader-mac-voice - (setq result (concat "-v" greader-mac-voice)) - (setq result nil))) - result))) + (list (read-string "Voice: " nil nil (greader--mac-get-voices)))) + (when voice + (setq-local greader-mac-voice + (if (string-equal "system" voice) nil voice))) + (when greader-mac-voice (concat "-v" greader-mac-voice))) ;;;###autoload (defun greader-mac (command &optional arg &rest _) @@ -87,25 +78,21 @@ COMMAND must be a string suitable for `make-process'." (put 'greader-mac 'greader-backend-name "greader-mac") (defun greader-mac-get-sentence () - (let ((sentence-start (make-marker))) - (setq sentence-start (point)) + (let ((sentence-start (point))) (save-excursion - (when (not (eobp)) - (if (not (re-search-forward greader-mac-end-of-sentence-regexp nil t)) - (end-of-buffer)) + (greader-mac-forward-sentence) (if (> (point) sentence-start) (string-trim (buffer-substring-no-properties sentence-start (point)) "[ \t\n\r]+") - nil))))) + nil)))) (defun greader-mac-forward-sentence () - (if (not (re-search-forward greader-mac-end-of-sentence-regexp nil t)) - (end-of-buffer))) + (re-search-forward greader-mac-end-of-sentence-regexp nil 'move)) (defun greader--mac-get-voices () "Return a list which contains all voices suitable for this backend." (with-temp-buffer (call-process "say" nil t nil "-v" "?") - (beginning-of-buffer) + (goto-char (point-min)) (let ((lines (list "system"))) (while (not (eobp)) (let ((mymarker (make-marker))) diff --git a/greader-speechd.el b/greader-speechd.el index c928de5a55..2913cab8bd 100644 --- a/greader-speechd.el +++ b/greader-speechd.el @@ -82,27 +82,14 @@ for further documentation, see the `greader-speechd-rate' variable." "Return a suitable parameter to pass to spd-say for setting punctuation level. PUNCT must be a numeric value, 0 for no punctuation, 1 for some and 2 or >2 for all punctuation." - (catch 'return - (cond - ((booleanp punct) - (if punct - (progn - (setq-local greader-speechd-punctuation "all") - (throw 'return (concat "-mall"))) - (throw 'return greader-speechd-punctuation))) - ((numberp punct) - (if (= punct 0) - (progn - (setq-local greader-speechd-punctuation "none") - (throw 'return (concat "-mnone")))) - (if (= punct 1) - (progn - (setq-local greader-speechd-punctuation "some") - (throw 'return (concat "-msome")))) - (if (>= punct 2) - (progn - (setq-local greader-speechd-punctuation "all") - (throw 'return (concat "-mall")))))))) + (setq-local greader-speechd-punctuation + (pcase punct + ('t "all") + ('0 "none") + ('1 "some") + ((and (pred numberp) (pred (<= 2))) "all") + (_ (error "Unknown punctuation: %S" punct)))) + (concat "-m" greader-speechd-punctuation)) (defun greader-speechd-stop () "Stops speech-dispatcher client." diff --git a/greader.el b/greader.el index bfe2ea837f..017505e782 100644 --- a/greader.el +++ b/greader.el @@ -78,18 +78,13 @@ the function should return modified sentence, or nil if no operation (defun greader--call-functions-after-get-of-sentence (sentence) "Call functions in `greader-after-get-sentence-functions'. Return SENTENCE, eventually modified by the functions." - (if greader-after-get-sentence-functions - (progn - (let ((result sentence)) - (dolist (func greader-after-get-sentence-functions result) - (when (fboundp func) - (setq result (funcall func result)) - (unless result - (setq result sentence)))) - (if (not result) - sentence - result))) - sentence)) + (let ((result sentence)) + (run-hook-wrapped 'greader-after-get-sentence-functions + (lambda (func) + (when (fboundp func) + (setq result (or (funcall func result) + sentence))))) + result)) (defvar greader-before-read-hook nil "Code to execute just before start of reading.") @@ -108,15 +103,8 @@ If all the functions called return nil, reading finishes normally.") (defun greader--call-before-finish-functions () "Return t if at least one of the function return t. If all the functions in the hook return nil, this function return nil." - (if greader-before-finish-functions - (progn - (let ((flag nil) (result nil)) - (dolist (func greader-before-finish-functions) - (setq result (funcall func)) - (when result - (setq flag t))) - flag)) - nil)) + (run-hook-with-args-until-success 'greader-before-finish-functions)) + (defvar greader-after-stop-hook nil "Hook run just after tts is stopped.") @@ -400,31 +388,29 @@ available backends." (interactive (list (if current-prefix-arg - (completing-read"back-end:" (greader--get-backends))))) - (if (functionp backend) - (if (memq backend greader-backends) - (setq-local greader-current-backend backend) - (error "%s" "The function you have specified is not a greader's back-end."))) - (if (stringp backend) - (progn - (let ((result nil)) - (dolist (elem greader-backends result) - (if - (equal - (get elem 'greader-backend-name) backend) - (setq result elem))) - (if result - (setq-local greader-current-backend result) - (error "%s" "the function name you have specified is not a greader's back-end."))))) - (if (not backend) - (let - ((index (seq-position greader-backends greader-current-backend)) - (len (length greader-backends))) - (if - (= (+ index 1) len) - (setq-local greader-current-backend (elt greader-backends 0)) - (setq-local greader-current-backend (elt greader-backends (+ index 1)))))) - (message "Current back-end is %s." (get greader-current-backend 'greader-backend-name))) + (completing-read "Back-end: " (greader--get-backends))))) + (setq-local greader-current-backend + (cond + ((functionp backend) + (if (memq backend greader-backends) + backend + (error "Not a greader's back-end: %S" backend))) + ((stringp backend) + (let ((result nil)) + (dolist (elem greader-backends result) + (if + (equal + (get elem 'greader-backend-name) backend) + (setq result elem))) + (or result + (user-error "Not a greader's back-end: %S" backend)))) + (backend + (error "backend should be a string or a function: %S" backend)) + (t + (car (or (cdr (memq greader-current-backend greader-backends)) + greader-backends))))) + (message "Current back-end is %s" + (get greader-current-backend 'greader-backend-name))) (defun greader-load-backends () "Load backends taken from `greader-backends'." @@ -438,16 +424,14 @@ available backends." (greader-build-args) (if (and txt (greader-sentence-needs-dehyphenation txt)) (setq txt (greader-dehyphenate txt))) - (let (backend text) - (setq text (concat text " ")) - (setq text (concat text txt)) - (setq txt text) - (setq backend (append greader-backend `(,txt) backend)) - (and (stringp txt) (setq-local greader-synth-process (make-process - :name "greader-backend" - :sentinel #'greader-action - :filter #'greader-process-filter - :command backend))) + (let* ((txt (concat " " txt)) + (backend (append greader-backend `(,txt)))) + (and (stringp txt) + (setq-local greader-synth-process (make-process + :name "greader-backend" + :sentinel #'greader-action + :filter #'greader-process-filter + :command backend))) (if greader-debug (progn (set-process-buffer greader-synth-process greader-debug-buffer) @@ -471,8 +455,7 @@ available backends." (progn (greader-debug "greader-action entered.\n") (greader-debug (format "event: %S\n" event)))) - (when greader-backend-action - (funcall greader-backend-action process event))) + (funcall greader-backend-action process event)) (defun greader-tts-stop () "Stop reading of current buffer." @@ -679,11 +662,10 @@ buffer, so if you want to set it globally, please use `M-x customize-option RET greader-language RET'." (interactive (list - (let (result) - (setq result (greader-call-backend 'set-voice nil)) - (when (equal result 'not-implemented) - (setq result (read-string "Set language to: "))) - result))) + (let ((result (greader-call-backend 'set-voice nil))) + (if (equal result 'not-implemented) + (read-string "Set language to: ") + result)))) (greader-call-backend 'lang lang)) (defun greader-set-punctuation (flag) "Set punctuation to FLAG." @@ -752,9 +734,7 @@ Optional argument TIMER-IN-MINS timer in minutes (integer)." (defun greader-timer-flag-p () "Not yet documented." - (if greader-timer-flag - t - nil)) + greader-timer-flag) (defun greader-setup-timers () "Set up timers, that is, call `run-at-time' using settings you have specified." @@ -989,9 +969,7 @@ If prefix, it will be used to decrement rate." (defun greader-sentence-needs-dehyphenation (str) "Return t if there are lines broken by hyphens in STR, nil otherwise." - (if (string-match greader-hyphen-regex str) - t - nil)) + (string-match greader-hyphen-regex str)) (defun greader-dehyphenate (sentence) "Join lines broken by hyphens in SENTENCE. @@ -1041,10 +1019,17 @@ administrator." (error "Please set or customize `greader-compile-dictsource' to define espeak-ng dictionary source location")) (add-hook 'after-save-hook #'greader-check-visited-file) + ;; FIXME: AFAIK `define-minor-mode' will emit pretty much + ;; this exact message if we don't. (message "greader-compile minor mode enabled")) (when (member #'greader-check-visited-file after-save-hook) - (message "greader-compile mode disabled") - (remove-hook 'after-save-hook #'greader-check-visited-file)))) + ;; FIXME: AFAIK `define-minor-mode' will emit pretty much + ;; this exact message if we don't. + (message "greader-compile mode disabled")) + ;; Call `remove-hook' even if the `member' test failed: + ;; it's safer to do so anyway (e.g. the `member' test may + ;; actually give the wrong answer). + (remove-hook 'after-save-hook #'greader-check-visited-file))) (defvar greader-compile-history nil) (defun greader-compile (&optional lang)