From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alex Kost Subject: [PATCH] emacs: Add 'guix-prettify'. Date: Thu, 06 Nov 2014 16:13:33 +0300 Message-ID: <87r3xgbhfm.fsf_-_@gmail.com> References: <87d2926he1.fsf@gmail.com> <87h9ye8x6d.fsf@gnu.org> <87d291uby6.fsf@gmail.com> <874mud4dbb.fsf@gnu.org> <8761ettjj4.fsf@gmail.com> <87oaskoek1.fsf@gnu.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:36288) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XmMsg-0000Vp-Iq for guix-devel@gnu.org; Thu, 06 Nov 2014 08:13:47 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XmMsc-0004Ak-2m for guix-devel@gnu.org; Thu, 06 Nov 2014 08:13:42 -0500 In-Reply-To: <87oaskoek1.fsf@gnu.org> ("Ludovic \=\?utf-8\?Q\?Court\=C3\=A8s\=22'\?\= \=\?utf-8\?Q\?s\?\= message of "Thu, 06 Nov 2014 10:37:18 +0100") List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org Sender: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org To: Ludovic =?utf-8?Q?Court=C3=A8s?= Cc: guix-devel@gnu.org --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Ludovic Court=C3=A8s (2014-11-06 12:37 +0300) wrote: > Alex Kost skribis: > >> Ludovic Court=C3=A8s (2014-11-05 23:12 +0300) wrote: >> >>> Alex Kost skribis: [...] >>>> I've realized that "pretty-sha-path" is a bad name, because those 32 >>>> numbers and letters have nothing to do with SHA-sequences as I thought >>>> initially. So maybe it would be better to rename it into >>>> "pretty-hash-path" or "guix-pretty-path" (as it will be a part of Guix) >>>> or something else. Or is it OK to leave it as it is? >>> >>> Good point. Prefixing with =E2=80=98guix-=E2=80=99 makes sense, and it= will be easier >>> for users to find it. >>> >>> While we=E2=80=99re at it, =E2=80=9Cpath=E2=80=9D in GNU normally means= =E2=80=9Csearch path=E2=80=9D, not =E2=80=9Cfile >>> name=E2=80=9D (info "(standards) GNU Manuals"), so perhaps >>> =E2=80=98guix-pretty-file-names=E2=80=99 or something like that would b= e even better. >>> WDYT? >> >> I think =E2=80=98guix-pretty-file-names=E2=80=99 is too long for a packa= ge name as all >> symbols have to be prefixed with it. What about =E2=80=98guix-prettify= =E2=80=99? > > OK! Thanks, here is the patch again: the package was renamed; regexp was corrected; a reference in =E2=80=9Cguix.texi=E2=80=9D was made and "path"-s= were replaced by "file name"-s. It's still not too late to rename everything if =E2=80=98guix-prettify=E2=80=99 looks unsatisfactory. --=-=-= Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename=0001-emacs-Add-guix-prettify.patch Content-Transfer-Encoding: quoted-printable >From e074a41a5a96d4b3a4c6e5dbb4f11993b500b429 Mon Sep 17 00:00:00 2001 From: Alex Kost Date: Tue, 4 Nov 2014 19:38:27 +0300 Subject: [PATCH] emacs: Add 'guix-prettify'. * emacs/guix-prettify.el: New file. * emacs.am (ELFILES): Add it. * doc/emacs.texi (Emacs Prettify): New node. * doc/guix.texi (Features): Mention it. --- doc/emacs.texi | 42 ++++++++++ doc/guix.texi | 4 +- emacs.am | 1 + emacs/guix-prettify.el | 204 +++++++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 emacs/guix-prettify.el diff --git a/doc/emacs.texi b/doc/emacs.texi index 9e8fec4..89e2570 100644 --- a/doc/emacs.texi +++ b/doc/emacs.texi @@ -18,6 +18,7 @@ guix package}). Specifically, ``guix.el'' makes it easy = to: * Initial Setup: Emacs Initial Setup. Preparing @file{~/.emacs}. * Usage: Emacs Usage. Using the interface. * Configuration: Emacs Configuration. Configuring the interface. +* Prettify Mode: Emacs Prettify. Abbreviating @file{/gnu/store/@dots{}} fi= le names. @end menu =20 @node Emacs Initial Setup @@ -422,3 +423,44 @@ buffers. Various settings for ``info'' buffers. =20 @end table + + +@node Emacs Prettify +@subsection Guix Prettify Mode + +Along with ``guix.el'', GNU@tie{}Guix comes with ``guix-prettify.el''. +It provides a minor mode for abbreviating store file names by replacing +hash sequences of symbols with ``@dots{}'': + +@example +/gnu/store/72f54nfp6g1hz873w8z3gfcah0h4nl9p-foo-0.1 +@result{} /gnu/store/=E2=80=A6-foo-0.1 +@end example + +Once you set up ``guix.el'' (@pxref{Emacs Initial Setup}), the following +commands become available: + +@table @kbd + +@item M-x guix-prettify-mode +Enable/disable prettifying for the current buffer. + +@item M-x global-guix-prettify-mode +Enable/disable prettifying globally. + +@end table + +To automatically enable @code{guix-prettify-mode} globally on Emacs +start, add the following line to your init file: + +@example +(global-guix-prettify-mode) +@end example + +If you want to enable it only for specific major modes, add it to the +mode hooks (@pxref{Hooks,,, emacs, The GNU Emacs Manual}), for example: + +@example +(add-hook 'shell-mode-hook 'guix-prettify-mode) +(add-hook 'dired-mode-hook 'guix-prettify-mode) +@end example diff --git a/doc/guix.texi b/doc/guix.texi index 4a596bc..35fe27f 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -628,7 +628,9 @@ management tools it provides. =20 When using Guix, each package ends up in the @dfn{package store}, in its own directory---something that resembles -@file{/gnu/store/xxx-package-1.2}, where @code{xxx} is a base32 string. +@file{/gnu/store/xxx-package-1.2}, where @code{xxx} is a base32 string +(note that Guix comes with an Emacs extension to shorten those file +names, @ref{Emacs Prettify}.) =20 Instead of referring to these directories, users have their own @dfn{profile}, which points to the packages that they actually want to diff --git a/emacs.am b/emacs.am index 9279078..be7e77e 100644 --- a/emacs.am +++ b/emacs.am @@ -25,6 +25,7 @@ ELFILES =3D \ emacs/guix-info.el \ emacs/guix-list.el \ emacs/guix-messages.el \ + emacs/guix-prettify.el \ emacs/guix-utils.el \ emacs/guix.el =20 diff --git a/emacs/guix-prettify.el b/emacs/guix-prettify.el new file mode 100644 index 0000000..b01495c --- /dev/null +++ b/emacs/guix-prettify.el @@ -0,0 +1,204 @@ +;;; guix-prettify.el --- Prettify Guix store file names + +;; Copyright =C2=A9 2014 Alex Kost + +;; This file is part of GNU Guix. + +;; GNU Guix 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. + +;; GNU Guix 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 . + +;;; Commentary: + +;; This package provides minor-mode for prettifying Guix store file +;; names =E2=80=94 i.e., after enabling `guix-prettify-mode', +;; '/gnu/store/72f54nfp6g1hz873w8z3gfcah0h4nl9p-foo-0.1' names will be +;; replaced with '/gnu/store/=E2=80=A6-foo-0.1' in the current buffer. Th= ere is +;; also `global-guix-prettify-mode' for global prettifying. + +;; To install, add the following to your emacs init file: +;; +;; (add-to-list 'load-path "/path/to/dir-with-guix-prettify") +;; (autoload 'guix-prettify-mode "guix-prettify" nil t) +;; (autoload 'global-guix-prettify-mode "guix-prettify" nil t) + +;; If you want to enable/disable composition after "M-x font-lock-mode", +;; use the following setting: +;; +;; (setq font-lock-extra-managed-props +;; (cons 'composition font-lock-extra-managed-props)) + +;; Credits: +;; +;; Thanks to Ludovic Court=C3=A8s for the idea of this package. +;; +;; Thanks to the authors of `prettify-symbols-mode' (part of Emacs 24.4) +;; and "pretty-symbols.el" +;; for the code. It helped to write this package. + +;;; Code: + +(defgroup guix-prettify nil + "Prettify Guix store file names." + :prefix "guix-prettify-" + :group 'font-lock + :group 'convenience) + +(defcustom guix-prettify-char ?=E2=80=A6 + "Character used for prettifying." + :type 'character + :group 'guix-prettify) + +(defcustom guix-prettify-decompose-force nil + "If non-nil, remove any composition. + +By default, after disabling `guix-prettify-mode', +compositions (prettifying names with `guix-prettify-char') are +removed only from strings matching `guix-prettify-regexp', so +that compositions created by other modes are left untouched. + +Set this variable to non-nil, if you want to remove any +composition unconditionally (like `prettify-symbols-mode' does). +Most likely it will do no harm and will make the process of +disabling `guix-prettify-mode' a little faster." + :type 'boolean + :group 'guix-prettify) + +(defcustom guix-prettify-regexp + (rx "/" + (or "nix" "gnu") + "/store/" + ;; Hash-parts do not include "e", "o", "u" and "t". See base32Chars + ;; at + (group (=3D 32 (any "0-9" "a-d" "f-n" "p-s" "v-z")))) + "Regexp matching file names for prettifying. + +Disable `guix-prettify-mode' before modifying this variable and +make sure to modify `guix-prettify-regexp-group' if needed. + +Example of a \"deeper\" prettifying: + + (setq guix-prettify-regexp \"store/[[:alnum:]]\\\\\\=3D{32\\\\}\" + guix-prettify-regexp-group 0) + +This will transform +'/gnu/store/72f54nfp6g1hz873w8z3gfcah0h4nl9p-foo-0.1' into +'/gnu/=E2=80=A6-foo-0.1'" + :type 'regexp + :group 'guix-prettify) + +(defcustom guix-prettify-regexp-group 1 + "Regexp group in `guix-prettify-regexp' for prettifying." + :type 'integer + :group 'guix-prettify) + +(defvar guix-prettify-special-modes + '(guix-info-mode ibuffer-mode) + "List of special modes that support font-locking. + +By default, \\[global-guix-prettify-mode] enables prettifying in +all buffers except the ones where `font-lock-defaults' is +nil (see Info node `(elisp) Font Lock Basics'), because it may +break the existing highlighting. + +Modes from this list and all derived modes are exceptions +\(`global-guix-prettify-mode' enables prettifying there).") + +(defvar guix-prettify-flush-function + (cond ((fboundp 'font-lock-flush) #'font-lock-flush) + ((fboundp 'jit-lock-refontify) #'jit-lock-refontify)) + "Function used to refontify buffer. +This function is called without arguments after +enabling/disabling `guix-prettify-mode'. If nil, do nothing.") + +(defun guix-prettify-compose () + "Compose matching region in the current buffer." + (let ((beg (match-beginning guix-prettify-regexp-group)) + (end (match-end guix-prettify-regexp-group))) + (compose-region beg end guix-prettify-char 'decompose-region)) + ;; Return nil because we're not adding any face property. + nil) + +(defun guix-prettify-decompose-buffer () + "Remove file names compositions from the current buffer." + (with-silent-modifications + (let ((inhibit-read-only t)) + (if guix-prettify-decompose-force + (remove-text-properties (point-min) + (point-max) + '(composition nil)) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward guix-prettify-regexp nil t) + (remove-text-properties + (match-beginning guix-prettify-regexp-group) + (match-end guix-prettify-regexp-group) + '(composition nil)))))))) + +;;;###autoload +(define-minor-mode guix-prettify-mode + "Toggle Guix Prettify mode. + +With a prefix argument ARG, enable Guix Prettify mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +When Guix Prettify mode is enabled, hash-parts of the Guix store +file names (see `guix-prettify-regexp') are prettified, +i.e. displayed as `guix-prettify-char' character. This mode can +be enabled programmatically using hooks: + + (add-hook 'shell-mode-hook 'guix-prettify-mode) + +It is possible to enable the mode in any buffer, however not any +buffer's highlighting may survive after adding new elements to +`font-lock-keywords' (see `guix-prettify-special-modes' for +details). + +Also you can use `global-guix-prettify-mode' to enable Guix +Prettify mode for all modes that support font-locking." + :init-value nil + :lighter " =E2=80=A6" + (let ((keywords `((,guix-prettify-regexp + (,guix-prettify-regexp-group + (guix-prettify-compose)))))) + (if guix-prettify-mode + ;; Turn on. + (font-lock-add-keywords nil keywords) + ;; Turn off. + (font-lock-remove-keywords nil keywords) + (guix-prettify-decompose-buffer)) + (and guix-prettify-flush-function + (funcall guix-prettify-flush-function)))) + +(defun guix-prettify-supported-p () + "Return non-nil, if the mode can be harmlessly enabled in current buffer= ." + (or font-lock-defaults + (apply #'derived-mode-p guix-prettify-special-modes))) + +(defun guix-prettify-turn-on () + "Enable `guix-prettify-mode' in the current buffer if needed. +See `guix-prettify-special-modes' for details." + (and (not guix-prettify-mode) + (guix-prettify-supported-p) + (guix-prettify-mode))) + +;;;###autoload +(define-globalized-minor-mode global-guix-prettify-mode + guix-prettify-mode guix-prettify-turn-on) + +;;;###autoload +(defalias 'guix-prettify-global-mode 'global-guix-prettify-mode) + +(provide 'guix-prettify) + +;;; guix-prettify.el ends here --=20 2.1.2 --=-=-=--