guix-emacs.el 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. ;;; guix-emacs.el --- Emacs packages installed with Guix
  2. ;; Copyright © 2014, 2015, 2016, 2017 Alex Kost <alezost@gmail.com>
  3. ;; Copyright © 2017 Kyle Meyer <kyle@kyleam.com>
  4. ;; This file is part of GNU Guix.
  5. ;; GNU Guix is free software; you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation, either version 3 of the License, or
  8. ;; (at your option) any later version.
  9. ;; GNU Guix is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Commentary:
  16. ;; This file provides auxiliary code to autoload Emacs packages
  17. ;; installed with Guix.
  18. ;;; Code:
  19. (require 'cl-lib)
  20. (defvar guix-user-profile (expand-file-name "~/.guix-profile"))
  21. (defvar guix-emacs-autoloads nil
  22. "List of the last loaded Emacs autoloads.")
  23. (defvar guix-emacs-autoloads-regexp
  24. (rx (group (* any) "-autoloads")
  25. ".el" (zero-or-one "c") string-end)
  26. "Regexp to match Emacs 'autoloads' file.")
  27. (defun guix-emacs-directory (&optional profile)
  28. "Return directory with Emacs packages installed in PROFILE.
  29. If PROFILE is nil, use `guix-user-profile'."
  30. (expand-file-name "share/emacs/site-lisp"
  31. (or profile guix-user-profile)))
  32. (defun guix-emacs-find-autoloads (directory)
  33. "Return a list of Emacs 'autoloads' files in DIRECTORY.
  34. The files in the list do not have extensions (.el, .elc)."
  35. (cl-remove-duplicates
  36. (delq nil
  37. (mapcar (lambda (file)
  38. (when (string-match guix-emacs-autoloads-regexp file)
  39. (match-string 1 file)))
  40. (directory-files directory 'full-name nil 'no-sort)))
  41. :test #'string=))
  42. (defun guix-emacs-subdirs (directory)
  43. "Return list of DIRECTORY subdirectories."
  44. (cl-remove-if (lambda (file)
  45. (or (string-match-p (rx "/." string-end) file)
  46. (string-match-p (rx "/.." string-end) file)
  47. (not (file-directory-p file))))
  48. (directory-files directory 'full-name nil 'no-sort)))
  49. (defun guix-emacs-directories (&optional profile)
  50. "Return the list of directories under PROFILE that contain Emacs packages.
  51. This includes both `share/emacs/site-lisp/guix.d/PACKAGE'
  52. sub-directories and `share/emacs/site-lisp' itself.
  53. If PROFILE is nil, use `guix-user-profile'.
  54. Return nil, if Emacs packages are not installed in PROFILE."
  55. (let ((root-dir (guix-emacs-directory (or profile guix-user-profile))))
  56. (when (file-directory-p root-dir)
  57. (let* ((pkgs-dir (expand-file-name "guix.d" root-dir))
  58. (pkgs-dirs (when (file-directory-p pkgs-dir)
  59. (guix-emacs-subdirs pkgs-dir))))
  60. (cons root-dir pkgs-dirs)))))
  61. ;;;###autoload
  62. (defun guix-emacs-autoload-packages (&rest profiles)
  63. "Autoload Emacs packages installed in PROFILES.
  64. If PROFILES are not specified, use a default user and system
  65. profiles.
  66. 'Autoload' means add directories with Emacs packages to
  67. `load-path' and load 'autoloads' files matching
  68. `guix-emacs-autoloads-regexp'."
  69. (interactive (list (if (fboundp 'guix-read-package-profile)
  70. (funcall 'guix-read-package-profile)
  71. guix-user-profile)))
  72. (let* ((env (getenv "GUIX_ENVIRONMENT"))
  73. (profiles (or profiles
  74. (append (list "/run/current-system/profile"
  75. guix-user-profile)
  76. (and env (list env))))))
  77. (dolist (profile profiles)
  78. (let ((dirs (guix-emacs-directories profile)))
  79. (when dirs
  80. (let* ((autoloads (cl-mapcan #'guix-emacs-find-autoloads
  81. dirs))
  82. (new-autoloads (cl-nset-difference autoloads
  83. guix-emacs-autoloads
  84. :test #'string=)))
  85. (dolist (dir dirs)
  86. (cl-pushnew (directory-file-name dir)
  87. load-path
  88. :test #'string=))
  89. (dolist (file new-autoloads)
  90. (load file 'noerror))
  91. (setq guix-emacs-autoloads
  92. (append new-autoloads guix-emacs-autoloads))))))))
  93. (provide 'guix-emacs)
  94. ;;; guix-emacs.el ends here