branch: externals/greader commit 19c324134ab0a662e4f582f98a2a7402e4ad912b Author: Michelangelo Rodriguez <michelangelo.rodrig...@gmail.com> Commit: Michelangelo Rodriguez <michelangelo.rodrig...@gmail.com>
Command `greader-get-rate' added. This command has to be supported at backend level, so a back-end that want to support this feature has to implement the command `get-language'. I decided to keep also the old way to do that, calling the command «lang 'value'; However, this new approach seems to be more explicit. This change is to prepare greader for audiobook conversion. --- greader-espeak.el | 2 + greader-mac.el | 2 + greader-speechd.el | 2 + greader.el | 151 ++++++++++++++++++++++++++++++++++++++--------------- 4 files changed, 115 insertions(+), 42 deletions(-) diff --git a/greader-espeak.el b/greader-espeak.el index a90fe9a6b6..d32431e1ff 100644 --- a/greader-espeak.el +++ b/greader-espeak.el @@ -77,6 +77,8 @@ COMMAND must be a string suitable for `make-process'." nil)))) ('get-language greader-espeak-language) + ('get-rate + greader-espeak-rate) (_ 'not-implemented))) (put 'greader-espeak 'greader-backend-name "greader-espeak") diff --git a/greader-mac.el b/greader-mac.el index 0aee5d223b..a5d3dedc35 100644 --- a/greader-mac.el +++ b/greader-mac.el @@ -71,6 +71,8 @@ COMMAND must be a string suitable for `make-process'." (greader-mac-set-rate arg)))) ('punctuation nil) + ('get-rate + greader-mac-rate) (_ 'not-implemented))) (put 'greader-mac 'greader-backend-name "greader-mac") diff --git a/greader-speechd.el b/greader-speechd.el index 23bcf34c35..bac0f2f3ab 100644 --- a/greader-speechd.el +++ b/greader-speechd.el @@ -127,6 +127,8 @@ or >2 for all punctuation." (greader-speechd-stop)) ('extra "-w") + ('get-rate + greader-speechd-rate) (_ 'not-implemented))) (put 'greader-speechd 'greader-backend-name "greader-speechd") diff --git a/greader.el b/greader.el index 36e8c8c6e6..40c029fbd1 100644 --- a/greader.el +++ b/greader.el @@ -63,7 +63,8 @@ (require 'seq) (define-obsolete-variable-alias 'greader-before-get-sentence-functions - 'greader-before-get-sentence-hook "2023") + 'greader-before-get-sentence-hook + "2023") (defvar greader-before-get-sentence-hook nil "Hook run before getting a sentence. Functions in this variable don't receive arguments.") @@ -93,7 +94,8 @@ Return SENTENCE, eventually modified by the functions." "Execute code just after reading a sentence.") (define-obsolete-variable-alias 'greader-before-finish-hook - 'greader-before-finish-functions "2023") + 'greader-before-finish-functions + "2023") (defvar greader-before-finish-functions nil "Code executed just after finishing reading of buffer. Functions in this hook should return non-nil if at least one function @@ -195,7 +197,8 @@ Instead, the sentence will be read completely." :tag "enable debug" :type 'boolean) -(defcustom greader-hook nil ;; FIXME: Can't see where it's run! +(defcustom greader-hook nil + ;; FIXME: Can't see where it's run! "Hook run after mode activation. Through this hook you can customize your key definitions for greader, for example." @@ -373,7 +376,8 @@ This only happens if the variables `greader-start-region' and (defun greader-call-backend (command &optional arg) "Call backend passing it COMMAND and ARG. -\(internal use!\)." ;; FIXME: Use "--" in the name, then. +\(internal use!\)." + ;; FIXME: Use "--" in the name, then. (if arg (funcall greader-current-backend command arg) @@ -407,11 +411,15 @@ available backends." (get elem 'greader-backend-name) backend) (setq result elem))) (or result - (user-error "Not a greader's back-end: %S" backend)))) + (user-error "Not a greader's back-end: %S" + backend)))) (backend - (error "backend should be a string or a function: %S" backend)) + (error "backend should be a string or a function: %S" + backend)) (t - (car (or (cdr (memq greader-current-backend greader-backends)) + (car (or + (cdr + (memq greader-current-backend greader-backends)) greader-backends))))) (message "Current back-end is %s" (get greader-current-backend 'greader-backend-name))) @@ -434,12 +442,15 @@ available backends." (setq-local greader-synth-process (make-process :name "greader-backend" :sentinel #'greader-action - :filter #'greader-process-filter + :filter + #'greader-process-filter :command backend))) (if greader-debug (progn - (set-process-buffer greader-synth-process greader-debug-buffer) - (greader-debug (message "greader-read-asynchronous: %S" backend)))))) + (set-process-buffer greader-synth-process + greader-debug-buffer) + (greader-debug + (message "greader-read-asynchronous: %S" backend)))))) (defun greader-get-status () "Return greader status." @@ -463,7 +474,8 @@ available backends." (defun greader-tts-stop () "Stop reading of current buffer." - (set-process-sentinel greader-synth-process #'greader--default-action) + (set-process-sentinel greader-synth-process + #'greader--default-action) (if (not (eq @@ -477,7 +489,8 @@ available backends." Optional argument PROCESS Optional argument EVENT ." (if greader-debug - (greader-debug (format "greader--default-action entered.\nevent: %S\n" event))) + (greader-debug + (format "greader--default-action entered.\nevent: %S\n" event))) (cond ((and (greader-timer-flag-p) (timerp greader-stop-timer)) (greader-cancel-elapsed-timer) @@ -586,7 +599,8 @@ function, point jumps at the last position you called command `greader-read'." (let ((chunk (funcall greader-read-chunk-of-text))) (if chunk (progn - (setq chunk (greader--call-functions-after-get-of-sentence chunk)) + (setq chunk + (greader--call-functions-after-get-of-sentence chunk)) ;; This extra verification is necessary because espeak has a bug that, ;; when we pass a string containing a vocal plus only 2 .. it reads ;; garbage. @@ -608,7 +622,9 @@ function, point jumps at the last position you called command `greader-read'." ((and (> greader-elapsed-time 0) greader-timer-flag) (greader-cancel-elapsed-timer) (greader-cancel-stop-timer) - (if (>= greader-elapsed-time (1- (greader-convert-mins-to-secs greader-timer))) + (if + (>= greader-elapsed-time + (1- (greader-convert-mins-to-secs greader-timer))) (greader-reset-elapsed-time)) (setq-local greader-stop-timer 0))) (greader-set-greader-keymap) @@ -630,7 +646,9 @@ Argument ARG is not used." (let ((result (greader-call-backend 'next-text))) (if (not (equal result 'not-implemented)) result - (let ((sentence-end (if greader-classic-nav-mode nil greader-sentence-regexp))) + (let + ((sentence-end + (if greader-classic-nav-mode nil greader-sentence-regexp))) (forward-sentence))))) (defun greader-backward-sentence () @@ -638,7 +656,9 @@ Argument ARG is not used." (let ((result (greader-call-backend 'next-text))) (if (not (equal result 'not-implemented)) result - (let ((sentence-end (if greader-classic-nav-mode nil greader-sentence-regexp))) + (let + ((sentence-end + (if greader-classic-nav-mode nil greader-sentence-regexp))) (backward-sentence))))) (defun greader-get-sentence () @@ -655,7 +675,8 @@ If at end of buffer, nil is returned." (when (not (eobp)) (greader-forward-sentence)) (if (> (point) sentence-start) - (string-trim (buffer-substring sentence-start (point)) "[ \t\n\r ]+") + (string-trim (buffer-substring sentence-start (point)) + "[ \t\n\r]+") nil)))))) (defun greader-sentence-at-point () @@ -694,11 +715,13 @@ buffer, so if you want to set it globally, please use "Returns the language code from the system's locale." (let ((locale (or (getenv "LANG") ; First try with the LANG environment variable (getenv "LC_ALL") ; Then with LC_ALL - "en"))) ; Default to "en" if nothing is found + "en"))) + ; Default to "en" if nothing is found ;; Extracts the language code from the locale (e.g., "en_US.UTF-8" becomes "en") (if (string-match "\\([a-z]+\\)_" locale) (match-string 1 locale) - "en"))) ; Default to "en" if the locale format is unrecognized + "en"))) + ; Default to "en" if the locale format is unrecognized (defun greader-get-language () "return language set in current back-end. @@ -711,6 +734,14 @@ get the language from the environment." (setq lang (greader-call-backend 'get-language))) lang)) +(defun greader-get-rate () + "return the numerical value for current back-end rate." + (let ((result (greader-call-backend 'get-rate))) + (if (not (equal result 'not-implemented)) + result + (user-error "Backend feature \"get-rate\" not implemented for +the current backend")))) + (defun greader-toggle-punctuation () "Toggle punctuation locally for current buffer." (interactive) @@ -777,7 +808,11 @@ Optional argument TIMER-IN-MINS timer in minutes (integer)." (catch 'timer-is-nil (cond ((greader-timer-flag-p) - (setq-local greader-stop-timer (run-at-time (- (greader-convert-mins-to-secs greader-timer) greader-elapsed-time) nil #'greader-stop-timer-callback)) + (setq-local greader-stop-timer + (run-at-time + (- (greader-convert-mins-to-secs greader-timer) + greader-elapsed-time) + nil #'greader-stop-timer-callback)) (setq-local greader-elapsed-timer (run-at-time 1 1 #'greader-elapsed-time))) ((not (greader-timer-flag-p)) @@ -915,12 +950,16 @@ Enabling tired mode implicitly enables timer also." (setq-local greader-auto-tired-mode t) (greader-auto-tired-mode-setup)))) -(defun greader-toggle-auto-tired-mode () "Enable auto tired mode. +(defun greader-toggle-auto-tired-mode () + "Enable auto tired mode. In this mode, greader will enter in tired mode at a customizable time and will exit from it at another time. The default is 22:00 for - entering and 08:00 for exiting." (interactive) + entering and 08:00 for exiting." + (interactive) (greader-toggle-auto-tired-mode-flag) (if greader-auto-tired-mode - (message "auto-tired mode enabled in current buffer") (message + (message + "auto-tired mode enabled in current buffer") + (message "auto-tired mode disabled in current buffer."))) (defun greader-current-time () @@ -952,7 +991,8 @@ In this mode, greader will enter in tired mode at a customizable time (let ((current-t (current-time))) (if - (and (time-less-p time1 current-t) (time-less-p current-t time2)) + (and (time-less-p time1 current-t) + (time-less-p current-t time2)) t nil))) @@ -960,22 +1000,31 @@ In this mode, greader will enter in tired mode at a customizable time "Not documented, internal use." (if (stringp greader-auto-tired-mode-time) - (setq-local greader-auto-tired-mode-time (greader-convert-time greader-auto-tired-mode-time))) + (setq-local greader-auto-tired-mode-time + (greader-convert-time greader-auto-tired-mode-time))) (if (stringp greader-auto-tired-time-end) - (setq-local greader-auto-tired-time-end (greader-convert-time greader-auto-tired-time-end))) + (setq-local greader-auto-tired-time-end + (greader-convert-time greader-auto-tired-time-end))) (if (and - (greader-current-time-in-interval-p greader-auto-tired-mode-time greader-auto-tired-time-end) + (greader-current-time-in-interval-p + greader-auto-tired-mode-time greader-auto-tired-time-end) (not greader-tired-flag)) (greader-toggle-tired-mode)) (if (and - (not (greader-current-time-in-interval-p greader-auto-tired-mode-time greader-auto-tired-time-end)) + (not + (greader-current-time-in-interval-p + greader-auto-tired-mode-time greader-auto-tired-time-end)) greader-tired-flag) (progn - (setq-local greader-auto-tired-mode-time (number-to-string (nth 2 (decode-time greader-auto-tired-mode-time)))) - (setq-local greader-auto-tired-time-end (number-to-string (nth 2 (decode-time greader-auto-tired-time-end)))) + (setq-local greader-auto-tired-mode-time + (number-to-string + (nth 2 (decode-time greader-auto-tired-mode-time)))) + (setq-local greader-auto-tired-time-end + (number-to-string + (nth 2 (decode-time greader-auto-tired-time-end)))) (greader-toggle-tired-mode)))) (defun greader-set-rate (n) @@ -1101,7 +1150,12 @@ function is specifically designed to be executed by a hook." (setq lang (greader-compile-guess-lang)) - (let (data-is-writable (command (append '("espeak") (list (concat greader-compile-command lang)) greader-compile-extra-parameters))) + (let + (data-is-writable + (command + (append '("espeak") + (list (concat greader-compile-command lang)) + greader-compile-extra-parameters))) (with-temp-buffer (call-process "espeak" nil t t "--version") @@ -1169,7 +1223,8 @@ When called from a function, you should specify SRC and DST, even if SRC and DST are declared as optional." (interactive "P") (unless greader-compile-default-source - (error "You must set or customize `greader-compile-default-source'")) + (error + "You must set or customize `greader-compile-default-source'")) (unless src (setq src (thing-at-point 'word t)) @@ -1187,7 +1242,9 @@ When called from a function, you should specify SRC and DST, even if (let ((lang-file (if (string-prefix-p "/" greader-compile-default-source) greader-compile-default-source - (concat (car greader-compile-dictsource) (substring greader-espeak-language 0 2) "_" greader-compile-default-source)))) + (concat (car greader-compile-dictsource) + (substring greader-espeak-language 0 2) "_" + greader-compile-default-source)))) (with-current-buffer (find-file-noselect lang-file) (goto-char (point-max)) (insert (concat src " " dst "\n")) @@ -1201,7 +1258,8 @@ When called from a function, you should specify SRC and DST, even if (if (string-match "/" greader-compile-default-source) (find-file greader-compile-default-source) (find-file (concat (car greader-compile-dictsource) - greader-espeak-language "_" greader-compile-default-source)))) + greader-espeak-language "_" + greader-compile-default-source)))) (defcustom greader-backward-acoustic-feedback nil "If t, when point returns to the end of sentence, plays a beep." @@ -1223,14 +1281,17 @@ When called from a function, you should specify SRC and DST, even if (defun greader--forward () (when (and (equal - (point) greader--marker-backward) greader-reading-mode) + (point) greader--marker-backward) + greader-reading-mode) (greader-forward-sentence) (backward-char 2) (when greader-backward-acoustic-feedback (beep)))) (defun greader--set-forward-timer () - (setq greader--timer-backward(run-with-idle-timer greader-backward-seconds nil #'greader--forward))) + (setq greader--timer-backward + (run-with-idle-timer greader-backward-seconds nil + #'greader--forward))) (defun greader-backward () "Restart reading from start of sentence. @@ -1359,7 +1420,8 @@ If INDEX is nil, use `greader-queue-current-element'." (user-error "Queue is emty")) (let ((result nil)) (when (< greader-queue-current-element (length greader-queue)) - (setq result (buffer-substring (car (elt greader-queue index)) (cdr (elt + (setq result (buffer-substring (car (elt greader-queue index)) + (cdr (elt greader-queue index))))) result)) @@ -1374,7 +1436,8 @@ If the current element is the last one, then return nil." (if (equal (1+ greader-queue-current-element) (length greader-queue)) nil - (setq greader-queue-current-element (1+ greader-queue-current-element)) + (setq greader-queue-current-element + (1+ greader-queue-current-element)) (greader-queue-get-element))) ;; This function returns the previous item in the queue, if it is @@ -1500,7 +1563,8 @@ If it is a function, it must return a string." (modified nil) (result (copy-sequence input-string))) ;; Search for the location of the next link. - (while (setq pos (next-single-property-change pos 'mouse-face result)) + (while + (setq pos (next-single-property-change pos 'mouse-face result)) ;; Check if the location has the 'mouse-face' property set. (when (get-text-property pos 'mouse-face result) (setq modified t) @@ -1602,8 +1666,10 @@ the reading process, returning nil in such cases." (goto-char (- (point-max) 1))) (funcall command) (greader-read)) - t) ; Returns t if no error occurs. - ((debug error) nil))) ; Returns nil in case of an error. + t) + ; Returns t if no error occurs. + ((debug error) nil))) + ; Returns nil in case of an error. ;; greader-continuous-mode ;; This minor-mode will take care of adding to the hook @@ -1625,7 +1691,8 @@ called the `info-scroll-up' function instead of finishing reading." (let ((error-string (concat "I can't determine the function for -scroll in " (symbol-name major-mode) ".\nPlease add +scroll in " + (symbol-name major-mode) ".\nPlease add this major mode to the variable `greader-continuous-modes'"))) (greader-continuous-mode -1) (user-error "%s" error-string)))