guix-prettify.el 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. ;;; guix-prettify.el --- Prettify Guix store file names
  2. ;; Copyright © 2014, 2015, 2017 Alex Kost <alezost@gmail.com>
  3. ;; This file is part of Emacs-Guix.
  4. ;; Emacs-Guix is free software; you can redistribute it and/or modify
  5. ;; it under the terms of the GNU General Public License as published by
  6. ;; the Free Software Foundation, either version 3 of the License, or
  7. ;; (at your option) any later version.
  8. ;;
  9. ;; Emacs-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. ;;
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with Emacs-Guix. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;; This package provides minor-mode for prettifying Guix store file
  18. ;; names — i.e., after enabling `guix-prettify-mode',
  19. ;; '/gnu/store/72f54nfp6g1hz873w8z3gfcah0h4nl9p-foo-0.1' names will be
  20. ;; replaced with '/gnu/store/…-foo-0.1' in the current buffer. There is
  21. ;; also `global-guix-prettify-mode' for global prettifying.
  22. ;; To install, add the following to your emacs init file:
  23. ;;
  24. ;; (add-to-list 'load-path "/path/to/dir-with-guix-prettify")
  25. ;; (autoload 'guix-prettify-mode "guix-prettify" nil t)
  26. ;; (autoload 'global-guix-prettify-mode "guix-prettify" nil t)
  27. ;; If you want to enable/disable composition after "M-x font-lock-mode",
  28. ;; use the following setting:
  29. ;;
  30. ;; (setq font-lock-extra-managed-props
  31. ;; (cons 'composition font-lock-extra-managed-props))
  32. ;; Credits:
  33. ;;
  34. ;; Thanks to Ludovic Courtès for the idea of this package.
  35. ;;
  36. ;; Thanks to the authors of `prettify-symbols-mode' (part of Emacs 24.4)
  37. ;; and "pretty-symbols.el" <http://github.com/drothlis/pretty-symbols>
  38. ;; for the code. It helped to write this package.
  39. ;;; Code:
  40. (require 'guix nil t)
  41. (require 'guix-utils)
  42. (defgroup guix-prettify nil
  43. "Prettify Guix store file names."
  44. :prefix "guix-prettify-"
  45. :group 'guix
  46. :group 'font-lock
  47. :group 'convenience)
  48. (defcustom guix-prettify-char ?…
  49. "Character used for prettifying."
  50. :type 'character
  51. :group 'guix-prettify)
  52. (defcustom guix-prettify-decompose-force nil
  53. "If non-nil, remove any composition.
  54. By default, after disabling `guix-prettify-mode',
  55. compositions (prettifying names with `guix-prettify-char') are
  56. removed only from strings matching `guix-prettify-regexp', so
  57. that compositions created by other modes are left untouched.
  58. Set this variable to non-nil, if you want to remove any
  59. composition unconditionally (like `prettify-symbols-mode' does).
  60. Most likely it will do no harm and will make the process of
  61. disabling `guix-prettify-mode' a little faster."
  62. :type 'boolean
  63. :group 'guix-prettify)
  64. (defcustom guix-prettify-regexp
  65. ;; The following file names / URLs should be abbreviated:
  66. ;; /gnu/store/aiywpm2w299pk1ps96a8d8qwnwkzfr2g-foo-0.1
  67. ;; /nix/store/inb6pfvfm2vqpn9wlyrivj3iyx7k2pv6-foo-0.1
  68. ;; http://hydra.gnu.org/nar/hrr424q661d9wdpkr48gyk5a9w8nrlcr-foo-0.1
  69. ;; http://hydra.gnu.org/log/fjbx25bap58k3mywzpmc8w9fjdydxqv8-foo-0.1
  70. ;; https://bayfront.guixsd.org/nar/gzip/m4ccn9nzlsbvlj36w45555pq98spy007-foo-0.1
  71. (rx "/" (or "store" "log" (and "nar" (zero-or-one "/gzip")))
  72. ;; Hash-parts do not include "e", "o", "u" and "t". See base32Chars
  73. ;; at <https://github.com/NixOS/nix/blob/master/src/libutil/hash.cc>
  74. "/" (group (= 32 (any "0-9" "a-d" "f-n" "p-s" "v-z"))))
  75. "Regexp matching file names for prettifying.
  76. Disable `guix-prettify-mode' before modifying this variable and
  77. make sure to modify `guix-prettify-regexp-group' if needed.
  78. Example of a \"deeper\" prettifying:
  79. (setq guix-prettify-regexp \"store/[[:alnum:]]\\\\\\={32\\\\}\"
  80. guix-prettify-regexp-group 0)
  81. This will transform
  82. '/gnu/store/72f54nfp6g1hz873w8z3gfcah0h4nl9p-foo-0.1' into
  83. '/gnu/…-foo-0.1'"
  84. :type 'regexp
  85. :group 'guix-prettify)
  86. (defcustom guix-prettify-regexp-group 1
  87. "Regexp group in `guix-prettify-regexp' for prettifying."
  88. :type 'integer
  89. :group 'guix-prettify)
  90. (defvar guix-prettify-special-modes
  91. '(ibuffer-mode)
  92. "List of special modes that support font-locking.
  93. By default, \\[global-guix-prettify-mode] enables prettifying in
  94. all buffers except the ones where `font-lock-defaults' is
  95. nil (see Info node `(elisp) Font Lock Basics'), because it may
  96. break the existing highlighting.
  97. Modes from this list and all derived modes are exceptions
  98. \(`global-guix-prettify-mode' enables prettifying there).")
  99. (defun guix-prettify-compose ()
  100. "Compose matching region in the current buffer."
  101. (let ((beg (match-beginning guix-prettify-regexp-group))
  102. (end (match-end guix-prettify-regexp-group)))
  103. (compose-region beg end guix-prettify-char 'decompose-region))
  104. ;; Return nil because we're not adding any face property.
  105. nil)
  106. (defun guix-prettify-decompose-buffer ()
  107. "Remove file names compositions from the current buffer."
  108. (with-silent-modifications
  109. (let ((inhibit-read-only t))
  110. (if guix-prettify-decompose-force
  111. (remove-text-properties (point-min)
  112. (point-max)
  113. '(composition nil))
  114. (guix-while-search guix-prettify-regexp
  115. (remove-text-properties
  116. (match-beginning guix-prettify-regexp-group)
  117. (match-end guix-prettify-regexp-group)
  118. '(composition nil)))))))
  119. ;;;###autoload
  120. (define-minor-mode guix-prettify-mode
  121. "Toggle Guix Prettify mode.
  122. With a prefix argument ARG, enable Guix Prettify mode if ARG is
  123. positive, and disable it otherwise. If called from Lisp, enable
  124. the mode if ARG is omitted or nil.
  125. When Guix Prettify mode is enabled, hash parts of the Guix store
  126. file names (see `guix-prettify-regexp') are displayed as
  127. `guix-prettify-char' character, i.e.:
  128. /gnu/store/…-foo-0.1 instead of:
  129. /gnu/store/72f54nfp6g1hz873w8z3gfcah0h4nl9p-foo-0.1
  130. This mode can be enabled programmatically using hooks:
  131. (add-hook 'shell-mode-hook 'guix-prettify-mode)
  132. It is possible to enable the mode in any buffer, however not any
  133. buffer's highlighting may survive after adding new elements to
  134. `font-lock-keywords' (see `guix-prettify-special-modes' for
  135. details).
  136. Also you can use `global-guix-prettify-mode' to enable Guix
  137. Prettify mode for all modes that support font-locking."
  138. :init-value nil
  139. :lighter " …"
  140. (let ((keywords `((,guix-prettify-regexp
  141. (,guix-prettify-regexp-group
  142. (guix-prettify-compose))))))
  143. (if guix-prettify-mode
  144. ;; Turn on.
  145. (font-lock-add-keywords nil keywords)
  146. ;; Turn off.
  147. (font-lock-remove-keywords nil keywords)
  148. (guix-prettify-decompose-buffer))
  149. (guix-font-lock-flush)))
  150. (defun guix-prettify-supported-p ()
  151. "Return non-nil, if the mode can be harmlessly enabled in current buffer."
  152. (or font-lock-defaults
  153. (apply #'derived-mode-p guix-prettify-special-modes)))
  154. (defun guix-prettify-turn-on ()
  155. "Enable `guix-prettify-mode' in the current buffer if needed.
  156. See `guix-prettify-special-modes' for details."
  157. (and (not guix-prettify-mode)
  158. (guix-prettify-supported-p)
  159. (guix-prettify-mode)))
  160. ;;;###autoload
  161. (define-globalized-minor-mode global-guix-prettify-mode
  162. guix-prettify-mode guix-prettify-turn-on)
  163. ;;;###autoload
  164. (defalias 'guix-prettify-global-mode 'global-guix-prettify-mode)
  165. (provide 'guix-prettify)
  166. ;;; guix-prettify.el ends here