[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Search]

assorted patches for customizing speech output



I've been making a bunch of modifications to parts of Emacspeak to get
speech output that I like better; I figured others might also find
them useful so I'm attaching them here as 3 separate patches.

All the features are behind customization variables, so you can
control them through the usual customize interface, and they default
to what Emacspeak does already.

Here's a summary of each patch and the customizations each adds:

======
* pitch.patch:
    This has straightforward Espeak-specific settings for default
pitch and pitch-range:

    * espeak-default-speech-pitch: (integer, defaults to 50)
    * espeak-default-speech-pitch-range: (integer, defaults to 50)

------

* move_line_ends.patch:
    This  lets you change what gets spoken when moving to the
beginning or end of a line.

    * emacspeak-speak-at-ends-of-line: (can be line, word, character,
or nothing; defaults to line)

------

* speak_indent.patch:
    This lets you customize precisely how line indentation is spoken.
    The settings fall into 3 groups.

    * emacspeak-audio-indentation-tab-grouped: (toggle, defaults to off)
        When this mode is turned on, indentation levels are split up
into two components:
        a tab component which is multiple of the tab-width, and a space offset.
        For example, if your tab-width is set to 4,
        an indentation of 11 will get split up into a multiple of 2
and an offset of 3.

    The text for the indentation level announcements is stitched together
    by inserting the digits between string segments which are given in
the following settings.

    * settings for normal indentation announcements:
        * emacspeak-audio-indentation-before: defaults to "indent "
        * emacspeak-audio-indentation-after: defaults to ""

    * settings for tab-grouped indentation announcements:
        * emacspeak-audio-indentation-before-tab: (defaults to "")
        * emacspeak-audio-indentation-after-tab: (defaults to " tabs")
        * emacspeak-audio-indentation-tab-grouped-separator: (defaults to " ")
        * emacspeak-audio-indentation-before-offset: (defaults to "")
        * emacspeak-audio-indentation-after-offset: (defaults to " spaces")

    To illustrate how this works:
    if you again have tab-width set to 4 and an indentation level of 11,
    with the following settings:

        emacspeak-audio-indentation-before = "indent "
        emacspeak-audio-indentation-after = ""
        emacspeak-audio-indentation-before-tab = "indent "
        emacspeak-audio-indentation-after-tab = " tabs"
        emacspeak-audio-indentation-tab-grouped-separator = ", and "
        emacspeak-audio-indentation-before-offset = ""
        emacspeak-audio-indentation-after-offset = " spaces"

    In normal mode, this gets announced as "indent 11",
    and in tab-grouped mode, this gets announced as "indent 2 tabs,
and 3 spaces".

------

Here's the relevant part of my .emacs where I've used these customizations:

(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(emacspeak-audio-indentation-after " spaces")
 '(emacspeak-audio-indentation-before "")
 '(emacspeak-character-echo nil)
 '(emacspeak-speak-at-ends-of-line (quote char))
 '(espeak-default-speech-pitch 75)
 '(espeak-default-speech-pitch-range 100)
 '(espeak-default-speech-rate 900)
 '(package-selected-packages (quote (evil)))
 '(tab-width 4))
======

To build emacspeak with any of these patches:

    (1) Clone the Emacspeak source from Github.
    (2) Download the patchfile and move it into the emacspeak directory.
    (3) In the emacspeak directory, apply the patch by running the command:
        git apply <patch_file>
    (4) Continue building Emacspeak as usual.


You can also check these modifications out of branches with
corresponding names from this Git repository:
https://www.github.com/hussainmkj/emacspeak.git/.

Note that if you want to do a git-based build with more than one of
the branches, you should check out  master and then do a single-merge
of the branches you want:

git checkout master
git merge --no-commit <branch_1> <branch_2> [<branch_3>]

Trying to merge them in sequentially will result in merge conflicts.

------

If anyone does find these useful, or wants more more customization
options for the features, let me know!

Cheers,
Hussain
From 5b5bdc607639d3b0bf2db4486ed11474d625cd30 Mon Sep 17 00:00:00 2001
From: Hussain Jasim <hussain.jasim@xxxxxxxxxxx>
Date: Fri, 8 Jun 2018 10:53:52 -0400
Subject: [PATCH 1/3] Added functions to the Espeak server for setting pitch
 and pitch-range.

---
 servers/espeak                      | 20 +++++++++
 servers/native-espeak/tclespeak.cpp | 88 +++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)

