• Stars
    star
    228
  • Rank 175,267 (Top 4 %)
  • Language
    Emacs Lisp
  • License
    GNU General Publi...
  • Created over 5 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Disperse Lisp forms (and other languages) into a spectrum of colors by depth

prism.el

prism disperses lisp forms (and other languages) into a spectrum of color by depth. It’s similar to rainbow-blocks, but it respects existing non-color face properties, and allows flexible configuration of faces and colors. It also optionally colorizes strings and/or comments by code depth in a similar, customizable way.

Contents

Screenshots

Lisp and C-like languages

One of the benefits of prism is making it easy to see which list elements are in. For example, in this excerpt from org-get-entries-from-diary from org-agenda.el, the funcall’s first argument is an unusually indented if form, and the indentation nearly aligns the funcall’s second argument, date, at the column where the if’s else clause would usually be. But with depth-based colorization, it’s easy to see that date and 1 are arguments to funcall, not part of the if form.

It’s also easy to distinguish the diary-list-entries-hook variable’s value form from other variables, and the entries variable’s different color clearly shows that it has no value form.

images/one-armed-if.png

It is also useful for non-Lisp languages. For example, here’s an example of JSON in prism-mode:

images/json.png

Here’s an Emacs C function:

images/c.png

It might even help save you from deeply nested, callback-style JavaScript, turning this:

images/js-before.png

Into this (using theme doom-outrun-electric). Note how the bind is the same color as the function keyword and braces that it corresponds to:

images/js-after.png

Colorize parens distinctly

Inspired by paren-face, when the option prism-parens is enabled, parens (any character classified as parenthesis-like syntax by the buffer’s mode) may be colored distinctly from other text, e.g. to make them fade away or stand out. For example, this shows parens being blended into the background with 50% opacity:

images/parens-0.5.png

And here, at 25%:

images/parens-0.25.png

Highlighting mistakes

In this screenshot, the second and third top-level forms are colorized differently than the first, which points to a programmer error: the first defun’s closing parens are on a line after a comment.

images/prism-shows-mistakes.png

Whitespace-sensitive languages

For whitespace-sensitive languages, prism-whitespace-mode determines depth by a combination of indentation and list nesting. For example, Python (showing theme doom-vibrant with these faces set in variable prism-colors: font-lock-type-face, font-lock-function-name-face, font-lock-constant-face, and font-lock-keyword-face):

images/python.png

This example shows Python with prism-comments enabled (showing theme doom-challenger-deep):

images/python-doom-challenger-deep.png

Here, even though these if statements’ conditions are parenthesized and split across lines, they are colorized at the same logical depth–and the parts of them in brackets, at a deeper logical depth, are also colorized at the proper depth:

images/python-3.png

Thanks to Emacs’s mode-specific syntax tables, even complex shell scripts are properly interpreted. In this example, even though the subsequent lines of this shell function are indented more deeply than the first, they are at the same logical depth because of their being continued lines, so they are colorized at the same initial depth, with their parenthesized and bracketed portions colorized at deeper depths (showing theme doom-solarized-dark with a reversed-rainbow palette):

images/shell-1.png

And in this function, even though Emacs indents each part of the the doubly continued line more deeply, they’re colorized with the same color, because they’re at the same logical depth:

images/shell-2.png

It even works in Haskell (showing theme doom-molokai):

images/haskell-doom-molokai.png

Customizable colors

It’s easy to adjust the colors with prism-set-colors. Here are some examples.

You can use just a few faces in combination with the desaturations and lightens to create a palette of colors:

images/2-faces.png images/4-faces.png

Or even a single color, going in one direction:

images/1-color.png

…or the other:

images/1-color-reversed.png

The default configuration looks decent in the default Emacs theme:

images/default-emacs.png

If you use Doom themes, you can use doom-color to get colors from the theme:

images/doom-spacegrey.png

But some of them look nice without any customization, like doom-gruvbox:

images/doom-gruvbox.png

If you use solarized-theme, you can use solarized-with-color-variables to get colors from the theme:

images/1.png

And you can adjust the palette extensively by changing the applied desaturation and lightening:

images/2.png images/5.png

You can shuffle the order of the colors until you find a pattern you like:

images/shuffled.png

Buffer-local themes

You can even set themes buffer-locally (the theme-choosing command shown here is not included, but you can easily define your own “chooser” command using unpackaged/define-chooser):

images/prism-themes.gif

Comparisons

