Permalink
Switch branches/tags
Nothing to show
Find file
b4c9b50 Dec 10, 2016
214 lines (183 sloc) 7.83 KB
;;; prettify-utils.el --- Helper functions for prettify-symbols-mode -*- lexical-binding: t; -*-
;; Copyright © 2016 Ilazki
;; Author: Ilazki
;; Created: 31 Oct 2016
;; URL: https://github.com/Ilazki/prettify-utils.el
;; Keywords: lisp tools prettify utils prettify-symbols
;; Version: 1.0.1
;; Package-Version: 20161110.0430
;; Package-Requires: ((emacs "24.4"))
;; This file is not part of GNU Emacs.
;;; Commentary:
;; Prettify-utils provides helper functions to simplify configuration of emacs'
;; prettify-symbols-mode. For the unfamiliar, prettify-symbols-mode detects
;; user-defined character combinations and replaces them with different ones
;; (usually ligatures) on-screen without changing the source file. For example,
;; it can be used to display "≥" any time ">=" is found.
;;
;; Unfortunately, setup of prettify-symbols-mode is more complicated than it
;; needs to be, especially if you want the replacement string to be multiple
;; characters instead of just one. For example, displaying "→ " for "->" in
;; order to improve appearance while still preserving the real character length.
;;
;; To use prettify-symbols, you have to set a buffer-local variable,
;; prettify-symbols-alist, to an alist containing string/replacement pairs. This
;; package provides a helper macro, prettify-utils-generate, to create the alist
;; in a simple, uniform manner, like so:
;;
;; (setq prettify-symbols-alist
;; (prettify-utils-generate
;; ("lambda" "λ")
;; ("<=" "≤")
;; (">=" "≥")
;; ("->" "→ ")))
;;
;;
;; Since prettify-symbols uses buffer-local settings, you have to add the alist
;; for each buffer. The easiest way to do this is to add it to a mode's hooks.
;; Example:
;;
;; (add-hook 'prog-mode-hook (lambda ()
;; (setq prettify-symbols-alist
;; (prettify-utils-generate
;; ("lambda" "λ")))))
;;
;; Or, if you're using the same alist for multiple modes, you can create a named
;; function and pass that to the mode hooks:
;;
;; (defun my-symbols-alist ()
;; (setq prettify-symbols-alist
;; (prettify-utils-generate
;; ("lambda" "λ")
;; ("->" "→")
;; ("=>" "⇒"))))
;; (add-hook 'prog-mode-hook 'my-symbols-alist)
;;
;; Generally, prettify-utils-generate should be the only thing needed, but some
;; additional helpers are provided in case a need arises:
;;
;; * prettify-utils-generate-f is the function equivalent of using
;; prettify-utils-generate. Should only be needed for creating higher-order
;; functions.
;; * prettify-utils-create-pair is the function used by other functions to create
;; alist pairs.
;; * prettify-utils-string converts a string into the list format required by
;; prettify-symbols-alist.
;;
;; For more information about any functions or macros provided, as well as
;; additional example use, refer to any function's docstring with
;; `M-x describe-function`.
;;; Code:
(provide 'prettify-utils)
;;;###autoload
(defun prettify-utils--list (l &optional glue)
"Takes two lists and interleaves the (optional) second between each element of
the first. Used to create multi-character sequences for use with the minor mode
'prettify-symbols'. If not supplied, GLUE defaults to '(Br . Bl). For more
information about GLUE, refer to the documentation for the 'compose-region
function and the 'reference-point-alist variable.
This function is used by prettify-utils-string to create the lists given to
prettify-symbols-alist. Calling prettify-utils--list directly is probably not
what you want, check the documentation for prettify-utils-string and
prettify-utils-generate instead.
Example use:
(prettify-utils--list (string-to-list \"hello\") '(Br . Bl))
"
(let ((glue (or glue '(Br . Bl)))
(head (car l))
(tail (cdr l)))
(cond
((not (consp l)) '())
((not (consp tail)) (list head))
(t (cons head
(cons glue
(prettify-utils--list tail glue)))))))
;;;###autoload
(defun prettify-utils-string (s &optional glue)
"Takes a string and an optional list, and returns a list of the string's
characters with GLUE interleaved between each character, for use with
prettify-symbols mode. If no GLUE is supplied, uses the
prettify-utils--list default. For more information about GLUE, refer to the
documentation for the 'compose-region function and the 'reference-point-alist
variable.
This function can be used to simplify multiple-character replacements when
manually constructing a prettify-symbols-alist. For something more high-level,
consider using prettify-utils-generate to create the entire alist instead.
Example:
(prettify-utils-string \"example\" '(Br . Bl))
"
(prettify-utils--list (append s nil) glue))
;; Was used during macro creation then removed
(defun prettify-utils-create-pair (old new &optional glue)
"Takes two strings, OLD and NEW, and an optional GLUE list, and creates an
alist pair for use when creating a prettify-symbols-alist. For more information
about GLUE, refer to the documentation for the 'compose-region function and the
'reference-point-alist variable.
This function is primarily for use by the user-friendly 'prettify-utils-generate
macro, but may be useful if manual alist creation is desired for some reason.
Example:
(setq prettify-symbols-alist `((\">=\" ?≥)
,(prettify-utils-create-pair \"foo\" \"bar\" '(Br . Bl))))
"
(cons old (prettify-utils-string new glue)))
;;;###autoload
(defmacro prettify-utils-generate (&rest pairs)
"Generates an alist for use when setting prettify-symbols-alist. Takes one or
more lists, each consisting of two strings and an optional GLUE list to be
interleaved between characters in the replacement list. If the optional GLUE
list is not supplied, uses the prettify-list default of '(Br . Bl). For more
information about GLUE, refer to the documentation for the 'compose-region
function and the 'reference-point-alist variable.
Example #1:
(setq prettify-symbols-alist
(prettify-utils-generate (\"foo\" \"bar\")
(\">=\" \"\" (Br . Bl))
(\"->\" \"\")))
Example #2:
(setq prettify-symbols-alist
(prettify-generate
(\"lambda\" \"λ\")
(\"|>\" \"\")
(\"<|\" \"\")
(\"->>\" \"\")
(\"->\" \"\")
(\"<-\" \"\")
(\"=>\" \"\")
(\"<=\" \"\")
(\">=\" \"\")))
"
(let* ((head (car pairs))
(tail (cdr pairs))
(old-string (car head))
(new-string (cadr head))
(glue-list (caddr head)))
(if (not (consp head))
'()
`(cons (quote ,(prettify-utils-create-pair old-string new-string glue-list))
(prettify-utils-generate ,@tail)))))
;;;###autoload
(defun prettify-utils-generate-f (&rest pairs)
"Generates an alist for use when setting prettify-symbols-alist. Takes one or
more lists, each consisting of two strings and an optional GLUE list to be
interleaved between characters in the replacement list. If the optional GLUE
list is not supplied, uses the prettify-list default of '(Br . Bl). For more
information about GLUE, refer to the documentation for the 'compose-region
function and the 'reference-point-alist variable.
This is a function equivalent of the prettify-utils-generate macro. Unless
you specifically need a function, such as for use with a higher-order function,
you should use the 'prettify-utils-generate macro instead.
Example:
(prettify-utils-generate-f '(\"foo\" \"bar\")
'(\">=\" \"\" (Br . Bl))
'(\"->\" \"\"))
"
(let* ((head (car pairs))
(tail (cdr pairs))
(old-string (car head))
(new-string (cadr head))
(glue-list (caddr head)))
(if (not (consp head))
'()
(cons (prettify-utils-create-pair old-string new-string glue-list)
(apply 'prettify-utils-generate-f tail)))))
;;; prettify-utils.el ends here