branch: externals/ivy
commit 35d1e9ad160622d75304b2d65395789718bad810
Author: Basil L. Contovounesios <ba...@contovou.net>
Commit: Basil L. Contovounesios <ba...@contovou.net>

    Clean up Make target scripts
    
    * .elpaignore: Remove elpa.el, which is moved under targets, and
    doc/scripts.el, which is deleted.
    * .github/workflows/test.yml: More granular build steps.
    
    * Makefile: Add copyright notice.  Prefer := for internal vars.
    (emacs): Rename 'public' variable...
    (EMACS): ...to this; all uses changed.
    (opt-elcs): New variable holding files that depend on external
    packages, which need different ELCFLAGS to be built (#2583).
    (deps): Replace install-deps.el with new elpa.el.
    (test): Let ivy-test.el activate optional packages itself.
    (checkdoc): Run with -Q and -L.  Pass source files as a list of
    arguments.
    (plain): Remove call to -version; can be inferred in other ways.
    Let plain.el load elpa.el itself.
    (obsolete): Remove; there are better ways to test byte-compiler
    warnings.
    (%.elc): Use ELCFLAGS variable.
    (ivy-avy.elc, ivy-hydra.elc): Use it to activate needed packages.
    
    * doc/Makefile: Add copyright notice.
    (INFO_INSTALL_DIR): Rename...
    (infodir): ...to this more conventional name.  All uses changed.
    Let shell quote/expand $HOME variable within recipe.
    (ivy.info): Remove; rely on predefined implicit rule.
    Move --no-split argument...
    (MAKEINFO_FLAGS): ...to this predefined variable.
    (EMACS, info-src, info-dest): New variables.
    (INSTALL, INSTALL_DATA, RM): Define conventional variables.
    (info, uninstall, clean): Define conventional targets.  Set info as
    default.
    (install): Mark as .PHONY.  Replace cp with INSTALL_DATA.
    Categorize install-info as post-install step.  Call install-info on
    installed .info file, not the srcdir one.
    (ivy.texi): Run Emacs with -Q.  Replace scripts.el with Emacs 28
    org-texinfo-export-to-texinfo-batch.
    
    * doc/scripts.el:
    * targets/install-deps.el:
    * targets/obsolete-config.el: Delete files.
    
    * elpa.el: Move...
    * targets/elpa.el: ...to here, incorporating functionality of
    install-deps.el.  Enable lexical-binding.  Expand copyright notice.
    Avoid side effects at load time.  Check ELPA_STABLE before
    MELPA_STABLE, the idea being to eventually default to GNU ELPA
    instead.  Improve messaging.
    (ivy--elpa-stable, ivy--elpa-dir, ivy--elpa-user-dir)
    (ivy--elpa-archive, ivy--elpa-archives, ivy--elpa-pkgs)
    (ivy--elpa-activated, ivy--elpa-refreshed): New variables.
    (ivy--elpa-activate, ivy--elpa-refresh, ivy--elpa-install-pkg)
    (ivy--elpa-install): New functions.
    
    * ivy-test.el: Try activating external packages.  Don't print
    emacs-version at load time.
    
    * targets/checkdoc.el: Enable lexical-binding.  Expand copyright
    notice.  Activate external packages.  Take command-line arguments.
    
    * targets/plain.el: Enable lexical-binding.  Expand copyright
    notice.  Use targets/elpa.el for installing and activating optional
    packages.  #'-quote command symbols.  When trying to load avy.el,
    catch only file-error.  Provide targets/plain feature.
---
 .elpaignore                |   2 -
 .github/workflows/test.yml |  10 ++--
 Makefile                   |  68 ++++++++++++++----------
 doc/Makefile               |  58 ++++++++++++++++++---
 doc/scripts.el             |   6 ---
 elpa.el                    |   6 ---
 ivy-test.el                |   7 ++-
 targets/checkdoc.el        |  29 ++++++++---
 targets/elpa.el            | 125 +++++++++++++++++++++++++++++++++++++++++++++
 targets/install-deps.el    |  40 ---------------
 targets/obsolete-config.el |   5 --
 targets/plain.el           |  43 ++++++++++++----
 12 files changed, 285 insertions(+), 114 deletions(-)

diff --git a/.elpaignore b/.elpaignore
index e86fe172b6..f675cf8b37 100644
--- a/.elpaignore
+++ b/.elpaignore
@@ -5,7 +5,6 @@ tests
 .mailmap
 CONTRIBUTING.org
 Makefile
-elpa.el
 ivy-test.el
 
 doc/Makefile
@@ -13,4 +12,3 @@ doc/fdl-1.3.txt
 doc/gpl-3.0.txt
 doc/ivy.org
 doc/ivy-ox.el
-doc/scripts.el
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index ba676faef8..3d35ca029d 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -57,7 +57,11 @@ jobs:
     - name: Check Emacs version
       run: emacs --version
 
+    - name: Dependencies
+      run: make deps
+
+    - name: Compile
+      run: make
+
     - name: Test
-      run: |
-        make deps
-        make test
+      run: make test
diff --git a/Makefile b/Makefile
index a823ddeea6..0fbb6213bf 100644
--- a/Makefile
+++ b/Makefile
@@ -1,53 +1,67 @@
-emacs ?= emacs
+# Build and test Ivy from a source checkout.
+
+# Copyright (C) 2015-2025 Free Software Foundation, Inc.
+#
+# This file is part of GNU Emacs.
+#
+# This program 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.
+#
+# This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
+
+EMACS ?= emacs
 RM ?= rm -f
 
-src-elcs = \
+opt-elcs := \
+  ivy-avy.elc \
+  ivy-hydra.elc
+
+src-elcs := \
   colir.elc \
   ivy-faces.elc \
   ivy-overlay.elc \
   ivy.elc \
-  ivy-avy.elc \
-  ivy-hydra.elc \
   swiper.elc \
-  counsel.elc
+  counsel.elc \
+  $(opt-elcs)
 
-test-elcs = ivy-test.elc
+test-elcs := ivy-test.elc
 
 .PHONY: all
 all: compile
 
 .PHONY: deps
 deps:
-       $(emacs) -Q -batch -l targets/install-deps.el
+       $(EMACS) -Q -batch -l targets/elpa.el -f ivy--elpa-install
+
+.PHONY: compile
+compile: $(src-elcs)
 
 .PHONY: test
 test: compile $(test-elcs)
-       $(emacs) -Q -batch -l elpa.el -L . -l ivy-test -f ivy-test-run-tests
+       $(EMACS) -Q -batch -L . $(test-elcs:%.elc=-l %) -f ivy-test-run-tests
+
+.PHONY: clean
+clean:
+       $(RM) $(src-elcs) $(test-elcs)
 
 .PHONY: checkdoc
 checkdoc:
-       $(emacs) -batch -l targets/checkdoc.el
-
-.PHONY: compile
-compile: $(src-elcs)
+       $(EMACS) -Q -batch -L . -l targets/checkdoc.el $(src-elcs:c=)
 
 .PHONY: plain
 plain: compile
-       $(emacs) -version
-       $(emacs) -Q -l elpa.el -L . -l targets/plain.el
-
-.PHONY: obsolete
-obsolete:
-       $(emacs) -batch -l targets/obsolete-config.el
-
-.PHONY: clean
-clean:
-       $(RM) $(src-elcs) $(test-elcs)
+       $(EMACS) -Q -L . -l targets/plain.el
 
 %.elc: %.el
-       $(emacs) -Q -batch -L . -f batch-byte-compile $<
+       $(EMACS) -Q -batch -L . $(ELCFLAGS) -f batch-byte-compile $<
 
-ivy-avy.elc: ivy-avy.el
-ivy-hydra.elc: ivy-hydra.el
-ivy-avy.elc ivy-hydra.elc:
-       $(emacs) -Q -batch -l elpa.el -L . -f batch-byte-compile $<
+$(opt-elcs): ELCFLAGS += -l targets/elpa.el -f ivy--elpa-activate
diff --git a/doc/Makefile b/doc/Makefile
index 1d6964af2c..c6dbe40062 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -1,11 +1,53 @@
-INFO_INSTALL_DIR="${HOME}/git/gnu-elpa/packages/ivy"
+# Build and install Ivy Info manual from Org source.
 
-ivy.texi: ivy.org ivy-ox.el scripts.el
-       emacs -batch -l ivy-ox.el -l scripts.el --eval "(org-to-texi 
\"ivy.org\")"
+# Copyright (C) 2018-2025 Free Software Foundation, Inc.
+#
+# This file is part of GNU Emacs.
+#
+# This program 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.
+#
+# This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
 
-ivy.info: ivy.texi
-       makeinfo --no-split $^
+EMACS ?= emacs
+INSTALL ?= install
+INSTALL_DATA ?= $(INSTALL) -m 644
+MAKEINFO_FLAGS += --no-split
+RM ?= rm -f
+infodir ?= $${HOME}/git/gnu-elpa/packages/ivy
 
-install: ivy.info
-       cp $^ $(INFO_INSTALL_DIR)
-       install-info --info-dir=$(INFO_INSTALL_DIR) --info-file=$^
+info-src := ivy.info
+info-dest = $(infodir)/$(info-src)
+
+.PHONY: info
+info: $(info-src)
+
+.PHONY: install
+install: info
+       $(INSTALL_DATA) $(info-src) "$(infodir)"
+       $(POST_INSTALL)
+       install-info --info-dir="$(infodir)" "$(info-dest)"
+
+.PHONY: uninstall
+uninstall:
+       $(PRE_UNINSTALL)
+       install-info --delete --info-dir="$(infodir)" "$(info-dest)"
+       $(NORMAL_UNINSTALL)
+       $(RM) "$(info-dest)"
+
+.PHONY: clean
+clean:
+       $(RM) $(info-src)
+
+ivy.texi: ivy.org ivy-ox.el
+       $(EMACS) -Q -batch -l ivy-ox.el \
+         -eval '(setq org-confirm-babel-evaluate nil)' \
+         -f org-texinfo-export-to-texinfo-batch $< $@
diff --git a/doc/scripts.el b/doc/scripts.el
deleted file mode 100644
index 97b1827af6..0000000000
--- a/doc/scripts.el
+++ /dev/null
@@ -1,6 +0,0 @@
-;; Copyright (C) 2020-2025 Free Software Foundation, Inc.
-(setq org-confirm-babel-evaluate nil)
-(defun org-to-texi (fname)
-  (find-file fname)
-  (setq-default indent-tabs-mode nil)
-  (org-texinfo-export-to-texinfo))
diff --git a/elpa.el b/elpa.el
deleted file mode 100644
index 86ec715629..0000000000
--- a/elpa.el
+++ /dev/null
@@ -1,6 +0,0 @@
-;; Copyright (C) 2019-2025 Free Software Foundation, Inc.
-(setq package-user-dir
-      (expand-file-name
-       (format "~/.elpa/%s/elpa"
-               (concat emacs-version (when (getenv "MELPA_STABLE") 
"-stable")))))
-(package-initialize)
diff --git a/ivy-test.el b/ivy-test.el
index f3d9271e90..6e0a4dfd16 100644
--- a/ivy-test.el
+++ b/ivy-test.el
@@ -26,6 +26,11 @@
 
 ;;; Code:
 
+;; Optional dependencies.
+(and (require 'targets/elpa nil t)
+     (fboundp 'ivy--elpa-activate)
+     (ivy--elpa-activate))
+
 (defvar ivy-empty "tests/find-file/empty-dir/")
 
 (defvar ivy-features nil
@@ -49,8 +54,6 @@ Intended as :after-while advice for `require'."
 
 (require 'ert)
 
-(message "%s" (emacs-version))
-
 (setq ivy-last (make-ivy-state))
 
 (ert-deftest ivy--lazy-load-ffap--ffap-url-p ()
diff --git a/targets/checkdoc.el b/targets/checkdoc.el
index 8d27423b14..f2edba78f6 100644
--- a/targets/checkdoc.el
+++ b/targets/checkdoc.el
@@ -1,7 +1,24 @@
+;;; targets/checkdoc.el --- Batch mode checkdoc-file -*- lexical-binding: t -*-
+
 ;; Copyright (C) 2017-2025 Free Software Foundation, Inc.
-(checkdoc-file "colir.el")
-(checkdoc-file "counsel.el")
-(checkdoc-file "ivy-overlay.el")
-(checkdoc-file "ivy-test.el")
-(checkdoc-file "ivy.el")
-(checkdoc-file "swiper.el")
+
+;; This program 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.
+
+;; This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'targets/elpa)
+(ivy--elpa-activate)
+
+(while command-line-args-left
+  (checkdoc-file (pop command-line-args-left)))
diff --git a/targets/elpa.el b/targets/elpa.el
new file mode 100644
index 0000000000..e80dc6a981
--- /dev/null
+++ b/targets/elpa.el
@@ -0,0 +1,125 @@
+;;; targets/elpa.el --- Optional Ivy dependencies -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2025 Free Software Foundation, Inc.
+
+;; This program 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.
+
+;; This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'package)
+
+(defvar ivy--elpa-stable
+  (or (getenv "ELPA_STABLE")
+      (getenv "MELPA_STABLE"))
+  "Non-nil if GNU ELPA should be used instead of GNU-devel ELPA.")
+
+(defvar ivy--elpa-dir "~/.elpa"
+  "Parent directory for installing optional dependencies.")
+
+(defvar ivy--elpa-user-dir
+  (expand-file-name
+   (format "%s%s/elpa" emacs-version (if ivy--elpa-stable "-stable" ""))
+   ivy--elpa-dir)
+  "Instance-specific value for `package-user-dir'.")
+
+;; FIXME: Switch to `gnu' once https://bugs.gnu.org/76264 is resolved.
+(defvar ivy--elpa-archive 'melpa
+  "Preferred ELPA archive; keys `ivy--elpa-archives'.")
+
+(defvar ivy--elpa-archives
+  ;; Check default value rather than `gnutls-available-p': even when
+  ;; the latter is non-nil my Emacs 24.5 fails with https://.
+  (let ((s (if (string-prefix-p "https" (cdar package-archives)) "s" "")))
+    `((gnu
+       ("gnu" . ,(format "http%s://elpa.gnu.org/%s/"
+                         s (if ivy--elpa-stable "packages" "devel")))
+       ;; For `wgrep'.
+       ("nongnu" . ,(format "http%s://elpa.nongnu.org/nongnu%s/"
+                            s (if ivy--elpa-stable "" "-devel"))))
+      (melpa
+       ("melpa" . ,(format "https://%smelpa.org/packages/";
+                           (if ivy--elpa-stable "stable." ""))))))
+  "Map ELPA archive symbols to their `package-archives'.")
+
+(defvar ivy--elpa-pkgs
+  '(avy
+    hydra
+    wgrep)
+  "List of optional (or development) package dependencies.")
+
+(defvar ivy--elpa-activated nil
+  "Non-nil if `ivy--elpa-activate' succeeded.")
+
+(defvar ivy--elpa-refreshed nil
+  "Non-nil if `ivy--elpa-refresh' succeeded.")
+
+(defun ivy--elpa-activate ()
+  "Ensure packages under `ivy--elpa-dir' are activated."
+  (unless ivy--elpa-activated
+    (setq package-user-dir ivy--elpa-user-dir)
+    (let ((msg (format "Activating packages in %s" package-user-dir)))
+      (message "%s..." msg)
+      (package-initialize)
+      (message "%s...done" msg))
+    (setq ivy--elpa-activated t)))
+
+(defun ivy--elpa-refresh ()
+  "Ensure archive contents are refreshed."
+  (defvar gnutls-algorithm-priority)
+  (unless ivy--elpa-refreshed
+    (let ((archive ivy--elpa-archive))
+      (setq package-archives (cdr (assq archive ivy--elpa-archives)))
+      (and (eq archive 'melpa)
+           (version< emacs-version "26.3")
+           ;; See https://melpa.org/#/getting-started.
+           (setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3")))
+    (package-refresh-contents)
+    (setq ivy--elpa-refreshed (and package-archive-contents t))))
+
+(defun ivy--elpa-install-pkg (pkg)
+  "Compatibility shim for Emacs 25 `package-install'."
+  (condition-case nil
+      (package-install pkg t)
+    (wrong-number-of-arguments
+     (package-install pkg))))
+
+(defun ivy--elpa-install ()
+  "Install any missing `ivy--elpa-pkgs' with demoted errors."
+  (ivy--elpa-activate)
+  (ivy--elpa-refresh)
+  (let ((msg-all (format "Installing in %s" package-user-dir))
+        any-ok any-err)
+    (message "%s..." msg-all)
+    (dolist (pkg ivy--elpa-pkgs)
+      (unless (package-installed-p pkg)
+        (let ((msg (format "Installing %s" pkg))
+              err)
+          (message "%s..." msg)
+          (condition-case-unless-debug e
+              (ivy--elpa-install-pkg pkg)
+            (error (message "Error: %s" (error-message-string e))
+                   (message "%s...INCOMPLETE" msg)
+                   (setq any-err t)
+                   (setq err e)))
+          (unless err
+            (message "%s...done" msg)
+            (setq any-ok t)))))
+    (message "%s...%s" msg-all
+             (cond (any-err "INCOMPLETE")
+                   (any-ok "done")
+                   (t "already present")))))
+
+;; TODO: upgrade-deps target?
+
+(provide 'targets/elpa)
diff --git a/targets/install-deps.el b/targets/install-deps.el
deleted file mode 100644
index af12419ab5..0000000000
--- a/targets/install-deps.el
+++ /dev/null
@@ -1,40 +0,0 @@
-;; Copyright (C) 2019-2025 Free Software Foundation, Inc.
-(setq melpa-stable (getenv "MELPA_STABLE"))
-(setq package-user-dir
-      (expand-file-name
-       (format "~/.elpa/%s/elpa"
-               (concat emacs-version (when melpa-stable "-stable")))))
-(message "installing in %s ...\n" package-user-dir)
-(package-initialize)
-(setq package-archives
-      (list (if melpa-stable
-                '("melpa-stable" . "https://stable.melpa.org/packages/";)
-              '("melpa" . "https://melpa.org/packages/";))
-            ;; '("gnu" . "https://elpa.gnu.org/packages/";)
-            ))
-(package-refresh-contents)
-
-(defconst ivy-dev-packages
-  '(avy
-    hydra
-    wgrep))
-
-(dolist (package ivy-dev-packages)
-  (if (package-installed-p package)
-      (message "%S: OK" package)
-    (condition-case nil
-        (progn
-          (package-install package)
-          (message "%S: ...OK" package))
-      (error
-       (message "%S: FAIL" package)))))
-
-(save-window-excursion
-  (package-list-packages t)
-  (condition-case nil
-      (progn
-        (package-menu-mark-upgrades)
-        (package-menu-execute t))
-    (error
-     (message "All packages up to date"))))
-(provide 'targets/install-deps)
diff --git a/targets/obsolete-config.el b/targets/obsolete-config.el
deleted file mode 100644
index aa6c0677f1..0000000000
--- a/targets/obsolete-config.el
+++ /dev/null
@@ -1,5 +0,0 @@
-;; Copyright (C) 2016-2025 Free Software Foundation, Inc.
-(add-to-list 'load-path (directory-file-name default-directory))
-(require 'counsel)
-(ivy-set-display-transformer 'ivy-switch-buffer 
#'ivy-switch-buffer-transformer)
-(byte-compile-file (expand-file-name "targets/obsolete-config.el"))
diff --git a/targets/plain.el b/targets/plain.el
index 44a68f099d..2a3cbf4f3b 100644
--- a/targets/plain.el
+++ b/targets/plain.el
@@ -1,18 +1,43 @@
+;;; targets/plain.el --- Canned Ivy configuration -*- lexical-binding: t -*-
+
 ;; Copyright (C) 2017-2025 Free Software Foundation, Inc.
-;; (package-initialize)
+
+;; This program 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.
+
+;; This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
 (require 'counsel)
+(require 'targets/elpa)
+
 (ivy-mode)
 (counsel-mode)
+
 (setq enable-recursive-minibuffers t)
-(global-set-key (kbd "C-c C-r") 'ivy-resume)
-(global-set-key (kbd "C-s") 'swiper)
-(global-set-key (kbd "C-c j") 'counsel-git-grep)
-(global-set-key (kbd "C-c k") 'counsel-rg)
-(global-set-key (kbd "<f2> j") 'counsel-set-variable)
-(global-set-key (kbd "C-c s") 'isearch-forward-regexp)
 (setq ivy-use-virtual-buffers t)
+
+(global-set-key (kbd "C-c C-r") #'ivy-resume)
+(global-set-key (kbd "C-s") #'swiper)
+(global-set-key (kbd "C-c j") #'counsel-git-grep)
+(global-set-key (kbd "C-c k") #'counsel-rg)
+(global-set-key (kbd "<f2> j") #'counsel-set-variable)
+(global-set-key (kbd "C-c s") #'isearch-forward-regexp)
+
+(ivy--elpa-activate)
 (condition-case nil
     (require 'ivy-avy)
-  (error
-   (require 'targets/install-deps)
+  (file-error
+   (ivy--elpa-install)
    (require 'ivy-avy)))
+
+(provide 'targets/plain)

Reply via email to