prism is much like rainbow-blocks, but it differs in a few ways:

  • prism optionally colorizes comments and strings according to the depth of their surrounding code.
  • prism highlights parens with the color of the outer list’s symbols, which helps parens stand out from symbols and shows which depth surrounds a list.
  • prism adds to the face text property, which respects existing fontification, while rainbow-blocks sets the font-lock-face text property, which overrides existing fontification. This means that prism is compatible with packages like highlight-function-calls and highlight-quoted.
  • prism uses font-lock-add-keywords, while rainbow-blocks uses jit-lock-register. Which is better? Good question. Hopefully, the former…

Installation

The easiest way is to use quelpa-use-package like this:

(use-package prism
  :quelpa (prism :fetcher github :repo "alphapapa/prism.el"))

Usage

  1. Run the appropriate command for the current buffer:
    • For Lisp and C-like languages, use prism-mode.
    • For significant-whitespace languages like Python, or ones whose depth is not always indicated by parenthetical characters, like shell, use prism-whitespace-mode instead.
  2. Enjoy.
  • If the colors aren’t satisfactory, use command prism-randomize-colors to randomize the prism colors according to the current Emacs theme. When you find a set you like, you may save the colors with command prism-save-colors.
  • When a theme is loaded or disabled, and prism-colors is a list of faces (rather than a list of colors), prism-colors is automatically updated. If prism-colors is a list of colors, call prism-set-colors or prism-randomize-colors manually to update for a new theme.
  • To customize, see the prism customization group, e.g. by using M-x customize-group RET prism RET. For example, by default, comments and strings are colorized according to depth, similarly to code, but this can be disabled.

Advanced

More advanced customization of faces is done by calling prism-set-colors, which can override the default settings and perform additional color manipulations. The primary argument is COLORS, which should be a list of colors, each of which may be a name, a hex RGB string, or a face name (of which the foreground color is used). Note that the list of colors need not be as long as the number of faces that’s actually set (e.g. the default is 16 faces), because the colors are automatically repeated and adjusted as necessary.

Faces may be remapped buffer-locally by setting the LOCAL argument to t (interactively, with one universal prefix); if set to reset (interactively, with two prefixes), local remappings are cleared.

If prism-set-colors is called with the SAVE argument, the results are saved to customization options so that prism-mode will use those colors by default.

Here’s an example that the author finds pleasant (seen in the first screenshot):

