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