;;; gnus-util.el --- utility functions for Gnus
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;; 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2011 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
(eval-when-compile
(require 'cl))
-(eval-when-compile
- (unless (fboundp 'with-no-warnings)
- (defmacro with-no-warnings (&rest body)
- `(progn ,@body))))
+(require 'time-date)
(defcustom gnus-completing-read-function 'gnus-emacs-completing-read
"Function use to do completing read."
(setq start (when end
(next-single-property-change start prop))))))
+(defun gnus-find-text-property-region (start end prop)
+ "Return a list of text property regions that has property PROP."
+ (let (regions value)
+ (unless (get-text-property start prop)
+ (setq start (next-single-property-change start prop)))
+ (while start
+ (setq value (get-text-property start prop)
+ end (text-property-not-all start (point-max) prop value))
+ (if (not end)
+ (setq start nil)
+ (when value
+ (push (list (set-marker (make-marker) start)
+ (set-marker (make-marker) end)
+ value)
+ regions))
+ (setq start (next-single-property-change start prop))))
+ (nreverse regions)))
+
(defun gnus-newsgroup-directory-form (newsgroup)
"Make hierarchical directory name from NEWSGROUP name."
(let* ((newsgroup (gnus-newsgroup-savable-name newsgroup))
(and (= (car fdate) (car date))
(> (nth 1 fdate) (nth 1 date))))))
+;; Every version of Emacs Gnus supports has built-in float-time.
+;; The featurep test silences an irritating compiler warning.
(eval-and-compile
- (if (and (fboundp 'float-time)
- (subrp (symbol-function 'float-time)))
+ (if (or (featurep 'emacs)
+ (fboundp 'float-time))
(defalias 'gnus-float-time 'float-time)
(defun gnus-float-time (&optional time)
"Convert time value TIME to a floating point number.
TIME defaults to the current time."
- (with-no-warnings (time-to-seconds (or time (current-time)))))))
+ (time-to-seconds (or time (current-time))))))
;;; Keymap macros.
(put-text-property 0 1 'gnus-time time d)
time)))))
-(defvar gnus-user-date-format-alist
- '(((gnus-seconds-today) . "%k:%M")
- (604800 . "%a %k:%M") ;;that's one week
- ((gnus-seconds-month) . "%a %d")
- ((gnus-seconds-year) . "%b %d")
- (t . "%b %d '%y")) ;;this one is used when no
- ;;other does match
- "Specifies date format depending on age of article.
-This is an alist of items (AGE . FORMAT). AGE can be a number (of
-seconds) or a Lisp expression evaluating to a number. When the age of
-the article is less than this number, then use `format-time-string'
-with the corresponding FORMAT for displaying the date of the article.
-If AGE is not a number or a Lisp expression evaluating to a
-non-number, then the corresponding FORMAT is used as a default value.
-
-Note that the list is processed from the beginning, so it should be
-sorted by ascending AGE. Also note that items following the first
-non-number AGE will be ignored.
-
-You can use the functions `gnus-seconds-today', `gnus-seconds-month'
-and `gnus-seconds-year' in the AGE spec. They return the number of
-seconds passed since the start of today, of this month, of this year,
-respectively.")
-
-(defun gnus-user-date (messy-date)
- "Format the messy-date according to gnus-user-date-format-alist.
-Returns \" ? \" if there's bad input or if another error occurs.
-Input should look like this: \"Sun, 14 Oct 2001 13:34:39 +0200\"."
- (condition-case ()
- (let* ((messy-date (gnus-float-time (gnus-date-get-time messy-date)))
- (now (gnus-float-time))
- ;;If we don't find something suitable we'll use this one
- (my-format "%b %d '%y"))
- (let* ((difference (- now messy-date))
- (templist gnus-user-date-format-alist)
- (top (eval (caar templist))))
- (while (if (numberp top) (< top difference) (not top))
- (progn
- (setq templist (cdr templist))
- (setq top (eval (caar templist)))))
- (if (stringp (cdr (car templist)))
- (setq my-format (cdr (car templist)))))
- (format-time-string (eval my-format) (seconds-to-time messy-date)))
- (error " ? ")))
-
(defun gnus-dd-mmm (messy-date)
"Return a string like DD-MMM from a big messy string."
(condition-case ()
(defun gnus-write-buffer (file)
"Write the current buffer's contents to FILE."
+ (require 'nnmail)
(let ((file-name-coding-system nnmail-pathname-coding-system))
;; Make sure the directory exists.
(gnus-make-directory (file-name-directory file))
FILENAME exists and is Babyl format."
(require 'rmail)
(require 'mm-util)
+ (require 'nnmail)
;; Some of this codes is borrowed from rmailout.el.
(setq filename (expand-file-name filename))
;; FIXME should we really be messing with this defcustom?
(defun gnus-output-to-mail (filename &optional ask)
"Append the current article to a mail file named FILENAME."
+ (require 'nnmail)
(setq filename (expand-file-name filename))
(let ((artbuf (current-buffer))
(tmpbuf (get-buffer-create " *Gnus-output*")))
initial-input history def))
-(autoload 'iswitchb-read-buffer "iswitchb")
+(declare-function iswitchb-read-buffer "iswitchb"
+ (prompt &optional default require-match start matches-set))
+(defvar iswitchb-temp-buflist)
+
(defun gnus-iswitchb-completing-read (prompt collection &optional require-match
initial-input history def)
"`iswitchb' based completing-read function."
+ ;; Make sure iswitchb is loaded before we let-bind its variables.
+ ;; If it is loaded inside the let, variables can become unbound afterwards.
+ (require 'iswitchb)
(let ((iswitchb-make-buflist-hook
(lambda ()
(setq iswitchb-temp-buflist
(nreverse filtered-choices))))))
(unwind-protect
(progn
- (when (not iswitchb-mode)
- (add-hook 'minibuffer-setup-hook 'iswitchb-minibuffer-setup))
+ (or iswitchb-mode
+ (add-hook 'minibuffer-setup-hook 'iswitchb-minibuffer-setup))
(iswitchb-read-buffer prompt def require-match))
- (when (not iswitchb-mode)
- (remove-hook 'minibuffer-setup-hook 'iswitchb-minibuffer-setup)))))
+ (or iswitchb-mode
+ (remove-hook 'minibuffer-setup-hook 'iswitchb-minibuffer-setup)))))
(defun gnus-graphic-display-p ()
(if (featurep 'xemacs)
(kill-buffer buf))
tchar))
-(if (fboundp 'select-frame-set-input-focus)
+(if (featurep 'emacs)
(defalias 'gnus-select-frame-set-input-focus 'select-frame-set-input-focus)
- ;; XEmacs 21.4, SXEmacs
- (defun gnus-select-frame-set-input-focus (frame)
- "Select FRAME, raise it, and set input focus, if possible."
- (raise-frame frame)
- (select-frame frame)
- (focus-frame frame)))
+ (if (fboundp 'select-frame-set-input-focus)
+ (defalias 'gnus-select-frame-set-input-focus 'select-frame-set-input-focus)
+ ;; XEmacs 21.4, SXEmacs
+ (defun gnus-select-frame-set-input-focus (frame)
+ "Select FRAME, raise it, and set input focus, if possible."
+ (raise-frame frame)
+ (select-frame frame)
+ (focus-frame frame))))
(defun gnus-frame-or-window-display-name (object)
"Given a frame or window, return the associated display name.
(defalias 'gnus-set-process-query-on-exit-flag
'process-kill-without-query))
-(if (fboundp 'with-local-quit)
- (defalias 'gnus-with-local-quit 'with-local-quit)
- (defmacro gnus-with-local-quit (&rest body)
- "Execute BODY, allowing quits to terminate BODY but not escape further.
-When a quit terminates BODY, `gnus-with-local-quit' returns nil but
-requests another quit. That quit will be processed as soon as quitting
-is allowed once again. (Immediately, if `inhibit-quit' is nil.)"
- ;;(declare (debug t) (indent 0))
- `(condition-case nil
- (let ((inhibit-quit nil))
- ,@body)
- (quit (setq quit-flag t)
- ;; This call is to give a chance to handle quit-flag
- ;; in case inhibit-quit is nil.
- ;; Without this, it will not be handled until the next function
- ;; call, and that might allow it to exit thru a condition-case
- ;; that intends to handle the quit signal next time.
- (eval '(ignore nil))))))
-
(defalias 'gnus-read-shell-command
(if (fboundp 'read-shell-command) 'read-shell-command 'read-string))
image)))
image)))
+(defun gnus-list-memq-of-list (elements list)
+ "Return non-nil if any of the members of ELEMENTS are in LIST."
+ (let ((found nil))
+ (dolist (elem elements)
+ (setq found (or found
+ (memq elem list))))
+ found))
+
+(eval-and-compile
+ (cond
+ ((fboundp 'match-substitute-replacement)
+ (defalias 'gnus-match-substitute-replacement 'match-substitute-replacement))
+ (t
+ (defun gnus-match-substitute-replacement (replacement &optional fixedcase literal string subexp)
+ "Return REPLACEMENT as it will be inserted by `replace-match'.
+In other words, all back-references in the form `\\&' and `\\N'
+are substituted with actual strings matched by the last search.
+Optional FIXEDCASE, LITERAL, STRING and SUBEXP have the same
+meaning as for `replace-match'.
+
+This is the definition of match-substitute-replacement in subr.el from GNU Emacs."
+ (let ((match (match-string 0 string)))
+ (save-match-data
+ (set-match-data (mapcar (lambda (x)
+ (if (numberp x)
+ (- x (match-beginning 0))
+ x))
+ (match-data t)))
+ (replace-match replacement fixedcase literal match subexp)))))))
+
+(if (fboundp 'string-match-p)
+ (defalias 'gnus-string-match-p 'string-match-p)
+ (defsubst gnus-string-match-p (regexp string &optional start)
+ "\
+Same as `string-match' except this function does not change the match data."
+ (save-match-data
+ (string-match regexp string start))))
+
+(eval-and-compile
+ (if (fboundp 'macroexpand-all)
+ (defalias 'gnus-macroexpand-all 'macroexpand-all)
+ (defun gnus-macroexpand-all (form &optional environment)
+ "Return result of expanding macros at all levels in FORM.
+If no macros are expanded, FORM is returned unchanged.
+The second optional arg ENVIRONMENT specifies an environment of macro
+definitions to shadow the loaded ones for use in file byte-compilation."
+ (if (consp form)
+ (let ((idx 1)
+ (len (length (setq form (copy-sequence form))))
+ expanded)
+ (while (< idx len)
+ (setcar (nthcdr idx form) (gnus-macroexpand-all (nth idx form)
+ environment))
+ (setq idx (1+ idx)))
+ (if (eq (setq expanded (macroexpand form environment)) form)
+ form
+ (gnus-macroexpand-all expanded environment)))
+ form))))
+
(provide 'gnus-util)
;;; gnus-util.el ends here