From 4303c5c768c35022c9eda800cacfa401946e144b Mon Sep 17 00:00:00 2001 From: Miles Bader Date: Fri, 4 Jul 2008 00:09:30 +0000 Subject: [PATCH] Merge from emacs--devo--0, gnus--rel--5.10 Patches applied: * emacs--devo--0 (patch 1254-1310) - Update from CVS - Fix behavior of text-scale-increase when text-scale-mode is disabled - Tweak interface of buffer-face-mode functions - Fix variable names in buffer-face-mode-invoke - Fix autoload building command in src Makefile - Fix autoload directives in lisp/face-remap.el - (text-scale-adjust): Bind `echo-keystrokes' to nil. - Handle void selection in mouse-appearance-menu - Update from CVS: lisp/ibuf-ext.el (diff-sentinel): Declare. - Fix a bug with parsing of overlapping markup sequences in rcirc - Merge from emacs--rel--22 - Implement display-time wrap/line-prefix feature - Merge from gnus--devo--0 - Add missing doc/misc/ChangeLog entry * emacs--rel--22 (patch 277) * gnus--rel--5.10 (patch 297) - Update from CVS 2008-07-02 Juanma Barranquero * lisp/nnimap.el (nnimap-id): * lisp/sieve-manage.el (sieve-manage-open): Doc fixes. 2008-07-02 Francesc Rocher * lisp/gnus.el (gnus-group-startup-message): Prefer SVG or PNG image, if available. 2008-06-25 Stefan Monnier * lisp/mm-util.el (mm-with-multibyte, mm-with-unibyte): Remove. * lisp/nnkiboze.el (nnkiboze-generate-group): Use explicit mm-disable-multibyte rather than mm-with-unibyte. * lisp/nnmairix.el: Require CL. Revision: emacs@sv.gnu.org/gnus--devo--0--patch-517 --- etc/images/README | 22 +- etc/images/gnus/README | 14 +- etc/images/gnus/gnus.png | Bin 0 -> 20051 bytes etc/images/gnus/gnus.svg | 108 ++++ etc/images/splash.png | Bin 0 -> 39572 bytes etc/images/splash.svg | 273 ++++++++++ lisp/ChangeLog | 33 +- lisp/ChangeLog.2 | 6 +- lisp/gnus-demon.el | 2 +- lisp/gnus.el | 4 +- lisp/hashcash.el | 2 + lisp/message.el | 2 +- lisp/mm-util.el | 14 - lisp/mml1991.el | 8 +- lisp/nndb.el | 6 +- lisp/nnimap.el | 4 +- lisp/nnkiboze.el | 191 +++---- lisp/nnmairix.el | 2 + lisp/rfc2047.el | 2 +- lisp/sasl-ntlm.el | 8 +- lisp/sasl.el | 12 +- lisp/sieve-manage.el | 12 +- lisp/smime.el | 2 +- lisp/vc-annotate.el | 631 ++++++++++++++++++++++ lisp/vc-dir.el | 1067 ++++++++++++++++++++++++++++++++++++++ texi/gnus.texi | 2 +- texi/sasl.texi | 4 +- 27 files changed, 2266 insertions(+), 165 deletions(-) create mode 100644 etc/images/gnus/gnus.png create mode 100644 etc/images/gnus/gnus.svg create mode 100644 etc/images/splash.png create mode 100644 etc/images/splash.svg create mode 100644 lisp/vc-annotate.el create mode 100644 lisp/vc-dir.el diff --git a/etc/images/README b/etc/images/README index c7aa70467..25b219597 100644 --- a/etc/images/README +++ b/etc/images/README @@ -16,22 +16,24 @@ Thanks to jan.h.d@swipnet.se for the help. COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES -* The following icons are a part of Emacs: +* The following icons are part of Emacs. All are licensed under the + GNU General Public License version 3 (see COPYING) or later. + The xpm and svg files contain copyright and license information, but + it is reproduced here for convenience. File: mh-logo.xpm -Author: Satyaki Das -Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 - Free Software Foundation, Inc. -License: GNU General Public License version 3 or later (see COPYING) - -The files splash.xpm, splash8.xpm contain copyright and license -information, but it is reproduced here for convenience. + Author: Satyaki Das + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 + Free Software Foundation, Inc. Files: splash.pbm, splash.xpm, splash8.xpm, gnus.pbm Author: Luis Fernandes - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. - License: GNU General Public License version 3 or later (see COPYING) + +Files: splash.png, splash.svg + Author: Francesc Rocher + Copyright (C) 2008 Free Software Foundation, Inc. * The following icons are from GTK+ 2.x. They are not part of Emacs, but diff --git a/etc/images/gnus/README b/etc/images/gnus/README index 16a52f135..2b5823819 100644 --- a/etc/images/gnus/README +++ b/etc/images/gnus/README @@ -1,10 +1,14 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES +* The following icons are part of Emacs. All are licensed under the + GNU General Public License version 3 (see COPYING) or later. + The file gnus.svg contains copyright and license information, but it + is reproduced here for convenience. + Files: important.xpm, unimportant.xpm Author: Simon Josefsson Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. -License: GNU General Public License version 3 or later (see COPYING) Files: catchup.pbm catchup.xpm cu-exit.pbm cu-exit.xpm describe-group.pbm describe-group.xpm exit-gnus.pbm exit-gnus.xpm @@ -20,9 +24,13 @@ Files: catchup.pbm catchup.xpm cu-exit.pbm cu-exit.xpm Author: Luis Fernandes Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. -License: GNU General Public License version 3 or later (see COPYING) -The following icons are from GNOME 2.x. They are not part of Emacs, +Files: gnus.png, gnus.svg + Author: Francesc Rocher + Copyright (C) 2008 Free Software Foundation, Inc. + + +* The following icons are from GNOME 2.x. They are not part of Emacs, but are distributed and used by Emacs. They are licensed under the GNU General Public License version 2 or later. See the source of the gnome-icons-theme package for more information. diff --git a/etc/images/gnus/gnus.png b/etc/images/gnus/gnus.png new file mode 100644 index 0000000000000000000000000000000000000000..f497993d13276015e8e3cab96a3aaab730387646 GIT binary patch literal 20051 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 uEJiVon + + + + + + + image/svg+xml + + + gnus + 2008/06/28 + + + Francesc Rocher + + + + + GPL + + + gnus splash image + + + + + + + + + + + diff --git a/etc/images/splash.png b/etc/images/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..9d051319c1b6d9664207be0f581c9e1c62be6035 GIT binary patch literal 39572 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 XzFeh+v+&nO00000NkvXXu0mjf8<-8O literal 0 HcmV?d00001 diff --git a/etc/images/splash.svg b/etc/images/splash.svg new file mode 100644 index 000000000..353053c2b --- /dev/null +++ b/etc/images/splash.svg @@ -0,0 +1,273 @@ + + + + + + + + image/svg+xml + + splash + 2008/06/28 + + + Francesc Rocher + + + + + GPL + + + GNU Emacs splash image + + + Based on the original work by Luis Fernandes. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 0ce3f4817..ac2adfb2e 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -17,6 +17,25 @@ * gnus-score.el (gnus-score-find-trace): Add "Total score" line. +2008-07-02 Juanma Barranquero + + * nnimap.el (nnimap-id): + * sieve-manage.el (sieve-manage-open): Doc fixes. + +2008-07-02 Francesc Rocher + + * gnus.el (gnus-group-startup-message): Prefer SVG or PNG image, + if available. + +2008-06-25 Stefan Monnier + + * mm-util.el (mm-with-multibyte, mm-with-unibyte): Remove. + + * nnkiboze.el (nnkiboze-generate-group): + Use explicit mm-disable-multibyte rather than mm-with-unibyte. + + * nnmairix.el: Require CL. + 2008-06-16 Katsumi Yamaoka * dgnushack.el: Autoload get-display-table and put-display-table for @@ -31,16 +50,16 @@ 2008-06-14 Aidan Kehoe - * gnus-util.el (gnus-put-display-table, gnus-get-display-table): New - macros that expand to an `aset'/`aref' call under Emacs, and to a + * gnus-util.el (gnus-put-display-table, gnus-get-display-table): + New macros that expand to an `aset'/`aref' call under Emacs, and to a runtime choice under XEmacs. - * gnus-sum.el (gnus-summary-set-display-table): Use - `gnus-put-display-table', `gnus-get-display-table', + * gnus-sum.el (gnus-summary-set-display-table): + Use `gnus-put-display-table', `gnus-get-display-table', `gnus-set-display-table' for the display table, instead of `aset'. - * gnus-xmas.el (gnus-xmas-summary-set-display-table): Use - `gnus-put-display-table', `gnus-get-display-table', + * gnus-xmas.el (gnus-xmas-summary-set-display-table): + Use `gnus-put-display-table', `gnus-get-display-table', `gnus-set-display-table' for the display table. 2008-06-14 Reiner Steib @@ -10319,7 +10338,7 @@ 2004-09-01 Simon Josefsson * message.el (message-canlock-generate): Require sha1, not - sha1-el. (Can we get rid of this require alltogheter? It is ugly + sha1-el. (Can we get rid of this require altogether? It is ugly to require within a function. Sadly, if sha1.el isn't loaded, the let binding in m-c-g will hide the defcustom definition, which is bad.) diff --git a/lisp/ChangeLog.2 b/lisp/ChangeLog.2 index c80508a33..6834cc006 100644 --- a/lisp/ChangeLog.2 +++ b/lisp/ChangeLog.2 @@ -2456,7 +2456,7 @@ 2003-05-10 Lars Magne Ingebrigtsen - * gnus.el (gnus-logo-color-alist): Added no colours. + * gnus.el (gnus-logo-color-alist): Added no colors. 2003-05-09 Dave Love @@ -12530,7 +12530,7 @@ * mm-encode.el (mm-encode-content-transfer-encoding): Fix error message. (Gnus does not "default" to using 8bit for the message, it default to use 8bit encoding and the user-supplied CTE - value. Calling this behaviour "treating it as 8bit" is perhaps + value. Calling this behavior "treating it as 8bit" is perhaps better.) * mm-bodies.el (mm-body-encoding): Intern encoding if needed @@ -12815,7 +12815,7 @@ (imap-remassoc): Copied from `gnus-remassoc'. (imap-add-callback): New function. (imap-mailbox-expunge, imap-mailbox-close): Support asynchronous - behaviour. + behavior. (imap-parse-response): Call the callback. * message.el (message-insert-canlock): New variable. diff --git a/lisp/gnus-demon.el b/lisp/gnus-demon.el index 565be3bcb..bf7b4db88 100644 --- a/lisp/gnus-demon.el +++ b/lisp/gnus-demon.el @@ -1,4 +1,4 @@ -;;; gnus-demon.el --- daemonic Gnus behaviour +;;; gnus-demon.el --- daemonic Gnus behavior ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, ;; 2005, 2006, 2007, 2008 Free Software Foundation, Inc. diff --git a/lisp/gnus.el b/lisp/gnus.el index 8c7559b4a..fe34891ff 100644 --- a/lisp/gnus.el +++ b/lisp/gnus.el @@ -1015,7 +1015,9 @@ be set in `.emacs' instead." (symbol-value 'image-load-path)) (t load-path))) (image (find-image - `((:type xpm :file "gnus.xpm" + `((:type svg :file "gnus.svg") + (:type png :file "gnus.png") + (:type xpm :file "gnus.xpm" :color-symbols (("thing" . ,(car gnus-logo-colors)) ("shadow" . ,(cadr gnus-logo-colors)) diff --git a/lisp/hashcash.el b/lisp/hashcash.el index 4875cbb29..7f291515e 100644 --- a/lisp/hashcash.el +++ b/lisp/hashcash.el @@ -50,6 +50,8 @@ (eval-and-compile (unless (fboundp 'declare-function) (defmacro declare-function (&rest r)))) +(eval-when-compile (require 'cl)) ; for case + (defgroup hashcash nil "Hashcash configuration." :group 'mail) diff --git a/lisp/message.el b/lisp/message.el index 8ccce9665..0a38ec028 100644 --- a/lisp/message.el +++ b/lisp/message.el @@ -4543,7 +4543,7 @@ to find out how to use this." (apply 'call-process-region (point-min) (point-max) message-qmail-inject-program nil nil nil - ;; qmail-inject's default behaviour is to look for addresses on the + ;; qmail-inject's default behavior is to look for addresses on the ;; command line; if there're none, it scans the headers. ;; yes, it does The Right Thing w.r.t. Resent-To and it's kin. ;; diff --git a/lisp/mm-util.el b/lisp/mm-util.el index ad0921303..453beae52 100644 --- a/lisp/mm-util.el +++ b/lisp/mm-util.el @@ -1093,20 +1093,6 @@ Emacs 23 (unicode)." (put 'mm-with-unibyte-current-buffer 'lisp-indent-function 0) (put 'mm-with-unibyte-current-buffer 'edebug-form-spec '(body)) -(defmacro mm-with-unibyte (&rest forms) - "Eval the FORMS with the default value of `enable-multibyte-characters' nil." - `(let (default-enable-multibyte-characters) - ,@forms)) -(put 'mm-with-unibyte 'lisp-indent-function 0) -(put 'mm-with-unibyte 'edebug-form-spec '(body)) - -(defmacro mm-with-multibyte (&rest forms) - "Eval the FORMS with the default value of `enable-multibyte-characters' t." - `(let ((default-enable-multibyte-characters t)) - ,@forms)) -(put 'mm-with-multibyte 'lisp-indent-function 0) -(put 'mm-with-multibyte 'edebug-form-spec '(body)) - (defun mm-find-charset-region (b e) "Return a list of Emacs charsets in the region B to E." (cond diff --git a/lisp/mml1991.el b/lisp/mml1991.el index 17793b2a4..1a7588b43 100644 --- a/lisp/mml1991.el +++ b/lisp/mml1991.el @@ -133,7 +133,7 @@ Whether the passphrase is cached at all is controlled by 'never)) cipher (result-buffer (get-buffer-create "*GPG Result*"))) - ;; Strip MIME Content[^ ]: headers since it will be ASCII ARMOURED + ;; Strip MIME Content[^ ]: headers since it will be ASCII ARMORED (goto-char (point-min)) (while (looking-at "^Content[^ ]+:") (forward-line)) (unless (bobp) @@ -213,7 +213,7 @@ Whether the passphrase is cached at all is controlled by (let ((text (current-buffer)) cipher (result-buffer (get-buffer-create "*GPG Result*"))) - ;; Strip MIME Content[^ ]: headers since it will be ASCII ARMOURED + ;; Strip MIME Content[^ ]: headers since it will be ASCII ARMORED (goto-char (point-min)) (while (looking-at "^Content[^ ]+:") (forward-line)) (unless (bobp) @@ -303,7 +303,7 @@ Whether the passphrase is cached at all is controlled by (let ((cte (save-restriction (narrow-to-region (point-min) (point)) (mail-fetch-field "content-transfer-encoding")))) - ;; Strip MIME headers since it will be ASCII armoured. + ;; Strip MIME headers since it will be ASCII armored. (forward-line 1) (delete-region (point-min) (point)) (when cte @@ -424,7 +424,7 @@ If no one is selected, default secret key is used. " (let ((cte (save-restriction (narrow-to-region (point-min) (point)) (mail-fetch-field "content-transfer-encoding")))) - ;; Strip MIME headers since it will be ASCII armoured. + ;; Strip MIME headers since it will be ASCII armored. (forward-line 1) (delete-region (point-min) (point)) (when cte diff --git a/lisp/nndb.el b/lisp/nndb.el index 53ad69630..602895826 100644 --- a/lisp/nndb.el +++ b/lisp/nndb.el @@ -1,7 +1,7 @@ ;;; nndb.el --- nndb access for Gnus -;; Copyright (C) 1997, 1998, 2000, 2002, 2003, 2004, -;; 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +;; Copyright (C) 1997, 1998, 2000, 2002, 2003, 2004, 2005, 2006, 2007, +;; 2008 Free Software Foundation, Inc. ;; Author: Masanobu UMEDA ;; Kai Grossjohann @@ -307,7 +307,7 @@ Optional LAST is ignored." ; nndb-request-rename-group does not exist ; todo -- maybe later -;; -- standard compatability functions +;; -- standard compatibility functions (deffoo nndb-status-message (&optional server) "Return server status as a string." diff --git a/lisp/nnimap.el b/lisp/nnimap.el index 8a9d5c706..49166b8de 100644 --- a/lisp/nnimap.el +++ b/lisp/nnimap.el @@ -424,8 +424,8 @@ restrict visible folders.") (defcustom nnimap-id nil "Plist with client identity to send to server upon login. -Nil means no information is sent, symbol `no' to disable ID query -alltogheter, or plist with identifier-value pairs to send to +A nil value means no information is sent, symbol `no' to disable ID query +altogether, or plist with identifier-value pairs to send to server. RFC 2971 describes the list as follows: Any string may be sent as a field, but the following are defined to diff --git a/lisp/nnkiboze.el b/lisp/nnkiboze.el index ab657a610..9ad06a870 100644 --- a/lisp/nnkiboze.el +++ b/lisp/nnkiboze.el @@ -247,101 +247,102 @@ Finds out what articles are to be part of the nnkiboze groups." (unless info (error "No such group: %s" group)) ;; Load the kiboze newsrc file for this group. - (mm-with-unibyte - (when (file-exists-p newsrc-file) - (load newsrc-file)) - (let ((coding-system-for-write nnkiboze-file-coding-system)) - (gnus-make-directory (file-name-directory nov-file)) - (with-temp-file nov-file - (when (file-exists-p nov-file) - (insert-file-contents nov-file)) - (setq nov-buffer (current-buffer)) - ;; Go through the active hashtb and add new all groups that match the - ;; kiboze regexp. - (mapatoms - (lambda (group) - (and (string-match nnkiboze-regexp - (setq gname (symbol-name group))) ; Match - (not (assoc gname nnkiboze-newsrc)) ; It isn't registered - (numberp (car (symbol-value group))) ; It is active - (or (> nnkiboze-level 7) - (and (setq glevel - (gnus-info-level (gnus-get-info gname))) - (>= nnkiboze-level glevel))) - (not (string-match "^nnkiboze:" gname)) ; Exclude kibozes - (push (cons gname (1- (car (symbol-value group)))) - nnkiboze-newsrc))) - gnus-active-hashtb) - ;; `newsrc' is set to the list of groups that possibly are - ;; component groups to this kiboze group. This list has elements - ;; on the form `(GROUP . NUMBER)', where NUMBER is the highest - ;; number that has been kibozed in GROUP in this kiboze group. - (setq newsrc nnkiboze-newsrc) - (while newsrc - (if (not (setq active (gnus-active (caar newsrc)))) - ;; This group isn't active after all, so we remove it from - ;; the list of component groups. - (setq nnkiboze-newsrc (delq (car newsrc) nnkiboze-newsrc)) - (setq lowest (cdar newsrc)) - ;; Ok, we have a valid component group, so we jump to it. - (switch-to-buffer gnus-group-buffer) - (gnus-group-jump-to-group (caar newsrc)) - (gnus-message 3 "nnkiboze: Checking %s..." (caar newsrc)) - (setq ginfo (gnus-get-info (gnus-group-group-name)) - orig-info (gnus-copy-sequence ginfo) - num-unread (gnus-group-unread (caar newsrc))) - (unwind-protect - (progn - ;; We set all list of article marks to nil. Since we operate - ;; on copies of the real lists, we can destroy anything we - ;; want here. - (when (nth 3 ginfo) - (setcar (nthcdr 3 ginfo) nil)) - ;; We set the list of read articles to be what we expect for - ;; this kiboze group -- either nil or `(1 . LOWEST)'. - (when ginfo - (setcar (nthcdr 2 ginfo) - (and (not (= lowest 1)) (cons 1 lowest)))) - (when (and (or (not ginfo) - (> (length (gnus-list-of-unread-articles - (car ginfo))) - 0)) - (progn - (ignore-errors - (gnus-group-select-group nil)) - (eq major-mode 'gnus-summary-mode))) - ;; We are now in the group where we want to be. - (setq method (gnus-find-method-for-group - gnus-newsgroup-name)) - (when (eq method gnus-select-method) - (setq method nil)) - ;; We go through the list of scored articles. - (while gnus-newsgroup-scored - (when (> (caar gnus-newsgroup-scored) lowest) - ;; If it has a good score, then we enter this article - ;; into the kiboze group. - (nnkiboze-enter-nov - nov-buffer - (gnus-summary-article-header - (caar gnus-newsgroup-scored)) - gnus-newsgroup-name)) - (setq gnus-newsgroup-scored (cdr gnus-newsgroup-scored))) - ;; That's it. We exit this group. - (when (eq major-mode 'gnus-summary-mode) - (kill-buffer (current-buffer))))) - ;; Restore the proper info. - (when ginfo - (setcdr ginfo (cdr orig-info))) - (setcar (gnus-group-entry (caar newsrc)) num-unread))) - (setcdr (car newsrc) (cdr active)) - (gnus-message 3 "nnkiboze: Checking %s...done" (caar newsrc)) - (setq newsrc (cdr newsrc))))) - ;; We save the kiboze newsrc for this group. - (gnus-make-directory (file-name-directory newsrc-file)) - (with-temp-file newsrc-file - (insert "(setq nnkiboze-newsrc '") - (gnus-prin1 nnkiboze-newsrc) - (insert ")\n"))) + (when (file-exists-p newsrc-file) + (load newsrc-file)) + (let ((coding-system-for-write nnkiboze-file-coding-system)) + (gnus-make-directory (file-name-directory nov-file)) + (with-temp-file nov-file + (mm-disable-multibyte) + (when (file-exists-p nov-file) + (insert-file-contents nov-file)) + (setq nov-buffer (current-buffer)) + ;; Go through the active hashtb and add new all groups that match the + ;; kiboze regexp. + (mapatoms + (lambda (group) + (and (string-match nnkiboze-regexp + (setq gname (symbol-name group))) ; Match + (not (assoc gname nnkiboze-newsrc)) ; It isn't registered + (numberp (car (symbol-value group))) ; It is active + (or (> nnkiboze-level 7) + (and (setq glevel + (gnus-info-level (gnus-get-info gname))) + (>= nnkiboze-level glevel))) + (not (string-match "^nnkiboze:" gname)) ; Exclude kibozes + (push (cons gname (1- (car (symbol-value group)))) + nnkiboze-newsrc))) + gnus-active-hashtb) + ;; `newsrc' is set to the list of groups that possibly are + ;; component groups to this kiboze group. This list has elements + ;; on the form `(GROUP . NUMBER)', where NUMBER is the highest + ;; number that has been kibozed in GROUP in this kiboze group. + (setq newsrc nnkiboze-newsrc) + (while newsrc + (if (not (setq active (gnus-active (caar newsrc)))) + ;; This group isn't active after all, so we remove it from + ;; the list of component groups. + (setq nnkiboze-newsrc (delq (car newsrc) nnkiboze-newsrc)) + (setq lowest (cdar newsrc)) + ;; Ok, we have a valid component group, so we jump to it. + (switch-to-buffer gnus-group-buffer) + (gnus-group-jump-to-group (caar newsrc)) + (gnus-message 3 "nnkiboze: Checking %s..." (caar newsrc)) + (setq ginfo (gnus-get-info (gnus-group-group-name)) + orig-info (gnus-copy-sequence ginfo) + num-unread (gnus-group-unread (caar newsrc))) + (unwind-protect + (progn + ;; We set all list of article marks to nil. Since we operate + ;; on copies of the real lists, we can destroy anything we + ;; want here. + (when (nth 3 ginfo) + (setcar (nthcdr 3 ginfo) nil)) + ;; We set the list of read articles to be what we expect for + ;; this kiboze group -- either nil or `(1 . LOWEST)'. + (when ginfo + (setcar (nthcdr 2 ginfo) + (and (not (= lowest 1)) (cons 1 lowest)))) + (when (and (or (not ginfo) + (> (length (gnus-list-of-unread-articles + (car ginfo))) + 0)) + (progn + (ignore-errors + (gnus-group-select-group nil)) + (eq major-mode 'gnus-summary-mode))) + ;; We are now in the group where we want to be. + (setq method (gnus-find-method-for-group + gnus-newsgroup-name)) + (when (eq method gnus-select-method) + (setq method nil)) + ;; We go through the list of scored articles. + (while gnus-newsgroup-scored + (when (> (caar gnus-newsgroup-scored) lowest) + ;; If it has a good score, then we enter this article + ;; into the kiboze group. + (nnkiboze-enter-nov + nov-buffer + (gnus-summary-article-header + (caar gnus-newsgroup-scored)) + gnus-newsgroup-name)) + (setq gnus-newsgroup-scored (cdr gnus-newsgroup-scored))) + ;; That's it. We exit this group. + (when (eq major-mode 'gnus-summary-mode) + (kill-buffer (current-buffer))))) + ;; Restore the proper info. + (when ginfo + (setcdr ginfo (cdr orig-info))) + (setcar (gnus-group-entry (caar newsrc)) num-unread))) + (setcdr (car newsrc) (cdr active)) + (gnus-message 3 "nnkiboze: Checking %s...done" (caar newsrc)) + (setq newsrc (cdr newsrc))))) + ;; We save the kiboze newsrc for this group. + (gnus-make-directory (file-name-directory newsrc-file)) + (with-temp-file newsrc-file + (mm-disable-multibyte) + (insert "(setq nnkiboze-newsrc '") + (gnus-prin1 nnkiboze-newsrc) + (insert ")\n")) (unless inhibit-list-groups (save-excursion (set-buffer gnus-group-buffer) diff --git a/lisp/nnmairix.el b/lisp/nnmairix.el index dbc0a55e1..6917b7739 100644 --- a/lisp/nnmairix.el +++ b/lisp/nnmairix.el @@ -163,6 +163,8 @@ ;;; Code: +(eval-when-compile (require 'cl)) ;For (pop (cdr ogroup)). + (require 'nnoo) (require 'gnus-group) (require 'gnus-sum) diff --git a/lisp/rfc2047.el b/lisp/rfc2047.el index 89c10a99e..ea5274798 100644 --- a/lisp/rfc2047.el +++ b/lisp/rfc2047.el @@ -291,7 +291,7 @@ Should be called narrowed to the head of the message." ;; 8-bit names. The group name mail copy just got ;; unconditionally encoded. Previously, it would ask ;; whether to encode, which was quite confusing for the - ;; user. If the new behaviour is wrong, tell me. I have + ;; user. If the new behavior is wrong, tell me. I have ;; left the old code commented out below. ;; -- Per Abrahamsen Date: 2001-10-07. ;; Modified by Dave Love, with the commented-out code changed diff --git a/lisp/sasl-ntlm.el b/lisp/sasl-ntlm.el index 41a1fdb18..7b8af9c78 100644 --- a/lisp/sasl-ntlm.el +++ b/lisp/sasl-ntlm.el @@ -36,12 +36,12 @@ '(ignore ;nothing to do before making sasl-ntlm-request ;authentication request sasl-ntlm-response) ;response to challenge - "A list of functions to be called in sequnece for the NTLM -authentication steps. Ther are called by 'sasl-next-step.") + "A list of functions to be called in sequence for the NTLM +authentication steps. They are called by `sasl-next-step'.") (defun sasl-ntlm-request (client step) "SASL step function to generate a NTLM authentication request to the server. -Called from 'sasl-next-step. +Called from `sasl-next-step'. CLIENT is a vector [mechanism user service server sasl-client-properties] STEP is a vector [ ]" (let ((user (sasl-client-name client))) @@ -49,7 +49,7 @@ STEP is a vector [ ]" (defun sasl-ntlm-response (client step) "SASL step function to generate a NTLM response against the server -challenge stored in the 2nd element of STEP. Called from 'sasl-next-step." +challenge stored in the 2nd element of STEP. Called from `sasl-next-step'." (let* ((user (sasl-client-name client)) (passphrase (sasl-read-passphrase (format "NTLM passphrase for %s: " user))) diff --git a/lisp/sasl.el b/lisp/sasl.el index 23d8e6227..6616bffc3 100644 --- a/lisp/sasl.el +++ b/lisp/sasl.el @@ -86,7 +86,7 @@ The second argument PLIST is the new property list." (setplist (aref client 4) plist)) (defun sasl-client-set-property (client property value) - "Add the given property/value to CLIENT." + "Add the given PROPERTY/VALUE to CLIENT." (put (aref client 4) property value)) (defun sasl-client-property (client property) @@ -103,7 +103,7 @@ The second argument PLIST is the new property list." (defun sasl-make-mechanism (name steps) "Make an authentication mechanism. NAME is a IANA registered SASL mechanism name. -STEPS is list of continuation function." +STEPS is list of continuation functions." (vector name (mapcar (lambda (step) @@ -121,7 +121,7 @@ STEPS is list of continuation function." (aref mechanism 1)) (defun sasl-find-mechanism (mechanisms) - "Retrieve an apropriate mechanism object from MECHANISMS hints." + "Retrieve an appropriate mechanism object from MECHANISMS hints." (let* ((sasl-mechanisms sasl-mechanisms) (mechanism (catch 'done @@ -147,9 +147,9 @@ STEPS is list of continuation function." (defun sasl-next-step (client step) "Evaluate the challenge and prepare an appropriate next response. -The data type of the value and optional 2nd argument STEP is nil or -opaque authentication step which holds the reference to the next action -and the current challenge. At the first time STEP should be set to nil." +The data type of the value and 2nd argument STEP is nil or opaque +authentication step which holds the reference to the next action and +the current challenge. At the first time STEP should be set to nil." (let* ((steps (sasl-mechanism-steps (sasl-client-mechanism client))) diff --git a/lisp/sieve-manage.el b/lisp/sieve-manage.el index 38fece27a..513aa9fc0 100644 --- a/lisp/sieve-manage.el +++ b/lisp/sieve-manage.el @@ -443,12 +443,12 @@ Returns t if login was successful, nil otherwise." (defun sieve-manage-open (server &optional port stream auth buffer) "Open a network connection to a managesieve SERVER (string). -Optional variable PORT is port number (integer) on remote server. -Optional variable STREAM is any of `sieve-manage-streams' (a symbol). -Optional variable AUTH indicates authenticator to use, see -`sieve-manage-authenticators' for available authenticators. If nil, chooses -the best stream the server is capable of. -Optional variable BUFFER is buffer (buffer, or string naming buffer) +Optional argument PORT is port number (integer) on remote server. +Optional argument STREAM is any of `sieve-manage-streams' (a symbol). +Optional argument AUTH indicates authenticator to use, see +`sieve-manage-authenticators' for available authenticators. +If nil, chooses the best stream the server is capable of. +Optional argument BUFFER is buffer (buffer, or string naming buffer) to work in." (setq buffer (or buffer (format " *sieve* %s:%d" server (or port 2000)))) (with-current-buffer (get-buffer-create buffer) diff --git a/lisp/smime.el b/lisp/smime.el index 712880d48..c7d32e477 100644 --- a/lisp/smime.el +++ b/lisp/smime.el @@ -63,7 +63,7 @@ ;; ;; Now you should be able to sign messages! Create a buffer and write ;; something and run M-x smime-sign-buffer RET RET and you should see -;; your message MIME armoured and a signature. Encryption, M-x +;; your message MIME armored and a signature. Encryption, M-x ;; smime-encrypt-buffer, should also work. ;; ;; To be able to verify messages you need to build up trust with diff --git a/lisp/vc-annotate.el b/lisp/vc-annotate.el new file mode 100644 index 000000000..63a99f1ea --- /dev/null +++ b/lisp/vc-annotate.el @@ -0,0 +1,631 @@ +;;; vc-annotate.el --- VC Annotate Support + +;; Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006, +;; 2007, 2008 Free Software Foundation, Inc. + +;; Author: Martin Lorentzson +;; Maintainer: FSF +;; Keywords: tools + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: +;; + +(require 'vc-hooks) +(require 'vc) + +;;; Code: +(eval-when-compile + (require 'cl)) + +(defcustom vc-annotate-display-mode 'fullscale + "Which mode to color the output of \\[vc-annotate] with by default." + :type '(choice (const :tag "By Color Map Range" nil) + (const :tag "Scale to Oldest" scale) + (const :tag "Scale Oldest->Newest" fullscale) + (number :tag "Specify Fractional Number of Days" + :value "20.5")) + :group 'vc) + +(defcustom vc-annotate-color-map + (if (and (tty-display-color-p) (<= (display-color-cells) 8)) + ;; A custom sorted TTY colormap + (let* ((colors + (sort + (delq nil + (mapcar (lambda (x) + (if (not (or + (string-equal (car x) "white") + (string-equal (car x) "black") )) + (car x))) + (tty-color-alist))) + (lambda (a b) + (cond + ((or (string-equal a "red") (string-equal b "blue")) t) + ((or (string-equal b "red") (string-equal a "blue")) nil) + ((string-equal a "yellow") t) + ((string-equal b "yellow") nil) + ((string-equal a "cyan") t) + ((string-equal b "cyan") nil) + ((string-equal a "green") t) + ((string-equal b "green") nil) + ((string-equal a "magenta") t) + ((string-equal b "magenta") nil) + (t (string< a b)))))) + (date 20.) + (delta (/ (- 360. date) (1- (length colors))))) + (mapcar (lambda (x) + (prog1 + (cons date x) + (setq date (+ date delta)))) colors)) + ;; Normal colormap: hue stepped from 0-240deg, value=1., saturation=0.75 + '(( 20. . "#FF3F3F") + ( 40. . "#FF6C3F") + ( 60. . "#FF993F") + ( 80. . "#FFC63F") + (100. . "#FFF33F") + (120. . "#DDFF3F") + (140. . "#B0FF3F") + (160. . "#83FF3F") + (180. . "#56FF3F") + (200. . "#3FFF56") + (220. . "#3FFF83") + (240. . "#3FFFB0") + (260. . "#3FFFDD") + (280. . "#3FF3FF") + (300. . "#3FC6FF") + (320. . "#3F99FF") + (340. . "#3F6CFF") + (360. . "#3F3FFF"))) + "Association list of age versus color, for \\[vc-annotate]. +Ages are given in units of fractional days. Default is eighteen +steps using a twenty day increment, from red to blue. For TTY +displays with 8 or fewer colors, the default is red to blue with +all other colors between (excluding black and white)." + :type 'alist + :group 'vc) + +(defcustom vc-annotate-very-old-color "#3F3FFF" + "Color for lines older than the current color range in \\[vc-annotate]]." + :type 'string + :group 'vc) + +(defcustom vc-annotate-background "black" + "Background color for \\[vc-annotate]. +Default color is used if nil." + :type '(choice (const :tag "Default background" nil) (color)) + :group 'vc) + +(defcustom vc-annotate-menu-elements '(2 0.5 0.1 0.01) + "Menu elements for the mode-specific menu of VC-Annotate mode. +List of factors, used to expand/compress the time scale. See `vc-annotate'." + :type '(repeat number) + :group 'vc) + +(defvar vc-annotate-mode-map + (let ((m (make-sparse-keymap))) + (define-key m "a" 'vc-annotate-revision-previous-to-line) + (define-key m "d" 'vc-annotate-show-diff-revision-at-line) + (define-key m "D" 'vc-annotate-show-changeset-diff-revision-at-line) + (define-key m "f" 'vc-annotate-find-revision-at-line) + (define-key m "j" 'vc-annotate-revision-at-line) + (define-key m "l" 'vc-annotate-show-log-revision-at-line) + (define-key m "n" 'vc-annotate-next-revision) + (define-key m "p" 'vc-annotate-prev-revision) + (define-key m "w" 'vc-annotate-working-revision) + (define-key m "v" 'vc-annotate-toggle-annotation-visibility) + m) + "Local keymap used for VC-Annotate mode.") + +;;; Annotate functionality + +;; Declare globally instead of additional parameter to +;; temp-buffer-show-function (not possible to pass more than one +;; parameter). The use of annotate-ratio is deprecated in favor of +;; annotate-mode, which replaces it with the more sensible "span-to +;; days", along with autoscaling support. +(defvar vc-annotate-ratio nil "Global variable.") + +;; internal buffer-local variables +(defvar vc-annotate-backend nil) +(defvar vc-annotate-parent-file nil) +(defvar vc-annotate-parent-rev nil) +(defvar vc-annotate-parent-display-mode nil) + +(defconst vc-annotate-font-lock-keywords + ;; The fontification is done by vc-annotate-lines instead of font-lock. + '((vc-annotate-lines))) + +(define-derived-mode vc-annotate-mode special-mode "Annotate" + "Major mode for output buffers of the `vc-annotate' command. + +You can use the mode-specific menu to alter the time-span of the used +colors. See variable `vc-annotate-menu-elements' for customizing the +menu items." + ;; Frob buffer-invisibility-spec so that if it is originally a naked t, + ;; it will become a list, to avoid initial annotations being invisible. + (add-to-invisibility-spec 'foo) + (remove-from-invisibility-spec 'foo) + (set (make-local-variable 'truncate-lines) t) + (set (make-local-variable 'font-lock-defaults) + '(vc-annotate-font-lock-keywords t))) + +(defun vc-annotate-toggle-annotation-visibility () + "Toggle whether or not the annotation is visible." + (interactive) + (funcall (if (memq 'vc-annotate-annotation buffer-invisibility-spec) + 'remove-from-invisibility-spec + 'add-to-invisibility-spec) + 'vc-annotate-annotation) + (force-window-update (current-buffer))) + +(defun vc-annotate-display-default (ratio) + "Display the output of \\[vc-annotate] using the default color range. +The color range is given by `vc-annotate-color-map', scaled by RATIO. +The current time is used as the offset." + (interactive (progn (kill-local-variable 'vc-annotate-color-map) '(1.0))) + (message "Redisplaying annotation...") + (vc-annotate-display ratio) + (message "Redisplaying annotation...done")) + +(defun vc-annotate-oldest-in-map (color-map) + "Return the oldest time in the COLOR-MAP." + ;; Since entries should be sorted, we can just use the last one. + (caar (last color-map))) + +(defun vc-annotate-get-time-set-line-props () + (let ((bol (point)) + (date (vc-call-backend vc-annotate-backend 'annotate-time)) + (inhibit-read-only t)) + (assert (>= (point) bol)) + (put-text-property bol (point) 'invisible 'vc-annotate-annotation) + date)) + +(defun vc-annotate-display-autoscale (&optional full) + "Highlight the output of \\[vc-annotate] using an autoscaled color map. +Autoscaling means that the map is scaled from the current time to the +oldest annotation in the buffer, or, with prefix argument FULL, to +cover the range from the oldest annotation to the newest." + (interactive "P") + (let ((newest 0.0) + (oldest 999999.) ;Any CVS users at the founding of Rome? + (current (vc-annotate-convert-time (current-time))) + date) + (message "Redisplaying annotation...") + ;; Run through this file and find the oldest and newest dates annotated. + (save-excursion + (goto-char (point-min)) + (while (not (eobp)) + (when (setq date (vc-annotate-get-time-set-line-props)) + (when (> date newest) + (setq newest date)) + (when (< date oldest) + (setq oldest date))) + (forward-line 1))) + (vc-annotate-display + (/ (- (if full newest current) oldest) + (vc-annotate-oldest-in-map vc-annotate-color-map)) + (if full newest)) + (message "Redisplaying annotation...done \(%s\)" + (if full + (format "Spanned from %.1f to %.1f days old" + (- current oldest) + (- current newest)) + (format "Spanned to %.1f days old" (- current oldest)))))) + +;; Menu -- Using easymenu.el +(easy-menu-define vc-annotate-mode-menu vc-annotate-mode-map + "VC Annotate Display Menu" + `("VC-Annotate" + ["By Color Map Range" (unless (null vc-annotate-display-mode) + (setq vc-annotate-display-mode nil) + (vc-annotate-display-select)) + :style toggle :selected (null vc-annotate-display-mode)] + ,@(let ((oldest-in-map (vc-annotate-oldest-in-map vc-annotate-color-map))) + (mapcar (lambda (element) + (let ((days (* element oldest-in-map))) + `[,(format "Span %.1f days" days) + (vc-annotate-display-select nil ,days) + :style toggle :selected + (eql vc-annotate-display-mode ,days) ])) + vc-annotate-menu-elements)) + ["Span ..." + (vc-annotate-display-select + nil (float (string-to-number (read-string "Span how many days? "))))] + "--" + ["Span to Oldest" + (unless (eq vc-annotate-display-mode 'scale) + (vc-annotate-display-select nil 'scale)) + :help + "Use an autoscaled color map from the oldest annotation to the current time" + :style toggle :selected + (eq vc-annotate-display-mode 'scale)] + ["Span Oldest->Newest" + (unless (eq vc-annotate-display-mode 'fullscale) + (vc-annotate-display-select nil 'fullscale)) + :help + "Use an autoscaled color map from the oldest to the newest annotation" + :style toggle :selected + (eq vc-annotate-display-mode 'fullscale)] + "--" + ["Toggle annotation visibility" vc-annotate-toggle-annotation-visibility + :help + "Toggle whether the annotation is visible or not"] + ["Annotate previous revision" vc-annotate-prev-revision + :help "Visit the annotation of the revision previous to this one"] + ["Annotate next revision" vc-annotate-next-revision + :help "Visit the annotation of the revision after this one"] + ["Annotate revision at line" vc-annotate-revision-at-line + :help + "Visit the annotation of the revision identified in the current line"] + ["Annotate revision previous to line" vc-annotate-revision-previous-to-line + :help "Visit the annotation of the revision before the revision at line"] + ["Annotate latest revision" vc-annotate-working-revision + :help "Visit the annotation of the working revision of this file"] + ["Show log of revision at line" vc-annotate-show-log-revision-at-line + :help "Visit the log of the revision at line"] + ["Show diff of revision at line" vc-annotate-show-diff-revision-at-line + :help "Visit the diff of the revision at line from its previous revision"] + ["Show changeset diff of revision at line" + vc-annotate-show-changeset-diff-revision-at-line + :enable + (eq 'repository (vc-call-backend ,vc-annotate-backend 'revision-granularity)) + :help "Visit the diff of the revision at line from its previous revision"] + ["Visit revision at line" vc-annotate-find-revision-at-line + :help "Visit the revision identified in the current line"])) + +(defun vc-annotate-display-select (&optional buffer mode) + "Highlight the output of \\[vc-annotate]. +By default, the current buffer is highlighted, unless overridden by +BUFFER. `vc-annotate-display-mode' specifies the highlighting mode to +use; you may override this using the second optional arg MODE." + (interactive) + (when mode (setq vc-annotate-display-mode mode)) + (pop-to-buffer (or buffer (current-buffer))) + (cond ((null vc-annotate-display-mode) + ;; The ratio is global, thus relative to the global color-map. + (kill-local-variable 'vc-annotate-color-map) + (vc-annotate-display-default (or vc-annotate-ratio 1.0))) + ;; One of the auto-scaling modes + ((eq vc-annotate-display-mode 'scale) + (vc-exec-after `(vc-annotate-display-autoscale))) + ((eq vc-annotate-display-mode 'fullscale) + (vc-exec-after `(vc-annotate-display-autoscale t))) + ((numberp vc-annotate-display-mode) ; A fixed number of days lookback + (vc-annotate-display-default + (/ vc-annotate-display-mode + (vc-annotate-oldest-in-map vc-annotate-color-map)))) + (t (error "No such display mode: %s" + vc-annotate-display-mode)))) + +;;;###autoload +(defun vc-annotate (file rev &optional display-mode buf move-point-to) + "Display the edit history of the current file using colors. + +This command creates a buffer that shows, for each line of the current +file, when it was last edited and by whom. Additionally, colors are +used to show the age of each line--blue means oldest, red means +youngest, and intermediate colors indicate intermediate ages. By +default, the time scale stretches back one year into the past; +everything that is older than that is shown in blue. + +With a prefix argument, this command asks two questions in the +minibuffer. First, you may enter a revision number; then the buffer +displays and annotates that revision instead of the working revision +\(type RET in the minibuffer to leave that default unchanged). Then, +you are prompted for the time span in days which the color range +should cover. For example, a time span of 20 days means that changes +over the past 20 days are shown in red to blue, according to their +age, and everything that is older than that is shown in blue. + +If MOVE-POINT-TO is given, move the point to that line. + +Customization variables: + +`vc-annotate-menu-elements' customizes the menu elements of the +mode-specific menu. `vc-annotate-color-map' and +`vc-annotate-very-old-color' define the mapping of time to colors. +`vc-annotate-background' specifies the background color." + (interactive + (save-current-buffer + (vc-ensure-vc-buffer) + (list buffer-file-name + (let ((def (vc-working-revision buffer-file-name))) + (if (null current-prefix-arg) def + (read-string + (format "Annotate from revision (default %s): " def) + nil nil def))) + (if (null current-prefix-arg) + vc-annotate-display-mode + (float (string-to-number + (read-string "Annotate span days (default 20): " + nil nil "20"))))))) + (vc-ensure-vc-buffer) + (setq vc-annotate-display-mode display-mode) ;Not sure why. --Stef + (let* ((temp-buffer-name (format "*Annotate %s (rev %s)*" (buffer-name) rev)) + (temp-buffer-show-function 'vc-annotate-display-select) + ;; If BUF is specified, we presume the caller maintains current line, + ;; so we don't need to do it here. This implementation may give + ;; strange results occasionally in the case of REV != WORKFILE-REV. + (current-line (or move-point-to (unless buf (line-number-at-pos))))) + (message "Annotating...") + ;; If BUF is specified it tells in which buffer we should put the + ;; annotations. This is used when switching annotations to another + ;; revision, so we should update the buffer's name. + (when buf (with-current-buffer buf + (rename-buffer temp-buffer-name t) + ;; In case it had to be uniquified. + (setq temp-buffer-name (buffer-name)))) + (with-output-to-temp-buffer temp-buffer-name + (let ((backend (vc-backend file))) + (vc-call-backend backend 'annotate-command file + (get-buffer temp-buffer-name) rev) + ;; we must setup the mode first, and then set our local + ;; variables before the show-function is called at the exit of + ;; with-output-to-temp-buffer + (with-current-buffer temp-buffer-name + (unless (equal major-mode 'vc-annotate-mode) + (vc-annotate-mode)) + (set (make-local-variable 'vc-annotate-backend) backend) + (set (make-local-variable 'vc-annotate-parent-file) file) + (set (make-local-variable 'vc-annotate-parent-rev) rev) + (set (make-local-variable 'vc-annotate-parent-display-mode) + display-mode)))) + + (with-current-buffer temp-buffer-name + (vc-exec-after + `(progn + ;; Ideally, we'd rather not move point if the user has already + ;; moved it elsewhere, but really point here is not the position + ;; of the user's cursor :-( + (when ,current-line ;(and (bobp)) + (goto-line ,current-line) + (setq vc-sentinel-movepoint (point))) + (unless (active-minibuffer-window) + (message "Annotating... done"))))))) + +(defun vc-annotate-prev-revision (prefix) + "Visit the annotation of the revision previous to this one. + +With a numeric prefix argument, annotate the revision that many +revisions previous." + (interactive "p") + (vc-annotate-warp-revision (- 0 prefix))) + +(defun vc-annotate-next-revision (prefix) + "Visit the annotation of the revision after this one. + +With a numeric prefix argument, annotate the revision that many +revisions after." + (interactive "p") + (vc-annotate-warp-revision prefix)) + +(defun vc-annotate-working-revision () + "Visit the annotation of the working revision of this file." + (interactive) + (if (not (equal major-mode 'vc-annotate-mode)) + (message "Cannot be invoked outside of a vc annotate buffer") + (let ((warp-rev (vc-working-revision vc-annotate-parent-file))) + (if (equal warp-rev vc-annotate-parent-rev) + (message "Already at revision %s" warp-rev) + (vc-annotate-warp-revision warp-rev))))) + +(defun vc-annotate-extract-revision-at-line () + "Extract the revision number of the current line." + ;; This function must be invoked from a buffer in vc-annotate-mode + (vc-call-backend vc-annotate-backend 'annotate-extract-revision-at-line)) + +(defun vc-annotate-revision-at-line () + "Visit the annotation of the revision identified in the current line." + (interactive) + (if (not (equal major-mode 'vc-annotate-mode)) + (message "Cannot be invoked outside of a vc annotate buffer") + (let ((rev-at-line (vc-annotate-extract-revision-at-line))) + (if (not rev-at-line) + (message "Cannot extract revision number from the current line") + (if (equal rev-at-line vc-annotate-parent-rev) + (message "Already at revision %s" rev-at-line) + (vc-annotate-warp-revision rev-at-line)))))) + +(defun vc-annotate-find-revision-at-line () + "Visit the revision identified in the current line." + (interactive) + (if (not (equal major-mode 'vc-annotate-mode)) + (message "Cannot be invoked outside of a vc annotate buffer") + (let ((rev-at-line (vc-annotate-extract-revision-at-line))) + (if (not rev-at-line) + (message "Cannot extract revision number from the current line") + (vc-revision-other-window rev-at-line))))) + +(defun vc-annotate-revision-previous-to-line () + "Visit the annotation of the revision before the revision at line." + (interactive) + (if (not (equal major-mode 'vc-annotate-mode)) + (message "Cannot be invoked outside of a vc annotate buffer") + (let ((rev-at-line (vc-annotate-extract-revision-at-line)) + (prev-rev nil)) + (if (not rev-at-line) + (message "Cannot extract revision number from the current line") + (setq prev-rev + (vc-call-backend vc-annotate-backend 'previous-revision + vc-annotate-parent-file rev-at-line)) + (vc-annotate-warp-revision prev-rev))))) + +(defun vc-annotate-show-log-revision-at-line () + "Visit the log of the revision at line." + (interactive) + (if (not (equal major-mode 'vc-annotate-mode)) + (message "Cannot be invoked outside of a vc annotate buffer") + (let ((rev-at-line (vc-annotate-extract-revision-at-line))) + (if (not rev-at-line) + (message "Cannot extract revision number from the current line") + (vc-print-log rev-at-line))))) + +(defun vc-annotate-show-diff-revision-at-line-internal (fileset) + (if (not (equal major-mode 'vc-annotate-mode)) + (message "Cannot be invoked outside of a vc annotate buffer") + (let ((rev-at-line (vc-annotate-extract-revision-at-line)) + (prev-rev nil)) + (if (not rev-at-line) + (message "Cannot extract revision number from the current line") + (setq prev-rev + (vc-call-backend vc-annotate-backend 'previous-revision + vc-annotate-parent-file rev-at-line)) + (if (not prev-rev) + (message "Cannot diff from any revision prior to %s" rev-at-line) + (save-window-excursion + (vc-diff-internal + nil + ;; The value passed here should follow what + ;; `vc-deduce-fileset' returns. + (cons vc-annotate-backend (cons fileset nil)) + prev-rev rev-at-line)) + (switch-to-buffer "*vc-diff*")))))) + +(defun vc-annotate-show-diff-revision-at-line () + "Visit the diff of the revision at line from its previous revision." + (interactive) + (vc-annotate-show-diff-revision-at-line-internal (list vc-annotate-parent-file))) + +(defun vc-annotate-show-changeset-diff-revision-at-line () + "Visit the diff of the revision at line from its previous revision for all files in the changeset." + (interactive) + (when (eq 'file (vc-call-backend vc-annotate-backend 'revision-granularity)) + (error "The %s backend does not support changeset diffs" vc-annotate-backend)) + (vc-annotate-show-diff-revision-at-line-internal nil)) + +(defun vc-annotate-warp-revision (revspec) + "Annotate the revision described by REVSPEC. + +If REVSPEC is a positive integer, warp that many revisions +forward, if possible, otherwise echo a warning message. If +REVSPEC is a negative integer, warp that many revisions backward, +if possible, otherwise echo a warning message. If REVSPEC is a +string, then it describes a revision number, so warp to that +revision." + (if (not (equal major-mode 'vc-annotate-mode)) + (message "Cannot be invoked outside of a vc annotate buffer") + (let* ((buf (current-buffer)) + (oldline (line-number-at-pos)) + (revspeccopy revspec) + (newrev nil)) + (cond + ((and (integerp revspec) (> revspec 0)) + (setq newrev vc-annotate-parent-rev) + (while (and (> revspec 0) newrev) + (setq newrev (vc-call-backend vc-annotate-backend 'next-revision + vc-annotate-parent-file newrev)) + (setq revspec (1- revspec))) + (unless newrev + (message "Cannot increment %d revisions from revision %s" + revspeccopy vc-annotate-parent-rev))) + ((and (integerp revspec) (< revspec 0)) + (setq newrev vc-annotate-parent-rev) + (while (and (< revspec 0) newrev) + (setq newrev (vc-call-backend vc-annotate-backend 'previous-revision + vc-annotate-parent-file newrev)) + (setq revspec (1+ revspec))) + (unless newrev + (message "Cannot decrement %d revisions from revision %s" + (- 0 revspeccopy) vc-annotate-parent-rev))) + ((stringp revspec) (setq newrev revspec)) + (t (error "Invalid argument to vc-annotate-warp-revision"))) + (when newrev + (vc-annotate vc-annotate-parent-file newrev + vc-annotate-parent-display-mode + buf + ;; Pass the current line so that vc-annotate will + ;; place the point in the line. + (min oldline (progn (goto-char (point-max)) + (forward-line -1) + (line-number-at-pos)))))))) + +(defun vc-annotate-compcar (threshold a-list) + "Test successive cons cells of A-LIST against THRESHOLD. +Return the first cons cell with a car that is not less than THRESHOLD, +nil if no such cell exists." + (let ((i 1) + (tmp-cons (car a-list))) + (while (and tmp-cons (< (car tmp-cons) threshold)) + (setq tmp-cons (car (nthcdr i a-list))) + (setq i (+ i 1))) + tmp-cons)) ; Return the appropriate value + +(defun vc-annotate-convert-time (time) + "Convert a time value to a floating-point number of days. +The argument TIME is a list as returned by `current-time' or +`encode-time', only the first two elements of that list are considered." + (/ (+ (* (float (car time)) (lsh 1 16)) (cadr time)) 24 3600)) + +(defun vc-annotate-difference (&optional offset) + "Return the time span in days to the next annotation. +This calls the backend function annotate-time, and returns the +difference in days between the time returned and the current time, +or OFFSET if present." + (let ((next-time (vc-annotate-get-time-set-line-props))) + (when next-time + (- (or offset + (vc-call-backend vc-annotate-backend 'annotate-current-time)) + next-time)))) + +(defun vc-default-annotate-current-time (backend) + "Return the current time, encoded as fractional days." + (vc-annotate-convert-time (current-time))) + +(defvar vc-annotate-offset nil) + +(defun vc-annotate-display (ratio &optional offset) + "Highlight `vc-annotate' output in the current buffer. +RATIO, is the expansion that should be applied to `vc-annotate-color-map'. +The annotations are relative to the current time, unless overridden by OFFSET." + (when (/= ratio 1.0) + (set (make-local-variable 'vc-annotate-color-map) + (mapcar (lambda (elem) (cons (* (car elem) ratio) (cdr elem))) + vc-annotate-color-map))) + (set (make-local-variable 'vc-annotate-offset) offset) + (font-lock-mode 1)) + +(defun vc-annotate-lines (limit) + (while (< (point) limit) + (let ((difference (vc-annotate-difference vc-annotate-offset)) + (start (point)) + (end (progn (forward-line 1) (point)))) + (when difference + (let* ((color (or (vc-annotate-compcar difference vc-annotate-color-map) + (cons nil vc-annotate-very-old-color))) + ;; substring from index 1 to remove any leading `#' in the name + (face-name (concat "vc-annotate-face-" + (if (string-equal + (substring (cdr color) 0 1) "#") + (substring (cdr color) 1) + (cdr color)))) + ;; Make the face if not done. + (face (or (intern-soft face-name) + (let ((tmp-face (make-face (intern face-name)))) + (set-face-foreground tmp-face (cdr color)) + (when vc-annotate-background + (set-face-background tmp-face + vc-annotate-background)) + tmp-face)))) ; Return the face + (put-text-property start end 'face face))))) + ;; Pretend to font-lock there were no matches. + nil) + +(provide 'vc-annotate) + +;; arch-tag: c3454a89-80e5-4ffd-8993-671b59612898 +;;; vc-annotate.el ends here diff --git a/lisp/vc-dir.el b/lisp/vc-dir.el new file mode 100644 index 000000000..5beba0be5 --- /dev/null +++ b/lisp/vc-dir.el @@ -0,0 +1,1067 @@ +;;; vc-dir.el --- Directory status display under VC + +;; Copyright (C) 2007, 2008 +;; Free Software Foundation, Inc. + +;; Author: Dan Nicolaescu +;; Keywords: tools + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Credits: + +;; The original VC directory status implementation was based on dired. +;; This implementation was inspired by PCL-CVS. +;; Many people contributed comments, ideas and code to this +;; implementation. These include: +;; +;; Alexandre Julliard +;; Stefan Monnier +;; Tom Tromey + +;;; Commentary: +;; + +;;; Todo: see vc.el. + +(require 'vc-hooks) +(require 'vc) +(require 'tool-bar) +(require 'ewoc) + +;;; Code: +(eval-when-compile + (require 'cl)) + +(defcustom vc-dir-mode-hook nil + "Normal hook run by `vc-dir-mode'. +See `run-hooks'." + :type 'hook + :group 'vc) + +;; Used to store information for the files displayed in the directory buffer. +;; Each item displayed corresponds to one of these defstructs. +(defstruct (vc-dir-fileinfo + (:copier nil) + (:type list) ;So we can use `member' on lists of FIs. + (:constructor + ;; We could define it as an alias for `list'. + vc-dir-create-fileinfo (name state &optional extra marked directory)) + (:conc-name vc-dir-fileinfo->)) + name ;Keep it as first, for `member'. + state + ;; For storing backend specific information. + extra + marked + ;; To keep track of not updated files during a global refresh + needs-update + ;; To distinguish files and directories. + directory) + +(defvar vc-ewoc nil) + +(defvar vc-dir-process-buffer nil + "The buffer used for the asynchronous call that computes status.") + +(defvar vc-dir-backend nil + "The backend used by the current *vc-dir* buffer.") + +(defun vc-dir-move-to-goal-column () + ;; Used to keep the cursor on the file name column. + (beginning-of-line) + (unless (eolp) + ;; Must be in sync with vc-default-status-printer. + (forward-char 25))) + +(defun vc-dir-prepare-status-buffer (bname dir backend &optional create-new) + "Find a buffer named BNAME showing DIR, or create a new one." + (setq dir (expand-file-name dir)) + (let* + ;; Look for another buffer name BNAME visiting the same directory. + ((buf (save-excursion + (unless create-new + (dolist (buffer (buffer-list)) + (set-buffer buffer) + (when (and (derived-mode-p 'vc-dir-mode) + (eq vc-dir-backend backend) + (string= (expand-file-name default-directory) dir)) + (return buffer))))))) + (or buf + ;; Create a new buffer named BNAME. + (with-current-buffer (create-file-buffer bname) + (cd dir) + (vc-setup-buffer (current-buffer)) + ;; Reset the vc-parent-buffer-name so that it does not appear + ;; in the mode-line. + (setq vc-parent-buffer-name nil) + (current-buffer))))) + +(defvar vc-dir-menu-map + (let ((map (make-sparse-keymap "VC-dir"))) + (define-key map [quit] + '(menu-item "Quit" quit-window + :help "Quit")) + (define-key map [kill] + '(menu-item "Kill Update Command" vc-dir-kill-dir-status-process + :enable (vc-dir-busy) + :help "Kill the command that updates the directory buffer")) + (define-key map [refresh] + '(menu-item "Refresh" revert-buffer + :enable (not (vc-dir-busy)) + :help "Refresh the contents of the directory buffer")) + (define-key map [remup] + '(menu-item "Hide up-to-date" vc-dir-hide-up-to-date + :help "Hide up-to-date items from display")) + ;; Movement. + (define-key map [sepmv] '("--")) + (define-key map [next-line] + '(menu-item "Next line" vc-dir-next-line + :help "Go to the next line" :keys "n")) + (define-key map [previous-line] + '(menu-item "Previous line" vc-dir-previous-line + :help "Go to the previous line")) + ;; Marking. + (define-key map [sepmrk] '("--")) + (define-key map [unmark-all] + '(menu-item "Unmark All" vc-dir-unmark-all-files + :help "Unmark all files that are in the same state as the current file\ +\nWith prefix argument unmark all files")) + (define-key map [unmark-previous] + '(menu-item "Unmark previous " vc-dir-unmark-file-up + :help "Move to the previous line and unmark the file")) + + (define-key map [mark-all] + '(menu-item "Mark All" vc-dir-mark-all-files + :help "Mark all files that are in the same state as the current file\ +\nWith prefix argument mark all files")) + (define-key map [unmark] + '(menu-item "Unmark" vc-dir-unmark + :help "Unmark the current file or all files in the region")) + + (define-key map [mark] + '(menu-item "Mark" vc-dir-mark + :help "Mark the current file or all files in the region")) + + (define-key map [sepopn] '("--")) + (define-key map [open-other] + '(menu-item "Open in other window" vc-dir-find-file-other-window + :help "Find the file on the current line, in another window")) + (define-key map [open] + '(menu-item "Open file" vc-dir-find-file + :help "Find the file on the current line")) + (define-key map [sepvcdet] '("--")) + ;; FIXME: This needs a key binding. And maybe a better name + ;; ("Insert" like PCL-CVS uses does not sound that great either)... + (define-key map [ins] + '(menu-item "Show File" vc-dir-show-fileentry + :help "Show a file in the VC status listing even though it might be up to date")) + (define-key map [annotate] + '(menu-item "Annotate" vc-annotate + :help "Display the edit history of the current file using colors")) + (define-key map [diff] + '(menu-item "Compare with Base Version" vc-diff + :help "Compare file set with the base version")) + (define-key map [log] + '(menu-item "Show history" vc-print-log + :help "List the change log of the current file set in a window")) + ;; VC commands. + (define-key map [sepvccmd] '("--")) + (define-key map [update] + '(menu-item "Update to latest version" vc-update + :help "Update the current fileset's files to their tip revisions")) + (define-key map [revert] + '(menu-item "Revert to base version" vc-revert + :help "Revert working copies of the selected fileset to their repository contents.")) + (define-key map [next-action] + ;; FIXME: This really really really needs a better name! + ;; And a key binding too. + '(menu-item "Check In/Out" vc-next-action + :help "Do the next logical version control operation on the current fileset")) + (define-key map [register] + '(menu-item "Register" vc-register + :help "Register file set into the version control system")) + map) + "Menu for dispatcher status") + +;; VC backends can use this to add mode-specific menu items to +;; vc-dir-menu-map. +(defun vc-dir-menu-map-filter (orig-binding) + (when (and (symbolp orig-binding) (fboundp orig-binding)) + (setq orig-binding (indirect-function orig-binding))) + (let ((ext-binding + (when (derived-mode-p 'vc-dir-mode) + (vc-call-backend vc-dir-backend 'extra-status-menu)))) + (if (null ext-binding) + orig-binding + (append orig-binding + '("----") + ext-binding)))) + +(defvar vc-dir-mode-map + (let ((map (make-keymap))) + (suppress-keymap map) + ;; VC commands + (define-key map "v" 'vc-next-action) ;; C-x v v + (define-key map "=" 'vc-diff) ;; C-x v = + (define-key map "i" 'vc-register) ;; C-x v i + (define-key map "+" 'vc-update) ;; C-x v + + (define-key map "l" 'vc-print-log) ;; C-x v l + ;; More confusing than helpful, probably + ;;(define-key map "R" 'vc-revert) ;; u is taken by dispatcher unmark. + ;;(define-key map "A" 'vc-annotate) ;; g is taken by dispatcher refresh + ;; Marking. + (define-key map "m" 'vc-dir-mark) + (define-key map "M" 'vc-dir-mark-all-files) + (define-key map "u" 'vc-dir-unmark) + (define-key map "U" 'vc-dir-unmark-all-files) + (define-key map "\C-?" 'vc-dir-unmark-file-up) + (define-key map "\M-\C-?" 'vc-dir-unmark-all-files) + ;; Movement. + (define-key map "n" 'vc-dir-next-line) + (define-key map " " 'vc-dir-next-line) + (define-key map "\t" 'vc-dir-next-directory) + (define-key map "p" 'vc-dir-previous-line) + (define-key map [backtab] 'vc-dir-previous-directory) + ;;; Rebind paragraph-movement commands. + (define-key map "\M-}" 'vc-dir-next-directory) + (define-key map "\M-{" 'vc-dir-previous-directory) + (define-key map [C-down] 'vc-dir-next-directory) + (define-key map [C-up] 'vc-dir-previous-directory) + ;; The remainder. + (define-key map "f" 'vc-dir-find-file) + (define-key map "\C-m" 'vc-dir-find-file) + (define-key map "o" 'vc-dir-find-file-other-window) + (define-key map "\C-c\C-c" 'vc-dir-kill-dir-status-process) + (define-key map [down-mouse-3] 'vc-dir-menu) + (define-key map [mouse-2] 'vc-dir-toggle-mark) + (define-key map "x" 'vc-dir-hide-up-to-date) + + ;; Hook up the menu. + (define-key map [menu-bar vc-dir-mode] + `(menu-item + ;; VC backends can use this to add mode-specific menu items to + ;; vc-dir-menu-map. + "VC-dir" ,vc-dir-menu-map :filter vc-dir-menu-map-filter)) + map) + "Keymap for directory buffer.") + +(defmacro vc-at-event (event &rest body) + "Evaluate `body' with point located at event-start of `event'. +If `body' uses `event', it should be a variable, + otherwise it will be evaluated twice." + (let ((posn (make-symbol "vc-at-event-posn"))) + `(let ((,posn (event-start ,event))) + (save-excursion + (set-buffer (window-buffer (posn-window ,posn))) + (goto-char (posn-point ,posn)) + ,@body)))) + +(defun vc-dir-menu (e) + "Popup the dispatcher status menu." + (interactive "e") + (vc-at-event e (popup-menu vc-dir-menu-map e))) + +(defvar vc-dir-tool-bar-map + (let ((map (make-sparse-keymap))) + (tool-bar-local-item-from-menu 'vc-dir-find-file "open" + map vc-dir-mode-map) + (tool-bar-local-item "bookmark_add" + 'vc-dir-toggle-mark 'vc-dir-toggle-mark map + :help "Toggle mark on current item") + (tool-bar-local-item-from-menu 'vc-dir-previous-line "left-arrow" + map vc-dir-mode-map + :rtl "right-arrow") + (tool-bar-local-item-from-menu 'vc-dir-next-line "right-arrow" + map vc-dir-mode-map + :rtl "left-arrow") + (tool-bar-local-item-from-menu 'vc-print-log "info" + map vc-dir-mode-map) + (tool-bar-local-item-from-menu 'revert-buffer "refresh" + map vc-dir-mode-map) + (tool-bar-local-item-from-menu 'nonincremental-search-forward + "search" map) + (tool-bar-local-item-from-menu 'vc-dir-kill-dir-status-process "cancel" + map vc-dir-mode-map) + (tool-bar-local-item-from-menu 'quit-window "exit" + map vc-dir-mode-map) + map)) + +(defun vc-dir-node-directory (node) + ;; Compute the directory for NODE. + ;; If it's a directory node, get it from the the node. + (let ((data (ewoc-data node))) + (or (vc-dir-fileinfo->directory data) + ;; Otherwise compute it from the file name. + (file-name-directory + (expand-file-name + (vc-dir-fileinfo->name data)))))) + +(defun vc-dir-update (entries buffer &optional noinsert) + "Update BUFFER's ewoc from the list of ENTRIES. +If NOINSERT, ignore elements on ENTRIES which are not in the ewoc." + ;; Add ENTRIES to the vc-dir buffer BUFFER. + (with-current-buffer buffer + ;; Insert the entries sorted by name into the ewoc. + ;; We assume the ewoc is sorted too, which should be the + ;; case if we always add entries with vc-dir-update. + (setq entries + ;; Sort: first files and then subdirectories. + ;; XXX: this is VERY inefficient, it computes the directory + ;; names too many times + (sort entries + (lambda (entry1 entry2) + (let ((dir1 (file-name-directory (expand-file-name (car entry1)))) + (dir2 (file-name-directory (expand-file-name (car entry2))))) + (cond + ((string< dir1 dir2) t) + ((not (string= dir1 dir2)) nil) + ((string< (car entry1) (car entry2)))))))) + ;; Insert directory entries in the right places. + (let ((entry (car entries)) + (node (ewoc-nth vc-ewoc 0))) + ;; Insert . if it is not present. + (unless node + (let ((rd (file-relative-name default-directory))) + (ewoc-enter-last + vc-ewoc (vc-dir-create-fileinfo + rd nil nil nil (expand-file-name default-directory)))) + (setq node (ewoc-nth vc-ewoc 0))) + + (while (and entry node) + (let* ((entryfile (car entry)) + (entrydir (file-name-directory (expand-file-name entryfile))) + (nodedir (vc-dir-node-directory node))) + (cond + ;; First try to find the directory. + ((string-lessp nodedir entrydir) + (setq node (ewoc-next vc-ewoc node))) + ((string-equal nodedir entrydir) + ;; Found the directory, find the place for the file name. + (let ((nodefile (vc-dir-fileinfo->name (ewoc-data node)))) + (cond + ((string-lessp nodefile entryfile) + (setq node (ewoc-next vc-ewoc node))) + ((string-equal nodefile entryfile) + (setf (vc-dir-fileinfo->state (ewoc-data node)) (nth 1 entry)) + (setf (vc-dir-fileinfo->extra (ewoc-data node)) (nth 2 entry)) + (setf (vc-dir-fileinfo->needs-update (ewoc-data node)) nil) + (ewoc-invalidate vc-ewoc node) + (setq entries (cdr entries)) + (setq entry (car entries)) + (setq node (ewoc-next vc-ewoc node))) + (t + (ewoc-enter-before vc-ewoc node + (apply 'vc-dir-create-fileinfo entry)) + (setq entries (cdr entries)) + (setq entry (car entries)))))) + (t + ;; We might need to insert a directory node if the + ;; previous node was in a different directory. + (let* ((rd (file-relative-name entrydir)) + (prev-node (ewoc-prev vc-ewoc node)) + (prev-dir (vc-dir-node-directory prev-node))) + (unless (string-equal entrydir prev-dir) + (ewoc-enter-before + vc-ewoc node (vc-dir-create-fileinfo rd nil nil nil entrydir)))) + ;; Now insert the node itself. + (ewoc-enter-before vc-ewoc node + (apply 'vc-dir-create-fileinfo entry)) + (setq entries (cdr entries) entry (car entries)))))) + ;; We're past the last node, all remaining entries go to the end. + (unless (or node noinsert) + (let ((lastdir (vc-dir-node-directory (ewoc-nth vc-ewoc -1)))) + (dolist (entry entries) + (let ((entrydir (file-name-directory (expand-file-name (car entry))))) + ;; Insert a directory node if needed. + (unless (string-equal lastdir entrydir) + (setq lastdir entrydir) + (let ((rd (file-relative-name entrydir))) + (ewoc-enter-last + vc-ewoc (vc-dir-create-fileinfo rd nil nil nil entrydir)))) + ;; Now insert the node itself. + (ewoc-enter-last vc-ewoc + (apply 'vc-dir-create-fileinfo entry))))))))) + +(defun vc-dir-busy () + (and (buffer-live-p vc-dir-process-buffer) + (get-buffer-process vc-dir-process-buffer))) + +(defun vc-dir-kill-dir-status-process () + "Kill the temporary buffer and associated process." + (interactive) + (when (buffer-live-p vc-dir-process-buffer) + (let ((proc (get-buffer-process vc-dir-process-buffer))) + (when proc (delete-process proc)) + (setq vc-dir-process-buffer nil) + (setq mode-line-process nil)))) + +(defun vc-dir-kill-query () + ;; Make sure that when the status buffer is killed the update + ;; process running in background is also killed. + (if (vc-dir-busy) + (when (y-or-n-p "Status update process running, really kill status buffer? ") + (vc-dir-kill-dir-status-process) + t) + t)) + +(defun vc-dir-next-line (arg) + "Go to the next line. +If a prefix argument is given, move by that many lines." + (interactive "p") + (with-no-warnings + (ewoc-goto-next vc-ewoc arg) + (vc-dir-move-to-goal-column))) + +(defun vc-dir-previous-line (arg) + "Go to the previous line. +If a prefix argument is given, move by that many lines." + (interactive "p") + (ewoc-goto-prev vc-ewoc arg) + (vc-dir-move-to-goal-column)) + +(defun vc-dir-next-directory () + "Go to the next directory." + (interactive) + (let ((orig (point))) + (if + (catch 'foundit + (while t + (let* ((next (ewoc-next vc-ewoc (ewoc-locate vc-ewoc)))) + (cond ((not next) + (throw 'foundit t)) + (t + (progn + (ewoc-goto-node vc-ewoc next) + (vc-dir-move-to-goal-column) + (if (vc-dir-fileinfo->directory (ewoc-data next)) + (throw 'foundit nil)))))))) + (goto-char orig)))) + +(defun vc-dir-previous-directory () + "Go to the previous directory." + (interactive) + (let ((orig (point))) + (if + (catch 'foundit + (while t + (let* ((prev (ewoc-prev vc-ewoc (ewoc-locate vc-ewoc)))) + (cond ((not prev) + (throw 'foundit t)) + (t + (progn + (ewoc-goto-node vc-ewoc prev) + (vc-dir-move-to-goal-column) + (if (vc-dir-fileinfo->directory (ewoc-data prev)) + (throw 'foundit nil)))))))) + (goto-char orig)))) + +(defun vc-dir-mark-unmark (mark-unmark-function) + (if (use-region-p) + (let ((firstl (line-number-at-pos (region-beginning))) + (lastl (line-number-at-pos (region-end)))) + (save-excursion + (goto-char (region-beginning)) + (while (<= (line-number-at-pos) lastl) + (funcall mark-unmark-function)))) + (funcall mark-unmark-function))) + +(defun vc-dir-parent-marked-p (arg) + ;; Return nil if none of the parent directories of arg is marked. + (let* ((argdir (vc-dir-node-directory arg)) + (arglen (length argdir)) + (crt arg) + data dir) + ;; Go through the predecessors, checking if any directory that is + ;; a parent is marked. + (while (setq crt (ewoc-prev vc-ewoc crt)) + (setq data (ewoc-data crt)) + (setq dir (vc-dir-node-directory crt)) + (when (and (vc-dir-fileinfo->directory data) + (vc-string-prefix-p dir argdir)) + (when (vc-dir-fileinfo->marked data) + (error "Cannot mark `%s', parent directory `%s' marked" + (vc-dir-fileinfo->name (ewoc-data arg)) + (vc-dir-fileinfo->name data))))) + nil)) + +(defun vc-dir-children-marked-p (arg) + ;; Return nil if none of the children of arg is marked. + (let* ((argdir-re (concat "\\`" (regexp-quote (vc-dir-node-directory arg)))) + (is-child t) + (crt arg) + data dir) + (while (and is-child (setq crt (ewoc-next vc-ewoc crt))) + (setq data (ewoc-data crt)) + (setq dir (vc-dir-node-directory crt)) + (if (string-match argdir-re dir) + (when (vc-dir-fileinfo->marked data) + (error "Cannot mark `%s', child `%s' marked" + (vc-dir-fileinfo->name (ewoc-data arg)) + (vc-dir-fileinfo->name data))) + ;; We are done, we got to an entry that is not a child of `arg'. + (setq is-child nil))) + nil)) + +(defun vc-dir-mark-file (&optional arg) + ;; Mark ARG or the current file and move to the next line. + (let* ((crt (or arg (ewoc-locate vc-ewoc))) + (file (ewoc-data crt)) + (isdir (vc-dir-fileinfo->directory file))) + (when (or (and isdir (not (vc-dir-children-marked-p crt))) + (and (not isdir) (not (vc-dir-parent-marked-p crt)))) + (setf (vc-dir-fileinfo->marked file) t) + (ewoc-invalidate vc-ewoc crt) + (unless (or arg (mouse-event-p last-command-event)) + (vc-dir-next-line 1))))) + +(defun vc-dir-mark () + "Mark the current file or all files in the region. +If the region is active, mark all the files in the region. +Otherwise mark the file on the current line and move to the next +line." + (interactive) + (vc-dir-mark-unmark 'vc-dir-mark-file)) + +(defun vc-dir-mark-all-files (arg) + "Mark all files with the same state as the current one. +With a prefix argument mark all files. +If the current entry is a directory, mark all child files. + +The commands operate on files that are on the same state. +This command is intended to make it easy to select all files that +share the same state." + (interactive "P") + (if arg + ;; Mark all files. + (progn + ;; First check that no directory is marked, we can't mark + ;; files in that case. + (ewoc-map + (lambda (filearg) + (when (and (vc-dir-fileinfo->directory filearg) + (vc-dir-fileinfo->marked filearg)) + (error "Cannot mark all files, directory `%s' marked" + (vc-dir-fileinfo->name filearg)))) + vc-ewoc) + (ewoc-map + (lambda (filearg) + (unless (vc-dir-fileinfo->marked filearg) + (setf (vc-dir-fileinfo->marked filearg) t) + t)) + vc-ewoc)) + (let ((data (ewoc-data (ewoc-locate vc-ewoc)))) + (if (vc-dir-fileinfo->directory data) + ;; It's a directory, mark child files. + (let ((crt (ewoc-locate vc-ewoc))) + (unless (vc-dir-children-marked-p crt) + (while (setq crt (ewoc-next vc-ewoc crt)) + (let ((crt-data (ewoc-data crt))) + (unless (vc-dir-fileinfo->directory crt-data) + (setf (vc-dir-fileinfo->marked crt-data) t) + (ewoc-invalidate vc-ewoc crt)))))) + ;; It's a file + (let ((state (vc-dir-fileinfo->state data)) + (crt (ewoc-nth vc-ewoc 0))) + (while crt + (let ((crt-data (ewoc-data crt))) + (when (and (not (vc-dir-fileinfo->marked crt-data)) + (eq (vc-dir-fileinfo->state crt-data) state) + (not (vc-dir-fileinfo->directory crt-data))) + (vc-dir-mark-file crt))) + (setq crt (ewoc-next vc-ewoc crt)))))))) + +(defun vc-dir-unmark-file () + ;; Unmark the current file and move to the next line. + (let* ((crt (ewoc-locate vc-ewoc)) + (file (ewoc-data crt))) + (setf (vc-dir-fileinfo->marked file) nil) + (ewoc-invalidate vc-ewoc crt) + (unless (mouse-event-p last-command-event) + (vc-dir-next-line 1)))) + +(defun vc-dir-unmark () + "Unmark the current file or all files in the region. +If the region is active, unmark all the files in the region. +Otherwise mark the file on the current line and move to the next +line." + (interactive) + (vc-dir-mark-unmark 'vc-dir-unmark-file)) + +(defun vc-dir-unmark-file-up () + "Move to the previous line and unmark the file." + (interactive) + ;; If we're on the first line, we won't move up, but we will still + ;; remove the mark. This seems a bit odd but it is what buffer-menu + ;; does. + (let* ((prev (ewoc-goto-prev vc-ewoc 1)) + (file (ewoc-data prev))) + (setf (vc-dir-fileinfo->marked file) nil) + (ewoc-invalidate vc-ewoc prev) + (vc-dir-move-to-goal-column))) + +(defun vc-dir-unmark-all-files (arg) + "Unmark all files with the same state as the current one. +With a prefix argument unmark all files. +If the current entry is a directory, unmark all the child files. + +The commands operate on files that are on the same state. +This command is intended to make it easy to deselect all files +that share the same state." + (interactive "P") + (if arg + (ewoc-map + (lambda (filearg) + (when (vc-dir-fileinfo->marked filearg) + (setf (vc-dir-fileinfo->marked filearg) nil) + t)) + vc-ewoc) + (let* ((crt (ewoc-locate vc-ewoc)) + (data (ewoc-data crt))) + (if (vc-dir-fileinfo->directory data) + ;; It's a directory, unmark child files. + (while (setq crt (ewoc-next vc-ewoc crt)) + (let ((crt-data (ewoc-data crt))) + (unless (vc-dir-fileinfo->directory crt-data) + (setf (vc-dir-fileinfo->marked crt-data) nil) + (ewoc-invalidate vc-ewoc crt)))) + ;; It's a file + (let ((crt-state (vc-dir-fileinfo->state (ewoc-data crt)))) + (ewoc-map + (lambda (filearg) + (when (and (vc-dir-fileinfo->marked filearg) + (eq (vc-dir-fileinfo->state filearg) crt-state)) + (setf (vc-dir-fileinfo->marked filearg) nil) + t)) + vc-ewoc)))))) + +(defun vc-dir-toggle-mark-file () + (let* ((crt (ewoc-locate vc-ewoc)) + (file (ewoc-data crt))) + (if (vc-dir-fileinfo->marked file) + (vc-dir-unmark-file) + (vc-dir-mark-file)))) + +(defun vc-dir-toggle-mark (e) + (interactive "e") + (vc-at-event e (vc-dir-mark-unmark 'vc-dir-toggle-mark-file))) + +(defun vc-dir-delete-file () + "Delete the marked files, or the current file if no marks." + (interactive) + (mapc 'vc-delete-file (or (vc-dir-marked-files) + (list (vc-dir-current-file))))) + +(defun vc-dir-find-file () + "Find the file on the current line." + (interactive) + (find-file (vc-dir-current-file))) + +(defun vc-dir-find-file-other-window () + "Find the file on the current line, in another window." + (interactive) + (find-file-other-window (vc-dir-current-file))) + +(defun vc-dir-current-file () + (let ((node (ewoc-locate vc-ewoc))) + (unless node + (error "No file available")) + (expand-file-name (vc-dir-fileinfo->name (ewoc-data node))))) + +(defun vc-dir-marked-files () + "Return the list of marked files." + (mapcar + (lambda (elem) (expand-file-name (vc-dir-fileinfo->name elem))) + (ewoc-collect vc-ewoc 'vc-dir-fileinfo->marked))) + +(defun vc-dir-marked-only-files-and-states () + "Return the list of conses (FILE . STATE) for the marked files. +For marked directories return the corresponding conses for the +child files." + (let ((crt (ewoc-nth vc-ewoc 0)) + result) + (while crt + (let ((crt-data (ewoc-data crt))) + (if (vc-dir-fileinfo->marked crt-data) + ;; FIXME: use vc-dir-child-files-and-states here instead of duplicating it. + (if (vc-dir-fileinfo->directory crt-data) + (let* ((dir (vc-dir-fileinfo->directory crt-data)) + (dirlen (length dir)) + data) + (while + (and (setq crt (ewoc-next vc-ewoc crt)) + (vc-string-prefix-p dir + (progn + (setq data (ewoc-data crt)) + (vc-dir-node-directory crt)))) + (unless (vc-dir-fileinfo->directory data) + (push + (cons (expand-file-name (vc-dir-fileinfo->name data)) + (vc-dir-fileinfo->state data)) + result)))) + (push (cons (expand-file-name (vc-dir-fileinfo->name crt-data)) + (vc-dir-fileinfo->state crt-data)) + result) + (setq crt (ewoc-next vc-ewoc crt))) + (setq crt (ewoc-next vc-ewoc crt))))) + result)) + +(defun vc-dir-child-files-and-states () + "Return the list of conses (FILE . STATE) for child files of the current entry if it's a directory. +If it is a file, return the corresponding cons for the file itself." + (let* ((crt (ewoc-locate vc-ewoc)) + (crt-data (ewoc-data crt)) + result) + (if (vc-dir-fileinfo->directory crt-data) + (let* ((dir (vc-dir-fileinfo->directory crt-data)) + (dirlen (length dir)) + data) + (while + (and (setq crt (ewoc-next vc-ewoc crt)) + (vc-string-prefix-p dir (progn + (setq data (ewoc-data crt)) + (vc-dir-node-directory crt)))) + (unless (vc-dir-fileinfo->directory data) + (push + (cons (expand-file-name (vc-dir-fileinfo->name data)) + (vc-dir-fileinfo->state data)) + result)))) + (push + (cons (expand-file-name (vc-dir-fileinfo->name crt-data)) + (vc-dir-fileinfo->state crt-data)) result)) + result)) + +(defun vc-dir-resynch-file (&optional fname) + "Update the entries for FILE in any directory buffers that list it." + (let ((file (or fname (expand-file-name buffer-file-name)))) + (if (file-directory-p file) + ;; FIXME: Maybe this should never happen? + ;; FIXME: But it is useful to update the state of a directory + ;; (more precisely the files in the directory) after some VC + ;; operations. + nil + (let ((found-vc-dir-buf nil)) + (save-excursion + (dolist (status-buf (buffer-list)) + (set-buffer status-buf) + ;; look for a vc-dir buffer that might show this file. + (when (derived-mode-p 'vc-dir-mode) + (setq found-vc-dir-buf t) + (let ((ddir (expand-file-name default-directory))) + (when (vc-string-prefix-p ddir file) + (let* + ;; FIXME: Any reason we don't use file-relative-name? + ((file-short (substring file (length ddir))) + (state (vc-call-backend vc-dir-backend 'state file)) + (extra (vc-call-backend vc-dir-backend + 'status-fileinfo-extra file)) + (entry + (list file-short state extra))) + (vc-dir-update (list entry) status-buf)))))) + ;; We didn't find any vc-dir buffers, remove the hook, it is + ;; not needed. + (unless found-vc-dir-buf + (remove-hook 'after-save-hook 'vc-dir-resynch-file))))))) + +(defvar use-vc-backend) ;; dynamically bound + +(define-derived-mode vc-dir-mode special-mode "VC dir" + "Major mode for dispatcher directory buffers. +Marking/Unmarking key bindings and actions: +m - marks a file/directory or if the region is active, mark all the files + in region. + Restrictions: - a file cannot be marked if any parent directory is marked + - a directory cannot be marked if any child file or + directory is marked +u - marks a file/directory or if the region is active, unmark all the files + in region. +M - if the cursor is on a file: mark all the files with the same state as + the current file + - if the cursor is on a directory: mark all child files + - with a prefix argument: mark all files +U - if the cursor is on a file: unmark all the files with the same state + as the current file + - if the cursor is on a directory: unmark all child files + - with a prefix argument: unmark all files + + +\\{vc-dir-mode-map}" + (set (make-local-variable 'vc-dir-backend) use-vc-backend) + (setq buffer-read-only t) + (when (boundp 'tool-bar-map) + (set (make-local-variable 'tool-bar-map) vc-dir-tool-bar-map)) + (let ((buffer-read-only nil)) + (erase-buffer) + (set (make-local-variable 'vc-dir-process-buffer) nil) + (set (make-local-variable 'vc-ewoc) + (ewoc-create #'vc-dir-status-printer + (vc-dir-headers vc-dir-backend default-directory))) + (set (make-local-variable 'revert-buffer-function) + 'vc-dir-revert-buffer-function) + (set (make-local-variable 'list-buffers-directory) + (expand-file-name default-directory)) + (add-hook 'after-save-hook 'vc-dir-resynch-file) + ;; Make sure that if the directory buffer is killed, the update + ;; process running in the background is also killed. + (add-hook 'kill-buffer-query-functions 'vc-dir-kill-query nil t) + (vc-dir-refresh))) + +(defun vc-dir-headers (backend dir) + "Display the headers in the *VC dir* buffer. +It calls the `status-extra-headers' backend method to display backend +specific headers." + (concat + (propertize "VC backend : " 'face 'font-lock-type-face) + (propertize (format "%s\n" backend) 'face 'font-lock-variable-name-face) + (propertize "Working dir: " 'face 'font-lock-type-face) + (propertize (format "%s\n" dir) 'face 'font-lock-variable-name-face) + (vc-call-backend backend 'status-extra-headers dir) + "\n")) + +(defun vc-dir-refresh-files (files default-state) + "Refresh some files in the *VC-dir* buffer." + (let ((def-dir default-directory) + (backend vc-dir-backend)) + (vc-set-mode-line-busy-indicator) + ;; Call the `dir-status-file' backend function. + ;; `dir-status-file' is supposed to be asynchronous. + ;; It should compute the results, and then call the function + ;; passed as an argument in order to update the vc-dir buffer + ;; with the results. + (unless (buffer-live-p vc-dir-process-buffer) + (setq vc-dir-process-buffer + (generate-new-buffer (format " *VC-%s* tmp status" backend)))) + (lexical-let ((buffer (current-buffer))) + (with-current-buffer vc-dir-process-buffer + (cd def-dir) + (erase-buffer) + (vc-call-backend + backend 'dir-status-files def-dir files default-state + (lambda (entries &optional more-to-come) + ;; ENTRIES is a list of (FILE VC_STATE EXTRA) items. + ;; If MORE-TO-COME is true, then more updates will come from + ;; the asynchronous process. + (with-current-buffer buffer + (vc-dir-update entries buffer) + (unless more-to-come + (setq mode-line-process nil) + ;; Remove the ones that haven't been updated at all. + ;; Those not-updated are those whose state is nil because the + ;; file/dir doesn't exist and isn't versioned. + (ewoc-filter vc-ewoc + (lambda (info) + ;; The state for directory entries might + ;; have been changed to 'up-to-date, + ;; reset it, othewise it will be removed when doing 'x' + ;; next time. + ;; FIXME: There should be a more elegant way to do this. + (when (and (vc-dir-fileinfo->directory info) + (eq (vc-dir-fileinfo->state info) + 'up-to-date)) + (setf (vc-dir-fileinfo->state info) nil)) + + (not (vc-dir-fileinfo->needs-update info)))))))))))) + +(defun vc-dir-revert-buffer-function (&optional ignore-auto noconfirm) + (vc-dir-refresh)) + +(defun vc-dir-refresh () + "Refresh the contents of the *VC-dir* buffer. +Throw an error if another update process is in progress." + (interactive) + (if (vc-dir-busy) + (error "Another update process is in progress, cannot run two at a time") + (let ((def-dir default-directory) + (backend vc-dir-backend)) + (vc-set-mode-line-busy-indicator) + ;; Call the `dir-status' backend function. + ;; `dir-status' is supposed to be asynchronous. + ;; It should compute the results, and then call the function + ;; passed as an argument in order to update the vc-dir buffer + ;; with the results. + + ;; Create a buffer that can be used by `dir-status' and call + ;; `dir-status' with this buffer as the current buffer. Use + ;; `vc-dir-process-buffer' to remember this buffer, so that + ;; it can be used later to kill the update process in case it + ;; takes too long. + (unless (buffer-live-p vc-dir-process-buffer) + (setq vc-dir-process-buffer + (generate-new-buffer (format " *VC-%s* tmp status" backend)))) + ;; set the needs-update flag on all entries + (ewoc-map (lambda (info) (setf (vc-dir-fileinfo->needs-update info) t) nil) + vc-ewoc) + (lexical-let ((buffer (current-buffer))) + (with-current-buffer vc-dir-process-buffer + (cd def-dir) + (erase-buffer) + (vc-call-backend + backend 'dir-status def-dir + (lambda (entries &optional more-to-come) + ;; ENTRIES is a list of (FILE VC_STATE EXTRA) items. + ;; If MORE-TO-COME is true, then more updates will come from + ;; the asynchronous process. + (with-current-buffer buffer + (vc-dir-update entries buffer) + (unless more-to-come + (let ((remaining + (ewoc-collect + vc-ewoc 'vc-dir-fileinfo->needs-update))) + (if remaining + (vc-dir-refresh-files + (mapcar 'vc-dir-fileinfo->name remaining) + 'up-to-date) + (setq mode-line-process nil)))))))))))) + +(defun vc-dir-show-fileentry (file) + "Insert an entry for a specific file into the current *VC-dir* listing. +This is typically used if the file is up-to-date (or has been added +outside of VC) and one wants to do some operation on it." + (interactive "fShow file: ") + (vc-dir-update (list (list (file-relative-name file) (vc-state file))) (current-buffer))) + +(defun vc-dir-hide-up-to-date () + "Hide up-to-date items from display." + (interactive) + (let ((crt (ewoc-nth vc-ewoc -1)) + (first (ewoc-nth vc-ewoc 0))) + ;; Go over from the last item to the first and remove the + ;; up-to-date files and directories with no child files. + (while (not (eq crt first)) + (let* ((data (ewoc-data crt)) + (dir (vc-dir-fileinfo->directory data)) + (next (ewoc-next vc-ewoc crt)) + (prev (ewoc-prev vc-ewoc crt)) + ;; ewoc-delete does not work without this... + (inhibit-read-only t)) + (when (or + ;; Remove directories with no child files. + (and dir + (or + ;; Nothing follows this directory. + (not next) + ;; Next item is a directory. + (vc-dir-fileinfo->directory (ewoc-data next)))) + ;; Remove files in the up-to-date state. + (eq (vc-dir-fileinfo->state data) 'up-to-date)) + (ewoc-delete vc-ewoc crt)) + (setq crt prev))))) + +(defun vc-dir-status-printer (fileentry) + (vc-call-backend vc-dir-backend 'status-printer fileentry)) + +(defun vc-dir-deduce-fileset (&optional state-model-only-files) + (let ((marked (vc-dir-marked-files)) + files + only-files-list + state + model) + (if marked + (progn + (setq files marked) + (when state-model-only-files + (setq only-files-list (vc-dir-marked-only-files-and-states)))) + (let ((crt (vc-dir-current-file))) + (setq files (list crt)) + (when state-model-only-files + (setq only-files-list (vc-dir-child-files-and-states))))) + + (when state-model-only-files + (setq state (cdar only-files-list)) + ;; Check that all files are in a consistent state, since we use that + ;; state to decide which operation to perform. + (dolist (crt (cdr only-files-list)) + (unless (vc-compatible-state (cdr crt) state) + (error "%s:%s clashes with %s:%s" + (car crt) (cdr crt) (caar only-files-list) state))) + (setq only-files-list (mapcar 'car only-files-list)) + (when (and state (not (eq state 'unregistered))) + (setq model (vc-checkout-model vc-dir-backend only-files-list)))) + (list vc-dir-backend files only-files-list state model))) + +;;;###autoload +(defun vc-dir (dir &optional backend) + "Show the VC status for DIR. +Optional second argument BACKEND specifies the VC backend to use. +Interactively, a prefix argument means to ask for the backend." + (interactive + (list + (read-file-name "VC status for directory: " + default-directory default-directory t + nil #'file-directory-p) + (if current-prefix-arg + (intern + (completing-read + "Use VC backend: " + (mapcar (lambda (b) (list (symbol-name b))) + vc-handled-backends) + nil t nil nil))))) + (unless backend + (setq backend (vc-responsible-backend dir))) + (pop-to-buffer (vc-dir-prepare-status-buffer "*vc-dir*" dir backend)) + (if (derived-mode-p 'vc-dir-mode) + (vc-dir-refresh) + ;; FIXME: find a better way to pass the backend to `vc-dir-mode'. + (let ((use-vc-backend backend)) + (vc-dir-mode)))) + +(defun vc-default-status-extra-headers (backend dir) + ;; Be loud by default to remind people to add code to display + ;; backend specific headers. + ;; XXX: change this to return nil before the release. + (concat + (propertize "Extra : " 'face 'font-lock-type-face) + (propertize "Please add backend specific headers here. It's easy!" + 'face 'font-lock-warning-face))) + +(defun vc-default-status-printer (backend fileentry) + "Pretty print FILEENTRY." + ;; If you change the layout here, change vc-dir-move-to-goal-column. + (let* ((isdir (vc-dir-fileinfo->directory fileentry)) + (state (if isdir "" (vc-dir-fileinfo->state fileentry))) + (filename (vc-dir-fileinfo->name fileentry))) + (insert + (propertize + (format "%c" (if (vc-dir-fileinfo->marked fileentry) ?* ? )) + 'face 'font-lock-type-face) + " " + (propertize + (format "%-20s" state) + 'face (cond ((eq state 'up-to-date) 'font-lock-builtin-face) + ((memq state '(missing conflict)) 'font-lock-warning-face) + (t 'font-lock-variable-name-face)) + 'mouse-face 'highlight) + " " + (propertize + (format "%s" filename) + 'face + (if isdir 'font-lock-comment-delimiter-face 'font-lock-function-name-face) + 'help-echo + (if isdir + "Directory\nVC operations can be applied to it\nmouse-3: Pop-up menu" + "File\nmouse-3: Pop-up menu") + 'mouse-face 'highlight)))) + +(defun vc-default-extra-status-menu (backend) + nil) + +(defun vc-default-status-fileinfo-extra (backend file) + "Default absence of extra information returned for a file." + nil) + +(provide 'vc-dir) + +;; arch-tag: 0274a2e3-e8e9-4b1a-a73c-e8b9129d5d15 +;;; vc-dir.el ends here diff --git a/texi/gnus.texi b/texi/gnus.texi index 53bda3d71..7e41f97b2 100644 --- a/texi/gnus.texi +++ b/texi/gnus.texi @@ -12781,7 +12781,7 @@ Displayed when the signature has been hidden in the Article buffer. Displayed when Gnus has treated overstrike characters in the article buffer. @item e -Displayed when Gnus has treated emphasised strings in the article buffer. +Displayed when Gnus has treated emphasized strings in the article buffer. @end table diff --git a/texi/sasl.texi b/texi/sasl.texi index 3ba64d241..9874bb7f8 100644 --- a/texi/sasl.texi +++ b/texi/sasl.texi @@ -124,9 +124,9 @@ A list of mechanism names. @defun sasl-find-mechanism mechanisms -Retrieve an apropriate mechanism. +Retrieve an appropriate mechanism. This function compares @var{mechanisms} and @code{sasl-mechanisms} then -returns apropriate @code{sasl-mechanism} object. +returns appropriate @code{sasl-mechanism} object. @example (let ((sasl-mechanisms '("CRAM-MD5" "DIGEST-MD5"))) -- 2.25.1