(prism-set-colors :num 16
  :desaturations (cl-loop for i from 0 below 16
                          collect (* i 2.5))
  :lightens (cl-loop for i from 0 below 16
                     collect (* i 2.5))
  :colors (list "dodgerblue" "medium sea green" "sandy brown")

  :comments-fn
  (lambda (color)
    (prism-blend color
                 (face-attribute 'font-lock-comment-face :foreground) 0.25))

  :strings-fn
  (lambda (color)
    (prism-blend color "white" 0.5)))

Changelog

0.3.2

Fixed

  • When prism-comments is enabled in major modes whose syntax tables do not allow searching for comment delimiters. (Related to #18.) (Thanks to Jason Zhen for reporting.)

0.3.1

Added

  • Failsafe to prevent bugs from causing infinte loops in Emacs.

Fixed

  • Infinite loop with certain buffer contents. (Further fixes #18.) (Thanks to Jason Zhen and fkr-0 for reporting.)

0.3

Added

  • Option prism-parens, which allows parenthesis characters (by syntax type, not only ( )) to be colorized differently (e.g. to make them fade away or stand out). The function prism-set-colors’s new argument, parens-fn, defaults to one which fades parens into the background (which only applies when the option is enabled).

Changed

  • Both prism-mode and prism-whitespace-mode deactivate the other mode when activated, allowing them to be switched between without having to disable one first.

Fixed

  • Code comments in strings (or what appeared to be, e.g. ~”Foo; bar”~ in Lisp) were fontified as comments rather than strings.
  • End-of-buffer errors signaled in font-lock-fontify-keywords-region. (Fixes #6. With thanks to @vuori and @piknik.)
  • Call font-lock-flush when disabling modes. (Thanks to Joseph Turner for reporting.)
  • Infinite loop with certain buffer contents (involving strings directly adjacent to other tokens). (Fixes #18. Thanks to @nathanvy for reporting.)

0.2.3

Fixed

  • Depth of logically continued lines (e.g. in Python, an expression split across lines) and physically continued lines (e.g. in Shell, a statement split across backslash-continued lines) in prism-whitespace-mode.

0.2.2

Fixed

  • The fix in previous version. Oops.

0.2.1

Fixed

  • Ignore faces with unspecified- colors (e.g. when used in a terminal).

0.2

Added

  • Command prism-randomize-colors, which sets faces based on a random, shuffled selection of font-lock faces in the current Emacs theme.

Fixed

  • Performance issues with large Lisp forms.

0.1

First tagged version. Possibly a few sneaky bugs lurking, but seems to work well.

Credits

Inspired by rainbow-blocks, rainbow-identifiers, and rainbow-delimiters.

Development

Bug reports, feature requests, suggestions — oh my!

In the event that a bug in the font-locking functions cause Emacs to enter an infinite loop, you can stop it without killing Emacs by following these steps:

  1. From a shell, run pkill -SIGUSR2 emacs. Usually once is enough, but not always.
  2. After Emacs displays a backtrace, switch to the buffer where prism-mode was enabled and call prism-mode again to disable it.
  3. Please report the backtrace to the issue tracker so it can be fixed. Include contents of the buffer when possible.

License

GPLv3

More Repositories

1

org-super-agenda

Supercharge your Org daily/weekly agenda by grouping items
Emacs Lisp
1,182
star
2

org-ql

An Org-mode query language, including search commands and saved views
Emacs Lisp
1,159
star
3

emacs-package-dev-handbook

An Emacs package development handbook. Built with Emacs, by Emacs package developers, for Emacs package developers.
JavaScript
987
star
4

magit-todos

Show source files' TODOs (and FIXMEs, etc) in Magit status buffer
Emacs Lisp
601
star
5

org-web-tools

View, capture, and archive Web pages in Org-mode
Emacs Lisp
519
star
6

org-sidebar

A helpful sidebar for Org mode
Shell
492
star
7

org-rifle

Rifle through your Org-mode buffers and acquire your target
Emacs Lisp
488
star
8

org-protocol-capture-html

Capture HTML from the browser selection into Emacs as org-mode content
Emacs Lisp
442
star
9

bufler.el

A butler for your buffers. Group buffers into workspaces with programmable rules, and easily switch to and manipulate them.
Emacs Lisp
378
star
10

ement.el

Matrix client for Emacs
Emacs Lisp
354
star
11

unpackaged.el

A collection of useful Emacs Lisp code that isn't substantial enough to be packaged
Emacs Lisp
345
star
12

solarized-everything-css

A collection of Solarized user-stylesheets for...everything?
CSS
277
star
13

burly.el

Save and restore frames and windows with their buffers in Emacs
Emacs Lisp
252
star
14

matrix-client.el

A Matrix client for Emacs! (deprecated in favor of Ement.el)
Emacs Lisp
242
star
15

org-graph-view

View Org buffers as a clickable, graphical mind-map
Emacs Lisp
190
star
16

pocket-reader.el

Emacs client for Pocket reading list (getpocket.com)
Emacs Lisp
188
star
17

yequake

Drop-down Emacs frames, like Yakuake
Emacs Lisp
175
star
18

ts.el

Emacs timestamp and date-time library
Emacs Lisp
159
star
19

dogears.el

Never lose your place in Emacs again
Emacs Lisp
154
star
20

with-emacs.sh

Script to easily run Emacs with specified configurations
Shell
142
star
21

makem.sh

Makefile-like script for building and testing Emacs Lisp packages
Shell
128
star
22

plz.el

An HTTP library for Emacs
Emacs Lisp
126
star
23

bucket

A bucket for your shell (like a set of registers, or a clipboard manager)
Shell
118
star
24

restic-runner

Configure and run Restic more easily
Shell
108
star
25

hammy.el

Programmable, interactive interval timers (e.g. for working/resting)
Emacs Lisp
103
star
26

org-sticky-header

Show off-screen Org heading at top of window
Emacs Lisp
103
star
27

alpha-org

A powerful Org configuration
Emacs Lisp
100
star
28

org-make-toc

Automatic tables of contents for Org files
Shell
83
star
29

taxy.el

Programmable taxonomical hierarchies for arbitrary objects
Emacs Lisp
82
star
30

transclusion-in-emacs

Resources about implementing transclusion in Emacs
79
star
31

topsy.el

Simple sticky header showing definition beyond top of window
Emacs Lisp
77
star
32

org-bookmark-heading

Emacs bookmark support for Org-mode
Emacs Lisp
75
star
33

snow.el

Let it snow in Emacs!
Emacs Lisp
72
star
34

org-now

Conveniently show current Org tasks in a sidebar window
Emacs Lisp
50
star
35

bashcaster

An actually simple screen recorder for Linux
Shell
48
star
36

org-recent-headings

Go to recently used Org headings
Shell
47
star
37

obvious.el

Who needs comments when the code is so obvious
Emacs Lisp
46
star
38

frame-purpose.el

Purpose-specific frames for Emacs
Emacs Lisp
46
star
39

org-almanac

Almanac for Org mode
43
star
40

mosey.el

Mosey around inside your Emacs buffer
Emacs Lisp
37
star
41

org-html-theme-darksun

A Solarized Dark version of the Bigblow Org HTML export theme
JavaScript
36
star
42

salv.el

Local minor mode to save a buffer when Emacs is idle
Emacs Lisp
33
star
43

sword-to-org

Convert Sword modules to Org-mode outlines
Emacs Lisp
33
star
44

org-auto-expand

Automatically expand certain Org headings
Shell
28
star
45

mangle

Mangle man pages to show just the parts you need (suitable for aliasing to "man")
Shell
26
star
46

magit.sh

Run Magit in a separate Emacs instance
Shell
26
star
47

org-notely

Pop to new Org headings for quick notetaking
Shell
26
star
48

scrollkeeper.el

Configurable scrolling commands with visual guidelines, for Emacs
Emacs Lisp
22
star
49

ap.el

A simple, Emacs Lisp-focused Emacs config
Emacs Lisp
21
star
50

highlight-function-calls

Highlight function/macro calls in Emacs
Emacs Lisp
21
star
51

org-quick-peek

Quick inline peeks at agenda items and linked nodes in Org-mode
Emacs Lisp
21
star
52

defrepeater.el

Easily define repeatable Emacs commands
Emacs Lisp
20
star
53

pocket-lib.el

Emacs library for the getpocket.com API
Emacs Lisp
19
star
54

org-pocket

Tools to use Pocket with Org-mode
Emacs Lisp
16
star
55

elexandria

Alexandria-like library for Emacs Lisp
Emacs Lisp
13
star
56

sword-converter

Convert SWORD modules to JSON and SQLite and search the converted files
Emacs Lisp
13
star
57

frecency.el

Library to sort items by "frecency" in Emacs
Emacs Lisp
11
star
58

chromatext.el

Apply color gradients to lines of text in Emacs (possibly increasing legibility)
Emacs Lisp
9
star
59

plamix

Mix together M3U playlists, optionally with a desired duration, outputting either a list of files to STDOUT, or writing an M3U playlist to a file
Python
9
star
60

pyza

A command-line/terminal/console Songza player, using VLC or MPD to play audio
Python
8
star
61

melpa-stats

Stats tools for MELPA
Emacs Lisp
6
star
62

org-books

Tools for books in Org-mode
Emacs Lisp
5
star
63

rubbish.py

WIP: A CLI to the XDG trash bin in Python
Python
5
star
64

tp.el

Emacs text-property convenience library
Emacs Lisp
5
star
65

org-search-goto

org-search-goto
Emacs Lisp
5
star
66

buffer-groups.el

A lightweight, automatic grouping rule-based buffer grouper and switcher
Emacs Lisp
5
star
67

ibuffer-auto-groups

Automatically make groups for ibuffer
Emacs Lisp
5
star
68

ampd-tools

A small collection of MPD-related tools
Python
4
star
69

reddit-emacs-css

CSS for /r/emacs
CSS
4
star
70

ox-elisp

Export Org buffers to Emacs Lisp comments
Emacs Lisp
3
star
71

dbg.el

Simple debugging macros
Emacs Lisp
3
star
72

tabtint

Firefox extension which tints Firefox tabs to match color of web page
JavaScript
3
star
73

ya-solarized.el

Yet Another Solarized theme for Emacs
Emacs Lisp
2
star
74

overwatch-formula76

A racing custom game type for Overwatch
C
2
star
75

overwatch-custom-games

A collection of custom games for Overwatch
Emacs Lisp
2
star
76

listen.el

Audio/music player for Emacs
Emacs Lisp
2
star
77

unsplash.hy

Hy
1
star
78

helm-swish

Like helm-swoop, but a little bit faster
Emacs Lisp
1
star
79

greek-hebrew-emacs

How to set up Emacs to easily type Greek and Hebrew
1
star
80

source-status-linker

Turns output of Source engine's status command into links to Steam user profiles
Python
1
star
81

pentadactyl-tabmattach

JavaScript
1
star
82

github-solarized

A Solarized user stylesheet for GitHub made with Stylus
CSS
1
star