+Thu Aug 8 01:36:34 1996 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+
+ * gnus.el: Red Gnus v0.7 is released.
+
+Thu Aug 8 01:29:56 1996 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+
+ * message.el (message-deletable-headers): Have Lines be
+ deletable.
+
+Wed Aug 7 23:41:26 1996 Richard Pieri <ratinox@unilab.dfci.harvard.edu>
+
+ * gnus.el (gnus-short-group-name): New version.
+
+Wed Aug 7 19:55:25 1996 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+
+ * gnus-start.el (gnus-declare-backend): New function.
+
+ * gnus-xmas.el (gnus-xmas-pointer-glyph): New variable.
+ (gnus-xmas-modeline-glyph): New variable.
+ (gnus-xmas-mode-line-buffer-identification): New definition.
+
+ * nntp.el (nntp-request-article): Would sometimes return nil
+ falsely.
+ (nntp-find-group-and-number): Saved function.
+ (nntp-request-article): Use it.
+ (nntp-request-head): Saved.
+
+ * gnus-dup.el (gnus-dup-suppress-articles): Message.
+
+ * gnus-group.el (gnus-group-mark-group): Used string instead of
+ char.
+
+Wed Aug 7 02:52:55 1996 Lars Magne Ingebrigtsen <lars@eyesore.no>
+
+ * gnus-util.el: Use `format-time-string'.
+
+ * gnus-sum.el (gnus-summary-edit-article-postpone): Defined
+ again.
+
+ * article.el (article-make-date-line): Would say "unknown" on
+ "now" dates.
+
+Wed Aug 7 02:48:12 1996 Katsumi Yamaoka <yamaoka@ga.sony.co.jp>
+
+ * message.el (message-rename-buffer): Set proper outsave name.
+
+Wed Aug 7 00:28:44 1996 Lars Magne Ingebrigtsen <lars@eyesore.no>
+
+ * nnheader.el (nnheader-temp-write): Always use
+ `fundamental-mode'.
+
+ * gnus-util.el (gnus-date-iso8601): Illegal format.
+
+ * gnus-group.el (gnus-group-make-doc-group): Full name in server
+ name.
+
+ * gnus-undo.el (gnus-undo): Typo.
+
+ * gnus-group.el (gnus-group-mark-group): Don't touch props.
+
+ * gnus-score.el (gnus-score-headers): Don't root out 0 scores when
+ saving.
+
+ * gnus-art.el (gnus-narrow-to-page): Don't do a "next-page" if
+ `^L' is the last char.
+
+ * gnus.el (gnus): Autoload.
+
+Tue Aug 6 23:00:01 1996 Lars Magne Ingebrigtsen <lars@eyesore.no>
+
+ * gnus-score.el (gnus-score-string): Wiwnd't do word and fuzzy
+ matching properly.
+
+Mon Aug 5 22:23:03 1996 Raja R. Harinath <harinath@cs.umn.edu>
+
+ * gnus-gl.el (gnus-grouplens-mode): Clear proper variables.
+
+Mon Aug 5 20:27:11 1996 Lars Magne Ingebrigtsen <lars@eyesore.no>
+
+ * gnus-art.el (gnus-article-edit-exit): Would move point.
+ (gnus-article-edit): New command.
+
+ * nnml.el (nnml-request-rename-group): Copy over .overview file.
+ (nnml-request-group): Better error message.
+
+Sat Aug 3 17:52:01 1996 Steven L Baur <steve@miranova.com>
+
+ * gnus-setup.el (message): Can't require 'message until we know
+ where the Gnus .elcs are.
+
+Mon Aug 5 20:07:11 1996 François Pinard <pinard@progiciels-bpi.ca>
+
+ * gnus-util.el (gnus-date-iso8601): New function.
+
+Mon Aug 5 19:14:12 1996 Lars Magne Ingebrigtsen <lars@eyesore.no>
+
+ * gnus-sum.el (gnus-summary-search-article-forward): Show thread
+ when finding matches.
+
+ * nnmail.el (nnmail-get-spool-files): Sort procmail files.
+
+Mon Aug 5 02:25:06 1996 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+
+ * gnus.el: Red Gnus v0.6 is released.
+
Mon Aug 5 01:12:24 1996 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
* nntp.el (nntp-request-type): Defined again.
(gnus-encode-date
(timezone-make-date-arpa-standard
date nil "UT")))
- (error '(0 0))))
- (real-sec (+ (* (float (car real-time)) 65536)
- (cadr real-time)))
- (sec (abs real-sec))
+ (error nil)))
+ (real-sec (and real-time
+ (+ (* (float (car real-time)) 65536)
+ (cadr real-time))))
+ (sec (and real-time (abs real-sec)))
num prev)
(cond
- ((equal real-time '(0 0))
+ ((null real-time)
"X-Sent: Unknown\n")
((zerop sec)
"X-Sent: Now\n")
"\r" gnus-article-press-button
"\t" gnus-article-next-button
"\M-\t" gnus-article-prev-button
+ "e" gnus-article-edit
"<" beginning-of-buffer
">" end-of-buffer
"\C-c\C-i" gnus-info-find-node
(set-buffer gnus-article-buffer)
(goto-char (point-min))
(widen)
+ ;; Remove any old next/prev buttons.
(when (gnus-visual-p 'page-marker)
(let ((buffer-read-only nil))
(gnus-remove-text-with-property 'gnus-prev)
(goto-char (point-min))
(gnus-insert-prev-page-button)))
(when (and (gnus-visual-p 'page-marker)
- (not (= (1- (point-max)) (buffer-size))))
+ (< (+ (point-max) 2) (buffer-size)))
(save-excursion
(goto-char (point-max))
(gnus-insert-next-page-button)))))
(widen)
(run-hooks 'text-mode 'gnus-article-edit-mode-hook))
+(defun gnus-article-edit (&optional force)
+ "Edit the current article.
+This will have permanent effect only in mail groups.
+If FORCE is non-nil, allow editing of articles even in read-only
+groups."
+ (interactive "P")
+ (when (and (not force)
+ (gnus-group-read-only-p))
+ (error "The current newsgroup does not support article editing."))
+ (gnus-article-edit-article
+ `(lambda ()
+ (gnus-summary-edit-article-done
+ ,(or (mail-header-references gnus-current-headers) "")
+ ,(gnus-group-read-only-p) ,gnus-summary-buffer))))
+
(defun gnus-article-edit-article (exit-func)
"Start editing the contents of the current article buffer."
(let ((winconf (current-window-configuration)))
"Update the article edits and exit."
(interactive)
(let ((func gnus-article-edit-done-function)
- (buf (current-buffer)))
+ (buf (current-buffer))
+ (start (window-start)))
(gnus-article-edit-exit)
- (save-excursion
+ (let ((cur (current-buffer)))
+ (save-excursion
+ (set-buffer buf)
+ (let ((buffer-read-only nil))
+ (funcall func)))
(set-buffer buf)
- (let ((buffer-read-only nil))
- (funcall func)))))
+ (set-window-start (get-buffer-window buf) start)
+ (set-window-point (get-buffer-window buf) (point)))))
(defun gnus-article-edit-exit ()
"Exit the article editing without updating."
(interactive)
- ;; We remove all text props from the article buffer.
- (let ((buf (format "%s" (buffer-string)))
- (p (point))
- (window-start (window-start)))
- (erase-buffer)
- (insert buf)
+ ;; We remove all text props from the article buffer.
+ (let ((buf (format "%s" (buffer-string)))
+ (curbuf (current-buffer))
+ (p (point))
+ (window-start (window-start)))
+ (erase-buffer)
+ (insert buf)
+ (let ((winconf gnus-prev-winconf))
+ (gnus-article-mode)
+ ;; The cache and backlog have to be flushed somewhat.
+ (when gnus-use-cache
+ (gnus-cache-update-article
+ (car gnus-article-current) (cdr gnus-article-current)))
+ (when gnus-keep-backlog
+ (gnus-backlog-remove-article
+ (car gnus-article-current) (cdr gnus-article-current)))
+ ;; Flush original article as well.
+ (save-excursion
+ (when (get-buffer gnus-original-article-buffer)
+ (set-buffer gnus-original-article-buffer)
+ (setq gnus-original-article nil)))
+ (set-window-configuration winconf)
+ ;; Tippy-toe some to make sure that point remains where it was.
+ (let ((buf (current-buffer)))
+ (set-buffer curbuf)
+ (set-window-start (get-buffer-window (current-buffer)) window-start)
(goto-char p)
- (set-window-start (selected-window) window-start))
- (let ((winconf gnus-prev-winconf))
- (gnus-article-mode)
- ;; The cache and backlog have to be flushed somewhat.
- (when gnus-use-cache
- (gnus-cache-update-article
- (car gnus-article-current) (cdr gnus-article-current)))
- (when gnus-keep-backlog
- (gnus-backlog-remove-article
- (car gnus-article-current) (cdr gnus-article-current)))
- ;; Flush original article as well.
- (save-excursion
- (when (get-buffer gnus-original-article-buffer)
- (set-buffer gnus-original-article-buffer)
- (setq gnus-original-article nil)))
- (set-window-configuration winconf)))
+ (set-buffer buf)))))
(defun gnus-article-edit-full-stops ()
"Interactively repair spacing at end of sentences."
"Mark duplicate articles as read."
(unless gnus-dup-list
(gnus-dup-open))
+ (gnus-message 6 "Suppressing duplicates...")
(let ((headers gnus-newsgroup-headers)
number)
(while headers
gnus-newsgroup-unreads))
(push (cons number gnus-duplicate-mark)
gnus-newsgroup-reads))
- (pop headers))))
+ (pop headers)))
+ (gnus-message 6 "Suppressing duplicates...done"))
(provide 'gnus-dup)
(while (and (> n 0)
(not (eobp)))
(when (setq group (gnus-group-group-name))
- ;; Update the mark.
+ ;; Go to the mark position.
(beginning-of-line)
- (forward-char
- (or (cdr (assq 'process gnus-group-mark-positions)) 2))
- (delete-char 1)
- (if unmark
- (progn
- (insert " ")
- (setq gnus-group-marked (delete group gnus-group-marked)))
- (insert "#")
- (setq gnus-group-marked
- (cons group (delete group gnus-group-marked)))))
- (or no-advance (gnus-group-next-group 1))
+ (forward-char (or (cdr (assq 'process gnus-group-mark-positions)) 2))
+ (subst-char-in-region
+ (point) (1+ (point)) (following-char)
+ (if unmark
+ (progn
+ (setq gnus-group-marked (delete group gnus-group-marked))
+ ? )
+ (setq gnus-group-marked
+ (cons group (delete group gnus-group-marked)))
+ gnus-process-mark)))
+ (unless no-advance
+ (gnus-group-next-group 1))
(decf n))
(gnus-summary-position-point)
n))
(interactive
(list
(read-string "Group name: ")
- (gnus-read-server "From method: ")))
+ (gnus-read-method "From method: ")))
(let* ((meth (when (and method
(not (gnus-server-equal method gnus-select-method)))
(file-name-nondirectory file) '(nndoc "")))))
(gnus-group-make-group
(gnus-group-real-name name)
- (list 'nndoc (file-name-nondirectory file)
+ (list 'nndoc file
(list 'nndoc-address file)
(list 'nndoc-article-type (or type 'guess))))))
"Move from FROM-SERVER to TO-SERVER.
Update the .newsrc.eld file to reflect the change of nntp server."
(interactive
- (list gnus-select-method (gnus-read-server "Move to method: ")))
+ (list gnus-select-method (gnus-read-method "Move to method: ")))
;; First start Gnus.
(let ((gnus-activate-level 0)
(interactive
(let ((info (gnus-get-info (gnus-group-group-name))))
(list info (gnus-find-method-for-group (gnus-info-group info))
- (gnus-read-server (format "Move group %s to method: "
+ (gnus-read-method (format "Move group %s to method: "
(gnus-info-group info))))))
(save-excursion
(gnus-move-group-to-server info from-server to-server)
;; Add articles to `gnus-newsgroup-scored'.
(while gnus-scores-articles
- (or (= gnus-summary-default-score (cdar gnus-scores-articles))
- (setq gnus-newsgroup-scored
- (cons (cons (mail-header-number
- (caar gnus-scores-articles))
- (cdar gnus-scores-articles))
- gnus-newsgroup-scored)))
+ (when (or (/= gnus-summary-default-score
+ (cdar gnus-scores-articles))
+ gnus-save-score)
+ (push (cons (mail-header-number (caar gnus-scores-articles))
+ (cdar gnus-scores-articles))
+ gnus-newsgroup-scored))
(setq gnus-scores-articles (cdr gnus-scores-articles)))
(let (score)
(t 'gnus-request-article)))
entries alist ofunc article last)
(when articles
- (while (cdr articles)
- (setq articles (cdr articles)))
- (setq last (mail-header-number (caar articles)))
- (setq articles gnus-scores-articles)
+ (setq last (mail-header-number (caar (last articles))))
;; Not all backends support partial fetching. In that case,
;; we just fetch the entire article.
- (or (gnus-check-backend-function
- (and (string-match "^gnus-" (symbol-name request-func))
- (intern (substring (symbol-name request-func)
- (match-end 0))))
- gnus-newsgroup-name)
- (progn
- (setq ofunc request-func)
- (setq request-func 'gnus-request-article)))
+ (unless (gnus-check-backend-function
+ (and (string-match "^gnus-" (symbol-name request-func))
+ (intern (substring (symbol-name request-func)
+ (match-end 0))))
+ gnus-newsgroup-name)
+ (setq ofunc request-func)
+ (setq request-func 'gnus-request-article))
(while articles
(setq article (mail-header-number (caar articles)))
(gnus-message 7 "Scoring on article %s of %s..." article last)
(when fuzzies
;; Simplify the entire buffer for easy matching.
(gnus-simplify-buffer-fuzzy)
- (while (setq kill (cadr fuzzies))
+ (while (setq kill (cadar fuzzies))
(let* ((match (nth 0 kill))
(type (nth 3 kill))
(score (or (nth 1 kill) gnus-score-interactive-default-score))
(setcdr art (+ score (cdr art))))))
(forward-line 1))
;; Update expiry date
- (if trace
- (setq entries (cdr entries))
- (cond
- ;; Permanent.
- ((null date)
- (setq fuzzies (cdr fuzzies)))
- ;; Match, update date.
- ((and found gnus-update-score-entry-dates)
- (gnus-score-set 'touched '(t) alist)
- (setcar (nthcdr 2 kill) now)
- (setq fuzzies (cdr fuzzies)))
- ;; Old entry, remove.
- ((and expire (< date expire))
- (gnus-score-set 'touched '(t) alist)
- (setcdr fuzzies (cddr fuzzies)))
- (t
- (setq fuzzies (cdr fuzzies))))))))
+ (cond
+ ;; Permanent.
+ ((null date)
+ )
+ ;; Match, update date.
+ ((and found gnus-update-score-entry-dates)
+ (gnus-score-set 'touched '(t) alist)
+ (setcar (nthcdr 2 kill) now))
+ ;; Old entry, remove.
+ ((and expire (< date expire))
+ (gnus-score-set 'touched '(t) alist)
+ (setcdr (car fuzzies) (cddar fuzzies))))
+ (setq fuzzies (cdr fuzzies)))))
(when words
;; Enter all words into the hashtb.
(let ((hashtb (gnus-make-hashtable
(* 10 (count-lines (point-min) (point-max))))))
(gnus-enter-score-words-into-hashtb hashtb)
- (while (setq kill (cadr words))
+ (while (setq kill (cadar words))
(let* ((score (or (nth 1 kill) gnus-score-interactive-default-score))
(date (nth 2 kill))
found)
(while (setq art (pop arts))
(setcdr art (+ score (cdr art))))))
;; Update expiry date
- (if trace
- (setq entries (cdr entries))
- (cond
- ;; Permanent.
- ((null date)
- (setq words (cdr words)))
- ;; Match, update date.
- ((and found gnus-update-score-entry-dates)
- (gnus-score-set 'touched '(t) alist)
- (setcar (nthcdr 2 kill) now)
- (setq words (cdr words)))
- ;; Old entry, remove.
- ((and expire (< date expire))
- (gnus-score-set 'touched '(t) alist)
- (setcdr words (cddr words)))
- (t
- (setq words (cdr words)))))))))
+ (cond
+ ;; Permanent.
+ ((null date)
+ )
+ ;; Match, update date.
+ ((and found gnus-update-score-entry-dates)
+ (gnus-score-set 'touched '(t) alist)
+ (setcar (nthcdr 2 kill) now))
+ ;; Old entry, remove.
+ ((and expire (< date expire))
+ (gnus-score-set 'touched '(t) alist)
+ (setcdr (car words) (cddar words))))
+ (setq fuzzies (cdr fuzzies))))))
nil))
(defun gnus-enter-score-words-into-hashtb (hashtb)
;;; Code:
-(require 'message)
-
(defvar running-xemacs (string-match "XEmacs\\|Lucid" emacs-version))
(defvar gnus-emacs-lisp-directory (if running-xemacs
(if (null (member gnus-directory load-path))
(setq load-path (cons gnus-directory load-path))))
+;;; We can't do this until we know where Gnus is.
+(require 'message)
+
;;; Tools for MIME by
;;; UMEDA Masanobu <umerin@mse.kyutech.ac.jp>
;;; MORIOKA Tomohiko <morioka@jaist.ac.jp>
(when (looking-at "[^ \t]+[ \t]+\\(.*\\)")
(match-string 1)))))
+;;;###autoload
+(defun gnus-declare-backend (name &rest abilities)
+ "Declare backend NAME with ABILITIES as a Gnus backend."
+ (setq gnus-valid-select-methods
+ (nconc gnus-valid-select-methods
+ (list (apply 'list name abilities)))))
+
(provide 'gnus-start)
;;; gnus-start.el ends here
(?x ,(macroexpand '(mail-header-xref gnus-tmp-header)) ?s)
(?D ,(macroexpand '(mail-header-date gnus-tmp-header)) ?s)
(?d (gnus-dd-mmm (mail-header-date gnus-tmp-header)) ?s)
+ (?o (gnus-date-iso8601 gnus-tmp-header) ?s)
(?M ,(macroexpand '(mail-header-id gnus-tmp-header)) ?s)
(?r ,(macroexpand '(mail-header-references gnus-tmp-header)) ?s)
(?c (or (mail-header-chars gnus-tmp-header) 0) ?d)
;; If not, we try the first unread, if that is wanted.
((and subject
gnus-auto-select-same
+ ;; Make sure that we don't select the current article.
+ (not (eq (gnus-summary-article-number)
+ (save-excursion
+ (gnus-summary-first-subject t)
+ (gnus-summary-article-number))))
(gnus-summary-first-unread-article))
(gnus-summary-position-point)
(gnus-message 6 "Wrapped"))
(interactive)
(gnus-set-global-variables)
(prog1
- (if (gnus-summary-first-subject t)
- (progn
- (gnus-summary-show-thread)
- (gnus-summary-first-subject t)
- (gnus-summary-display-article (gnus-summary-article-number))))
+ (when (gnus-summary-first-subject t)
+ (gnus-summary-show-thread)
+ (gnus-summary-first-subject t)
+ (gnus-summary-display-article (gnus-summary-article-number)))
(gnus-summary-position-point)))
(defun gnus-summary-best-unread-article ()
(if (string-equal regexp "")
(setq regexp (or gnus-last-search-regexp ""))
(setq gnus-last-search-regexp regexp))
- (unless (gnus-summary-search-article regexp backward)
+ (if (gnus-summary-search-article regexp backward)
+ (gnus-summary-show-thread)
(error "Search failed: \"%s\"" regexp)))
(defun gnus-summary-search-article-backward (regexp)
(let ((gnus-select-article-hook nil) ;Disable hook.
(gnus-article-display-hook nil)
(gnus-mark-article-hook nil) ;Inhibit marking as read.
+ (gnus-use-article-prefetch nil)
(re-search
(if backward
're-search-backward 're-search-forward))
not-deleted))
(defun gnus-summary-edit-article (&optional force)
- "Enter into a buffer and edit the current article.
+ "Edit the current article.
This will have permanent effect only in mail groups.
If FORCE is non-nil, allow editing of articles even in read-only
-groups."
+groups."
(interactive "P")
(save-excursion
(set-buffer gnus-summary-buffer)
(gnus-article-edit-article
`(lambda ()
(gnus-summary-edit-article-done
- ,(mail-header-references gnus-current-headers)
+ ,(or (mail-header-references gnus-current-headers) "")
,(gnus-group-read-only-p) ,gnus-summary-buffer)))))
+(defalias 'gnus-summary-edit-article-postpone 'gnus-article-edit-exit)
+
(defun gnus-summary-edit-article-done (references read-only buffer)
"Make edits to the current article permanent."
(interactive)
;; Update the summary buffer.
(if (equal (message-tokenize-header references " ")
(message-tokenize-header
- (message-fetch-field "references") " "))
+ (or (message-fetch-field "references") "") " "))
;; We only have to update this line.
- (save-restriction
- (message-narrow-to-head)
- (let ((header (nnheader-parse-head t)))
- (set-buffer buffer)
- (mail-header-set-number header (cdr gnus-article-current))
- (gnus-summary-update-article-line
- (cdr gnus-article-current) header)))
+ (save-excursion
+ (save-restriction
+ (message-narrow-to-head)
+ (let ((header (nnheader-parse-head t)))
+ (set-buffer buffer)
+ (mail-header-set-number header (cdr gnus-article-current))
+ (gnus-summary-update-article-line
+ (cdr gnus-article-current) header))))
;; Update threads.
(set-buffer buffer)
(gnus-summary-update-article (cdr gnus-article-current)))
(let (actions action)
(while (setq actions (pop gnus-undo-last))
(unless action
- (errror "Nothing further to undo"))
+ (error "Nothing further to undo"))
(setq gnus-undo-actions (delq action gnus-undo-actions))
(while action
(funcall (pop action))))))
timezone-months-assoc))
"???"))))))
+(defun gnus-date-iso8601 (header)
+ "Convert the date field in HEADER to YYMMDDTHHMMSS"
+ (format-time-string "%y%m%dT%H%M%S"
+ (nnmail-date-to-time (mail-header-date header))))
+
(defun gnus-mode-string-quote (string)
"Quote all \"%\" in STRING."
(save-excursion
(recenter))
t)))
+(defvar gnus-xmas-pointer-glyph
+ (progn
+ (setq gnus-xmas-glyph-directory (message-xmas-find-glyph-directory "gnus"))
+ (make-pointer-glyph (concat gnus-xmas-glyph-directory "gnus-pointer."
+ (if (featurep 'xpm) "xpm" "xbm")))))
+
+(defvar gnus-xmas-modeline-left-extent
+ (let ((ext (copy-extent modeline-buffer-id-left-extent)))
+ (set-extent-property ext 'pointer gnus-xmas-pointer-glyph)
+ ext))
+
+(defvar gnus-xmas-modeline-right-extent
+ (let ((ext (copy-extent modeline-buffer-id-right-extent)))
+ (set-extent-property ext 'pointer gnus-xmas-pointer-glyph)
+ ext))
+
+(defvar gnus-xmas-modeline-glyph
+ (progn
+ (setq gnus-xmas-glyph-directory (message-xmas-find-glyph-directory "gnus"))
+ (let* ((file (concat gnus-xmas-glyph-directory "gnus-pointer."
+ (if (featurep 'xpm) "xpm" "xbm")))
+ (glyph (make-glyph file)))
+ (when (file-exists-p file)
+ (set-glyph-face glyph 'modeline-buffer-id)
+ glyph))))
+
(defun gnus-xmas-mode-line-buffer-identification (line)
(let ((line (car line))
chop)
(if (not (stringp line))
(list line)
- (unless (setq chop (string-match ":" line))
+ (if (setq chop (string-match ":" line))
+ (incf chop)
(setq chop (/ (length line) 2)))
- (list (cons modeline-buffer-id-left-extent (substring line 0 chop))
- (cons modeline-buffer-id-right-extent (substring line chop))))))
+ (list
+ (if (and (featurep 'x)
+ gnus-xmas-modeline-glyph)
+ (cons gnus-xmas-modeline-left-extent gnus-xmas-modeline-glyph)
+ (cons gnus-xmas-modeline-left-extent (substring line 0 chop)))
+ (cons gnus-xmas-modeline-right-extent (substring line chop))))))
(provide 'gnus-xmas)
(eval '(run-hooks 'gnus-load-hook))
-(defconst gnus-version-number "0.6"
+(defconst gnus-version-number "0.8"
"Version number for this version of Gnus.")
(defconst gnus-version (format "Red Gnus v%s" gnus-version-number)
(save-restriction
(narrow-to-region start end)
(indent-rigidly start end arg)
+ ;; We translate tabs into spaces -- not everybody uses
+ ;; an 8-character tab.
(goto-char (point-min))
(while (search-forward "\t" nil t)
(replace-match " " t t)))))
(when info
(gnus-info-set-score info (+ (gnus-info-score info) (or score 1))))))
-;; Function written by Stainless Steel Rat <ratinox@ccs.neu.edu>.
+;; Function written by Stainless Steel Rat <ratinox@peorth.gweep.net>
(defun gnus-short-group-name (group &optional levels)
- "Collapse GROUP name LEVELS."
- (let* ((name "")
- (foreign "")
- (depth 0)
- (skip 1)
+ "Collapse GROUP name LEVELS.
+Select methods are stripped and any remote host name is stripped down to
+just the host name."
+ (let* ((name "") (foreign "") (depth -1) (skip 1)
(levels (or levels
(progn
(while (string-match "\\." group skip)
(setq skip (match-end 0)
depth (+ depth 1)))
depth))))
+ ;; separate foreign select method from group name and collapse.
+ ;; if method contains a server, collapse to non-domain server name,
+ ;; otherwise collapse to select method
(if (string-match ":" group)
- (setq foreign (substring group 0 (match-end 0))
- group (substring group (match-end 0))))
+ (cond ((string-match "+" group)
+ (let* ((plus (string-match "+" group))
+ (colon (string-match ":" group))
+ (dot (string-match "\\." group)))
+ (setq foreign (concat
+ (substring group (+ 1 plus)
+ (cond ((< colon dot) colon)
+ ((< dot colon) dot))) ":")
+ group (substring group (+ 1 colon))
+ )))
+ (t
+ (let* ((colon (string-match ":" group)))
+ (setq foreign (concat (substring group 0 (+ 1 colon)))
+ group (substring group (+ 1 colon)))
+ ))))
+ ;; collapse group name leaving LEVELS uncollapsed elements
(while group
- (if (and (string-match "\\." group)
- (> levels (- gnus-group-uncollapsed-levels 1)))
+ (if (and (string-match "\\." group) (> levels 0))
(setq name (concat name (substring group 0 1))
group (substring group (match-end 0))
levels (- levels 1)
group nil)))
name))
+
\f
;;;
;;; Kill file handling.
(select-frame (make-frame))
(gnus arg)))
+;;;###autoload
(defun gnus (&optional arg dont-connect slave)
"Read network news.
If ARG is non-nil and a positive number, Gnus will use that as the
included. Organization, Lines and X-Mailer are optional.")
;;;###autoload
-(defvar message-deletable-headers '(Message-ID Date)
+(defvar message-deletable-headers '(Message-ID Date Lines)
"*Headers to be deleted if they already exist and were generated by message previously.")
;;;###autoload
(name-default (concat "*message* " mail-trimmed-to))
(name (if enter-string
(read-string "New buffer name: " name-default)
- name-default)))
- (rename-buffer name t)
- (setq buffer-auto-save-file-name
- (format "%s%s"
- (file-name-as-directory message-autosave-directory)
- (file-name-nondirectory buffer-auto-save-file-name)))))))
+ name-default))
+ (default-directory
+ (file-name-as-directory message-autosave-directory)))
+ (rename-buffer name t)))))
(defun message-fill-yanked-message (&optional justifyp)
"Fill the paragraphs of a message yanked into this one.
(defmacro nnheader-temp-write (file &rest forms)
"Create a new buffer, evaluate FORM there, and write the buffer to FILE."
`(save-excursion
- (let ((nnheader-temp-file ,file)
- (nnheader-temp-cur-buffer
- (nnheader-set-temp-buffer
- (generate-new-buffer-name " *nnheader temp*"))))
+ (let* ((nnheader-temp-file ,file)
+ (default-major-mode 'fundamental-mode)
+ (nnheader-temp-cur-buffer
+ (nnheader-set-temp-buffer
+ (generate-new-buffer-name " *nnheader temp*"))))
(when (and nnheader-temp-file
(not (file-directory-p (file-name-directory
nnheader-temp-file))))
(directory-files
nnmail-procmail-directory
t (concat (if group (concat "^" group) "")
- nnmail-procmail-suffix "$") t)))
+ nnmail-procmail-suffix "$"))))
(p procmails)
(crash (when (and (file-exists-p nnmail-crash-box)
(> (nnheader-file-size
(cond
((not (nnml-possibly-change-directory group server))
(nnheader-report 'nnml "Invalid group (no such directory)"))
+ ((not (file-exists-p nnml-current-directory))
+ (nnheader-report 'nnml "Directory %s does not exist"
+ nnml-current-directory))
((not (file-directory-p nnml-current-directory))
(nnheader-report 'nnml "%s is not a directory" nnml-current-directory))
(dont-check
(concat old-dir (cdar files))
(concat new-dir (cdar files)))
(pop files)))
+ ;; Move .overview file.
+ (let ((overview (concat old-dir nnml-nov-file-name)))
+ (when (file-exists-p overview)
+ (rename-file overview (concat new-dir nnml-nov-file-name))))
(when (<= (length (directory-files old-dir)) 2)
(condition-case ()
(delete-directory old-dir)
(copy-to-buffer nntp-server-buffer (point-min) (point-max))
'headers))))
-(deffoo nntp-request-article (article &optional group server buffer)
+(deffoo nntp-request-article (article &optional group server buffer command)
(nntp-possibly-change-group group server)
(when (nntp-send-command-and-decode
"\r\n\\.\r\n" "ARTICLE"
(when buffer
(save-excursion
(set-buffer nntp-server-buffer)
- (copy-to-buffer buffer (point-min) (point-max)))
- t)))
+ (copy-to-buffer buffer (point-min) (point-max))
+ (nntp-find-group-and-number)))
+ (nntp-find-group-and-number)))
+
+(deffoo nntp-request-head (article &optional group server)
+ (nntp-possibly-change-group group server)
+ (when (nntp-send-command-and-decode
+ "\r\n\\.\r\n" "HEAD"
+ (if (numberp article) (int-to-string article) article))
+ (nntp-find-group-and-number)))
(deffoo nntp-request-body (article &optional group server)
(nntp-possibly-change-group group server)
(save-excursion
(set-buffer (or (nntp-find-connection-buffer nntp-server-buffer)
nntp-server-buffer))
- (message "nntp reading%s" (make-string (/ (point-max) 1000) ?.))
+ (message "nntp reading%s" (make-string (/ (point-max) 10000) ?.))
(accept-process-output process 1)))
(defun nntp-accept-response ()
nntp-rlogin-parameters " ")))))
proc))
+(defun nntp-find-group-and-number ()
+ (save-excursion
+ (save-restriction
+ (set-buffer nntp-server-buffer)
+ (narrow-to-region (goto-char (point-min))
+ (or (search-forward "\n\n" nil t) (point-max)))
+ (goto-char (point-min))
+ ;; We first find the number by looking at the status line.
+ (let ((number (and (looking-at "2[0-9][0-9] +\\([0-9]+\\) ")
+ (string-to-int
+ (buffer-substring (match-beginning 1)
+ (match-end 1)))))
+ group newsgroups xref)
+ (and number (zerop number) (setq number nil))
+ ;; Then we find the group name.
+ (setq group
+ (cond
+ ;; If there is only one group in the Newsgroups header,
+ ;; then it seems quite likely that this article comes
+ ;; from that group, I'd say.
+ ((and (setq newsgroups (mail-fetch-field "newsgroups"))
+ (not (string-match "," newsgroups)))
+ newsgroups)
+ ;; If there is more than one group in the Newsgroups
+ ;; header, then the Xref header should be filled out.
+ ;; We hazard a guess that the group that has this
+ ;; article number in the Xref header is the one we are
+ ;; looking for. This might very well be wrong if this
+ ;; article happens to have the same number in several
+ ;; groups, but that's life.
+ ((and (setq xref (mail-fetch-field "xref"))
+ number
+ (string-match (format "\\([^ :]+\\):%d" number) xref))
+ (substring xref (match-beginning 1) (match-end 1)))
+ (t "")))
+ (when (string-match "\r" group)
+ (setq group (substring group 0 (match-beginning 0))))
+ (cons group number)))))
+
(provide 'nntp)
;;; nntp.el ends here
+Wed Aug 7 22:00:56 1996 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+
+ * gnus.texi (Hooking New Backends Into Gnus): New node.
+
+Wed Aug 7 01:02:08 1996 Lars Magne Ingebrigtsen <lars@eyesore.no>
+
+ * gnus.texi (Setting Marks): Addition.
+ (Formatting Variables): Addition.
+
+Mon Aug 5 20:20:42 1996 Lars Magne Ingebrigtsen <lars@eyesore.no>
+
+ * gnus.texi (Formatting Variables): Addition.
+
Sun Aug 4 07:15:28 1996 Lars Magne Ingebrigtsen <lars@eyesore.no>
* gnus.texi (Score File Format): Addition.
+++ /dev/null
-TEXI2DVI=texi2dvi
-EMACS=emacs
-MAKEINFO=$(EMACS) -batch -q -no-site-file
-INFOSWI=-l texinfmt -f texinfo-every-node-update -f texinfo-format-buffer -f save-buffer
-LATEX=latex
-DVIPS=dvips
-PERL=perl
-
-all: gnus message
-
-most: texi2latexi.elc latex latexps
-
-gnus: gnus.texi
- $(MAKEINFO) gnus.texi $(INFOSWI)
-
-message: message.texi
- $(MAKEINFO) message.texi $(INFOSWI)
-
-dvi: gnus.texi
- $(PERL) -n -e 'if (/\@iflatex/) { $$latex=1; } if (!$$latex) { print; } if (/\@end iflatex/) { $$latex=0; }' gnus.texi > gnus.tmptexi
- $(TEXI2DVI) gnus.tmptexi
-
-refcard.dvi: refcard.tex
- $(LATEX) refcard.tex
-
-clean:
- rm -f gnus.*.bak gnus.ky gnus.cp gnus.fn gnus.cps gnus.kys *.log \
- gnus.log gnus.pg gnus.tp gnus.vr gnus.toc gnus.latexi *.aux gnus.cidx \
- gnus.cind gnus.ilg gnus.ind gnus.kidx gnus.kind gnus.idx \
- gnus.tmptexi gnus.tmplatexi *.latexi texput.log *.orig *.rej
-
-makeinfo:
- makeinfo -o gnus gnus.texi
- makeinfo -o message message.texi
-
-texi2latexi.elc:
- $(EMACS) -batch -l bytecomp -f batch-byte-recompile-directory
-
-latex: gnus.texi
- $(EMACS) -batch -q -no-site-file gnus.texi -l ./texi2latex.elc -f latexi-translate
-
-latexps:
- $(LATEX) gnus.latexi
- splitindex
- makeindex -o gnus.kind gnus.kidx
- makeindex -o gnus.cind gnus.cidx
- egrep -v "end{document}|label.*Index|chapter.*Index" gnus.latexi > gnus.tmplatexi
- cat postamble.latexi >> gnus.tmplatexi
- $(LATEX) gnus.tmplatexi
- $(DVIPS) -f gnus.dvi > gnus.ps
-
-latexboth:
- rm -f gnus-manual-a4.ps.gz gnus-manual-standard.ps.gz
- make latexps
- mv gnus.ps gnus-manual-a4.ps
- gzip gnus-manual-a4.ps
- sed 's/,a4paper//' gnus.latexi > gnus-standard.latexi
- make latexps
- mv gnus.ps gnus-manual-standard.ps
- gzip gnus-manual-standard.ps
-
@kbd{C-c C-y} grabs the previous message and prefixes each line with
@code{ail-indentation-spaces} spaces or @code{mail-yank-prefix} if that is
non-nil, unless you have set your own @code{mail-citation-hook}, which will
-be called to to do the job.
+be called to do the job.
You might also consider the Supercite package, which allows for pretty
arbitrarily complex quoting styles. Some people love it, some people
@vindex gnus-group-mode-line-format
The mode line can be changed by setting
-(@code{gnus-group-mode-line-format}). It doesn't understand that many
-format specifiers:
+@code{gnus-group-mode-line-format} (@pxref{Formatting Variables}). It
+doesn't understand that many format specifiers:
@table @samp
@item S
server(s) you are connected to (@code{gnus-group-list-active}). This
might very well take quite a while. It might actually be a better idea
to do a @kbd{A m} to list all matching, and just give @samp{.} as the
-thing to match on.
+thing to match on. Also note that this command may list group that
+don't exist (yet)---these will be listed as if they are killed groups.
+Take the output with some grains of salt.
@item A a
@kindex A a (Group)
@vindex gnus-topic-line-format
The topic lines themselves are created according to the
-@code{gnus-topic-line-format} variable. @xref{Formatting Variables}.
-Elements allowed are:
+@code{gnus-topic-line-format} variable (@pxref{Formatting Variables}).
+Legal elements are:
@table @samp
@item i
@vindex gnus-summary-line-format
You can change the format of the lines in the summary buffer by changing
the @code{gnus-summary-line-format} variable. It works along the same
-lines a a normal @code{format} string, with some extensions.
+lines a a normal @code{format} string, with some extensions
+(@pxref{Formatting Variables}).
The default string is @samp{%U%R%z%I%(%[%4L: %-20,20n%]%) %s\n}.
@item S
Subject string.
@item s
-Subject if the article is the root, @code{gnus-summary-same-subject}
-otherwise.
+Subject if the article is the root or the previous article had a
+different subject, @code{gnus-summary-same-subject} otherwise.
+(@code{gnus-summary-same-subject} defaults to @samp{}.)
@item F
-Full @code{From} line.
+Full @code{From} header.
@item n
The name (from the @code{From} header).
@item a
pushes everything after it off the screen).
@item \[
Opening bracket, which is normally @samp{\[}, but can also be @samp{<}
-for adopted articles.
+for adopted articles (@pxref{Customizing Threading}).
@item \]
Closing bracket, which is normally @samp{\]}, but can also be @samp{>}
for adopted articles.
@code{Xref}.
@item D
@code{Date}.
+@item d
+The @code{Date} in @code{YY-MMM} format.
+@item o
+The @code{Date} in @code{YYMMDD-HH:MM:SS} format.
@item M
@code{Message-ID}.
@item r
Mark the current article as read
(@code{gnus-summary-mark-as-read-forward}).
+@item D
+@kindex D (Summary)
+@findex gnus-summary-mark-as-read-backward
+Mark the current article as read and move point to the previous line
+(@code{gnus-summary-mark-as-read-backward}).
+
@item M k
@itemx k
@kindex k (Summary)
@vindex gnus-cited-text-button-line-format
Gnus adds buttons show where the cited text has been hidden, and to
allow toggle hiding the text. The format of the variable is specified
-by this format-like variable. These specs are legal:
+by this format-like variable (@pxref{Formatting Variables}). These
+specs are legal:
@table @samp
@item b
Each @samp{%} element will be replaced by some string or other when the
buffer in question is generated. @samp{%5y} means ``insert the @samp{y}
-spec, and pad with spaces to get a 5-character field''. Just like a
+spec, and pad with spaces (to the left) to get a 5-character field''.
+(@samp{%-5y} means the same, but pad to the right instead.) Just like a
normal format spec, almost.
-You can also say @samp{%6,4y}, which means that the field will never be
-more than 4 characters wide and never less than 6 characters wide.
+You can also say @samp{%4,6y}, which means that the field will never be
+more than 6 characters wide and never less than 4 characters wide.
+
+All the specs allow for inserting user defined specifiers -- @samp{u}.
+The next character in the format string should be a letter. @sc{gnus}
+will call the function @code{gnus-user-format-function-}@samp{X}, where
+@samp{X} is the letter following @samp{%u}. The function will be passed
+a single parameter---what the parameter means depends on what buffer
+it's being called from. The function should return a string, which will
+be inserted into the buffer just like information from any other
+specifier. This function may also be called with dummy values, so it
+should protect against that.
There are also specs for highlighting, and these are shared by all the
format variables. Text inside the @samp{%(} and @samp{%)} specifiers
All these functions are expected to return data in the buffer
@code{nntp-server-buffer} (@samp{ *nntpd*}), which is somewhat
unfortunately named, but we'll have to live with it. When I talk about
-``resulting data'', I always refer to the data in that buffer. When I
-talk about ``return value'', I talk about the function value returned by
-the function call.
+@dfn{resulting data}, I always refer to the data in that buffer. When I
+talk about @dfn{return value}, I talk about the function value returned by
+the function call. Functions that fail should return @code{nil} as the
+return value.
Some backends could be said to be @dfn{server-forming} backends, and
some might be said to not be. The latter are backends that generally
* Required Backend Functions:: Functions that must be implemented.
* Optional Backend Functions:: Functions that need not be implemented.
* Writing New Backends:: Extending old backends.
+* Hooking New Backends Into Gnus:: What has to be done on the Gnus end.
@end menu
There should be no data returned by this function.
-@item (nnchoke-request-group GROUP &optional SERVER)
+@item (nnchoke-request-group GROUP &optional SERVER FAST)
Get data on @var{group}. This function also has the side effect of
making @var{group} the current group.
+If @var{FAST}, don't bother to return useful data, just make @var{group}
+the current group.
+
Here's an example of some result data and a definition of the same:
@example
@end lisp
+@node Hooking New Backends Into Gnus
+@subsubsection Hooking New Backends Into Gnus
+
+@vindex gnus-valid-select-methods
+Having Gnus start using your new backend is rather easy---you just
+declare it with the @code{gnus-declare-backend} functions. This will
+enter the backend into the @code{gnus-valid-select-methods} variable.
+
+@code{gnus-declare-backend} takes two parameters---the backend name and
+an arbitrary number of @dfn{abilities}.
+
+Here's an example:
+
+@lisp
+(gnus-declare-backend "nnchoke" 'mail 'respool 'address)
+@end lisp
+
+The abilities can be:
+
+@table @code
+@item mail
+This is a mailish backend---followups should (probably) go via mail.
+@item post
+This is a newsish backend---followups should (probably) go via news.
+@item post-mail
+This backend supports both mail and news.
+@item none
+This is neither a post or mail backend---it's something completely
+different.
+@item respool
+It supports respooling---or rather, it is able to modify its source
+articles and groups.
+@item address
+The name of the server should be in the virtual server name. This is
+true for almost all backends.
+@item prompt-address
+The user should be prompted for an address when doing commands like
+@kbd{B} in the group buffer. This is true for backends like
+@code{nntp}, but not @code{nnmbox}, for instance.
+@end table
+
+
@node Score File Syntax
@subsection Score File Syntax