:group 'find-function
:version "20.3")
-(defcustom find-library-include-other-files t
- "If non-nil, `read-library-name' will also include non-library files.
-This affects commands like `read-library'.
-
-If nil, only library files (i.e., \".el\" files) will be offered
-for completion."
+(defcustom find-library-include-other-files nil
+ "This variable is obsolete and has no effect."
:type 'boolean
- :version "29.1"
+ :version "30.1"
:group 'find-function)
+(make-obsolete-variable 'find-library-include-other-files nil "30.1")
+
;;; Functions:
(defun find-library-suffixes ()
See the `find-library-include-other-files' user option for
customizing the candidate completions."
- (interactive (list (read-library-name)))
+ (interactive (list (read-library-name "Display library")))
(display-buffer (find-file-noselect (find-library-name library))))
;;;###autoload
See the `find-library-include-other-files' user option for
customizing the candidate completions."
- (interactive (list (read-library-name)))
+ (interactive (list (read-library-name "Find library")))
(prog1
(switch-to-buffer (find-file-noselect (find-library-name library)))
(run-hooks 'find-function-after-hook)))
(put 'find-library 'minibuffer-action '(display-library . "find"))
+(defvar finder-known-keywords)
+(declare-function finder-unknown-keywords "finder" ())
+(declare-function lm-keywords "lisp-mnt" (&optional library))
+(declare-function lm-summary "lisp-mnt" (&optional library))
+
+(defun find-func--finder-keyword-affixation (keywords)
+ "Add annotations to list of keyword completion candidates KEYWORDS."
+ (require 'finder) ; `finder-known-keywords'
+ (let ((max (seq-max (cons 0 (mapcar #'string-width keywords)))))
+ (mapcar (lambda (keyword)
+ (list keyword
+ ""
+ (concat
+ (make-string (1+ (- max (string-width keyword))) ?\s)
+ (propertize
+ (alist-get (intern keyword) finder-known-keywords "")
+ 'face 'completions-annotations))))
+ keywords)))
+
+(defun read-library-name-narrow-completions-by-keyword ()
+ "Restrict library completions list to libraries with a given keyword."
+ (require 'finder) ; `finder-(un)known-keywords'
+ (require 'lisp-mnt) ; `lm-keywords'
+ (let* ((keyword (completing-read
+ "Keep libraries with keyword: "
+ (completion-table-with-metadata
+ (mapcar (compose #'symbol-name #'car)
+ (append finder-known-keywords
+ (finder-unknown-keywords)))
+ `((category . finder-keyword)
+ ,@(when completions-detailed
+ `((affixation-function
+ . find-func--finder-keyword-affixation))))))))
+ (cons (lambda (cand &rest _)
+ (let* ((string (cond
+ ((stringp cand) cand)
+ ((symbolp cand) (symbol-name cand))
+ (t (car cand))))
+ (sym (intern string)))
+ (string-match (concat "\\<" keyword "\\>")
+ (or (get sym 'library-keywords)
+ (let ((kws (or (lm-keywords (find-library-name string)) "")))
+ (put sym 'library-keywords kws)
+ kws)))))
+ (concat "keyword=" keyword))))
+
+(defun read-library-name-affixation (libraries)
+ "Add annotations to list of library completion candidates LIBRARIES."
+ (require 'lisp-mnt) ; `lm-summary'
+ (let ((max (seq-max (cons 0 (mapcar #'string-width libraries)))))
+ (mapcar (lambda (library)
+ (list library
+ ""
+ (concat
+ (make-string (1+ (- max (string-width library))) ?\s)
+ (let ((sym (intern library)))
+ (propertize
+ (or (get sym 'library-summary)
+ (let ((sum (or
+ (lm-summary (find-library-name library))
+ "[No summary available]")))
+ (put sym 'library-summary sum)
+ sum))
+ 'face 'completions-annotations)))))
+ libraries)))
+
;;;###autoload
-(defun read-library-name ()
+(defun read-library-name (&optional prompt)
"Read and return a library name, defaulting to the one near point.
A library name is the filename of an Emacs Lisp library located
in a directory under `load-path' (or `find-library-source-path',
-if non-nil)."
- (let* ((dirs (or find-library-source-path load-path))
- (suffixes (find-library-suffixes))
- (def (if (eq (function-called-at-point) 'require)
- ;; `function-called-at-point' may return 'require
- ;; with `point' anywhere on this line. So wrap the
- ;; `save-excursion' below in a `condition-case' to
- ;; avoid reporting a scan-error here.
- (condition-case nil
- (save-excursion
- (backward-up-list)
- (forward-char)
- (forward-sexp 2)
- (thing-at-point 'symbol))
- (error nil))
- (thing-at-point 'symbol))))
- (if find-library-include-other-files
- (let ((table (apply-partially #'locate-file-completion-table
- dirs suffixes)))
- (when (and def (not (test-completion def table)))
- (setq def nil))
- (completing-read (format-prompt "Library name" def)
- table nil nil nil nil def))
- (let ((files (read-library-name--find-files dirs suffixes)))
- (when (and def (not (member def files)))
- (setq def nil))
- (completing-read (format-prompt "Library name" def)
- files nil t nil nil def)))))
+if non-nil).
+
+Optional argument PROMPT is the minibuffer prompt to use, when nil or
+omitted it defaults to \"Library name\"."
+ (let* ((prompt (or prompt "Library name"))
+ (files (read-library-name--find-files
+ (or find-library-source-path load-path)
+ (find-library-suffixes)))
+ (def (thing-at-point 'symbol))
+ (def (and (member def files) def)))
+ (completing-read (format-prompt prompt def)
+ (completion-table-with-metadata
+ files
+ `((category . library)
+ (narrow-completions-function
+ . read-library-name-narrow-completions-by-keyword)
+ ,@(when completions-detailed
+ '((affixation-function
+ . read-library-name-affixation)))))
+ nil t nil nil def)))
(defun read-library-name--find-files (dirs suffixes)
"Return a list of all files in DIRS that match SUFFIXES."
"Find the Emacs Lisp source of LIBRARY in another window.
See `find-library' for more details."
- (interactive (list (read-library-name)))
+ (interactive (list (read-library-name "Find library")))
(prog1
(switch-to-buffer-other-window (find-file-noselect
(find-library-name library)))
"Find the Emacs Lisp source of LIBRARY in another frame.
See `find-library' for more details."
- (interactive (list (read-library-name)))
+ (interactive (list (read-library-name "Find library")))
(prog1
(switch-to-buffer-other-frame (find-file-noselect
(find-library-name library)))
(puthash function name help-fns--function-names)
name))))
+(declare-function find-library-name "find-func" (library))
+(declare-function lm-summary "lisp-mnt" (&optional file))
+(declare-function lm-keywords "lisp-mnt" (&optional file))
+(declare-function lm-commentary "lisp-mnt" (&optional file))
+
+;;;###autoload
+(defun describe-library (library)
+ "Display information about LIBRARY in a help buffer."
+ (interactive (list (read-library-name "Describe library")))
+ (require 'find-func)
+ (require 'lisp-mnt)
+ (let* ((file (find-library-name library))
+ (name (file-name-nondirectory file))
+ (help-buffer-under-preparation t))
+ (help-setup-xref (list #'describe-library library)
+ (called-interactively-p 'interactive))
+ (with-help-window (help-buffer)
+ (with-current-buffer standard-output
+ (insert name
+ " --- " (substitute-quotes (or (lm-summary file)
+ "[No summary available]"))
+ (if-let (keywords (lm-keywords file))
+ (concat "\n\nKeywords: ["
+ (replace-regexp-in-string ",? " "] [" keywords)
+ "]")
+ "")
+ "\n\n"
+ (substitute-quotes (or (lm-commentary file)
+ "[No description available]")))
+ (make-text-button (point-min) (+ (length name) (point-min))
+ 'type 'help-library-def 'help-args (list file))
+ (setq help-mode--current-data (list :file file))))))
+
+(put 'describe-library 'minibuffer-action "describe")
+
(provide 'help-fns)
;;; help-fns.el ends here