diff --git a/servers/espeak b/servers/espeak
index cdc68c487..f4db85ced 100755
--- a/servers/espeak
+++ b/servers/espeak
@@ -206,6 +206,26 @@ proc tts_set_speech_rate {rate} {
     return ""
 }
 
+proc tts_set_speech_pitch {pitch} {
+    global tts
+
+    set factor $tts(char_factor) 
+    set tts(speech_pitch) $pitch
+    setPitch 0 $pitch
+    service
+    return ""
+}
+
+proc tts_set_speech_pitch_range {pitch_range} {
+    global tts
+
+    set factor $tts(char_factor) 
+    set tts(speech_pitch_range) $pitch_range
+    setPitchRange 0 $pitch_range
+    service
+    return ""
+}
+
 proc tts_set_character_scale {factor} {
     global tts
 
diff --git a/servers/native-espeak/tclespeak.cpp b/servers/native-espeak/tclespeak.cpp
index c7e64a15d..48143de38 100644
--- a/servers/native-espeak/tclespeak.cpp
+++ b/servers/native-espeak/tclespeak.cpp
@@ -68,6 +68,10 @@ extern "C" EXPORT int Tclespeak_Init(Tcl_Interp *interp);
 
 int SetRate(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST[]);
 int GetRate(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST[]);
+int SetPitch(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST[]);
+int GetPitch(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST[]);
+int SetPitchRange(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST[]);
+int GetPitchRange(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST[]);
 int getTTSVersion(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST[]);
 int Punct(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST[]);
 int Caps(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST[]);
@@ -113,6 +117,14 @@ int Tclespeak_Init(Tcl_Interp *interp) {
                        TclEspeakFree);
   Tcl_CreateObjCommand(interp, "getRate", GetRate, (ClientData)handle,
                        TclEspeakFree);
+  Tcl_CreateObjCommand(interp, "setPitch", SetPitch, (ClientData)handle,
+                       TclEspeakFree);
+  Tcl_CreateObjCommand(interp, "getPitch", GetPitch, (ClientData)handle,
+                       TclEspeakFree);
+  Tcl_CreateObjCommand(interp, "setPitchRange", SetPitchRange, (ClientData)handle,
+                       TclEspeakFree);
+  Tcl_CreateObjCommand(interp, "getPitchRange", GetPitchRange, (ClientData)handle,
+                       TclEspeakFree);
   Tcl_CreateObjCommand(interp, "ttsVersion", getTTSVersion, (ClientData)handle,
                        TclEspeakFree);
   Tcl_CreateObjCommand(interp, "punct", Punct, (ClientData)handle, NULL);
@@ -182,6 +194,82 @@ int SetRate(ClientData handle, Tcl_Interp *interp, int objc,
   return success ? TCL_OK : TCL_ERROR;
 }
 
+int GetPitch(ClientData handle, Tcl_Interp *interp, int objc,
+            Tcl_Obj *CONST objv[]) {
+  int rc, pitch, voice;
+  if (objc != 2) {
+    Tcl_AppendResult(interp, "Usage: getPitch voiceCode  ", TCL_STATIC);
+    return TCL_ERROR;
+  }
+  rc = Tcl_GetIntFromObj(interp, objv[1], &voice);
+  if (rc != TCL_OK) return rc;
+
+  pitch = espeak_GetParameter(espeakPITCH, 1);
+
+  Tcl_SetObjResult(interp, Tcl_NewIntObj(pitch));
+  return TCL_OK;
+}
+
+int SetPitch(ClientData handle, Tcl_Interp *interp, int objc,
+            Tcl_Obj *CONST objv[]) {
+  static int current_pitch = -1;
+  int rc, pitch, voice;
+  int success = 1;
+  if (objc != 3) {
+    Tcl_AppendResult(interp, "Usage: setPitch voiceCode speechPitch ",
+                     TCL_STATIC);
+    return TCL_ERROR;
+  }
+  rc = Tcl_GetIntFromObj(interp, objv[1], &voice);
+  if (rc != TCL_OK) return rc;
+  rc = Tcl_GetIntFromObj(interp, objv[2], &pitch);
+  if (rc != TCL_OK) return rc;
+
+  if (pitch != current_pitch) {
+    success = (espeak_SetParameter(espeakPITCH, pitch, 0) == EE_OK);
+    if (success) current_pitch = pitch;
+  }
+  return success ? TCL_OK : TCL_ERROR;
+}
+
+int GetPitchRange(ClientData handle, Tcl_Interp *interp, int objc,
+            Tcl_Obj *CONST objv[]) {
+  int rc, pitch_range, voice;
+  if (objc != 2) {
+    Tcl_AppendResult(interp, "Usage: getPitchRange voiceCode  ", TCL_STATIC);
+    return TCL_ERROR;
+  }
+  rc = Tcl_GetIntFromObj(interp, objv[1], &voice);
+  if (rc != TCL_OK) return rc;
+
+  pitch_range = espeak_GetParameter(espeakRANGE, 1);
+
+  Tcl_SetObjResult(interp, Tcl_NewIntObj(pitch_range));
+  return TCL_OK;
+}
+
+int SetPitchRange(ClientData handle, Tcl_Interp *interp, int objc,
+            Tcl_Obj *CONST objv[]) {
+  static int current_pitch_range = -1;
+  int rc, pitch_range, voice;
+  int success = 1;
+  if (objc != 3) {
+    Tcl_AppendResult(interp, "Usage: setPitchRange voiceCode speechPitchRange ",
+                     TCL_STATIC);
+    return TCL_ERROR;
+  }
+  rc = Tcl_GetIntFromObj(interp, objv[1], &voice);
+  if (rc != TCL_OK) return rc;
+  rc = Tcl_GetIntFromObj(interp, objv[2], &pitch_range);
+  if (rc != TCL_OK) return rc;
+
+  if (pitch_range != current_pitch_range) {
+    success = (espeak_SetParameter(espeakRANGE, pitch_range, 0) == EE_OK);
+    if (success) current_pitch_range = pitch_range;
+  }
+  return success ? TCL_OK : TCL_ERROR;
+}
+
 //>
 //<say
 
-- 
2.15.0


From 7f4a4e2246f8918b03e4766652bc613371fa0fd4 Mon Sep 17 00:00:00 2001
From: Hussain Jasim <hussain.jasim@xxxxxxxxxxx>
Date: Wed, 20 Jun 2018 22:27:50 -0400
Subject: [PATCH 2/3] Added functions to the Espeak client for interactively
 setting pitch and pitch-range.

---
 lisp/espeak-voices.el | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/lisp/espeak-voices.el b/lisp/espeak-voices.el
index e98a7e4a7..59c21c648 100644
--- a/lisp/espeak-voices.el
+++ b/lisp/espeak-voices.el
@@ -57,6 +57,82 @@
                       (string-match "espeak$" (getenv "DTK_PROGRAM")))
              (setq-default dt-speech-rate val))))
 
