aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/erc/erc-speak.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/erc/erc-speak.el')
-rw-r--r--lisp/erc/erc-speak.el230
1 files changed, 230 insertions, 0 deletions
diff --git a/lisp/erc/erc-speak.el b/lisp/erc/erc-speak.el
new file mode 100644
index 00000000000..cd176f29fd2
--- /dev/null
+++ b/lisp/erc/erc-speak.el
@@ -0,0 +1,230 @@
1;;; erc-speak.el --- Speech-enable the ERC chat client
2
3;; Copyright 2001, 2002, 2003, 2004, 2007,
4;; 2008, 2009 Free Software Foundation, Inc.
5
6;; This file is part of GNU Emacs.
7
8;; GNU Emacs is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation; either version 3, or (at your option)
11;; any later version.
12
13;; GNU Emacs is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with GNU Emacs; see the file COPYING. If not, write to the
20;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21;; Boston, MA 02110-1301, USA.
22
23;;; Commentary:
24
25;; This file contains code to speech enable ERC using Emacspeak's functionality
26;; to access a speech synthesizer.
27;;
28;; It tries to be intelligent and produce actually understandable
29;; audio streams :). Hopefully it does. I use it on #debian at irc.debian.org
30;; with about 200 users, and I am amazed how easy it works.
31;;
32;; Currently, erc-speak is only written to listen to channels.
33;; There is no special functionality for interaction in the erc buffers.
34;; Although this shouldn't be hard. Look at the Todo list, there are
35;; definitely many things this script could do nicely to make a better
36;; IRC experience for anyone.
37;;
38;; More info? Read the code. It isn't that complicated.
39;;
40
41;;; Installation:
42
43;; Put erc.el and erc-speak.el somewhere in your load-path and
44;; (require 'erc-speak) in your .emacs. Remember to require only erc-speak
45;; because otherwise you get conflicts with emacspeak.
46
47;;; Bugs:
48
49;; erc-speak-rate doesn't seem to work here on outloud. Can anyone enlighten
50;; me on the use of dtk-interp-queue-set-rate or equivalent?
51
52;;; Code:
53
54(require 'emacspeak)
55(provide 'emacspeak-erc)
56(require 'erc)
57(require 'erc-button)
58
59(defgroup erc-speak nil
60 "Enable speech synthesis with the ERC chat client using Emacspeak"
61 :group 'erc)
62
63(defcustom erc-speak-personalities '((erc-default-face paul)
64 (erc-direct-msg-face paul-animated)
65 (erc-input-face paul-smooth)
66 (erc-bold-face paul-bold)
67 (erc-inverse-face betty)
68 (erc-underline-face ursula)
69 (erc-prompt-face harry)
70 (erc-notice-face paul-italic)
71 (erc-action-face paul-monotone)
72 (erc-error-face kid)
73 (erc-dangerous-host-face paul-surprized)
74 (erc-pal-face paul-animated)
75 (erc-fool-face paul-angry)
76 (erc-keyword-face paul-animated))
77 "Maps faces used in erc to speaker personalities in emacspeak."
78 :group 'erc-speak
79 :type '(repeat
80 (list :tag "mapping"
81 (symbol :tag "face")
82 (symbol :tag "personality"))))
83
84(add-hook 'erc-mode-hook (lambda () (setq voice-lock-mode t)))
85
86;; Override the definition in erc.el
87(defun erc-put-text-property (start end property value &optional object)
88 "This function sets the appropriate personality on the specified
89region in addition to setting the requested face."
90 (put-text-property start end property value object)
91 (when (eq property 'face)
92 (put-text-property start end
93 'personality
94 (cadr (assq value erc-speak-personalities))
95 object)))
96
97(add-hook 'erc-insert-post-hook 'erc-speak-region)
98(add-hook 'erc-send-post-hook 'erc-speak-region)
99
100(defcustom erc-speak-filter-host t
101 "Set to t if you want to filter out user@host constructs."
102 :group 'erc-speak
103 :type 'bool)
104
105(defcustom erc-speak-filter-timestamp t
106 "If non-nil, try to filter out the timestamp when speaking arriving messages.
107
108Note, your erc-timestamp-format variable needs to start with a [
109and end with ]."
110 :group 'erc-speak
111 :type 'bool)
112
113(defcustom erc-speak-acronyms '(("brb" "be right back")
114 ("btw" "by the way")
115 ("wtf" "what the fuck")
116 ("rotfl" "rolling on the floor and laughing")
117 ("afaik" "as far as I know")
118 ("afaics" "as far as I can see")
119 ("iirc" "if I remember correctly"))
120 "List of acronyms to expand."
121 :group 'erc-speak
122 :type '(repeat sexp))
123
124(defun erc-speak-acronym-replace (string)
125 "Replace acronyms in the current buffer."
126 (let ((case-fold-search nil))
127 (dolist (ac erc-speak-acronyms string)
128 (while (string-match (car ac) string)
129 (setq string (replace-match (cadr ac) nil t string))))))
130
131(defcustom erc-speak-smileys '((":-)" "smiling face")
132 (":)" "smiling face")
133 (":-(" "sad face")
134 (":(" "sad face"))
135;; please add more, send me patches, mlang@home.delysid.org tnx
136 "List of smileys and their textual description."
137 :group 'erc-speak
138 :type '(repeat (list 'symbol 'symbol)))
139
140(defcustom erc-speak-smiley-personality 'harry
141 "Personality used for smiley announcements."
142 :group 'erc-speak
143 :type 'symbol)
144
145(defun erc-speak-smiley-replace (string)
146 "Replace smileys with textual description."
147 (let ((case-fold-search nil))
148 (dolist (smiley erc-speak-smileys string)
149 (while (string-match (car smiley) string)
150 (let ((repl (cadr smiley)))
151 (put-text-property 0 (length repl) 'personality
152 erc-speak-smiley-personality repl)
153 (setq string (replace-match repl nil t string)))))))
154
155(defcustom erc-speak-channel-personality 'harry
156 "*Personality to announce channel names with."
157 :group 'erc-speak
158 :type 'symbol)
159
160(defun erc-speak-region ()
161 "Speak a region containing one IRC message using Emacspeak.
162This function tries to translate common IRC forms into
163intelligent speech."
164 (let ((target (if (erc-channel-p (erc-default-target))
165 (erc-propertize
166 (erc-default-target)
167 'personality erc-speak-channel-personality)
168 ""))
169 (dtk-stop-immediately nil))
170 (emacspeak-auditory-icon 'progress)
171 (when erc-speak-filter-timestamp
172 (save-excursion
173 (goto-char (point-min))
174 (when (re-search-forward "^\\[[a-zA-Z:,;.0-9 \t-]+\\]" nil t)
175 (narrow-to-region (point) (point-max)))))
176 (save-excursion
177 (goto-char (point-min))
178 (cond ((re-search-forward (concat "^<\\([^>]+\\)> "
179 (concat "\\("
180 erc-valid-nick-regexp
181 "\\)[;,:]")) nil t)
182 (let ((from (match-string 1))
183 (to (match-string 2))
184 (text (buffer-substring (match-end 2) (point-max))))
185 (tts-with-punctuations
186 "some"
187 (dtk-speak (concat (erc-propertize
188 (concat target " " from " to " to)
189 'personality erc-speak-channel-personality)
190 (erc-speak-smiley-replace
191 (erc-speak-acronym-replace text)))))))
192 ((re-search-forward "^<\\([^>]+\\)> " nil t)
193 (let ((from (match-string 1))
194 (msg (buffer-substring (match-end 0) (point-max))))
195 (tts-with-punctuations
196 "some"
197 (dtk-speak (concat target " " from " "
198 (erc-speak-smiley-replace
199 (erc-speak-acronym-replace msg)))))))
200 ((re-search-forward (concat "^" (regexp-quote erc-notice-prefix)
201 "\\(.+\\)")
202 (point-max) t)
203 (let ((notice (buffer-substring (match-beginning 1) (point-max))))
204 (tts-with-punctuations
205 "all"
206 (dtk-speak
207 (with-temp-buffer
208 (insert notice)
209 (when erc-speak-filter-host
210 (goto-char (point-min))
211 (when (re-search-forward "([^)@]+@[^)@]+)" nil t)
212 (replace-match "")))
213 (buffer-string))))))
214 (t (let ((msg (buffer-substring (point-min) (point-max))))
215 (tts-with-punctuations
216 "some"
217 (dtk-speak (concat target " "
218 (erc-speak-smiley-replace
219 (erc-speak-acronym-replace msg)))))))))))
220
221(provide 'erc-speak)
222
223;;; erc-speak.el ends here
224;;
225;; Local Variables:
226;; indent-tabs-mode: t
227;; tab-width: 8
228;; End:
229
230;; arch-tag: 4499cd13-2829-43b8-83de-d313481531c4