From 895a7897f2c62cc79c43088e71599dcc7b4f739a Mon Sep 17 00:00:00 2001 From: psg <> Date: Thu, 2 Jun 2005 14:33:33 +0000 Subject: debian-el: apt-utils.el: "apt-utils-show-package is broken", thanks to Thamer Mahmoud for reporting it and to Matt Hodges for fixing it in a new upstream version (Closes: #302888). --- apt-utils.el | 902 ++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 584 insertions(+), 318 deletions(-) diff --git a/apt-utils.el b/apt-utils.el index a168721..bb5354b 100644 --- a/apt-utils.el +++ b/apt-utils.el @@ -1,6 +1,6 @@ ;;; apt-utils.el --- Emacs interface to APT (Debian package management) -;;; Copyright (C) 2002, 2003, 2004 Matthew P. Hodges +;;; Copyright (C) 2002, 2003, 2004, 2005 Matthew P. Hodges ;; Author: Matthew P. Hodges ;; $Id$ @@ -17,12 +17,12 @@ ;;; Commentary: ;; -;; Package to interface Emacs with APT. Start things off using e.g.: +;; Package to interface Emacs with APT. Start things off using e.g.: ;; M-x apt-utils-show-package RET emacs21 RET ;; ;; Other packages (dependencies, conflicts etc.) can be navigated ;; using apt-utils-{next,previous}-package, -;; apt-utils-choose-package-link or apt-utils-follow-link. Return to +;; apt-utils-choose-package-link or apt-utils-follow-link. Return to ;; the previous package with apt-utils-view-previous-package. ;; ChangeLog and README files for the current package can easily be ;; accessed with, for example, apt-utils-view-changelog. @@ -36,6 +36,10 @@ ;;; Code: +(defconst apt-utils-version "2.4.0" + "Version number of this package.") + +(require 'browse-url) (require 'jka-compr) (cond @@ -52,7 +56,7 @@ (defgroup apt-utils nil "Emacs interface to APT (Debian package management)." :group 'tools - :link '(url-link "http://www.tc.bham.ac.uk/~matt/published/Public/AptUtilsEl.html")) + :link '(url-link "http://mph-emacs-pkgs.alioth.debian.org/AptUtilsEl.html")) (defcustom apt-utils-fill-packages t "*Fill APT package names if t." @@ -72,9 +76,10 @@ (defcustom apt-utils-automatic-update 'ask "*Controls automatic rebuilding of APT package lists. -If t always rebuilt when `apt-utils-timestamped-file' is newer than -`apt-utils-package-list-update-time'. If equal to the symbol ask, -ask the user about the update. If nil, never update automatically." +If t always rebuilt when `apt-utils-timestamped-file' is newer +than the timestamp stored in `apt-utils-package-list-built'. If +equal to the symbol ask, ask the user about the update. If nil, +never update automatically." :group 'apt-utils :type '(choice (const :tag "Always update automatically" t) (const :tag "Ask user about update" ask) @@ -85,20 +90,56 @@ ask the user about the update. If nil, never update automatically." :group 'apt-utils :type '(repeat string)) -(defcustom apt-utils-mode-name-update nil - "*String indicating that package lists need updating." - :group 'apt-utils - :type 'string) - (defcustom apt-utils-kill-buffer-confirmation-function 'yes-or-no-p "Function called before killing any buffers. -Used by `apt-utils-kill-other-window-buffers'." +The function is called with one argument, which is a prompt. +Suitable non-nil values include `yes-or-no-p', `y-or-n-p' and +`ignore'." :group 'apt-utils :type '(choice (const :tag "Kill buffers only after yes or no query" yes-or-no-p) (const :tag "Kill buffers only after y or n query" y-or-n-p) (const :tag "Never kill buffers" ignore) (const :tag "Kill buffers without confirmation" nil))) +(defcustom apt-utils-search-split-regexp "\\s-*&&\\s-*" + "Regular expression used to split multiple search terms. +See `apt-utils-search' and `apt-utils-search-names-only'." + :group 'apt-utils + :type 'regexp) + +(defcustom apt-utils-web-browse-debian-changelog-url + "http://packages.debian.org/changelogs/pool/main/%d/%s/%s_%v/changelog" + "Template URL for Debian ChangeLog files. +See `apt-utils-web-format-url'." + :group 'apt-utils + :type 'string) + +(defcustom apt-utils-web-browse-bug-reports-url + "http://bugs.debian.org/%p" + "Template URL for Debian bug reports. +See `apt-utils-web-format-url'." + :group 'apt-utils + :type 'string) + +(defcustom apt-utils-web-browse-copyright-url + "http://packages.debian.org/changelogs/pool/main/%d/%s/%s_%v/%p.copyright" + "Template URL for Debian copyright files. +See `apt-utils-web-format-url'." + :group 'apt-utils + :type 'string) + +(defcustom apt-utils-web-browse-versions-url + "http://packages.debian.org/%p" + "Template URL for Debian version information. +See `apt-utils-web-format-url'." + :group 'apt-utils + :type 'string) + +(defcustom apt-utils-show-package-hooks nil + "Hooks to be run after presenting package information." + :group 'apt-utils + :type 'hook) + ;; Faces (defface apt-utils-normal-package-face @@ -165,20 +206,20 @@ Used by `apt-utils-kill-other-window-buffers'." (defvar apt-utils-grep-dctrl-program "/usr/bin/grep-dctrl" "Location of the grep-dctrl program.") -(defvar apt-utils-grep-dctrl-file-list - (directory-files "/var/lib/apt/lists" t "_Packages") - "List of files searched by `apt-utils-search-grep-dctrl'.") +(defvar apt-utils-grep-dctrl-file-directory "/var/lib/apt/lists" + "Directory used by `apt-utils-search-grep-dctrl'. +See also `apt-utils-grep-dctrl-file-list'.") -(defvar apt-utils-completion-table nil - "List of packages known to APT; used by `completing-read'. -Only generated if `apt-utils-completing-read-hashtable-p' is -nil.") +(defvar apt-utils-grep-dctrl-file-list nil + "List of files searched by `apt-utils-search-grep-dctrl'. +If no list is specified, this is computed on demand from files in +`apt-utils-grep-dctrl-file-directory'.") -(defvar apt-utils-package-hashtable nil +(defvar apt-utils-package-list nil "Hash table containing APT packages types.") -(defvar apt-utils-package-lists-built nil - "Whether or not APT package lists are built.") +(defvar apt-utils-package-list-built nil + "If non-nil, a timestamp for the APT package list data.") (defvar apt-utils-package-history nil "History of packages for each `apt-utils-mode' buffer.") @@ -190,16 +231,13 @@ nil.") (defvar apt-utils-buffer-positions nil "Cache of positions associated with package history. -These are stored in a hash table. See also +These are stored in a hash table. See also `apt-utils-package-history'") (make-variable-buffer-local 'apt-utils-buffer-positions) (defvar apt-utils-dired-buffer nil "Keep track of dired buffer.") -(defvar apt-utils-package-list-update-time nil - "The time that `apt-utils-build-package-lists' was last done.") - (defvar apt-utils-automatic-update-asked nil "Non-nil if user already asked about updating package lists.") @@ -213,39 +251,31 @@ These are stored in a hash table. See also (string-match "XEmacs\\|Lucid" (emacs-version))) "True if we are using apt-utils under XEmacs.") -(if apt-utils-xemacs-p - (progn - (defalias 'apt-utils-line-end-position 'point-at-eol)) - (defalias 'apt-utils-line-end-position 'line-end-position)) - ;; Other version-dependent configuration +(defalias 'apt-utils-line-end-position + (cond + ((fboundp 'line-end-position) 'line-end-position) + ((fboundp 'point-at-eol) 'point-at-eol))) + (defconst apt-utils-completing-read-hashtable-p - (and (not apt-utils-xemacs-p) - (or - ;; Next released version after 21.3 will support this - (and - (>= emacs-major-version 21) - (>= emacs-minor-version 4)) - (>= emacs-major-version 22) - ;; As will the current pretest - (string-match "\\..*\\..*\\." emacs-version))) + ;; I think this is a valid way to check this feature... + (condition-case nil + (or (all-completions "" (make-hash-table)) t) + (error nil)) "Non-nil if `completing-read' supports hash table as input.") (defconst apt-utils-face-property - (cond - ((and (not apt-utils-xemacs-p) - (or - ;; Next released version after 21.3 will support this - (and - (>= emacs-major-version 21) - (>= emacs-minor-version 4)) - (>= emacs-major-version 22) - ;; As will the current pretest - (string-match "\\..*\\..*\\." emacs-version))) - 'font-lock-face) - (t - 'face)) + (if (with-temp-buffer + ;; We have to rename to something without a leading space, + ;; otherwise font-lock-mode won't get activated. + (rename-buffer "*test-font-lock*") + (font-lock-mode 1) + (and (boundp 'char-property-alias-alist) + (member 'font-lock-face + (assoc 'face char-property-alias-alist)))) + 'font-lock-face + 'face) "Use font-lock-face if `add-text-properties' supports it. Otherwise, just use face.") @@ -268,25 +298,26 @@ Otherwise, just use face.") ;; Commands and functions ;;;###autoload -(defun apt-utils-show-package () +(defun apt-utils-show-package (&optional new-session) "Show information for a Debian package. -A selection of known packages is presented. See `apt-utils-mode' -for more detailed help." - (interactive) - (apt-utils-show-package-1 t)) +A selection of known packages is presented. See `apt-utils-mode' +for more detailed help. If NEW-SESSION is non-nil, generate a +new `apt-utils-mode' buffer." + (interactive "P") + (apt-utils-show-package-1 t nil new-session)) (defun apt-utils-show-package-1 (&optional interactive package-spec new-session) "Present Debian package information in a dedicated buffer. If INTERACTIVE is non-nil, then we have been called interactively (or from a keyboard macro) via -`apt-utils-show-package'. Hence, reset the history of visited +`apt-utils-show-package'. Hence, reset the history of visited packages. If PACKAGE-SPEC is specified, this can either be a string (the name of the package) or a list, where the car of the list is the name of the package, and the cdr is the package type; if not -specified, a package name is prompted for. If NEW-SESSION is +specified, a package name is prompted for. If NEW-SESSION is non-nil, generate a new `apt-utils-mode' buffer." (apt-utils-check-package-lists) (let (package type) @@ -304,7 +335,8 @@ non-nil, generate a new `apt-utils-mode' buffer." (cond (new-session (set-buffer (generate-new-buffer "*APT package info*")) - (apt-utils-mode)) + (apt-utils-mode) + (apt-utils-update-mode-name)) ((eq major-mode 'apt-utils-mode) ;; do nothing ) @@ -337,13 +369,15 @@ non-nil, generate a new `apt-utils-mode' buffer." ((equal type 'search) (insert (format "Debian package search for %s\n\n" package)) (apply 'call-process apt-utils-apt-cache-program nil '(t nil) nil - "search" "--" (split-string package "&&")) + "search" "--" + (split-string package apt-utils-search-split-regexp)) (apt-utils-add-search-links 'search)) ;; Search for names only ((equal type 'search-names-only) (insert (format "Debian package search (names only) for %s\n\n" package)) (apply 'call-process apt-utils-apt-cache-program nil '(t nil) nil - "search" "--names-only" "--" (split-string package "&&")) + "search" "--names-only" "--" + (split-string package apt-utils-search-split-regexp)) (apt-utils-add-search-links 'search-names-only)) ;; Search for file names ((equal type 'search-file-names) @@ -364,11 +398,12 @@ non-nil, generate a new `apt-utils-mode' buffer." ;; or when choosing new packages with apt-utils-follow-link or ;; apt-utils-choose-package-link. (goto-char (point-min)) - (set-window-start (display-buffer (current-buffer)) (point-min)))) + (set-window-start (display-buffer (current-buffer)) (point-min))) + (run-hooks 'apt-utils-show-package-hooks)) (defun apt-utils-list-package-files () "List the files associated with the current package. -The list appears in a `dired-mode' buffer. Only works for +The list appears in a `dired-mode' buffer. Only works for installed packages; uses `apt-utils-dpkg-program'." (interactive) (let ((package (caar apt-utils-package-history)) @@ -389,63 +424,76 @@ installed packages; uses `apt-utils-dpkg-program'." (t (message "No files associated for type: %s." type))))) -(defun apt-utils-get-package-files (package &optional filter) +(defun apt-utils-get-package-files (package &optional filter installed) "Return a list of files belonging to package PACKAGE. With optional argument FILTER, return files matching this regular -expression." +expression. + +With non-nil INSTALLED, return t if package is installed, +otherwise nil." (let (files) - (with-temp-buffer - (call-process apt-utils-dpkg-program nil t nil "-L" package) - ;; Check for files - (cond - ((or (search-backward "does not contain any files" nil t) - (search-backward "not installed" nil t))) - (t - (goto-char (point-min)) - (insert "(setq files '(\n") - (while (re-search-forward "^\\(.+\\)$" nil t) - (replace-match "\"\\1\"")) - (insert "))") - (eval-buffer) - ;; Keep regular files or top directory (for dired) - (setq files - (delq nil - (mapcar (lambda (elt) - (if (and (or (file-regular-p elt) - (string-equal "/." elt)) - (string-match (or filter ".") elt)) - elt - nil)) - files)))))) - files)) + (catch 'installed + (with-temp-buffer + (call-process apt-utils-dpkg-program nil t nil "-L" package) + ;; Check for files + (cond + ((or (search-backward "does not contain any files" nil t) + (search-backward "not installed" nil t) + ;; dlocate returns nothing for uninstalled packages + (or (zerop (buffer-size)))) + (when installed + (throw 'installed nil))) + (installed + (throw 'installed t)) + (t + (setq files (split-string (buffer-string) "\n")) + ;; Keep regular files or top directory (for dired) + (setq files + (delq nil + (mapcar (lambda (elt) + (if (and (or (file-regular-p elt) + (string-equal "/." elt)) + (string-match (or filter ".") elt)) + elt + nil)) + files)))))) + files))) + +(defun apt-utils-current-package-installed-p () + "Return non-nil if the current-package is installed." + (apt-utils-get-package-files (caar apt-utils-package-history) nil t)) ;;;###autoload (defun apt-utils-search () "Search Debian packages for regular expression. -To search for multiple patterns use a string like \"foo&&bar\"." +To search for multiple patterns use a string like \"foo && bar\". +The regular expression used to split the +terms (`apt-utils-search-split-regexp') is customisable." (interactive) - (apt-utils-search-internal 'search)) + (apt-utils-search-internal 'search + "Search packages for regexp: ")) (defun apt-utils-search-names-only () "Search Debian package names for regular expression. -To search for multiple patterns use a string like \"foo&&bar\"." +To search for multiple patterns use a string like \"foo && bar\". +The regular expression used to split the +terms (`apt-utils-search-split-regexp') is customisable." (interactive) - (apt-utils-search-internal 'search-names-only)) + (apt-utils-search-internal 'search-names-only + "Search package names for regexp: ")) (defun apt-utils-search-file-names () "Search Debian file names for string." (interactive) - (apt-utils-search-internal 'search-file-names)) + (apt-utils-search-internal 'search-file-names + "Search file names for string: ")) -(defun apt-utils-search-internal (type) +(defun apt-utils-search-internal (type prompt) "Search Debian packages for regular expression or string. -The type of search is specified by TYPE." +The type of search is specified by TYPE, the prompt for the +search is specified by PROMPT." (apt-utils-check-package-lists) - (let ((regexp (read-from-minibuffer - (cond ((eq type 'search-file-names) - "Search file names for string: ") - (t - "Search packages for regexp: "))))) + (let ((regexp (read-from-minibuffer prompt))) ;; Set up the buffer (cond ((eq major-mode 'apt-utils-mode) @@ -469,11 +517,13 @@ The type of search is specified by TYPE." (cond ((eq type 'search) (apply 'call-process apt-utils-apt-cache-program nil '(t nil) nil - "search" "--" (split-string regexp "&&")) + "search" "--" + (split-string regexp apt-utils-search-split-regexp)) (setq apt-utils-package-history (cons (cons regexp 'search) nil))) ((eq type 'search-names-only) (apply 'call-process apt-utils-apt-cache-program nil '(t nil) nil - "search" "--names-only" "--" (split-string regexp "&&")) + "search" "--names-only" "--" + (split-string regexp apt-utils-search-split-regexp)) (setq apt-utils-package-history (cons (cons regexp 'search-names-only) nil))) ((eq type 'search-file-names) @@ -517,8 +567,10 @@ The type of search is specified by TYPE." (let ((inhibit-read-only t)) (erase-buffer) ;; Construct argument list (need to keep this) - (setq args (append apt-utils-grep-dctrl-args (list regexp fields show) - apt-utils-grep-dctrl-file-list)) + (setq args (append (list regexp fields show) apt-utils-grep-dctrl-args + (or apt-utils-grep-dctrl-file-list + (directory-files apt-utils-grep-dctrl-file-directory + t "_Packages")))) (insert (format "grep-dctrl search for %s\n\n" (mapconcat (lambda (elt) @@ -570,7 +622,6 @@ Use PROMPT for `completing-read'." (defun apt-utils-toggle-package-info () "Toggle between package and showpkg info for normal packages." (interactive) - (apt-utils-check-package-lists) (unless (equal major-mode 'apt-utils-mode) (error "Not in APT utils buffer")) (let ((package (caar apt-utils-package-history)) @@ -595,36 +646,43 @@ Use PROMPT for `completing-read'." (set-window-start (selected-window) (cadr posns))) ((equal type 'virtual) (message "Cannot toggle info for virtual packages.")) - ((or (equal type 'search) - (equal type 'search-names-only) - (equal type 'search-file-names) - (equal type 'search-grep-dctrl)) + ((memq type '(search search-names-only + search-file-names + search-grep-dctrl)) (message "Cannot toggle info for searches."))))) +(defun apt-utils-normal-package-p () + "Return non-nil if the current package is a normal package. +That is, not a normal-showpkg, search or a virtual package." + (eq (cdar apt-utils-package-history) 'normal)) + +(defun apt-utils-toggle-package-p () + "Return non-nil if we can toggle between package and showpkg. +See also `apt-utils-toggle-package-info'." + (memq (cdar apt-utils-package-history) '(normal normal-showpkg))) + (defun apt-utils-check-package-lists () "Determine whether package lists need rebuilding." + (apt-utils-update-mode-name) (cond - ((null apt-utils-package-lists-built) - (apt-utils-build-package-lists)) - ((and (apt-utils-time-less-p apt-utils-package-list-update-time - (nth 5 (file-attributes apt-utils-timestamped-file))) + ((null apt-utils-package-list-built) + (apt-utils-build-package-list)) + ((and (apt-utils-packages-needs-update) ;; Only act for non-nil apt-utils-automatic-update apt-utils-automatic-update (cond ((eq apt-utils-automatic-update t)) ((eq apt-utils-automatic-update 'ask) (unless apt-utils-automatic-update-asked - (when (eq major-mode 'apt-utils-mode) - (setq mode-name (concat "APT utils" apt-utils-mode-name-update))) (setq apt-utils-automatic-update-asked t) (yes-or-no-p "APT package lists may be out of date. Update them? "))))) - (apt-utils-build-package-lists t)))) + (apt-utils-build-package-list t)))) ;; Find ChangeLog files (defun apt-utils-view-changelog () - "Find ChangeLog for current package." + "Find ChangeLog for the current package." (interactive) (cond ((not (equal major-mode 'apt-utils-mode)) @@ -632,24 +690,26 @@ Use PROMPT for `completing-read'." ((not (equal (cdar apt-utils-package-history) 'normal)) (message "Not a normal package.")) (t - (let ((package (caar apt-utils-package-history))) - (apt-utils-view-changelog-file package))))) + (let* ((package (caar apt-utils-package-history)) + (file (apt-utils-changelog-file package))) + (if file + (apt-utils-view-file file) + (message "No ChangeLog file found for %s." package)))))) -(defun apt-utils-view-changelog-file (package) - "Find ChangeLog file for PACKAGE." +(defun apt-utils-changelog-file (&optional package) + "Find ChangeLog file for PACKAGE or the current package." + (unless package (setq package (caar apt-utils-package-history))) (let ((file (apt-utils-find-readable-file (format "/usr/share/doc/%s/" package) '("CHANGELOG" "ChangeLog" "Changelog" "changelog") '("" ".gz")))) - (if file - (apt-utils-view-file file) - (message "No ChangeLog file found for %s." package)))) + file)) ;; Find Debian ChangeLog files (defun apt-utils-view-debian-changelog () - "Find Debian ChangeLog for current package." + "Find Debian ChangeLog for the current package." (interactive) (cond ((not (equal major-mode 'apt-utils-mode)) @@ -657,24 +717,26 @@ Use PROMPT for `completing-read'." ((not (equal (cdar apt-utils-package-history) 'normal)) (message "Not a normal package.")) (t - (let ((package (caar apt-utils-package-history))) - (apt-utils-view-debian-changelog-file package))))) - -(defun apt-utils-view-debian-changelog-file (package) - "Find Debian ChangeLog file for PACKAGE." + (let* ((package (caar apt-utils-package-history)) + (file (apt-utils-debian-changelog-file package))) + (if file + (apt-utils-view-file file) + (message "No Debian ChangeLog file found for %s." package)))))) + +(defun apt-utils-debian-changelog-file (&optional package) + "Find Debian ChangeLog file for PACKAGE or the current package. " + (unless package (setq package (caar apt-utils-package-history))) (let ((file (apt-utils-find-readable-file (format "/usr/share/doc/%s/" package) '("changelog.Debian") '(".gz")))) - (if file - (apt-utils-view-file file) - (message "No Debian ChangeLog file found for %s." package)))) + file)) ;; Find NEWS files (defun apt-utils-view-news () - "Find NEWS for current package." + "Find NEWS for the current package." (interactive) (cond ((not (equal major-mode 'apt-utils-mode)) @@ -682,24 +744,26 @@ Use PROMPT for `completing-read'." ((not (equal (cdar apt-utils-package-history) 'normal)) (message "Not a normal package.")) (t - (let ((package (caar apt-utils-package-history))) - (apt-utils-view-news-file package))))) - -(defun apt-utils-view-news-file (package) - "Find NEWS file for PACKAGE." + (let* ((package (caar apt-utils-package-history)) + (file (apt-utils-news-file package))) + (if file + (apt-utils-view-file file) + (message "No NEWS file found for %s." package)))))) + +(defun apt-utils-news-file (&optional package) + "Find NEWS file for PACKAGE or the current package." + (unless package (setq package (caar apt-utils-package-history))) (let ((file (apt-utils-find-readable-file (format "/usr/share/doc/%s/" package) '("NEWS") '("" ".gz")))) - (if file - (apt-utils-view-file file) - (message "No NEWS file found for %s." package)))) + file)) ;; Find Debian NEWS files (defun apt-utils-view-debian-news () - "Find Debian NEWS for current package." + "Find Debian NEWS for the current package." (interactive) (cond ((not (equal major-mode 'apt-utils-mode)) @@ -707,24 +771,26 @@ Use PROMPT for `completing-read'." ((not (equal (cdar apt-utils-package-history) 'normal)) (message "Not a normal package.")) (t - (let ((package (caar apt-utils-package-history))) - (apt-utils-view-debian-news-file package))))) - -(defun apt-utils-view-debian-news-file (package) - "Find Debian NEWS file for PACKAGE." + (let* ((package (caar apt-utils-package-history)) + (file (apt-utils-debian-news-file package))) + (if file + (apt-utils-view-file file) + (message "No Debian NEWS file found for %s." package)))))) + +(defun apt-utils-debian-news-file (&optional package) + "Find Debian NEWS file for PACKAGE or the current package." + (unless package (setq package (caar apt-utils-package-history))) (let ((file (apt-utils-find-readable-file (format "/usr/share/doc/%s/" package) '("NEWS.Debian") '(".gz")))) - (if file - (apt-utils-view-file file) - (message "No Debian NEWS file found for %s." package)))) + file)) ;; Find README files (defun apt-utils-view-readme () - "Find README for current package." + "Find README for the current package." (interactive) (cond ((not (equal major-mode 'apt-utils-mode)) @@ -732,24 +798,26 @@ Use PROMPT for `completing-read'." ((not (equal (cdar apt-utils-package-history) 'normal)) (message "Not a normal package.")) (t - (let ((package (caar apt-utils-package-history))) - (apt-utils-view-readme-file package))))) - -(defun apt-utils-view-readme-file (package) - "Find README file for PACKAGE." + (let* ((package (caar apt-utils-package-history)) + (file (apt-utils-readme-file package))) + (if file + (apt-utils-view-file file) + (message "No README file found for %s." package)))))) + +(defun apt-utils-readme-file (&optional package) + "Find README file for PACKAGE or the current package." + (unless package (setq package (caar apt-utils-package-history))) (let ((file (apt-utils-find-readable-file (format "/usr/share/doc/%s/" package) - '("README") + '("README" "readme") '("" ".gz")))) - (if file - (apt-utils-view-file file) - (message "No README file found for %s." package)))) + file)) ;; Find Debian README files (defun apt-utils-view-debian-readme () - "Find Debian README for current package." + "Find Debian README for the current package." (interactive) (cond ((not (equal major-mode 'apt-utils-mode)) @@ -757,24 +825,26 @@ Use PROMPT for `completing-read'." ((not (equal (cdar apt-utils-package-history) 'normal)) (message "Not a normal package.")) (t - (let ((package (caar apt-utils-package-history))) - (apt-utils-view-debian-readme-file package))))) - -(defun apt-utils-view-debian-readme-file (package) - "Find Debian README file for PACKAGE." + (let* ((package (caar apt-utils-package-history)) + (file (apt-utils-debian-readme-file package))) + (if file + (apt-utils-view-file file) + (message "No Debian README file found for %s." package)))))) + +(defun apt-utils-debian-readme-file (&optional package) + "Find Debian README file for PACKAGE or the current package." + (unless package (setq package (caar apt-utils-package-history))) (let ((file (apt-utils-find-readable-file (format "/usr/share/doc/%s/" package) '("README.Debian" "README.debian") '("" ".gz")))) - (if file - (apt-utils-view-file file) - (message "No Debian README file found for %s." package)))) + file)) ;; Find copyright files (defun apt-utils-view-copyright () - "Find copyright file for current package." + "Find copyright file for the current package." (interactive) (cond ((not (equal major-mode 'apt-utils-mode)) @@ -782,19 +852,21 @@ Use PROMPT for `completing-read'." ((not (equal (cdar apt-utils-package-history) 'normal)) (message "Not a normal package.")) (t - (let ((package (caar apt-utils-package-history))) - (apt-utils-view-copyright-file package))))) - -(defun apt-utils-view-copyright-file (package) - "Find copyright file for PACKAGE." + (let* ((package (caar apt-utils-package-history)) + (file (apt-utils-copyright-file package))) + (if file + (apt-utils-view-file file) + (message "No copyright file found for %s." package)))))) + +(defun apt-utils-copyright-file (&optional package) + "Find copyright file for PACKAGE or the current package." + (unless package (setq package (caar apt-utils-package-history))) (let ((file (apt-utils-find-readable-file (format "/usr/share/doc/%s/copyright" package) '("") '("")))) - (if file - (apt-utils-view-file file) - (message "No copyright file found for %s." package)))) + file)) (defun apt-utils-view-man-page () "View man page for the current package. @@ -839,6 +911,39 @@ offer a choice." (woman-find-file chosen) (manual-entry chosen))))))) +(defun apt-utils-view-emacs-startup-file () + "View Emacs startup file for the current package. +If there is more than one file associated with the package, offer +a choice." + (interactive) + (cond + ((not (equal major-mode 'apt-utils-mode)) + (message "Not in APT utils buffer.")) + ((not (equal (cdar apt-utils-package-history) 'normal)) + (message "Not a normal package.")) + (t + (let ((package (caar apt-utils-package-history)) + chosen files table) + (setq files (apt-utils-get-package-files package + "^/etc/emacs/site-start.d/.*")) + (cond + ((null files) + (message "No Emacs startup files found for %s." package)) + ((not (cdr files)) + (setq chosen (car files))) + (t + (setq table (mapcar + (lambda (file) + (cons file file)) + files)) + (setq chosen + (cdr (assoc + (let ((completion-ignore-case t)) + (completing-read "Choose Emacs startup file: " table nil t)) + table))))) + (when chosen + (apt-utils-view-file chosen)))))) + ;; File-related utility functions (defun apt-utils-find-readable-file (dir prefixes suffixes) @@ -885,12 +990,15 @@ Argument EVENT is a mouse event." (let (package) (save-selected-window (mouse-set-point event) - (setq package - (cadr - (member 'apt-package (text-properties-at - (point))))) + (setq package (apt-utils-package-at-point)) (apt-utils-follow-link-internal package nil)))) +(defun apt-utils-package-at-point () + "Return name of package at point, if any." + (cadr + (member 'apt-package (text-properties-at + (point))))) + (defun apt-utils-follow-link-internal (package new-session) "Follow hyperlink for PACKAGE. With non-nil NEW-SESSION, follow link in a new buffer." @@ -924,6 +1032,11 @@ With non-nil NEW-SESSION, follow link in a new buffer." (setq apt-utils-package-history (cdr apt-utils-package-history))) (message "No further package history."))) +(defun apt-utils-previous-package-p () + "Return non-nil if there is a previous entry in the package history. +See also `apt-utils-package-history'." + (cdr apt-utils-package-history)) + ;; Adapted from widget-move (defun apt-utils-next-package (&optional arg) @@ -934,10 +1047,10 @@ ARG may be negative to move backward." (error "Not in APT utils buffer")) (cond ;; No links - ((null apt-utils-current-links) + ((= (hash-table-count apt-utils-current-links) 0) (message "No package links.")) ;; One link - ((= (length apt-utils-current-links) 1) + ((= (hash-table-count apt-utils-current-links) 1) (goto-char (point-min)) (goto-char (next-single-property-change (point) 'apt-package))) @@ -994,70 +1107,72 @@ With non-nil NEW-SESSION, follow link in a new buffer." (defun apt-utils-choose-package-link-internal (new-session) "Choose a Debian package from a list of links. With non-nil NEW-SESSION, follow link in a new buffer." - (unless (equal major-mode 'apt-utils-mode) + (cond + ((not (equal major-mode 'apt-utils-mode)) (error "Not in APT utils buffer")) - (let ((package - (completing-read "Choose related Debian package: " - (mapcar (lambda (elt) - (cons elt elt)) - apt-utils-current-links) nil t))) - (when (> (length package) 0) - (unless new-session - (apt-utils-update-buffer-positions 'forward)) - (apt-utils-show-package-1 nil package new-session) - (unless new-session - (setq apt-utils-package-history - (cons (cons package (apt-utils-package-type package)) - apt-utils-package-history)))))) - -(defun apt-utils-build-package-lists (&optional force) + ((= (hash-table-count apt-utils-current-links) 0) + (message "No package links.")) + (t + (let ((package + (completing-read "Choose related Debian package: " + (cond + (apt-utils-completing-read-hashtable-p + apt-utils-current-links) + (t + (apt-utils-build-completion-table + apt-utils-current-links))) + nil t))) + (when (> (length package) 0) + (unless new-session + (apt-utils-update-buffer-positions 'forward)) + (apt-utils-show-package-1 nil package new-session) + (unless new-session + (setq apt-utils-package-history + (cons (cons package (apt-utils-package-type package)) + apt-utils-package-history)))))))) + +(defun apt-utils-build-package-list (&optional force) "Build list of Debian packages known to APT. With optional argument FORCE, rebuild the packages lists even if -they are defined. When package lists are not up-to-date, this is +they are defined. When package lists are not up-to-date, this is indicated in `mode-name'." - (when (or force (null apt-utils-package-lists-built)) + (when (or force (null apt-utils-package-list-built)) (unwind-protect (progn - (setq apt-utils-package-lists-built nil - apt-utils-package-list-update-time nil - apt-utils-automatic-update-asked nil - apt-utils-completion-table nil) + (setq apt-utils-package-list-built nil + apt-utils-automatic-update-asked nil) (message "Building Debian package lists...") ;; Hash table listing package types - (if (hash-table-p apt-utils-package-hashtable) - (clrhash apt-utils-package-hashtable) - (setq apt-utils-package-hashtable (make-hash-table :test 'equal))) + (if (hash-table-p apt-utils-package-list) + (clrhash apt-utils-package-list) + (setq apt-utils-package-list (make-hash-table :test 'equal))) ;; All packages except virtual ones (with-temp-buffer ;; Virtual and normal packages (call-process apt-utils-apt-cache-program nil '(t nil) nil "pkgnames") (mapcar (lambda (elt) - (apt-utils-puthash elt 'virtual apt-utils-package-hashtable)) - (split-string (buffer-string))) + (apt-utils-puthash elt 'virtual apt-utils-package-list)) + (split-string (buffer-string) "\n")) ;; Normal packages (erase-buffer) (call-process apt-utils-apt-cache-program nil '(t nil) nil "pkgnames" "-o" "APT::Cache::AllNames=0") (mapcar (lambda (elt) - (apt-utils-puthash elt 'normal apt-utils-package-hashtable)) - (split-string (buffer-string)))) + (apt-utils-puthash elt 'normal apt-utils-package-list)) + (split-string (buffer-string) "\n"))) (message "Building Debian package lists...done.") - (setq apt-utils-package-lists-built t - apt-utils-package-list-update-time - (nth 5 (file-attributes apt-utils-timestamped-file))) - (when (eq major-mode 'apt-utils-mode) - (setq mode-name "APT utils"))) - (unless apt-utils-package-lists-built + (setq apt-utils-package-list-built (current-time)) + (apt-utils-update-mode-name)) + (unless apt-utils-package-list-built (message "Building Debian package lists...interrupted.") - (when (eq major-mode 'apt-utils-mode) - (setq mode-name (concat "APT utils" apt-utils-mode-name-update))) - (if (hash-table-p apt-utils-package-hashtable) - (clrhash apt-utils-package-hashtable)))))) + (apt-utils-update-mode-name) + (if (hash-table-p apt-utils-package-list) + (clrhash apt-utils-package-list)))))) (defun apt-utils-rebuild-package-lists () "Rebuild the APT package lists." (interactive) - (apt-utils-build-package-lists t)) + (apt-utils-build-package-list t)) (defun apt-utils-choose-package () "Choose a Debian package name." @@ -1065,26 +1180,25 @@ indicated in `mode-name'." (and (eq major-mode 'apt-utils-mode) (cadr (member 'apt-package (text-properties-at (point))))))) + (when (eq package 'broken) (setq package nil)) (completing-read "Choose Debian package: " (cond (apt-utils-completing-read-hashtable-p - apt-utils-package-hashtable) + apt-utils-package-list) (t - (or apt-utils-completion-table - (apt-utils-build-completion-table)))) + (apt-utils-build-completion-table + apt-utils-package-list))) nil t package))) -(defun apt-utils-build-completion-table () - "Build completion table for packages. -See `apt-utils-completion-table'." +(defun apt-utils-build-completion-table (hash) + "Build completion table for packages using keys of hashtable HASH. " (with-temp-buffer (maphash (lambda (key value) (insert key "\n")) - apt-utils-package-hashtable) - (setq apt-utils-completion-table - (mapcar (lambda (elt) - (list elt)) - (split-string (buffer-string)))))) + hash) + (mapcar (lambda (elt) + (list elt)) + (split-string (buffer-string) "\n")))) ;; Add hyperlinks @@ -1094,7 +1208,9 @@ See `apt-utils-completion-table'." "Pre-Depends" "Provides" "Recommends" "Replaces" "Suggests")) match) - (setq apt-utils-current-links nil) + (if (hash-table-p apt-utils-current-links) + (clrhash apt-utils-current-links) + (setq apt-utils-current-links (make-hash-table :test 'equal))) (goto-char (point-min)) (while (re-search-forward "^\\([^ \n:]+\\):\\( \\|$\\)" (point-max) t) @@ -1151,10 +1267,8 @@ See `apt-utils-completion-table'." (when (equal (char-before) ?\ ) (delete-char -1)) ; trailing whitespace (insert "\n" (make-string (+ 2 (length match)) ? ))) - ;; Store list of unique package links - (unless (member package apt-utils-current-links) - (setq apt-utils-current-links - (cons package apt-utils-current-links))) + ;; Store package links + (apt-utils-puthash package nil apt-utils-current-links) (forward-char length) (skip-chars-forward ", |\n") (setq packages (cdr packages))))) @@ -1180,7 +1294,9 @@ See `apt-utils-completion-table'." (let ((keywords '("Reverse Depends" "Reverse Provides")) (inhibit-read-only t) start end regexp face link) - (setq apt-utils-current-links nil) + (if (hash-table-p apt-utils-current-links) + (clrhash apt-utils-current-links) + (setq apt-utils-current-links (make-hash-table :test 'equal))) (while keywords (setq regexp (concat "^" (car keywords) ": ")) (goto-char (point-min)) @@ -1199,10 +1315,8 @@ See `apt-utils-completion-table'." (when (or (looking-at "^\\s-+\\(.*\\),") (looking-at "^\\(.*\\) ")) (setq link (match-string 1)) - ;; Store list of unique package links - (unless (member link apt-utils-current-links) - (setq apt-utils-current-links - (cons link apt-utils-current-links))) + ;; Store package links + (apt-utils-puthash link nil apt-utils-current-links) (cond ((equal (apt-utils-package-type link t) 'normal) (setq face 'apt-utils-normal-package-face)) @@ -1223,7 +1337,9 @@ See `apt-utils-completion-table'." The type of search is specified by TYPE." (let ((inhibit-read-only t) face link regexp) - (setq apt-utils-current-links nil) + (if (hash-table-p apt-utils-current-links) + (clrhash apt-utils-current-links) + (setq apt-utils-current-links (make-hash-table :test 'equal))) (goto-char (point-min)) (forward-line 2) ; Move past header (cond @@ -1237,10 +1353,8 @@ The type of search is specified by TYPE." (setq regexp"^\\([^ ]+\\) - "))) (while (re-search-forward regexp (point-max) t) (setq link (match-string 1)) - ;; Store list of unique package links - (unless (member link apt-utils-current-links) - (setq apt-utils-current-links - (cons link apt-utils-current-links))) + ;; Store package links + (apt-utils-puthash link nil apt-utils-current-links) (cond ((equal (apt-utils-package-type link t) 'normal) (setq face 'apt-utils-normal-package-face)) @@ -1263,7 +1377,7 @@ The type of search is specified by TYPE." "Return what type of package PACKAGE is. With optional argument NO-ERROR, don't flag an error for unknown packages." - (or (gethash package apt-utils-package-hashtable) + (or (gethash package apt-utils-package-list) (cond (no-error nil) @@ -1302,8 +1416,8 @@ packages." (defun apt-utils-kill-buffer () "Kill this `apt-utils-mode' buffer. -Also clean up `apt-utils-package-hashtable' and -`apt-utils-completion-table' using `apt-utils-cleanup'." +Also clean up `apt-utils-package-list' using +`apt-utils-cleanup'." (interactive) (unless (equal major-mode 'apt-utils-mode) (error "Not in APT utils buffer")) @@ -1312,17 +1426,15 @@ Also clean up `apt-utils-package-hashtable' and (defun apt-utils-cleanup () "Clean up lists used by `apt-utils-mode'. -Specifically, nullify `apt-utils-package-hashtable' and -`apt-utils-completion-table'. Only do this if there are no -buffers left in `apt-utils-mode'." +Specifically, nullify `apt-utils-package-list'. Only do this if +there are no buffers left in `apt-utils-mode'." (unless (memq 'apt-utils-mode (mapcar (lambda (b) (with-current-buffer b major-mode)) (buffer-list))) - (clrhash apt-utils-package-hashtable) - (setq apt-utils-completion-table nil - apt-utils-package-lists-built nil))) + (clrhash apt-utils-package-list) + (setq apt-utils-package-list-built nil))) (defun apt-utils-describe-package () "Describe package at point." @@ -1337,8 +1449,8 @@ customisation options." (unless (eq major-mode 'apt-utils-mode) (error "Not in APT utils buffer")) (when (or (null apt-utils-kill-buffer-confirmation-function) - (apply apt-utils-kill-buffer-confirmation-function - (list "Kill buffers in other windows? "))) + (funcall apt-utils-kill-buffer-confirmation-function + "Kill buffers in other windows? ")) (let ((buffer-list (delq (current-buffer) (mapcar #'window-buffer (window-list))))) @@ -1465,6 +1577,106 @@ TYPE can be forward, backward, or toggle." (and (= (car t1) (car t2)) (< (nth 1 t1) (nth 1 t2))))) +(defun apt-utils-web-browse-debian-changelog () + "Browse web version of Debian ChangeLog file for the current package." + (interactive) + (apt-utils-web-browse-url + apt-utils-web-browse-debian-changelog-url)) + +(defun apt-utils-web-browse-bug-reports () + "Browse Debian bug reports for the current package." + (interactive) + (apt-utils-web-browse-url + apt-utils-web-browse-bug-reports-url)) + +(defun apt-utils-web-browse-copyright () + "Browse web version of Debian copyright file for the current package." + (interactive) + (apt-utils-web-browse-url + apt-utils-web-browse-copyright-url)) + +(defun apt-utils-web-browse-versions () + "Browse web version information for the current package." + (interactive) + (apt-utils-web-browse-url + apt-utils-web-browse-versions-url)) + +(defun apt-utils-web-browse-url (url) + "Browse Debian-related URL. +The URL can contain tokens that need formatting (see +`apt-utils-web-format-url')." + (cond + ((not (equal major-mode 'apt-utils-mode)) + (message "Not in APT utils buffer.")) + ((not (memq (cdar apt-utils-package-history) '(normal normal-showpkg))) + (message "Not a normal package.")) + (t + (browse-url (apt-utils-web-format-url url))))) + +(defun apt-utils-web-format-url (url) + "Format and return Debian URL. +The tokens that can be replaced are: + %d: pool directory + %s: source package name + %p: package name + %v: package version." + (let ((buffer (current-buffer)) + (package (caar apt-utils-package-history)) + (type (cdar apt-utils-package-history)) + char source-package version) + (save-excursion ; for normal package type + (with-temp-buffer + (cond + ((eq type 'normal) + (set-buffer buffer)) + ((eq type 'normal-showpkg) + (call-process apt-utils-apt-cache-program nil '(t nil) nil "show" package))) + (goto-char (point-min)) + (if (re-search-forward "^Source: \\(.*\\)$" (point-max) t) + (setq source-package (match-string 1)) + (setq source-package package)) + (goto-char (point-min)) + (re-search-forward "^Version: \\([0-9]:\\)?\\(.*\\)$" (point-max)) + (setq version (match-string 2)))) + ;; Format the URL + (while (string-match "%\\(.\\)" url) + (setq char (string-to-char (match-string 1 url))) + (setq url (apt-utils-replace-regexp-in-string + (match-string 0 url) + (cond + ((eq char ?d) + (substring source-package 0 + (if (string-match "^lib[a-z]" + source-package) + 4 1))) + ((eq char ?s) source-package) + ((eq char ?p) package) + ((eq char ?v) version) + (t + (error "Unrecognized token (%%%c) in URL: %s" char url))) + url)))) + url) + +(defun apt-utils-packages-needs-update () + "Return t if `apt-utils' package lists needs updating." + (or (not apt-utils-package-list-built) + (apt-utils-time-less-p apt-utils-package-list-built + (nth 5 (file-attributes apt-utils-timestamped-file))))) + +(defun apt-utils-update-mode-name () + "Update `mode-name' for all buffers in `apt-utils-mode'." + (let* ((need-update (apt-utils-packages-needs-update)) + (update-string + (and need-update + (substitute-command-keys + ": update using \\\\[apt-utils-rebuild-package-lists]"))) + (name (concat "APT utils" update-string))) + (mapc (lambda (b) + (with-current-buffer b + (when (eq major-mode 'apt-utils-mode) + (setq mode-name name)))) + (buffer-list)))) + ;; Mode settings (defvar apt-utils-mode-map @@ -1474,31 +1686,36 @@ TYPE can be forward, backward, or toggle." (define-key map (kbd "<") 'apt-utils-view-previous-package) (define-key map (kbd ">") 'apt-utils-choose-package-link) (define-key map (kbd "?") 'describe-mode) - (define-key map (kbd "C") 'apt-utils-view-debian-changelog) (define-key map (kbd "DEL") 'scroll-down) (define-key map (kbd "M-TAB") 'apt-utils-previous-package) - (define-key map (kbd "N") 'apt-utils-view-debian-news) (define-key map (kbd "Q") 'apt-utils-kill-buffer) - (define-key map (kbd "R") 'apt-utils-view-debian-readme) (define-key map (kbd "RET") 'apt-utils-follow-link) - (define-key map (kbd "S") 'apt-utils-search) + (define-key map (kbd "S s") 'apt-utils-search) + (define-key map (kbd "S f") 'apt-utils-search-file-names) + (define-key map (kbd "S g") 'apt-utils-search-grep-dctrl) + (define-key map (kbd "S n") 'apt-utils-search-names-only) (define-key map (kbd "SPC") 'scroll-up) (define-key map (kbd "TAB") 'apt-utils-next-package) - (define-key map (kbd "c") 'apt-utils-view-changelog) + (define-key map (kbd "b C") 'apt-utils-web-browse-debian-changelog) + (define-key map (kbd "b b") 'apt-utils-web-browse-bug-reports) + (define-key map (kbd "b l") 'apt-utils-web-browse-copyright) + (define-key map (kbd "b v") 'apt-utils-web-browse-versions) (define-key map (kbd "d") 'apt-utils-describe-package) - (define-key map (kbd "f") 'apt-utils-search-file-names) - (define-key map (kbd "g") 'apt-utils-search-grep-dctrl) - (define-key map (kbd "i") 'apt-utils-view-copyright) (when (fboundp 'window-list) (define-key map (kbd "k") 'apt-utils-kill-other-window-buffers)) (define-key map (kbd "l") 'apt-utils-list-package-files) - (define-key map (kbd "m") 'apt-utils-view-man-page) - (define-key map (kbd "n") 'apt-utils-view-news) - (define-key map (kbd "o") 'apt-utils-search-names-only) (define-key map (kbd "q") 'apt-utils-quit) - (define-key map (kbd "r") 'apt-utils-view-readme) (define-key map (kbd "s") 'apt-utils-show-package) (define-key map (kbd "t") 'apt-utils-toggle-package-info) + (define-key map (kbd "v C") 'apt-utils-view-debian-changelog) + (define-key map (kbd "v R") 'apt-utils-view-debian-readme) + (define-key map (kbd "v N") 'apt-utils-view-debian-news) + (define-key map (kbd "v c") 'apt-utils-view-changelog) + (define-key map (kbd "v e") 'apt-utils-view-emacs-startup-file) + (define-key map (kbd "v l") 'apt-utils-view-copyright) + (define-key map (kbd "v m") 'apt-utils-view-man-page) + (define-key map (kbd "v n") 'apt-utils-view-news) + (define-key map (kbd "v r") 'apt-utils-view-readme) (define-key map [(shift iso-lefttab)] 'apt-utils-previous-package) (define-key map [(shift tab)] 'apt-utils-previous-package) (define-key map @@ -1507,11 +1724,6 @@ TYPE can be forward, backward, or toggle." map) "Keymap for apt-utils mode.") -(unless apt-utils-mode-name-update - (setq apt-utils-mode-name-update - (substitute-command-keys - ": update using \\\\[apt-utils-rebuild-package-lists]"))) - ;; Menus (defvar apt-utils-menu nil @@ -1520,33 +1732,62 @@ TYPE can be forward, backward, or toggle." (when (fboundp 'easy-menu-define) (easy-menu-define apt-utils-menu apt-utils-mode-map "Apt Utils Menu" - '("Apt Utils" - "---" + `("Apt Utils" ["Show Package" apt-utils-show-package t] - ["Toggle Package Info" apt-utils-toggle-package-info t] - ["View Previous Package" apt-utils-view-previous-package t] - ["Choose Package Link" apt-utils-choose-package-link t] - ["Next Package" apt-utils-next-package t] - ["Previous Package" apt-utils-previous-package t] - ["Follow Link" apt-utils-follow-link t] - ["List Package Files" apt-utils-list-package-files t] - "---" - ["Search" apt-utils-search t] - ["Search (names only)" apt-utils-search-names-only t] - ["Search (file names)" apt-utils-search-file-names t] - ["Search (grep-dctrl)" apt-utils-search-grep-dctrl t] - "---" - ["View ChangeLog" apt-utils-view-changelog t] - ["View Debian ChangeLog" apt-utils-view-debian-changelog t] - ["View README" apt-utils-view-readme t] - ["View Debian README" apt-utils-view-debian-readme t] - ["View NEWS" apt-utils-view-news t] - ["View Debian NEWS" apt-utils-view-debian-news t] - ["View copyright" apt-utils-view-copyright t] - ["View man page" apt-utils-view-man-page t] - "---" + ["Toggle Package Info" apt-utils-toggle-package-info + (apt-utils-toggle-package-p)] + ["View Previous Package" apt-utils-view-previous-package + (apt-utils-previous-package-p)] + ["Choose Package Link" apt-utils-choose-package-link + (> (hash-table-count apt-utils-current-links) 0)] + ["Next Package Link" apt-utils-next-package + (> (hash-table-count apt-utils-current-links) 0)] + ["Previous Package Link" apt-utils-previous-package + (> (hash-table-count apt-utils-current-links) 0)] + ["Follow Link at Point" apt-utils-follow-link + (apt-utils-package-at-point)] + ["List Package Files (dired)" apt-utils-list-package-files + (apt-utils-current-package-installed-p)] ["Rebuild Package Lists" apt-utils-rebuild-package-lists t] "---" + ("Search" + ["Package Descriptions" apt-utils-search t] + ["Package Names" apt-utils-search-names-only t] + ["Installed Files" apt-utils-search-file-names t] + ["Grep-Dctrl" apt-utils-search-grep-dctrl t]) + ("View Files" + ,@(list (if apt-utils-xemacs-p + :included + :active) + '(apt-utils-current-package-installed-p)) + ["ChangeLog" apt-utils-view-changelog + (apt-utils-changelog-file)] + ["Debian ChangeLog" apt-utils-view-debian-changelog + (apt-utils-debian-changelog-file)] + ["README" apt-utils-view-readme + (apt-utils-readme-file)] + ["Debian README" apt-utils-view-debian-readme + (apt-utils-debian-readme-file)] + ["NEWS" apt-utils-view-news + (apt-utils-news-file)] + ["Debian NEWS" apt-utils-view-debian-news + (apt-utils-debian-news-file)] + ["Copyright" apt-utils-view-copyright + (apt-utils-copyright-file)] + "---" + ["Man Page" apt-utils-view-man-page + (apt-utils-current-package-installed-p)]) + ("Browse URL" + ,@(list (if apt-utils-xemacs-p + :included + :active) + '(apt-utils-toggle-package-p)) + ["Debian ChangeLog" apt-utils-web-browse-debian-changelog t] + ["Bug Reports" apt-utils-web-browse-bug-reports t] + ["Copyright" apt-utils-web-browse-copyright t] + ["Package Versions" apt-utils-web-browse-versions t]) + "---" + ["Help" describe-mode t] ["Quit" apt-utils-quit t] ["Kill Buffer" apt-utils-kill-buffer t]))) @@ -1560,35 +1801,47 @@ Start things off with, for example: Other packages (dependencies, conflicts etc.) can be navigated using: + \\[apt-utils-toggle-package-info] toggle package and showpkg information + \\[apt-utils-view-previous-package] show the previous package from history + \\[apt-utils-choose-package-link] choose next package from current links \\[apt-utils-next-package] move to next package link \\[apt-utils-previous-package] move to previous package link - \\[apt-utils-choose-package-link] choose next package from current links \\[apt-utils-follow-link] show package for the link at point - \\[apt-utils-view-previous-package] show the previous package from history - \\[apt-utils-toggle-package-info] toggle package and showpkg information + \\[apt-utils-list-package-files] list package files (in a `dired' buffer) + +Confirmation will be requested before updating the list of known +packages. The update can be started at any time with +\\[apt-utils-rebuild-package-lists]. + +Package searches can be performed using: + + \\[apt-utils-search] search for regular expression in package names and descriptions + \\[apt-utils-search-names-only] search for regular expression in package names + \\[apt-utils-search-file-names] search for string in filenames + \\[apt-utils-search-grep-dctrl] search for regular expression in selected package fields + (using the grep-dctrl program) Files associated with installed packages can be accessed using: - \\[apt-utils-list-package-files] list package files (in a `dired' buffer) \\[apt-utils-view-changelog] view ChangeLog file \\[apt-utils-view-debian-changelog] view Debian ChangeLog file \\[apt-utils-view-readme] view README file \\[apt-utils-view-debian-readme] view Debian ChangeLog file \\[apt-utils-view-news] view NEWS file \\[apt-utils-view-debian-news] view Debian NEWS file - \\[apt-utils-view-copyright] view copyright file + \\[apt-utils-view-copyright] view copyright (licence) file \\[apt-utils-view-man-page] view man page -Package searchs can be performed using: +Web locations can be visited using: - \\[apt-utils-search] search for regular expression in package names and descriptions - \\[apt-utils-search-names-only] search for regular expression in package names - \\[apt-utils-search-grep-dctrl] search for regular expression in selected package fields - \\[apt-utils-search-file-names] search for string in filenames + \\[apt-utils-web-browse-debian-changelog] browse Debian ChangeLog URL + \\[apt-utils-web-browse-bug-reports] browse bug report URL + \\[apt-utils-web-browse-copyright] browse copyright (licence) URL + \\[apt-utils-web-browse-versions] browse package versions URL A history of navigated packages is maintained when package links are followed using `apt-utils-choose-package-link' or -`apt-utils-follow-link'. This history is reset when +`apt-utils-follow-link'. This history is reset when `apt-utils-show-package' or any of the search commands is used. Key definitions: @@ -1605,6 +1858,19 @@ Key definitions: (easy-menu-add apt-utils-menu)) (run-hooks 'apt-utils-mode-hook)) +;; Debugging + +(defun apt-utils-trace-all () + (require 'trace) + (let ((buffer (get-buffer-create "*APT Utils Trace*"))) + (buffer-disable-undo buffer) + (all-completions "apt-utils" obarray + (lambda (sym) + (and (fboundp sym) + (not (memq (car-safe (symbol-function sym)) + '(autoload macro))) + (trace-function-background sym buffer)))))) + (provide 'apt-utils) ;;; apt-utils.el ends here -- cgit v1.2.3