+;;{{{ espeak-specific controls
+;; Functions to interface with the Espeak server and interactively set pitch and pitch-range,
+;; which are defined here instead of dtk-speech.el because they are exclusive to Espeak.
+
+;;{{{  espeak pitch
+(defun espeak-interp-set-pitch (pitch)
+  (cl-declare (special dtk-speaker-process))
+  (process-send-string dtk-speaker-process
+                       (format "tts_set_speech_pitch %s\n"
+                               pitch)))
+
+;;;###autoload
+(defun espeak-set-pitch (pitch    &optional prefix)
+  "Set speaking PITCH for espeak.
+Interactive PREFIX arg means set   the global default value, and then set the
+current local  value to the result."
+  (interactive
+   (list
+    (read-from-minibuffer "Enter new pitch: ")
+    current-prefix-arg))
+  (cl-declare (special espeak-speech-pitch dtk-speaker-process
+                    espeak-default-speech-pitch
+                    dtk-program dtk-speak-server-initialized))
+  (when dtk-speak-server-initialized
+    (cond
+     (prefix
+      (unless (eq dtk-speaker-process (dtk-notify-process))
+        (let ((dtk-speaker-process (dtk-notify-process)))
+          (espeak-set-pitch pitch)))
+      (setq espeak-default-speech-pitch pitch)
+      (setq-default espeak-speech-pitch pitch)
+      (setq espeak-speech-pitch pitch))
+     (t (setq espeak-speech-pitch pitch)))
+    (espeak-interp-set-pitch pitch)
+    (when (called-interactively-p 'interactive)
+      (message "Set speech pitch to %s %s"
+               pitch
+               (if prefix "" "locally")))))
+
+;;}}}
+;;{{{  espeak pitch-range
+(defun espeak-interp-set-pitch-range (pitch-range)
+  (cl-declare (special dtk-speaker-process))
+  (process-send-string dtk-speaker-process
+                       (format "tts_set_speech_pitch_range %s\n"
+                               pitch-range)))
+
+;;;###autoload
+(defun espeak-set-pitch-range (pitch-range    &optional prefix)
+  "Set speaking PITCH for espeak.
+Interactive PREFIX arg means set   the global default value, and then set the
+current local  value to the result."
+  (interactive
+   (list
+    (read-from-minibuffer "Enter new pitch-range: ")
+    current-prefix-arg))
+  (cl-declare (special espeak-speech-pitch-range dtk-speaker-process
+                    espeak-default-speech-pitch-range
+                    dtk-program dtk-speak-server-initialized))
+  (when dtk-speak-server-initialized
+    (cond
+     (prefix
+      (unless (eq dtk-speaker-process (dtk-notify-process))
+        (let ((dtk-speaker-process (dtk-notify-process)))
+          (espeak-set-pitch-range pitch-range)))
+      (setq espeak-default-speech-pitch-range pitch-range)
+      (setq-default espeak-speech-pitch-range pitch-range)
+      (setq espeak-speech-pitch-range pitch-range))
+     (t (setq espeak-speech-pitch-range pitch-range)))
+    (espeak-interp-set-pitch-range pitch-range)
+    (when (called-interactively-p 'interactive)
+      (message "Set speech pitch-range to %s %s"
+               pitch-range
+               (if prefix "" "locally")))))
+
+;;}}}
 ;;}}}
 ;;{{{ Top-Level TTS Call
 
-- 
2.15.0


From 9174baeefde2f8ff561de1ce485832d3da526c12 Mon Sep 17 00:00:00 2001
From: Hussain Jasim <hussain.jasim@xxxxxxxxxxx>
Date: Wed, 20 Jun 2018 22:33:34 -0400
Subject: [PATCH 3/3] Added defaults and customizations to the Espeak client
 for pitch and pitch-range.

---
 lisp/espeak-voices.el | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/lisp/espeak-voices.el b/lisp/espeak-voices.el
index 59c21c648..a84435d41 100644
--- a/lisp/espeak-voices.el
+++ b/lisp/espeak-voices.el
@@ -57,6 +57,27 @@
                       (string-match "espeak$" (getenv "DTK_PROGRAM")))
              (setq-default dt-speech-rate val))))
 
+(defcustom espeak-default-speech-pitch 50
+  "Default speech pitch for eSpeak."
+  :group 'tts
+  :type 'integer
+  :set #'(lambda(sym val)
+           (set-default sym val)
+           (when (and (getenv "DTK_PROGRAM")
+                      (string-match "espeak$" (getenv "DTK_PROGRAM")))
+             (setq-default espeak-speech-pitch val))))
+
+(defcustom espeak-default-speech-pitch-range 50
+  "Default speech pitch range for eSpeak."
+  :group 'tts
+  :type 'integer
+  :set #'(lambda(sym val)
+           (set-default sym val)
+           (when (and (getenv "DTK_PROGRAM")
+                      (string-match "espeak$" (getenv "DTK_PROGRAM")))
+             (setq-default espeak-speech-pitch-range val))))
+
+;;}}}
 ;;{{{ espeak-specific controls
 ;; Functions to interface with the Espeak server and interactively set pitch and pitch-range,
 ;; which are defined here instead of dtk-speech.el because they are exclusive to Espeak.
@@ -561,6 +582,8 @@ and TABLE gives the values along that dimension."
   "Configure TTS environment to use eSpeak."
   (cl-declare (special tts-default-speech-rate
                        espeak-default-speech-rate
+                       espeak-default-speech-pitch
+                       espeak-default-speech-pitch-range
                        dtk-speaker-process
                        emacspeak-unspeakable-rule))
   (fset 'tts-list-voices'espeak-list-voices)
@@ -571,6 +594,8 @@ and TABLE gives the values along that dimension."
   (setq tts-default-voice nil)
   (setq tts-default-speech-rate espeak-default-speech-rate)
   (set-default 'tts-default-speech-rate espeak-default-speech-rate)
+  (espeak-set-pitch espeak-default-speech-pitch t)
+  (espeak-set-pitch-range espeak-default-speech-pitch-range t)
   (espeak-setup-character-to-speech-table)
   (dtk-unicode-update-untouched-charsets '(ascii latin-iso8859-1)))
 
@@ -579,10 +604,12 @@ and TABLE gives the values along that dimension."
 ;;;###autoload
 (defun espeak-make-tts-env  ()
   "Constructs a TTS environment for Espeak."
-  (cl-declare (special espeak-default-speech-rate))
+  (cl-declare (special espeak-default-speech-rate espeak-default-speech-pitch espeak-default-speech-pitch-range))
   (make-tts-env
    :name :espeak :default-voice 'paul
    :default-speech-rate espeak-default-speech-rate
+   :default-speech-pitch espeak-default-speech-pitch
+   :default-speech-pitch-range espeak-default-speech-pitch-range
    :list-voices #'espeak-list-voices
    :acss-voice-defined-p #'espeak-voice-defined-p
    :get-acss-voice-command #'espeak-get-voice-command
-- 
2.15.0

From 666f5664ba9a58fd6d6cbc19b9459ffb061bc5e6 Mon Sep 17 00:00:00 2001
From: Hussain Jasim <hussain.jasim@xxxxxxxxxxx>
Date: Wed, 20 Feb 2019 00:09:24 -0500
Subject: [PATCH] Implemented a customization variable for the unit of text
 that should be spoken when moving to the beginning and end of a line, and
 pulled this behaviour out into its own advice.

---
 lisp/emacspeak-advice.el | 32 +++++++++++++++++++++++++++++---
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/lisp/emacspeak-advice.el b/lisp/emacspeak-advice.el
index baa6abfbc..7f5b2a982 100644
--- a/lisp/emacspeak-advice.el
+++ b/lisp/emacspeak-advice.el
@@ -2247,9 +2247,7 @@ Produce an auditory icon if possible."
 
 (cl-loop
  for f in
- '(beginning-of-line end-of-line
-                     move-beginning-of-line move-end-of-line
-                     recenter-top-bottom recenter)
+ '(recenter-top-bottom recenter)
  do
  (eval
   `(defadvice ,f (before emacspeak pre act comp)
@@ -2259,6 +2257,34 @@ Produce an auditory icon if possible."
        (emacspeak-auditory-icon 'select-object)))))
 
 ;;}}}
+;;{{{ speak when moving to beginning and end of line
+
+(defcustom emacspeak-speak-at-ends-of-line 'line
+  "Current text unit under point to speak when moving to the beginning or end of a line.  Default is `line'."
+  :group 'emacspeak-advice
+  :type '(choice
+          (const :tag "nothing" nil)
+          (const :tag "line" line)
+          (const :tag "word" word)
+          (const :tag "character" char)))
+
+(cl-loop
+ for f in
+ '(beginning-of-line end-of-line
+                     move-beginning-of-line move-end-of-line)
+ do
+ (eval
+  `(defadvice ,f (after emacspeak pre act comp)
+     "Speak `emacspeak-speak-at-ends-of-line' under point."
+     (when (and (ems-interactive-p) (not (eq emacspeak-speak-at-ends-of-line 'nil)))
+       (and dtk-stop-immediately (dtk-stop))
+       (cond
+         ((eq emacspeak-speak-at-ends-of-line 'line) (emacspeak-speak-line))
+         ((eq emacspeak-speak-at-ends-of-line 'word) (emacspeak-speak-word))
+         ((eq emacspeak-speak-at-ends-of-line 'char) (emacspeak-speak-char t)))
+       (emacspeak-auditory-icon 'select-object)))))
+
+;;}}} 
 ;;{{{ yanking and popping
 
 (cl-loop
-- 
2.15.0

From 932adfe6dc83fed1bad65dc529bfa43e64de3744 Mon Sep 17 00:00:00 2001
From: Hussain Jasim <hussain.jasim@xxxxxxxxxxx>
Date: Wed, 20 Feb 2019 01:43:05 -0500
Subject: [PATCH] Implemented customization variables for: (1) controling the
 phrasing of line indentation level announcements; (2) grouping indentation
 level by multiples and offsets of the tab-width.

---
 lisp/emacspeak-speak.el | 54 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)

diff --git a/lisp/emacspeak-speak.el b/lisp/emacspeak-speak.el
index e61448b03..90a04305a 100644
--- a/lisp/emacspeak-speak.el
+++ b/lisp/emacspeak-speak.el
@@ -682,6 +682,46 @@ results in the Dectalk producing a tone whose length is a function of the
 line's indentation.  Specifying `speak'
 results in the number of initial spaces being spoken.")
 
+(defcustom emacspeak-audio-indentation-before "indent "
+  "Option specifying the phrase that is spoken before the indent level, when speaking line indentation."
+  :group 'emacspeak-speak
+  :type 'string)
+
+(defcustom emacspeak-audio-indentation-after ""
+  "Option specifying the phrase that is spoken after the indent level, when speaking line indentation."
+  :group 'emacspeak-speak
+  :type 'string)
+
+(defcustom emacspeak-audio-indentation-tab-grouped nil
+  "Option indicating whether indentation levels should be grouped into a multiple of the tab-width and an offset, when speaking line indentation."
+  :group 'emacspeak-speak
+  :type 'boolean)
+
+(defcustom emacspeak-audio-indentation-before-tab ""
+  "Option specifying the phrase that is spoken before the tab-width multiple, when speaking tab-grouped line indentation."
+  :group 'emacspeak-speak
+  :type 'string)
+
+(defcustom emacspeak-audio-indentation-after-tab " tabs"
+  "Option specifying the phrase that is spoken after the tab-width multiple, when speaking tab-grouped line indentation."
+  :group 'emacspeak-speak
+  :type 'string)
+
+(defcustom emacspeak-audio-indentation-tab-grouped-separator " "
+  "Option specifying the phrase that is spoken between the tab-width multiple and the tab-width offset, when speaking tab-grouped line indentation."
+  :group 'emacspeak-speak
+  :type 'string)
+
+(defcustom emacspeak-audio-indentation-before-offset ""
+  "Option specifying the phrase that is spoken before the tab-width offset, when speaking tab-grouped line indentation."
+  :group 'emacspeak-speak
+  :type 'string)
+
+(defcustom emacspeak-audio-indentation-after-offset " spaces"
+  "Option specifying the phrase that is spoken after the tab-width offset, when speaking tab-grouped line indentation."
+  :group 'emacspeak-speak
+  :type 'string)
+
 ;;}}}
 ;;{{{ filtering columns
 
@@ -1017,7 +1057,19 @@ with auditory icon `more'.  These can then be spoken using command
           (when
               (and (null arg) indent (> indent 0)
                    (eq 'speak emacspeak-audio-indentation-method))
-            (setq indent (format "indent %d" indent))
+            (setq indent
+              (cond
+                ((not emacspeak-audio-indentation-tab-grouped)
+                  (format "%s%d%s" emacspeak-audio-indentation-before indent emacspeak-audio-indentation-after))
+                ((< indent tab-width)
+                  (format "%s%d%s" emacspeak-audio-indentation-before-offset indent emacspeak-audio-indentation-after-offset))
+                ((eq 0 (% indent tab-width))
+                  (format "%s%d%s" emacspeak-audio-indentation-before-tab (/ indent tab-width) emacspeak-audio-indentation-after-tab))
+                (
+                  (format "%s%d%s%s%s%d%s"
+                    emacspeak-audio-indentation-before-tab (/ indent tab-width) emacspeak-audio-indentation-after-tab
+                    emacspeak-audio-indentation-tab-grouped-separator
+                    emacspeak-audio-indentation-before-offset (% indent tab-width) emacspeak-audio-indentation-after-offset))))
             (setq indent (propertize indent 'personality voice-indent))
             (setq line (concat indent line)))
           (when linenum
-- 
2.15.0



|May 1995 - Last Year |Current Year|


If you have questions about this archive or had problems using it, please contact us.

Contact Info Page