Mercurial > emacs
annotate lisp/gnus/gnus-util.el @ 88155:d7ddb3e565de
sync with trunk
author | Henrik Enberg <henrik.enberg@telia.com> |
---|---|
date | Mon, 16 Jan 2006 00:03:54 +0000 |
parents | 52d99cc2e9e3 |
children |
rev | line source |
---|---|
17493 | 1 ;;; gnus-util.el --- utility functions for Gnus |
88155 | 2 |
3 ;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 | |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
4 ;; Free Software Foundation, Inc. |
17493 | 5 |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
6 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org> |
17493 | 7 ;; Keywords: news |
8 | |
9 ;; This file is part of GNU Emacs. | |
10 | |
11 ;; GNU Emacs is free software; you can redistribute it and/or modify | |
12 ;; it under the terms of the GNU General Public License as published by | |
13 ;; the Free Software Foundation; either version 2, or (at your option) | |
14 ;; any later version. | |
15 | |
16 ;; GNU Emacs is distributed in the hope that it will be useful, | |
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 ;; GNU General Public License for more details. | |
20 | |
21 ;; You should have received a copy of the GNU General Public License | |
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the | |
88155 | 23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
24 ;; Boston, MA 02110-1301, USA. | |
17493 | 25 |
26 ;;; Commentary: | |
27 | |
28 ;; Nothing in this file depends on any other parts of Gnus -- all | |
29 ;; functions and macros in this file are utility functions that are | |
30 ;; used by Gnus and may be used by any other package without loading | |
31 ;; Gnus first. | |
32 | |
88155 | 33 ;; [Unfortunately, it does depend on other parts of Gnus, e.g. the |
34 ;; autoloads below...] | |
35 | |
17493 | 36 ;;; Code: |
37 | |
38 (require 'custom) | |
35051
d80c28ab0b86
(nnmail-pathname-coding-system): Defvar when
Dave Love <fx@gnu.org>
parents:
34833
diff
changeset
|
39 (eval-when-compile |
d80c28ab0b86
(nnmail-pathname-coding-system): Defvar when
Dave Love <fx@gnu.org>
parents:
34833
diff
changeset
|
40 (require 'cl) |
d80c28ab0b86
(nnmail-pathname-coding-system): Defvar when
Dave Love <fx@gnu.org>
parents:
34833
diff
changeset
|
41 ;; Fixme: this should be a gnus variable, not nnmail-. |
88155 | 42 (defvar nnmail-pathname-coding-system) |
43 (defvar nnmail-active-file-coding-system) | |
44 | |
45 ;; Inappropriate references to other parts of Gnus. | |
46 (defvar gnus-emphasize-whitespace-regexp) | |
47 (defvar gnus-original-article-buffer) | |
48 (defvar gnus-user-agent) | |
49 ) | |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
50 (require 'time-date) |
88155 | 51 (require 'netrc) |
17493 | 52 |
53 (eval-and-compile | |
33287
83a1db714361
(nnheader): Don't require message (recursive
Dave Love <fx@gnu.org>
parents:
33267
diff
changeset
|
54 (autoload 'message-fetch-field "message") |
88155 | 55 (autoload 'gnus-get-buffer-window "gnus-win") |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
56 (autoload 'rmail-insert-rmail-file-header "rmail") |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
57 (autoload 'rmail-count-new-messages "rmail") |
88155 | 58 (autoload 'rmail-show-message "rmail") |
59 (autoload 'nnheader-narrow-to-headers "nnheader") | |
60 (autoload 'nnheader-replace-chars-in-string "nnheader")) | |
61 | |
62 (eval-and-compile | |
63 (cond | |
64 ((fboundp 'replace-in-string) | |
65 (defalias 'gnus-replace-in-string 'replace-in-string)) | |
66 ((fboundp 'replace-regexp-in-string) | |
67 (defun gnus-replace-in-string (string regexp newtext &optional literal) | |
68 "Replace all matches for REGEXP with NEWTEXT in STRING. | |
69 If LITERAL is non-nil, insert NEWTEXT literally. Return a new | |
70 string containing the replacements. | |
71 | |
72 This is a compatibility function for different Emacsen." | |
73 (replace-regexp-in-string regexp newtext string nil literal))) | |
74 (t | |
75 (defun gnus-replace-in-string (string regexp newtext &optional literal) | |
76 "Replace all matches for REGEXP with NEWTEXT in STRING. | |
77 If LITERAL is non-nil, insert NEWTEXT literally. Return a new | |
78 string containing the replacements. | |
79 | |
80 This is a compatibility function for different Emacsen." | |
81 (let ((start 0) tail) | |
82 (while (string-match regexp string start) | |
83 (setq tail (- (length string) (match-end 0))) | |
84 (setq string (replace-match newtext nil literal string)) | |
85 (setq start (- (length string) tail)))) | |
86 string)))) | |
87 | |
88 ;;; bring in the netrc functions as aliases | |
89 (defalias 'gnus-netrc-get 'netrc-get) | |
90 (defalias 'gnus-netrc-machine 'netrc-machine) | |
91 (defalias 'gnus-parse-netrc 'netrc-parse) | |
17493 | 92 |
93 (defun gnus-boundp (variable) | |
94 "Return non-nil if VARIABLE is bound and non-nil." | |
95 (and (boundp variable) | |
96 (symbol-value variable))) | |
97 | |
98 (defmacro gnus-eval-in-buffer-window (buffer &rest forms) | |
99 "Pop to BUFFER, evaluate FORMS, and then return to the original window." | |
100 (let ((tempvar (make-symbol "GnusStartBufferWindow")) | |
88155 | 101 (w (make-symbol "w")) |
102 (buf (make-symbol "buf"))) | |
17493 | 103 `(let* ((,tempvar (selected-window)) |
88155 | 104 (,buf ,buffer) |
105 (,w (gnus-get-buffer-window ,buf 'visible))) | |
17493 | 106 (unwind-protect |
88155 | 107 (progn |
108 (if ,w | |
109 (progn | |
110 (select-window ,w) | |
111 (set-buffer (window-buffer ,w))) | |
112 (pop-to-buffer ,buf)) | |
113 ,@forms) | |
114 (select-window ,tempvar))))) | |
17493 | 115 |
116 (put 'gnus-eval-in-buffer-window 'lisp-indent-function 1) | |
117 (put 'gnus-eval-in-buffer-window 'edebug-form-spec '(form body)) | |
118 | |
119 (defmacro gnus-intern-safe (string hashtable) | |
120 "Set hash value. Arguments are STRING, VALUE, and HASHTABLE." | |
121 `(let ((symbol (intern ,string ,hashtable))) | |
122 (or (boundp symbol) | |
123 (set symbol nil)) | |
124 symbol)) | |
125 | |
126 ;; Added by Geoffrey T. Dairiki <dairiki@u.washington.edu>. A safe way | |
127 ;; to limit the length of a string. This function is necessary since | |
128 ;; `(substr "abc" 0 30)' pukes with "Args out of range". | |
88155 | 129 ;; Fixme: Why not `truncate-string-to-width'? |
17493 | 130 (defsubst gnus-limit-string (str width) |
131 (if (> (length str) width) | |
132 (substring str 0 width) | |
133 str)) | |
134 | |
135 (defsubst gnus-goto-char (point) | |
136 (and point (goto-char point))) | |
137 | |
138 (defmacro gnus-buffer-exists-p (buffer) | |
139 `(let ((buffer ,buffer)) | |
140 (when buffer | |
141 (funcall (if (stringp buffer) 'get-buffer 'buffer-name) | |
142 buffer)))) | |
143 | |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
144 (defalias 'gnus-point-at-bol |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
145 (if (fboundp 'point-at-bol) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
146 'point-at-bol |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
147 'line-beginning-position)) |
17493 | 148 |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
149 (defalias 'gnus-point-at-eol |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
150 (if (fboundp 'point-at-eol) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
151 'point-at-eol |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
152 'line-end-position)) |
17493 | 153 |
88155 | 154 ;; The LOCAL arg to `add-hook' is interpreted differently in Emacs and |
155 ;; XEmacs. In Emacs we don't need to call `make-local-hook' first. | |
156 ;; It's harmless, though, so the main purpose of this alias is to shut | |
157 ;; up the byte compiler. | |
158 (defalias 'gnus-make-local-hook | |
159 (if (eq (get 'make-local-hook 'byte-compile) | |
160 'byte-compile-obsolete) | |
161 'ignore ; Emacs | |
162 'make-local-hook)) ; XEmacs | |
163 | |
17493 | 164 (defun gnus-delete-first (elt list) |
165 "Delete by side effect the first occurrence of ELT as a member of LIST." | |
166 (if (equal (car list) elt) | |
167 (cdr list) | |
168 (let ((total list)) | |
169 (while (and (cdr list) | |
170 (not (equal (cadr list) elt))) | |
171 (setq list (cdr list))) | |
172 (when (cdr list) | |
173 (setcdr list (cddr list))) | |
174 total))) | |
175 | |
176 ;; Delete the current line (and the next N lines). | |
177 (defmacro gnus-delete-line (&optional n) | |
88155 | 178 `(delete-region (gnus-point-at-bol) |
17493 | 179 (progn (forward-line ,(or n 1)) (point)))) |
180 | |
181 (defun gnus-byte-code (func) | |
182 "Return a form that can be `eval'ed based on FUNC." | |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
183 (let ((fval (indirect-function func))) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
184 (if (byte-code-function-p fval) |
17493 | 185 (let ((flist (append fval nil))) |
186 (setcar flist 'byte-code) | |
187 flist) | |
188 (cons 'progn (cddr fval))))) | |
189 | |
190 (defun gnus-extract-address-components (from) | |
88155 | 191 "Extract address components from a From header. |
192 Given an RFC-822 address FROM, extract full name and canonical address. | |
193 Returns a list of the form (FULL-NAME CANONICAL-ADDRESS). Much more simple | |
194 solution than `mail-extract-address-components', which works much better, but | |
195 is slower." | |
17493 | 196 (let (name address) |
197 ;; First find the address - the thing with the @ in it. This may | |
198 ;; not be accurate in mail addresses, but does the trick most of | |
199 ;; the time in news messages. | |
200 (when (string-match "\\b[^@ \t<>]+[!@][^@ \t<>]+\\b" from) | |
201 (setq address (substring from (match-beginning 0) (match-end 0)))) | |
202 ;; Then we check whether the "name <address>" format is used. | |
203 (and address | |
204 ;; Linear white space is not required. | |
205 (string-match (concat "[ \t]*<" (regexp-quote address) ">") from) | |
206 (and (setq name (substring from 0 (match-beginning 0))) | |
207 ;; Strip any quotes from the name. | |
88155 | 208 (string-match "^\".*\"$" name) |
17493 | 209 (setq name (substring name 1 (1- (match-end 0)))))) |
210 ;; If not, then "address (name)" is used. | |
211 (or name | |
212 (and (string-match "(.+)" from) | |
213 (setq name (substring from (1+ (match-beginning 0)) | |
214 (1- (match-end 0))))) | |
215 (and (string-match "()" from) | |
216 (setq name address)) | |
217 ;; XOVER might not support folded From headers. | |
218 (and (string-match "(.*" from) | |
219 (setq name (substring from (1+ (match-beginning 0)) | |
220 (match-end 0))))) | |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
221 (list (if (string= name "") nil name) (or address from)))) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
222 |
17493 | 223 |
224 (defun gnus-fetch-field (field) | |
225 "Return the value of the header FIELD of current article." | |
226 (save-excursion | |
227 (save-restriction | |
228 (let ((case-fold-search t) | |
229 (inhibit-point-motion-hooks t)) | |
230 (nnheader-narrow-to-headers) | |
231 (message-fetch-field field))))) | |
232 | |
88155 | 233 (defun gnus-fetch-original-field (field) |
234 "Fetch FIELD from the original version of the current article." | |
235 (with-current-buffer gnus-original-article-buffer | |
236 (gnus-fetch-field field))) | |
237 | |
238 | |
17493 | 239 (defun gnus-goto-colon () |
240 (beginning-of-line) | |
88155 | 241 (let ((eol (gnus-point-at-eol))) |
242 (goto-char (or (text-property-any (point) eol 'gnus-position t) | |
243 (search-forward ":" eol t) | |
244 (point))))) | |
245 | |
246 (defun gnus-decode-newsgroups (newsgroups group &optional method) | |
247 (let ((method (or method (gnus-find-method-for-group group)))) | |
248 (mapconcat (lambda (group) | |
249 (gnus-group-name-decode group (gnus-group-name-charset | |
250 method group))) | |
251 (message-tokenize-header newsgroups) | |
252 ","))) | |
17493 | 253 |
254 (defun gnus-remove-text-with-property (prop) | |
255 "Delete all text in the current buffer with text property PROP." | |
256 (save-excursion | |
257 (goto-char (point-min)) | |
258 (while (not (eobp)) | |
259 (while (get-text-property (point) prop) | |
260 (delete-char 1)) | |
261 (goto-char (next-single-property-change (point) prop nil (point-max)))))) | |
262 | |
263 (defun gnus-newsgroup-directory-form (newsgroup) | |
264 "Make hierarchical directory name from NEWSGROUP name." | |
88155 | 265 (let* ((newsgroup (gnus-newsgroup-savable-name newsgroup)) |
266 (idx (string-match ":" newsgroup))) | |
267 (concat | |
268 (if idx (substring newsgroup 0 idx)) | |
269 (if idx "/") | |
270 (nnheader-replace-chars-in-string | |
271 (if idx (substring newsgroup (1+ idx)) newsgroup) | |
272 ?. ?/)))) | |
17493 | 273 |
274 (defun gnus-newsgroup-savable-name (group) | |
275 ;; Replace any slashes in a group name (eg. an ange-ftp nndoc group) | |
276 ;; with dots. | |
277 (nnheader-replace-chars-in-string group ?/ ?.)) | |
278 | |
279 (defun gnus-string> (s1 s2) | |
280 (not (or (string< s1 s2) | |
281 (string= s1 s2)))) | |
282 | |
283 ;;; Time functions. | |
284 | |
285 (defun gnus-file-newer-than (file date) | |
286 (let ((fdate (nth 5 (file-attributes file)))) | |
287 (or (> (car fdate) (car date)) | |
288 (and (= (car fdate) (car date)) | |
289 (> (nth 1 fdate) (nth 1 date)))))) | |
290 | |
291 ;;; Keymap macros. | |
292 | |
293 (defmacro gnus-local-set-keys (&rest plist) | |
294 "Set the keys in PLIST in the current keymap." | |
295 `(gnus-define-keys-1 (current-local-map) ',plist)) | |
296 | |
297 (defmacro gnus-define-keys (keymap &rest plist) | |
298 "Define all keys in PLIST in KEYMAP." | |
299 `(gnus-define-keys-1 (quote ,keymap) (quote ,plist))) | |
300 | |
301 (defmacro gnus-define-keys-safe (keymap &rest plist) | |
302 "Define all keys in PLIST in KEYMAP without overwriting previous definitions." | |
303 `(gnus-define-keys-1 (quote ,keymap) (quote ,plist) t)) | |
304 | |
305 (put 'gnus-define-keys 'lisp-indent-function 1) | |
306 (put 'gnus-define-keys-safe 'lisp-indent-function 1) | |
307 (put 'gnus-local-set-keys 'lisp-indent-function 1) | |
308 | |
309 (defmacro gnus-define-keymap (keymap &rest plist) | |
310 "Define all keys in PLIST in KEYMAP." | |
311 `(gnus-define-keys-1 ,keymap (quote ,plist))) | |
312 | |
313 (put 'gnus-define-keymap 'lisp-indent-function 1) | |
314 | |
315 (defun gnus-define-keys-1 (keymap plist &optional safe) | |
316 (when (null keymap) | |
317 (error "Can't set keys in a null keymap")) | |
318 (cond ((symbolp keymap) | |
319 (setq keymap (symbol-value keymap))) | |
320 ((keymapp keymap)) | |
321 ((listp keymap) | |
322 (set (car keymap) nil) | |
323 (define-prefix-command (car keymap)) | |
324 (define-key (symbol-value (caddr keymap)) (cadr keymap) (car keymap)) | |
325 (setq keymap (symbol-value (car keymap))))) | |
326 (let (key) | |
327 (while plist | |
328 (when (symbolp (setq key (pop plist))) | |
329 (setq key (symbol-value key))) | |
330 (if (or (not safe) | |
331 (eq (lookup-key keymap key) 'undefined)) | |
332 (define-key keymap key (pop plist)) | |
333 (pop plist))))) | |
334 | |
88155 | 335 (defun gnus-completing-read-with-default (default prompt &rest args) |
17493 | 336 ;; Like `completing-read', except that DEFAULT is the default argument. |
337 (let* ((prompt (if default | |
88155 | 338 (concat prompt " (default " default "): ") |
339 (concat prompt ": "))) | |
17493 | 340 (answer (apply 'completing-read prompt args))) |
341 (if (or (null answer) (zerop (length answer))) | |
342 default | |
343 answer))) | |
344 | |
345 ;; Two silly functions to ensure that all `y-or-n-p' questions clear | |
346 ;; the echo area. | |
347 (defun gnus-y-or-n-p (prompt) | |
348 (prog1 | |
349 (y-or-n-p prompt) | |
350 (message ""))) | |
351 | |
352 (defun gnus-yes-or-no-p (prompt) | |
353 (prog1 | |
354 (yes-or-no-p prompt) | |
355 (message ""))) | |
356 | |
88155 | 357 ;; By Frank Schmitt <ich@Frank-Schmitt.net>. Allows to have |
358 ;; age-depending date representations. (e.g. just the time if it's | |
359 ;; from today, the day of the week if it's within the last 7 days and | |
360 ;; the full date if it's older) | |
361 | |
362 (defun gnus-seconds-today () | |
363 "Return the number of seconds passed today." | |
364 (let ((now (decode-time (current-time)))) | |
365 (+ (car now) (* (car (cdr now)) 60) (* (car (nthcdr 2 now)) 3600)))) | |
366 | |
367 (defun gnus-seconds-month () | |
368 "Return the number of seconds passed this month." | |
369 (let ((now (decode-time (current-time)))) | |
370 (+ (car now) (* (car (cdr now)) 60) (* (car (nthcdr 2 now)) 3600) | |
371 (* (- (car (nthcdr 3 now)) 1) 3600 24)))) | |
372 | |
373 (defun gnus-seconds-year () | |
374 "Return the number of seconds passed this year." | |
375 (let ((now (decode-time (current-time))) | |
376 (days (format-time-string "%j" (current-time)))) | |
377 (+ (car now) (* (car (cdr now)) 60) (* (car (nthcdr 2 now)) 3600) | |
378 (* (- (string-to-number days) 1) 3600 24)))) | |
379 | |
380 (defvar gnus-user-date-format-alist | |
381 '(((gnus-seconds-today) . "%k:%M") | |
382 (604800 . "%a %k:%M") ;;that's one week | |
383 ((gnus-seconds-month) . "%a %d") | |
384 ((gnus-seconds-year) . "%b %d") | |
385 (t . "%b %d '%y")) ;;this one is used when no | |
386 ;;other does match | |
387 "Specifies date format depending on age of article. | |
388 This is an alist of items (AGE . FORMAT). AGE can be a number (of | |
389 seconds) or a Lisp expression evaluating to a number. When the age of | |
390 the article is less than this number, then use `format-time-string' | |
391 with the corresponding FORMAT for displaying the date of the article. | |
392 If AGE is not a number or a Lisp expression evaluating to a | |
393 non-number, then the corresponding FORMAT is used as a default value. | |
394 | |
395 Note that the list is processed from the beginning, so it should be | |
396 sorted by ascending AGE. Also note that items following the first | |
397 non-number AGE will be ignored. | |
398 | |
399 You can use the functions `gnus-seconds-today', `gnus-seconds-month' | |
400 and `gnus-seconds-year' in the AGE spec. They return the number of | |
401 seconds passed since the start of today, of this month, of this year, | |
402 respectively.") | |
403 | |
404 (defun gnus-user-date (messy-date) | |
405 "Format the messy-date according to gnus-user-date-format-alist. | |
406 Returns \" ? \" if there's bad input or if an other error occurs. | |
407 Input should look like this: \"Sun, 14 Oct 2001 13:34:39 +0200\"." | |
408 (condition-case () | |
409 (let* ((messy-date (time-to-seconds (safe-date-to-time messy-date))) | |
410 (now (time-to-seconds (current-time))) | |
411 ;;If we don't find something suitable we'll use this one | |
412 (my-format "%b %d '%y")) | |
413 (let* ((difference (- now messy-date)) | |
414 (templist gnus-user-date-format-alist) | |
415 (top (eval (caar templist)))) | |
416 (while (if (numberp top) (< top difference) (not top)) | |
417 (progn | |
418 (setq templist (cdr templist)) | |
419 (setq top (eval (caar templist))))) | |
420 (if (stringp (cdr (car templist))) | |
421 (setq my-format (cdr (car templist))))) | |
422 (format-time-string (eval my-format) (seconds-to-time messy-date))) | |
423 (error " ? "))) | |
424 | |
17493 | 425 (defun gnus-dd-mmm (messy-date) |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
426 "Return a string like DD-MMM from a big messy string." |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
427 (condition-case () |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
428 (format-time-string "%d-%b" (safe-date-to-time messy-date)) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
429 (error " - "))) |
17493 | 430 |
431 (defmacro gnus-date-get-time (date) | |
432 "Convert DATE string to Emacs time. | |
433 Cache the result as a text property stored in DATE." | |
434 ;; Either return the cached value... | |
435 `(let ((d ,date)) | |
436 (if (equal "" d) | |
437 '(0 0) | |
438 (or (get-text-property 0 'gnus-time d) | |
439 ;; or compute the value... | |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
440 (let ((time (safe-date-to-time d))) |
17493 | 441 ;; and store it back in the string. |
442 (put-text-property 0 1 'gnus-time time d) | |
443 time))))) | |
444 | |
445 (defsubst gnus-time-iso8601 (time) | |
31785 | 446 "Return a string of TIME in YYYYMMDDTHHMMSS format." |
17493 | 447 (format-time-string "%Y%m%dT%H%M%S" time)) |
448 | |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
449 (defun gnus-date-iso8601 (date) |
31785 | 450 "Convert the DATE to YYYYMMDDTHHMMSS." |
17493 | 451 (condition-case () |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
452 (gnus-time-iso8601 (gnus-date-get-time date)) |
17493 | 453 (error ""))) |
454 | |
455 (defun gnus-mode-string-quote (string) | |
456 "Quote all \"%\"'s in STRING." | |
88155 | 457 (gnus-replace-in-string string "%" "%%")) |
17493 | 458 |
459 ;; Make a hash table (default and minimum size is 256). | |
460 ;; Optional argument HASHSIZE specifies the table size. | |
461 (defun gnus-make-hashtable (&optional hashsize) | |
462 (make-vector (if hashsize (max (gnus-create-hash-size hashsize) 256) 256) 0)) | |
463 | |
464 ;; Make a number that is suitable for hashing; bigger than MIN and | |
465 ;; equal to some 2^x. Many machines (such as sparcs) do not have a | |
466 ;; hardware modulo operation, so they implement it in software. On | |
467 ;; many sparcs over 50% of the time to intern is spent in the modulo. | |
468 ;; Yes, it's slower than actually computing the hash from the string! | |
469 ;; So we use powers of 2 so people can optimize the modulo to a mask. | |
470 (defun gnus-create-hash-size (min) | |
471 (let ((i 1)) | |
472 (while (< i min) | |
473 (setq i (* 2 i))) | |
474 i)) | |
475 | |
476 (defcustom gnus-verbose 7 | |
477 "*Integer that says how verbose Gnus should be. | |
478 The higher the number, the more messages Gnus will flash to say what | |
479 it's doing. At zero, Gnus will be totally mute; at five, Gnus will | |
480 display most important messages; and at ten, Gnus will keep on | |
481 jabbering all the time." | |
482 :group 'gnus-start | |
483 :type 'integer) | |
484 | |
485 (defun gnus-message (level &rest args) | |
88155 | 486 "If LEVEL is lower than `gnus-verbose' print ARGS using `message'. |
487 | |
488 Guideline for numbers: | |
489 1 - error messages, 3 - non-serious error messages, 5 - messages for things | |
490 that take a long time, 7 - not very important messages on stuff, 9 - messages | |
491 inside loops." | |
17493 | 492 (if (<= level gnus-verbose) |
493 (apply 'message args) | |
494 ;; We have to do this format thingy here even if the result isn't | |
495 ;; shown - the return value has to be the same as the return value | |
496 ;; from `message'. | |
497 (apply 'format args))) | |
498 | |
499 (defun gnus-error (level &rest args) | |
500 "Beep an error if LEVEL is equal to or less than `gnus-verbose'." | |
501 (when (<= (floor level) gnus-verbose) | |
502 (apply 'message args) | |
503 (ding) | |
504 (let (duration) | |
505 (when (and (floatp level) | |
506 (not (zerop (setq duration (* 10 (- level (floor level))))))) | |
507 (sit-for duration)))) | |
508 nil) | |
509 | |
510 (defun gnus-split-references (references) | |
511 "Return a list of Message-IDs in REFERENCES." | |
512 (let ((beg 0) | |
513 ids) | |
88155 | 514 (while (string-match "<[^<]+[^< \t]" references beg) |
17493 | 515 (push (substring references (match-beginning 0) (setq beg (match-end 0))) |
516 ids)) | |
517 (nreverse ids))) | |
518 | |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
519 (defsubst gnus-parent-id (references &optional n) |
17493 | 520 "Return the last Message-ID in REFERENCES. |
521 If N, return the Nth ancestor instead." | |
88155 | 522 (when (and references |
523 (not (zerop (length references)))) | |
524 (if n | |
525 (let ((ids (inline (gnus-split-references references)))) | |
526 (while (nthcdr n ids) | |
527 (setq ids (cdr ids))) | |
528 (car ids)) | |
529 (when (string-match "\\(<[^<]+>\\)[ \t]*\\'" references) | |
530 (match-string 1 references))))) | |
17493 | 531 |
88155 | 532 (defun gnus-buffer-live-p (buffer) |
17493 | 533 "Say whether BUFFER is alive or not." |
534 (and buffer | |
535 (get-buffer buffer) | |
536 (buffer-name (get-buffer buffer)))) | |
537 | |
538 (defun gnus-horizontal-recenter () | |
539 "Recenter the current buffer horizontally." | |
540 (if (< (current-column) (/ (window-width) 2)) | |
88155 | 541 (set-window-hscroll (gnus-get-buffer-window (current-buffer) t) 0) |
17493 | 542 (let* ((orig (point)) |
88155 | 543 (end (window-end (gnus-get-buffer-window (current-buffer) t))) |
17493 | 544 (max 0)) |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
545 (when end |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
546 ;; Find the longest line currently displayed in the window. |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
547 (goto-char (window-start)) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
548 (while (and (not (eobp)) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
549 (< (point) end)) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
550 (end-of-line) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
551 (setq max (max max (current-column))) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
552 (forward-line 1)) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
553 (goto-char orig) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
554 ;; Scroll horizontally to center (sort of) the point. |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
555 (if (> max (window-width)) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
556 (set-window-hscroll |
88155 | 557 (gnus-get-buffer-window (current-buffer) t) |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
558 (min (- (current-column) (/ (window-width) 3)) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
559 (+ 2 (- max (window-width))))) |
88155 | 560 (set-window-hscroll (gnus-get-buffer-window (current-buffer) t) 0)) |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
561 max)))) |
17493 | 562 |
88155 | 563 (defun gnus-read-event-char (&optional prompt) |
17493 | 564 "Get the next event." |
88155 | 565 (let ((event (read-event prompt))) |
17493 | 566 ;; should be gnus-characterp, but this can't be called in XEmacs anyway |
567 (cons (and (numberp event) event) event))) | |
568 | |
569 (defun gnus-sortable-date (date) | |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
570 "Make string suitable for sorting from DATE." |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
571 (gnus-time-iso8601 (date-to-time date))) |
17493 | 572 |
573 (defun gnus-copy-file (file &optional to) | |
574 "Copy FILE to TO." | |
575 (interactive | |
576 (list (read-file-name "Copy file: " default-directory) | |
577 (read-file-name "Copy file to: " default-directory))) | |
578 (unless to | |
579 (setq to (read-file-name "Copy file to: " default-directory))) | |
580 (when (file-directory-p to) | |
581 (setq to (concat (file-name-as-directory to) | |
582 (file-name-nondirectory file)))) | |
583 (copy-file file to)) | |
584 | |
585 (defvar gnus-work-buffer " *gnus work*") | |
586 | |
587 (defun gnus-set-work-buffer () | |
588 "Put point in the empty Gnus work buffer." | |
589 (if (get-buffer gnus-work-buffer) | |
590 (progn | |
591 (set-buffer gnus-work-buffer) | |
592 (erase-buffer)) | |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
593 (set-buffer (gnus-get-buffer-create gnus-work-buffer)) |
17493 | 594 (kill-all-local-variables) |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
595 (mm-enable-multibyte))) |
17493 | 596 |
597 (defmacro gnus-group-real-name (group) | |
598 "Find the real name of a foreign newsgroup." | |
599 `(let ((gname ,group)) | |
600 (if (string-match "^[^:]+:" gname) | |
601 (substring gname (match-end 0)) | |
602 gname))) | |
603 | |
604 (defun gnus-make-sort-function (funs) | |
88155 | 605 "Return a composite sort condition based on the functions in FUNS." |
17493 | 606 (cond |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
607 ;; Just a simple function. |
88155 | 608 ((functionp funs) funs) |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
609 ;; No functions at all. |
17493 | 610 ((null funs) funs) |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
611 ;; A list of functions. |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
612 ((or (cdr funs) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
613 (listp (car funs))) |
88155 | 614 (gnus-byte-compile |
615 `(lambda (t1 t2) | |
616 ,(gnus-make-sort-function-1 (reverse funs))))) | |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
617 ;; A list containing just one function. |
17493 | 618 (t |
619 (car funs)))) | |
620 | |
621 (defun gnus-make-sort-function-1 (funs) | |
88155 | 622 "Return a composite sort condition based on the functions in FUNS." |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
623 (let ((function (car funs)) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
624 (first 't1) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
625 (last 't2)) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
626 (when (consp function) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
627 (cond |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
628 ;; Reversed spec. |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
629 ((eq (car function) 'not) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
630 (setq function (cadr function) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
631 first 't2 |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
632 last 't1)) |
88155 | 633 ((functionp function) |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
634 ;; Do nothing. |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
635 ) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
636 (t |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
637 (error "Invalid sort spec: %s" function)))) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
638 (if (cdr funs) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
639 `(or (,function ,first ,last) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
640 (and (not (,function ,last ,first)) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
641 ,(gnus-make-sort-function-1 (cdr funs)))) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
642 `(,function ,first ,last)))) |
17493 | 643 |
644 (defun gnus-turn-off-edit-menu (type) | |
645 "Turn off edit menu in `gnus-TYPE-mode-map'." | |
646 (define-key (symbol-value (intern (format "gnus-%s-mode-map" type))) | |
647 [menu-bar edit] 'undefined)) | |
648 | |
88155 | 649 (defmacro gnus-bind-print-variables (&rest forms) |
650 "Bind print-* variables and evaluate FORMS. | |
651 This macro is used with `prin1', `pp', etc. in order to ensure printed | |
652 Lisp objects are loadable. Bind `print-quoted' and `print-readably' | |
653 to t, and `print-escape-multibyte', `print-escape-newlines', | |
654 `print-escape-nonascii', `print-length', `print-level' and | |
655 `print-string-length' to nil." | |
656 `(let ((print-quoted t) | |
657 (print-readably t) | |
658 ;;print-circle | |
659 ;;print-continuous-numbering | |
660 print-escape-multibyte | |
661 print-escape-newlines | |
662 print-escape-nonascii | |
663 ;;print-gensym | |
664 print-length | |
665 print-level | |
666 print-string-length) | |
667 ,@forms)) | |
668 | |
17493 | 669 (defun gnus-prin1 (form) |
670 "Use `prin1' on FORM in the current buffer. | |
88155 | 671 Bind `print-quoted' and `print-readably' to t, and `print-length' and |
672 `print-level' to nil. See also `gnus-bind-print-variables'." | |
673 (gnus-bind-print-variables (prin1 form (current-buffer)))) | |
17493 | 674 |
675 (defun gnus-prin1-to-string (form) | |
88155 | 676 "The same as `prin1'. |
677 Bind `print-quoted' and `print-readably' to t, and `print-length' and | |
678 `print-level' to nil. See also `gnus-bind-print-variables'." | |
679 (gnus-bind-print-variables (prin1-to-string form))) | |
680 | |
681 (defun gnus-pp (form) | |
682 "Use `pp' on FORM in the current buffer. | |
683 Bind `print-quoted' and `print-readably' to t, and `print-length' and | |
684 `print-level' to nil. See also `gnus-bind-print-variables'." | |
685 (gnus-bind-print-variables (pp form (current-buffer)))) | |
686 | |
687 (defun gnus-pp-to-string (form) | |
688 "The same as `pp-to-string'. | |
689 Bind `print-quoted' and `print-readably' to t, and `print-length' and | |
690 `print-level' to nil. See also `gnus-bind-print-variables'." | |
691 (gnus-bind-print-variables (pp-to-string form))) | |
17493 | 692 |
693 (defun gnus-make-directory (directory) | |
694 "Make DIRECTORY (and all its parents) if it doesn't exist." | |
35051
d80c28ab0b86
(nnmail-pathname-coding-system): Defvar when
Dave Love <fx@gnu.org>
parents:
34833
diff
changeset
|
695 (require 'nnmail) |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
696 (let ((file-name-coding-system nnmail-pathname-coding-system)) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
697 (when (and directory |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
698 (not (file-exists-p directory))) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
699 (make-directory directory t))) |
17493 | 700 t) |
701 | |
702 (defun gnus-write-buffer (file) | |
703 "Write the current buffer's contents to FILE." | |
704 ;; Make sure the directory exists. | |
705 (gnus-make-directory (file-name-directory file)) | |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
706 (let ((file-name-coding-system nnmail-pathname-coding-system)) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
707 ;; Write the buffer. |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
708 (write-region (point-min) (point-max) file nil 'quietly))) |
17493 | 709 |
710 (defun gnus-delete-file (file) | |
711 "Delete FILE if it exists." | |
712 (when (file-exists-p file) | |
713 (delete-file file))) | |
714 | |
88155 | 715 (defun gnus-delete-directory (directory) |
716 "Delete files in DIRECTORY. Subdirectories remain. | |
717 If there's no subdirectory, delete DIRECTORY as well." | |
718 (when (file-directory-p directory) | |
719 (let ((files (directory-files | |
720 directory t "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")) | |
721 file dir) | |
722 (while files | |
723 (setq file (pop files)) | |
724 (if (eq t (car (file-attributes file))) | |
725 ;; `file' is a subdirectory. | |
726 (setq dir t) | |
727 ;; `file' is a file or a symlink. | |
728 (delete-file file))) | |
729 (unless dir | |
730 (delete-directory directory))))) | |
731 | |
17493 | 732 (defun gnus-strip-whitespace (string) |
733 "Return STRING stripped of all whitespace." | |
734 (while (string-match "[\r\n\t ]+" string) | |
735 (setq string (replace-match "" t t string))) | |
736 string) | |
737 | |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
738 (defsubst gnus-put-text-property-excluding-newlines (beg end prop val) |
17493 | 739 "The same as `put-text-property', but don't put this prop on any newlines in the region." |
740 (save-match-data | |
741 (save-excursion | |
742 (save-restriction | |
743 (goto-char beg) | |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
744 (while (re-search-forward gnus-emphasize-whitespace-regexp end 'move) |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
745 (gnus-put-text-property beg (match-beginning 0) prop val) |
17493 | 746 (setq beg (point))) |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
747 (gnus-put-text-property beg (point) prop val))))) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
748 |
88155 | 749 (defsubst gnus-put-overlay-excluding-newlines (beg end prop val) |
750 "The same as `put-text-property', but don't put this prop on any newlines in the region." | |
751 (save-match-data | |
752 (save-excursion | |
753 (save-restriction | |
754 (goto-char beg) | |
755 (while (re-search-forward gnus-emphasize-whitespace-regexp end 'move) | |
756 (gnus-overlay-put | |
757 (gnus-make-overlay beg (match-beginning 0)) | |
758 prop val) | |
759 (setq beg (point))) | |
760 (gnus-overlay-put (gnus-make-overlay beg (point)) prop val))))) | |
761 | |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
762 (defun gnus-put-text-property-excluding-characters-with-faces (beg end |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
763 prop val) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
764 "The same as `put-text-property', but don't put props on characters with the `gnus-face' property." |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
765 (let ((b beg)) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
766 (while (/= b end) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
767 (when (get-text-property b 'gnus-face) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
768 (setq b (next-single-property-change b 'gnus-face nil end))) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
769 (when (/= b end) |
88155 | 770 (inline |
771 (gnus-put-text-property | |
772 b (setq b (next-single-property-change b 'gnus-face nil end)) | |
773 prop val)))))) | |
774 | |
775 (defmacro gnus-faces-at (position) | |
776 "Return a list of faces at POSITION." | |
777 (if (featurep 'xemacs) | |
778 `(let ((pos ,position)) | |
779 (mapcar-extents 'extent-face | |
780 nil (current-buffer) pos pos nil 'face)) | |
781 `(let ((pos ,position)) | |
782 (delq nil (cons (get-text-property pos 'face) | |
783 (mapcar | |
784 (lambda (overlay) | |
785 (overlay-get overlay 'face)) | |
786 (overlays-at pos))))))) | |
17493 | 787 |
788 ;;; Protected and atomic operations. dmoore@ucsd.edu 21.11.1996 | |
789 ;;; The primary idea here is to try to protect internal datastructures | |
790 ;;; from becoming corrupted when the user hits C-g, or if a hook or | |
791 ;;; similar blows up. Often in Gnus multiple tables/lists need to be | |
792 ;;; updated at the same time, or information can be lost. | |
793 | |
794 (defvar gnus-atomic-be-safe t | |
795 "If t, certain operations will be protected from interruption by C-g.") | |
796 | |
797 (defmacro gnus-atomic-progn (&rest forms) | |
798 "Evaluate FORMS atomically, which means to protect the evaluation | |
799 from being interrupted by the user. An error from the forms themselves | |
800 will return without finishing the operation. Since interrupts from | |
801 the user are disabled, it is recommended that only the most minimal | |
802 operations are performed by FORMS. If you wish to assign many | |
803 complicated values atomically, compute the results into temporary | |
804 variables and then do only the assignment atomically." | |
805 `(let ((inhibit-quit gnus-atomic-be-safe)) | |
806 ,@forms)) | |
807 | |
808 (put 'gnus-atomic-progn 'lisp-indent-function 0) | |
809 | |
810 (defmacro gnus-atomic-progn-assign (protect &rest forms) | |
811 "Evaluate FORMS, but insure that the variables listed in PROTECT | |
812 are not changed if anything in FORMS signals an error or otherwise | |
813 non-locally exits. The variables listed in PROTECT are updated atomically. | |
814 It is safe to use gnus-atomic-progn-assign with long computations. | |
815 | |
816 Note that if any of the symbols in PROTECT were unbound, they will be | |
48588 | 817 set to nil on a successful assignment. In case of an error or other |
17493 | 818 non-local exit, it will still be unbound." |
819 (let* ((temp-sym-map (mapcar (lambda (x) (list (make-symbol | |
820 (concat (symbol-name x) | |
821 "-tmp")) | |
822 x)) | |
823 protect)) | |
824 (sym-temp-map (mapcar (lambda (x) (list (cadr x) (car x))) | |
825 temp-sym-map)) | |
826 (temp-sym-let (mapcar (lambda (x) (list (car x) | |
827 `(and (boundp ',(cadr x)) | |
828 ,(cadr x)))) | |
829 temp-sym-map)) | |
830 (sym-temp-let sym-temp-map) | |
831 (temp-sym-assign (apply 'append temp-sym-map)) | |
832 (sym-temp-assign (apply 'append sym-temp-map)) | |
833 (result (make-symbol "result-tmp"))) | |
834 `(let (,@temp-sym-let | |
835 ,result) | |
836 (let ,sym-temp-let | |
837 (setq ,result (progn ,@forms)) | |
838 (setq ,@temp-sym-assign)) | |
839 (let ((inhibit-quit gnus-atomic-be-safe)) | |
840 (setq ,@sym-temp-assign)) | |
841 ,result))) | |
842 | |
843 (put 'gnus-atomic-progn-assign 'lisp-indent-function 1) | |
844 ;(put 'gnus-atomic-progn-assign 'edebug-form-spec '(sexp body)) | |
845 | |
846 (defmacro gnus-atomic-setq (&rest pairs) | |
847 "Similar to setq, except that the real symbols are only assigned when | |
848 there are no errors. And when the real symbols are assigned, they are | |
849 done so atomically. If other variables might be changed via side-effect, | |
850 see gnus-atomic-progn-assign. It is safe to use gnus-atomic-setq | |
851 with potentially long computations." | |
852 (let ((tpairs pairs) | |
853 syms) | |
854 (while tpairs | |
855 (push (car tpairs) syms) | |
856 (setq tpairs (cddr tpairs))) | |
857 `(gnus-atomic-progn-assign ,syms | |
858 (setq ,@pairs)))) | |
859 | |
860 ;(put 'gnus-atomic-setq 'edebug-form-spec '(body)) | |
861 | |
862 | |
863 ;;; Functions for saving to babyl/mail files. | |
864 | |
88155 | 865 (eval-when-compile |
866 (condition-case nil | |
867 (progn | |
868 (require 'rmail) | |
869 (autoload 'rmail-update-summary "rmailsum")) | |
870 (error | |
871 (define-compiler-macro rmail-select-summary (&rest body) | |
872 ;; Rmail of the XEmacs version is supplied by the package, and | |
873 ;; requires tm and apel packages. However, there may be those | |
874 ;; who haven't installed those packages. This macro helps such | |
875 ;; people even if they install those packages later. | |
876 `(eval '(rmail-select-summary ,@body))) | |
877 ;; If there's rmail but there's no tm (or there's apel of the | |
878 ;; mainstream, not the XEmacs version), loading rmail of the XEmacs | |
879 ;; version fails halfway, however it provides the rmail-select-summary | |
880 ;; macro which uses the following functions: | |
881 (autoload 'rmail-summary-displayed "rmail") | |
882 (autoload 'rmail-maybe-display-summary "rmail"))) | |
883 (defvar rmail-default-rmail-file) | |
884 (defvar mm-text-coding-system)) | |
885 | |
17493 | 886 (defun gnus-output-to-rmail (filename &optional ask) |
887 "Append the current article to an Rmail file named FILENAME." | |
888 (require 'rmail) | |
88155 | 889 (require 'mm-util) |
17493 | 890 ;; Most of these codes are borrowed from rmailout.el. |
891 (setq filename (expand-file-name filename)) | |
892 (setq rmail-default-rmail-file filename) | |
893 (let ((artbuf (current-buffer)) | |
894 (tmpbuf (get-buffer-create " *Gnus-output*"))) | |
895 (save-excursion | |
896 (or (get-file-buffer filename) | |
897 (file-exists-p filename) | |
898 (if (or (not ask) | |
899 (gnus-yes-or-no-p | |
900 (concat "\"" filename "\" does not exist, create it? "))) | |
901 (let ((file-buffer (create-file-buffer filename))) | |
902 (save-excursion | |
903 (set-buffer file-buffer) | |
904 (rmail-insert-rmail-file-header) | |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
905 (let ((require-final-newline nil) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
906 (coding-system-for-write mm-text-coding-system)) |
17493 | 907 (gnus-write-buffer filename))) |
908 (kill-buffer file-buffer)) | |
909 (error "Output file does not exist"))) | |
910 (set-buffer tmpbuf) | |
911 (erase-buffer) | |
912 (insert-buffer-substring artbuf) | |
913 (gnus-convert-article-to-rmail) | |
914 ;; Decide whether to append to a file or to an Emacs buffer. | |
915 (let ((outbuf (get-file-buffer filename))) | |
916 (if (not outbuf) | |
38861
f8833aa83b5e
* gnus-art.el (gnus-output-to-file): Bind file-name-coding-system.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
35051
diff
changeset
|
917 (let ((file-name-coding-system nnmail-pathname-coding-system)) |
f8833aa83b5e
* gnus-art.el (gnus-output-to-file): Bind file-name-coding-system.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
35051
diff
changeset
|
918 (mm-append-to-file (point-min) (point-max) filename)) |
17493 | 919 ;; File has been visited, in buffer OUTBUF. |
920 (set-buffer outbuf) | |
921 (let ((buffer-read-only nil) | |
922 (msg (and (boundp 'rmail-current-message) | |
923 (symbol-value 'rmail-current-message)))) | |
924 ;; If MSG is non-nil, buffer is in RMAIL mode. | |
925 (when msg | |
926 (widen) | |
927 (narrow-to-region (point-max) (point-max))) | |
928 (insert-buffer-substring tmpbuf) | |
929 (when msg | |
930 (goto-char (point-min)) | |
931 (widen) | |
88155 | 932 (search-backward "\n\^_") |
933 (narrow-to-region (point) (point-max)) | |
934 (rmail-count-new-messages t) | |
935 (when (rmail-summary-exists) | |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
936 (rmail-select-summary |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
937 (rmail-update-summary))) |
17493 | 938 (rmail-count-new-messages t) |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
939 (rmail-show-message msg)) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
940 (save-buffer))))) |
17493 | 941 (kill-buffer tmpbuf))) |
942 | |
943 (defun gnus-output-to-mail (filename &optional ask) | |
944 "Append the current article to a mail file named FILENAME." | |
945 (setq filename (expand-file-name filename)) | |
946 (let ((artbuf (current-buffer)) | |
947 (tmpbuf (get-buffer-create " *Gnus-output*"))) | |
948 (save-excursion | |
949 ;; Create the file, if it doesn't exist. | |
950 (when (and (not (get-file-buffer filename)) | |
951 (not (file-exists-p filename))) | |
952 (if (or (not ask) | |
953 (gnus-y-or-n-p | |
954 (concat "\"" filename "\" does not exist, create it? "))) | |
955 (let ((file-buffer (create-file-buffer filename))) | |
956 (save-excursion | |
957 (set-buffer file-buffer) | |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
958 (let ((require-final-newline nil) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
959 (coding-system-for-write mm-text-coding-system)) |
17493 | 960 (gnus-write-buffer filename))) |
961 (kill-buffer file-buffer)) | |
962 (error "Output file does not exist"))) | |
963 (set-buffer tmpbuf) | |
964 (erase-buffer) | |
965 (insert-buffer-substring artbuf) | |
966 (goto-char (point-min)) | |
967 (if (looking-at "From ") | |
968 (forward-line 1) | |
969 (insert "From nobody " (current-time-string) "\n")) | |
970 (let (case-fold-search) | |
971 (while (re-search-forward "^From " nil t) | |
972 (beginning-of-line) | |
973 (insert ">"))) | |
974 ;; Decide whether to append to a file or to an Emacs buffer. | |
975 (let ((outbuf (get-file-buffer filename))) | |
976 (if (not outbuf) | |
977 (let ((buffer-read-only nil)) | |
978 (save-excursion | |
979 (goto-char (point-max)) | |
980 (forward-char -2) | |
981 (unless (looking-at "\n\n") | |
982 (goto-char (point-max)) | |
983 (unless (bolp) | |
984 (insert "\n")) | |
985 (insert "\n")) | |
986 (goto-char (point-max)) | |
38861
f8833aa83b5e
* gnus-art.el (gnus-output-to-file): Bind file-name-coding-system.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
35051
diff
changeset
|
987 (let ((file-name-coding-system nnmail-pathname-coding-system)) |
f8833aa83b5e
* gnus-art.el (gnus-output-to-file): Bind file-name-coding-system.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
35051
diff
changeset
|
988 (mm-append-to-file (point-min) (point-max) filename)))) |
17493 | 989 ;; File has been visited, in buffer OUTBUF. |
990 (set-buffer outbuf) | |
991 (let ((buffer-read-only nil)) | |
992 (goto-char (point-max)) | |
993 (unless (eobp) | |
994 (insert "\n")) | |
995 (insert "\n") | |
996 (insert-buffer-substring tmpbuf))))) | |
997 (kill-buffer tmpbuf))) | |
998 | |
999 (defun gnus-convert-article-to-rmail () | |
1000 "Convert article in current buffer to Rmail message format." | |
1001 (let ((buffer-read-only nil)) | |
1002 ;; Convert article directly into Babyl format. | |
1003 (goto-char (point-min)) | |
1004 (insert "\^L\n0, unseen,,\n*** EOOH ***\n") | |
1005 (while (search-forward "\n\^_" nil t) ;single char | |
1006 (replace-match "\n^_" t t)) ;2 chars: "^" and "_" | |
1007 (goto-char (point-max)) | |
1008 (insert "\^_"))) | |
1009 | |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1010 (defun gnus-map-function (funs arg) |
88155 | 1011 "Apply the result of the first function in FUNS to the second, and so on. |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1012 ARG is passed to the first function." |
88155 | 1013 (while funs |
1014 (setq arg (funcall (pop funs) arg))) | |
1015 arg) | |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1016 |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1017 (defun gnus-run-hooks (&rest funcs) |
88155 | 1018 "Does the same as `run-hooks', but saves the current buffer." |
1019 (save-current-buffer | |
1020 (apply 'run-hooks funcs))) | |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1021 |
88155 | 1022 (defun gnus-run-mode-hooks (&rest funcs) |
1023 "Run `run-mode-hooks' if it is available, otherwise `run-hooks'. | |
1024 This function saves the current buffer." | |
1025 (if (fboundp 'run-mode-hooks) | |
1026 (save-current-buffer (apply 'run-mode-hooks funcs)) | |
1027 (save-current-buffer (apply 'run-hooks funcs)))) | |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1028 |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1029 ;;; Various |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1030 |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1031 (defvar gnus-group-buffer) ; Compiler directive |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1032 (defun gnus-alive-p () |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1033 "Say whether Gnus is running or not." |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1034 (and (boundp 'gnus-group-buffer) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1035 (get-buffer gnus-group-buffer) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1036 (save-excursion |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1037 (set-buffer gnus-group-buffer) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1038 (eq major-mode 'gnus-group-mode)))) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1039 |
88155 | 1040 (defun gnus-remove-if (predicate list) |
1041 "Return a copy of LIST with all items satisfying PREDICATE removed." | |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1042 (let (out) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1043 (while list |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1044 (unless (funcall predicate (car list)) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1045 (push (car list) out)) |
88155 | 1046 (setq list (cdr list))) |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1047 (nreverse out))) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1048 |
88155 | 1049 (if (fboundp 'assq-delete-all) |
1050 (defalias 'gnus-delete-alist 'assq-delete-all) | |
1051 (defun gnus-delete-alist (key alist) | |
1052 "Delete from ALIST all elements whose car is KEY. | |
1053 Return the modified alist." | |
1054 (let (entry) | |
1055 (while (setq entry (assq key alist)) | |
1056 (setq alist (delq entry alist))) | |
1057 alist))) | |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1058 |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1059 (defmacro gnus-pull (key alist &optional assoc-p) |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1060 "Modify ALIST to be without KEY." |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1061 (unless (symbolp alist) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1062 (error "Not a symbol: %s" alist)) |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1063 (let ((fun (if assoc-p 'assoc 'assq))) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1064 `(setq ,alist (delq (,fun ,key ,alist) ,alist)))) |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1065 |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1066 (defun gnus-globalify-regexp (re) |
88155 | 1067 "Return a regexp that matches a whole line, iff RE matches a part of it." |
24357
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1068 (concat (unless (string-match "^\\^" re) "^.*") |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1069 re |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1070 (unless (string-match "\\$$" re) ".*$"))) |
15fc6acbae7a
Upgrading to Gnus 5.7; see ChangeLog
Lars Magne Ingebrigtsen <larsi@gnus.org>
parents:
23319
diff
changeset
|
1071 |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1072 (defun gnus-set-window-start (&optional point) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1073 "Set the window start to POINT, or (point) if nil." |
88155 | 1074 (let ((win (gnus-get-buffer-window (current-buffer) t))) |
31716
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1075 (when win |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1076 (set-window-start win (or point (point)))))) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1077 |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1078 (defun gnus-annotation-in-region-p (b e) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1079 (if (= b e) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1080 (eq (cadr (memq 'gnus-undeletable (text-properties-at b))) t) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1081 (text-property-any b e 'gnus-undeletable t))) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1082 |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1083 (defun gnus-or (&rest elems) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1084 "Return non-nil if any of the elements are non-nil." |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1085 (catch 'found |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1086 (while elems |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1087 (when (pop elems) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1088 (throw 'found t))))) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1089 |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1090 (defun gnus-and (&rest elems) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1091 "Return non-nil if all of the elements are non-nil." |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1092 (catch 'found |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1093 (while elems |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1094 (unless (pop elems) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1095 (throw 'found nil))) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1096 t)) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1097 |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1098 (defun gnus-write-active-file (file hashtb &optional full-names) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1099 (let ((coding-system-for-write nnmail-active-file-coding-system)) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1100 (with-temp-file file |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1101 (mapatoms |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1102 (lambda (sym) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1103 (when (and sym |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1104 (boundp sym) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1105 (symbol-value sym)) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1106 (insert (format "%S %d %d y\n" |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1107 (if full-names |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1108 sym |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1109 (intern (gnus-group-real-name (symbol-name sym)))) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1110 (or (cdr (symbol-value sym)) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1111 (car (symbol-value sym))) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1112 (car (symbol-value sym)))))) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1113 hashtb) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1114 (goto-char (point-max)) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1115 (while (search-backward "\\." nil t) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1116 (delete-char 1))))) |
9968f55ad26e
Update to emacs-21-branch of the Gnus CVS repository.
Gerd Moellmann <gerd@gnu.org>
parents:
24357
diff
changeset
|
1117 |
88155 | 1118 ;; Fixme: Why not use `with-output-to-temp-buffer'? |
1119 (defmacro gnus-with-output-to-file (file &rest body) | |
1120 (let ((buffer (make-symbol "output-buffer")) | |
1121 (size (make-symbol "output-buffer-size")) | |
1122 (leng (make-symbol "output-buffer-length")) | |
1123 (append (make-symbol "output-buffer-append"))) | |
1124 `(let* ((,size 131072) | |
1125 (,buffer (make-string ,size 0)) | |
1126 (,leng 0) | |
1127 (,append nil) | |
1128 (standard-output | |
1129 (lambda (c) | |
1130 (aset ,buffer ,leng c) | |
1131 | |
1132 (if (= ,size (setq ,leng (1+ ,leng))) | |
1133 (progn (write-region ,buffer nil ,file ,append 'no-msg) | |
1134 (setq ,leng 0 | |
1135 ,append t)))))) | |
1136 ,@body | |
1137 (when (> ,leng 0) | |
1138 (let ((coding-system-for-write 'no-conversion)) | |
1139 (write-region (substring ,buffer 0 ,leng) nil ,file | |
1140 ,append 'no-msg)))))) | |
1141 | |
1142 (put 'gnus-with-output-to-file 'lisp-indent-function 1) | |
1143 (put 'gnus-with-output-to-file 'edebug-form-spec '(form body)) | |
1144 | |
1145 (if (fboundp 'union) | |
1146 (defalias 'gnus-union 'union) | |
1147 (defun gnus-union (l1 l2) | |
1148 "Set union of lists L1 and L2." | |
1149 (cond ((null l1) l2) | |
1150 ((null l2) l1) | |
1151 ((equal l1 l2) l1) | |
1152 (t | |
1153 (or (>= (length l1) (length l2)) | |
1154 (setq l1 (prog1 l2 (setq l2 l1)))) | |
1155 (while l2 | |
1156 (or (member (car l2) l1) | |
1157 (push (car l2) l1)) | |
1158 (pop l2)) | |
1159 l1)))) | |
1160 | |
34727
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1161 (defun gnus-add-text-properties-when |
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1162 (property value start end properties &optional object) |
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1163 "Like `gnus-add-text-properties', only applied on where PROPERTY is VALUE." |
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1164 (let (point) |
47938
65eaf21a0a44
(gnus-parse-netrc): Fix typo.
Juanma Barranquero <lekktu@gmail.com>
parents:
41494
diff
changeset
|
1165 (while (and start |
88155 | 1166 (< start end) ;; XEmacs will loop for every when start=end. |
34727
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1167 (setq point (text-property-not-all start end property value))) |
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1168 (gnus-add-text-properties start point properties object) |
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1169 (setq start (text-property-any point end property value))) |
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1170 (if start |
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1171 (gnus-add-text-properties start end properties object)))) |
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1172 |
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1173 (defun gnus-remove-text-properties-when |
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1174 (property value start end properties &optional object) |
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1175 "Like `remove-text-properties', only applied on where PROPERTY is VALUE." |
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1176 (let (point) |
47938
65eaf21a0a44
(gnus-parse-netrc): Fix typo.
Juanma Barranquero <lekktu@gmail.com>
parents:
41494
diff
changeset
|
1177 (while (and start |
88155 | 1178 (< start end) |
34727
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1179 (setq point (text-property-not-all start end property value))) |
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1180 (remove-text-properties start point properties object) |
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1181 (setq start (text-property-any point end property value))) |
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1182 (if start |
34833
aaf69bc74739
* gnus-art.el (gnus-article-check-hidden-text): Return t.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
34727
diff
changeset
|
1183 (remove-text-properties start end properties object)) |
aaf69bc74739
* gnus-art.el (gnus-article-check-hidden-text): Return t.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
34727
diff
changeset
|
1184 t)) |
34727
4b9a7a10deaa
* gnus-util.el (gnus-add-text-properties-when): New function.
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
33342
diff
changeset
|
1185 |
88155 | 1186 ;; This might use `compare-strings' to reduce consing in the |
1187 ;; case-insensitive case, but it has to cope with null args. | |
1188 ;; (`string-equal' uses symbol print names.) | |
1189 (defun gnus-string-equal (x y) | |
1190 "Like `string-equal', except it compares case-insensitively." | |
1191 (and (= (length x) (length y)) | |
1192 (or (string-equal x y) | |
1193 (string-equal (downcase x) (downcase y))))) | |
1194 | |
1195 (defcustom gnus-use-byte-compile t | |
1196 "If non-nil, byte-compile crucial run-time code. | |
1197 Setting it to nil has no effect after the first time `gnus-byte-compile' | |
1198 is run." | |
1199 :type 'boolean | |
1200 :version "22.1" | |
1201 :group 'gnus-various) | |
1202 | |
1203 (defun gnus-byte-compile (form) | |
1204 "Byte-compile FORM if `gnus-use-byte-compile' is non-nil." | |
1205 (if gnus-use-byte-compile | |
1206 (progn | |
1207 (condition-case nil | |
1208 ;; Work around a bug in XEmacs 21.4 | |
1209 (require 'byte-optimize) | |
1210 (error)) | |
1211 (require 'bytecomp) | |
1212 (defalias 'gnus-byte-compile | |
1213 (lambda (form) | |
1214 (let ((byte-compile-warnings '(unresolved callargs redefine))) | |
1215 (byte-compile form)))) | |
1216 (gnus-byte-compile form)) | |
1217 form)) | |
1218 | |
1219 (defun gnus-remassoc (key alist) | |
1220 "Delete by side effect any elements of LIST whose car is `equal' to KEY. | |
1221 The modified LIST is returned. If the first member | |
1222 of LIST has a car that is `equal' to KEY, there is no way to remove it | |
1223 by side effect; therefore, write `(setq foo (gnus-remassoc key foo))' to be | |
1224 sure of changing the value of `foo'." | |
1225 (when alist | |
1226 (if (equal key (caar alist)) | |
1227 (cdr alist) | |
1228 (setcdr alist (gnus-remassoc key (cdr alist))) | |
1229 alist))) | |
1230 | |
1231 (defun gnus-update-alist-soft (key value alist) | |
1232 (if value | |
1233 (cons (cons key value) (gnus-remassoc key alist)) | |
1234 (gnus-remassoc key alist))) | |
1235 | |
1236 (defun gnus-create-info-command (node) | |
1237 "Create a command that will go to info NODE." | |
1238 `(lambda () | |
1239 (interactive) | |
1240 ,(concat "Enter the info system at node " node) | |
1241 (Info-goto-node ,node) | |
1242 (setq gnus-info-buffer (current-buffer)) | |
1243 (gnus-configure-windows 'info))) | |
1244 | |
1245 (defun gnus-not-ignore (&rest args) | |
1246 t) | |
1247 | |
41494
933ab100fb4a
2001-11-25 ShengHuo ZHU <zsh@cs.rochester.edu>
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
38861
diff
changeset
|
1248 (defvar gnus-directory-sep-char-regexp "/" |
933ab100fb4a
2001-11-25 ShengHuo ZHU <zsh@cs.rochester.edu>
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
38861
diff
changeset
|
1249 "The regexp of directory separator character. |
933ab100fb4a
2001-11-25 ShengHuo ZHU <zsh@cs.rochester.edu>
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
38861
diff
changeset
|
1250 If you find some problem with the directory separator character, try |
933ab100fb4a
2001-11-25 ShengHuo ZHU <zsh@cs.rochester.edu>
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
38861
diff
changeset
|
1251 \"[/\\\\\]\" for some systems.") |
933ab100fb4a
2001-11-25 ShengHuo ZHU <zsh@cs.rochester.edu>
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
38861
diff
changeset
|
1252 |
88155 | 1253 (defun gnus-url-unhex (x) |
1254 (if (> x ?9) | |
1255 (if (>= x ?a) | |
1256 (+ 10 (- x ?a)) | |
1257 (+ 10 (- x ?A))) | |
1258 (- x ?0))) | |
1259 | |
1260 ;; Fixme: Do it like QP. | |
1261 (defun gnus-url-unhex-string (str &optional allow-newlines) | |
1262 "Remove %XX, embedded spaces, etc in a url. | |
1263 If optional second argument ALLOW-NEWLINES is non-nil, then allow the | |
1264 decoding of carriage returns and line feeds in the string, which is normally | |
1265 forbidden in URL encoding." | |
1266 (let ((tmp "") | |
1267 (case-fold-search t)) | |
1268 (while (string-match "%[0-9a-f][0-9a-f]" str) | |
1269 (let* ((start (match-beginning 0)) | |
1270 (ch1 (gnus-url-unhex (elt str (+ start 1)))) | |
1271 (code (+ (* 16 ch1) | |
1272 (gnus-url-unhex (elt str (+ start 2)))))) | |
1273 (setq tmp (concat | |
1274 tmp (substring str 0 start) | |
1275 (cond | |
1276 (allow-newlines | |
1277 (char-to-string code)) | |
1278 ((or (= code ?\n) (= code ?\r)) | |
1279 " ") | |
1280 (t (char-to-string code)))) | |
1281 str (substring str (match-end 0))))) | |
1282 (setq tmp (concat tmp str)) | |
1283 tmp)) | |
1284 | |
1285 (defun gnus-make-predicate (spec) | |
1286 "Transform SPEC into a function that can be called. | |
1287 SPEC is a predicate specifier that contains stuff like `or', `and', | |
1288 `not', lists and functions. The functions all take one parameter." | |
1289 `(lambda (elem) ,(gnus-make-predicate-1 spec))) | |
1290 | |
1291 (defun gnus-make-predicate-1 (spec) | |
1292 (cond | |
1293 ((symbolp spec) | |
1294 `(,spec elem)) | |
1295 ((listp spec) | |
1296 (if (memq (car spec) '(or and not)) | |
1297 `(,(car spec) ,@(mapcar 'gnus-make-predicate-1 (cdr spec))) | |
1298 (error "Invalid predicate specifier: %s" spec))))) | |
1299 | |
1300 (defun gnus-local-map-property (map) | |
1301 "Return a list suitable for a text property list specifying keymap MAP." | |
1302 (cond | |
1303 ((featurep 'xemacs) | |
1304 (list 'keymap map)) | |
1305 ((>= emacs-major-version 21) | |
1306 (list 'keymap map)) | |
1307 (t | |
1308 (list 'local-map map)))) | |
1309 | |
1310 (defmacro gnus-completing-read-maybe-default (prompt table &optional predicate | |
1311 require-match initial-contents | |
1312 history default) | |
1313 "Like `completing-read', allowing for non-existent 7th arg in older XEmacsen." | |
1314 `(completing-read ,prompt ,table ,predicate ,require-match | |
1315 ,initial-contents ,history | |
1316 ,@(if (and (featurep 'xemacs) (< emacs-minor-version 2)) | |
1317 () | |
1318 (list default)))) | |
1319 | |
1320 (defun gnus-completing-read (prompt table &optional predicate require-match | |
1321 history) | |
1322 (when (and history | |
1323 (not (boundp history))) | |
1324 (set history nil)) | |
1325 (gnus-completing-read-maybe-default | |
1326 (if (symbol-value history) | |
1327 (concat prompt " (" (car (symbol-value history)) "): ") | |
1328 (concat prompt ": ")) | |
1329 table | |
1330 predicate | |
1331 require-match | |
1332 nil | |
1333 history | |
1334 (car (symbol-value history)))) | |
1335 | |
1336 (defun gnus-graphic-display-p () | |
1337 (or (and (fboundp 'display-graphic-p) | |
1338 (display-graphic-p)) | |
1339 ;;;!!!This is bogus. Fixme! | |
1340 (and (featurep 'xemacs) | |
1341 t))) | |
1342 | |
1343 (put 'gnus-parse-without-error 'lisp-indent-function 0) | |
1344 (put 'gnus-parse-without-error 'edebug-form-spec '(body)) | |
1345 | |
1346 (defmacro gnus-parse-without-error (&rest body) | |
1347 "Allow continuing onto the next line even if an error occurs." | |
1348 `(while (not (eobp)) | |
1349 (condition-case () | |
1350 (progn | |
1351 ,@body | |
1352 (goto-char (point-max))) | |
1353 (error | |
1354 (gnus-error 4 "Invalid data on line %d" | |
1355 (count-lines (point-min) (point))) | |
1356 (forward-line 1))))) | |
1357 | |
1358 (defun gnus-cache-file-contents (file variable function) | |
1359 "Cache the contents of FILE in VARIABLE. The contents come from FUNCTION." | |
1360 (let ((time (nth 5 (file-attributes file))) | |
1361 contents value) | |
1362 (if (or (null (setq value (symbol-value variable))) | |
1363 (not (equal (car value) file)) | |
1364 (not (equal (nth 1 value) time))) | |
1365 (progn | |
1366 (setq contents (funcall function file)) | |
1367 (set variable (list file time contents)) | |
1368 contents) | |
1369 (nth 2 value)))) | |
1370 | |
1371 (defun gnus-multiple-choice (prompt choice &optional idx) | |
1372 "Ask user a multiple choice question. | |
1373 CHOICE is a list of the choice char and help message at IDX." | |
1374 (let (tchar buf) | |
1375 (save-window-excursion | |
1376 (save-excursion | |
1377 (while (not tchar) | |
1378 (message "%s (%s): " | |
1379 prompt | |
1380 (concat | |
1381 (mapconcat (lambda (s) (char-to-string (car s))) | |
1382 choice ", ") ", ?")) | |
1383 (setq tchar (read-char)) | |
1384 (when (not (assq tchar choice)) | |
1385 (setq tchar nil) | |
1386 (setq buf (get-buffer-create "*Gnus Help*")) | |
1387 (pop-to-buffer buf) | |
1388 (fundamental-mode) ; for Emacs 20.4+ | |
1389 (buffer-disable-undo) | |
1390 (erase-buffer) | |
1391 (insert prompt ":\n\n") | |
1392 (let ((max -1) | |
1393 (list choice) | |
1394 (alist choice) | |
1395 (idx (or idx 1)) | |
1396 (i 0) | |
1397 n width pad format) | |
1398 ;; find the longest string to display | |
1399 (while list | |
1400 (setq n (length (nth idx (car list)))) | |
1401 (unless (> max n) | |
1402 (setq max n)) | |
1403 (setq list (cdr list))) | |
1404 (setq max (+ max 4)) ; %c, `:', SPACE, a SPACE at end | |
1405 (setq n (/ (1- (window-width)) max)) ; items per line | |
1406 (setq width (/ (1- (window-width)) n)) ; width of each item | |
1407 ;; insert `n' items, each in a field of width `width' | |
1408 (while alist | |
1409 (if (< i n) | |
1410 () | |
1411 (setq i 0) | |
1412 (delete-char -1) ; the `\n' takes a char | |
1413 (insert "\n")) | |
1414 (setq pad (- width 3)) | |
1415 (setq format (concat "%c: %-" (int-to-string pad) "s")) | |
1416 (insert (format format (caar alist) (nth idx (car alist)))) | |
1417 (setq alist (cdr alist)) | |
1418 (setq i (1+ i)))))))) | |
1419 (if (buffer-live-p buf) | |
1420 (kill-buffer buf)) | |
1421 tchar)) | |
1422 | |
1423 (defun gnus-select-frame-set-input-focus (frame) | |
1424 "Select FRAME, raise it, and set input focus, if possible." | |
1425 (cond ((featurep 'xemacs) | |
1426 (raise-frame frame) | |
1427 (select-frame frame) | |
1428 (focus-frame frame)) | |
1429 ;; The function `select-frame-set-input-focus' won't set | |
1430 ;; the input focus under Emacs 21.2 and X window system. | |
1431 ;;((fboundp 'select-frame-set-input-focus) | |
1432 ;; (defalias 'gnus-select-frame-set-input-focus | |
1433 ;; 'select-frame-set-input-focus) | |
1434 ;; (select-frame-set-input-focus frame)) | |
1435 (t | |
1436 (raise-frame frame) | |
1437 (select-frame frame) | |
1438 (cond ((and (eq window-system 'x) | |
1439 (fboundp 'x-focus-frame)) | |
1440 (x-focus-frame frame)) | |
1441 ((eq window-system 'w32) | |
1442 (w32-focus-frame frame))) | |
1443 (when focus-follows-mouse | |
1444 (set-mouse-position frame (1- (frame-width frame)) 0))))) | |
1445 | |
1446 (defun gnus-frame-or-window-display-name (object) | |
1447 "Given a frame or window, return the associated display name. | |
1448 Return nil otherwise." | |
1449 (if (featurep 'xemacs) | |
1450 (device-connection (dfw-device object)) | |
1451 (if (or (framep object) | |
1452 (and (windowp object) | |
1453 (setq object (window-frame object)))) | |
1454 (let ((display (frame-parameter object 'display))) | |
1455 (if (and (stringp display) | |
1456 ;; Exclude invalid display names. | |
1457 (string-match "\\`[^:]*:[0-9]+\\(\\.[0-9]+\\)?\\'" | |
1458 display)) | |
1459 display))))) | |
1460 | |
1461 ;; Fixme: This has only one use (in gnus-agent), which isn't worthwhile. | |
1462 (defmacro gnus-mapcar (function seq1 &rest seqs2_n) | |
1463 "Apply FUNCTION to each element of the sequences, and make a list of the results. | |
1464 If there are several sequences, FUNCTION is called with that many arguments, | |
1465 and mapping stops as soon as the shortest sequence runs out. With just one | |
1466 sequence, this is like `mapcar'. With several, it is like the Common Lisp | |
1467 `mapcar' function extended to arbitrary sequence types." | |
1468 | |
1469 (if seqs2_n | |
1470 (let* ((seqs (cons seq1 seqs2_n)) | |
1471 (cnt 0) | |
1472 (heads (mapcar (lambda (seq) | |
1473 (make-symbol (concat "head" | |
1474 (int-to-string | |
1475 (setq cnt (1+ cnt)))))) | |
1476 seqs)) | |
1477 (result (make-symbol "result")) | |
1478 (result-tail (make-symbol "result-tail"))) | |
1479 `(let* ,(let* ((bindings (cons nil nil)) | |
1480 (heads heads)) | |
1481 (nconc bindings (list (list result '(cons nil nil)))) | |
1482 (nconc bindings (list (list result-tail result))) | |
1483 (while heads | |
1484 (nconc bindings (list (list (pop heads) (pop seqs))))) | |
1485 (cdr bindings)) | |
1486 (while (and ,@heads) | |
1487 (setcdr ,result-tail (cons (funcall ,function | |
1488 ,@(mapcar (lambda (h) (list 'car h)) | |
1489 heads)) | |
1490 nil)) | |
1491 (setq ,result-tail (cdr ,result-tail) | |
1492 ,@(apply 'nconc (mapcar (lambda (h) (list h (list 'cdr h))) heads)))) | |
1493 (cdr ,result))) | |
1494 `(mapcar ,function ,seq1))) | |
1495 | |
1496 (if (fboundp 'merge) | |
1497 (defalias 'gnus-merge 'merge) | |
1498 ;; Adapted from cl-seq.el | |
1499 (defun gnus-merge (type list1 list2 pred) | |
1500 "Destructively merge lists LIST1 and LIST2 to produce a new list. | |
1501 Argument TYPE is for compatibility and ignored. | |
1502 Ordering of the elements is preserved according to PRED, a `less-than' | |
1503 predicate on the elements." | |
1504 (let ((res nil)) | |
1505 (while (and list1 list2) | |
1506 (if (funcall pred (car list2) (car list1)) | |
1507 (push (pop list2) res) | |
1508 (push (pop list1) res))) | |
1509 (nconc (nreverse res) list1 list2)))) | |
1510 | |
1511 (eval-when-compile | |
1512 (defvar xemacs-codename) | |
1513 (defvar sxemacs-codename) | |
1514 (defvar emacs-program-version)) | |
1515 | |
1516 (defun gnus-emacs-version () | |
1517 "Stringified Emacs version." | |
1518 (let* ((lst (if (listp gnus-user-agent) | |
1519 gnus-user-agent | |
1520 '(gnus emacs type))) | |
1521 (system-v (cond ((memq 'config lst) | |
1522 system-configuration) | |
1523 ((memq 'type lst) | |
1524 (symbol-name system-type)) | |
1525 (t nil))) | |
1526 codename emacsname) | |
1527 (cond ((featurep 'sxemacs) | |
1528 (setq emacsname "SXEmacs" | |
1529 codename sxemacs-codename)) | |
1530 ((featurep 'xemacs) | |
1531 (setq emacsname "XEmacs" | |
1532 codename xemacs-codename)) | |
1533 (t | |
1534 (setq emacsname "Emacs"))) | |
1535 (cond | |
1536 ((not (memq 'emacs lst)) | |
1537 nil) | |
1538 ((string-match "^\\(\\([.0-9]+\\)*\\)\\.[0-9]+$" emacs-version) | |
1539 ;; Emacs: | |
1540 (concat "Emacs/" (match-string 1 emacs-version) | |
1541 (if system-v | |
1542 (concat " (" system-v ")") | |
1543 ""))) | |
1544 ((or (featurep 'sxemacs) (featurep 'xemacs)) | |
1545 ;; XEmacs or SXEmacs: | |
1546 (concat emacsname "/" emacs-program-version | |
1547 " (" | |
1548 (when (and (memq 'codename lst) | |
1549 codename) | |
1550 (concat codename | |
1551 (when system-v ", "))) | |
1552 (when system-v system-v) | |
1553 ")")) | |
1554 (t emacs-version)))) | |
1555 | |
1556 (defun gnus-rename-file (old-path new-path &optional trim) | |
1557 "Rename OLD-PATH as NEW-PATH. If TRIM, recursively delete | |
1558 empty directories from OLD-PATH." | |
1559 (when (file-exists-p old-path) | |
1560 (let* ((old-dir (file-name-directory old-path)) | |
1561 (old-name (file-name-nondirectory old-path)) | |
1562 (new-dir (file-name-directory new-path)) | |
1563 (new-name (file-name-nondirectory new-path)) | |
1564 temp) | |
1565 (gnus-make-directory new-dir) | |
1566 (rename-file old-path new-path t) | |
1567 (when trim | |
1568 (while (progn (setq temp (directory-files old-dir)) | |
1569 (while (member (car temp) '("." "..")) | |
1570 (setq temp (cdr temp))) | |
1571 (= (length temp) 0)) | |
1572 (delete-directory old-dir) | |
1573 (setq old-dir (file-name-as-directory | |
1574 (file-truename | |
1575 (concat old-dir ".."))))))))) | |
1576 | |
1577 (if (fboundp 'set-process-query-on-exit-flag) | |
1578 (defalias 'gnus-set-process-query-on-exit-flag | |
1579 'set-process-query-on-exit-flag) | |
1580 (defalias 'gnus-set-process-query-on-exit-flag | |
1581 'process-kill-without-query)) | |
1582 | |
17493 | 1583 (provide 'gnus-util) |
1584 | |
88155 | 1585 ;;; arch-tag: f94991af-d32b-4c97-8c26-ca12a934de49 |
17493 | 1586 ;;; gnus-util.el ends here |