;;; el-get.el --- Manage the external elisp bits and pieces you depend upon ;; ;; Copyright (C) 2010-2011 Dimitri Fontaine ;; ;; Author: Dimitri Fontaine ;; URL: http://www.emacswiki.org/emacs/el-get ;; GIT: https://github.com/dimitri/el-get ;; Licence: WTFPL, grab your copy here: http://sam.zoy.org/wtfpl/ ;; ;; This file is NOT part of GNU Emacs. ;; ;; Install ;; Please see the README.md file from the same distribution (require 'cl-lib) (require 'el-get-core) (require 'el-get-custom) (require 'autoload) (declare-function el-get-package-is-installed "el-get" (package)) (declare-function el-get-byte-compile-file "el-get-byte-compile" (el)) (declare-function el-get-package-def "el-get-recipes" (package)) (declare-function el-get-list-package-names-with-status "el-get-status" (&rest statuses)) (defvar el-get-outdated-autoloads nil "List of package names whose autoloads are outdated") (defun el-get-ensure-byte-compilable-autoload-file (file) "If FILE doesn't already exist, create it as a byte-compilable autoload file (the default created by autoload.el has a local no-byte-compile variable that suppresses byte compilation)." ;; If we don't explicitly strip out the no-byte-compile variable, ;; autoload.el will create it on demand (unless (file-exists-p file) (write-region (replace-regexp-in-string ";; no-byte-compile: t\n" "" (autoload-rubric file)) nil file))) (defun el-get-load-fast (file) "Load the compiled version of FILE if it exists; else load FILE verbatim" (load (file-name-sans-extension file) nil (not el-get-verbose))) (defun el-get-eval-autoloads () "Evaluate the autoloads from the autoload file." (when (and el-get-use-autoloads (file-exists-p el-get-autoload-file)) (el-get-verbose-message "el-get: evaluating autoload file") (el-get-load-fast el-get-autoload-file))) (defvar recentf-exclude) (defun el-get-update-autoloads (package) "Regenerate, compile, and load any outdated packages' autoloads." (when (el-get-want-autoloads-p package) (message "el-get: updating autoloads for %s" package) (let ( ;; Generating autoloads runs theses hooks; disable then fundamental-mode-hook prog-mode-hook emacs-lisp-mode-hook ;; use dynamic scoping to set up our loaddefs file for ;; update-directory-autoloads (generated-autoload-file el-get-autoload-file) (visited (find-buffer-visiting el-get-autoload-file)) ;; .loaddefs.el's buffer name MUST be `el-get-autoload-file' ;; or else `autoloads.el' thinks it's a secondary autoload ;; file and puts MD5 checksums instead of timestamps. (find-file-visit-truename nil) (recentf-exclude (cons (regexp-quote el-get-autoload-file) (bound-and-true-p recentf-exclude)))) (unless (or (not visited) (equal generated-autoload-file (buffer-file-name visited))) ;; Kill .loaddefs.el buffer if it has a different name. (kill-buffer visited) (setq visited nil)) ;; make sure we can actually byte-compile it (el-get-ensure-byte-compilable-autoload-file generated-autoload-file) (when (el-get-package-is-installed package) (mapc 'update-directory-autoloads (cl-remove-if-not #'file-directory-p (el-get-load-path package))) (let ((visiting (find-buffer-visiting el-get-autoload-file))) ;; `update-directory-autoloads' leaves file open (when (and (not visited) visiting) (kill-buffer visiting)))) (when (file-exists-p el-get-autoload-file) (message "el-get: byte-compiling autoload file") (when el-get-byte-compile (el-get-byte-compile-file el-get-autoload-file)) (el-get-eval-autoloads))))) (defconst el-get-autoload-regexp (let ((tmp nil)) (dolist (suf (get-load-suffixes)) (unless (string-match "\\.elc" suf) (push suf tmp))) (concat "^[^=.].*" (regexp-opt tmp t) "\\'")) "copied from `update-directory-autoloads'") (defun el-get-remove-autoloads (package) "Remove from `el-get-autoload-file' any autoloads associated with the named PACKAGE" (when (file-exists-p el-get-autoload-file) (let* ((files (cl-mapcan (lambda (dir) (when (file-directory-p dir) (directory-files dir t el-get-autoload-regexp))) (el-get-load-path package))) (generated-autoload-file el-get-autoload-file) (load-names (mapcar (lambda (f) (apply #'autoload-file-load-name ;; Starting from Emacs 28 auto-file-load-name ;; needs two parameters, versions before 28 only ;; one. (if (> emacs-major-version 27) `(,f ,el-get-autoload-file) `(,f)))) files)) (recentf-exclude (cons (regexp-quote el-get-autoload-file) (bound-and-true-p recentf-exclude))) (visited (find-buffer-visiting el-get-autoload-file))) (with-current-buffer (or visited (find-file-noselect el-get-autoload-file)) (widen) (goto-char (point-min)) (while (search-forward generate-autoload-section-header nil t) (when (member (nth 2 (autoload-read-section-header)) load-names) ;; We found a matching section, remove it. (autoload-remove-section (match-beginning 0))))) (el-get-update-autoloads package) (let ((visiting (find-buffer-visiting el-get-autoload-file))) (when visiting (when (buffer-modified-p visiting) ; Save loaddefs, if needed. (with-current-buffer visiting (save-buffer))) ;; Close loaddefs buffer, if we opened it ourselves. (unless visited (kill-buffer visiting))))))) (defun el-get-want-autoloads-p (package) "Return t iff the given PACKAGE should have its autoloads automatically generated by el-get" (let ((source (el-get-package-def package))) (or (not (plist-member source :autoloads)) (eq (plist-get source :autoloads) t)))) (defun el-get-invalidate-autoloads (&optional package) "Mark the named PACKAGE as needing new autoloads. If PACKAGE is nil, marks all installed packages as needing new autoloads." ;; If we're invalidating everything, try to start from a clean slate (unless package (ignore-errors (delete-file el-get-autoload-file) (delete-file (concat (file-name-sans-extension el-get-autoload-file) ".elc")))) (let ((packages (if package (list package) (el-get-list-package-names-with-status "installed")))) (mapc 'el-get-update-autoloads packages))) (provide 'el-get-autoloading)