bytemap is a library for creating text-based graphics using Unicode braille characters.
Each braille character contains 8 “pixels” arranged in a 2x4 grid, allowing for reasonably high-resolution terminal output.
This is a Clojure(Script) port of Ian Henry’s Janet library.
Add to your deps.edn:
{:deps {dev.tomwaddington/bytemap.clj {:mvn/version "RELEASE"}}
(require '[bytemap.core :as bm]
'[bytemap.plot :as bp])
;; Create a canvas and draw points
(-> (bm/new-canvas 10 5)
(bm/draw-point [10 10])
(bm/print-canvas!))
;; ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
;; ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
;; ⠀⠀⠀⠀⠀⠄⠀⠀⠀⠀
;; ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
;; ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
;; Draw lines
(-> (bm/new-canvas 10 5)
(bm/draw-line [0 0] [20 20])
(bm/draw-line [0 20] [20 0])
(bm/print-canvas!))
;; ⠑⢄⠀⠀⠀⠀⠀⠀⢀⠔
;; ⠀⠀⠑⢄⠀⠀⢀⠔⠁⠀
;; ⠀⠀⠀⠀⢑⢔⠁⠀⠀⠀
;; ⠀⠀⢀⠔⠁⠀⠑⢄⠀⠀
;; ⢀⠔⠁⠀⠀⠀⠀⠀⠑⢄
(let [canvas (bm/new-canvas 10 5)
;; Diagonal lines
canvas (reduce (fn [c x]
(-> c
(bm/draw-point [x x])
(bm/draw-point [x (- 20 x)])))
canvas
(range 21))
;; Cross lines
canvas (reduce (fn [c x]
(-> c
(bm/draw-point [10 x])
(bm/draw-point [x 10])))
canvas
(range 21))]
(bm/print-canvas! canvas))
;; ⠑⢄⠀⠀⠀⡇⠀⠀⢀⠔
;; ⠀⠀⠑⢄⠀⡇⢀⠔⠁⠀
;; ⠤⠤⠤⠤⢵⣷⠥⠤⠤⠤
;; ⠀⠀⢀⠔⠁⡇⠑⢄⠀⠀
;; ⢀⠔⠁⠀⠀⡇⠀⠀⠑⢄
;; Plot a sine wave (prints to stdout)
(bp/print-plot! #(Math/sin %) [40 10] Math/PI 1)
;; ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⢀⠤⠖⠚⠒⠒⢤⡀⠀⠀⠀⠀⠀⠀
;; ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⢀⠔⠁⠀⠀⠀⠀⠀⠀⠈⠢⡀⠀⠀⠀⠀
;; ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⢀⠔⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢆⠀⠀⠀
;; ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⢠⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠱⡀⠀
;; ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡷⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢄
;; ⠹⡉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⢉⠝⡏⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉
;; ⠀⠘⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠊⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
;; ⠀⠀⠈⠢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⠁⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
;; ⠀⠀⠀⠀⠑⢄⠀⠀⠀⠀⠀⠀⠀⠀⡠⠊⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
;; ⠀⠀⠀⠀⠀⠀⠑⢤⣀⣀⢀⣀⡤⠊⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
;; Get plot as a string (no side effects)
(def plot-str (bm/plot->string #(Math/cos %) [40 10] Math/PI 1))
;; Plot without axes
(bp/print-plot! #(Math/sin %) [40 10] Math/PI 1 :axis false)
;; ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠤⠖⠚⠒⠒⢤⡀⠀⠀⠀⠀⠀⠀
;; ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠔⠁⠀⠀⠀⠀⠀⠀⠈⠢⡀⠀⠀⠀⠀
;; ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠔⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢆⠀⠀⠀
;; ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠱⡀⠀
;; ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢄
;; ⠱⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠜⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
;; ⠀⠘⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
;; ⠀⠀⠈⠢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
;; ⠀⠀⠀⠀⠑⢄⠀⠀⠀⠀⠀⠀⠀⠀⡠⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
;; ⠀⠀⠀⠀⠀⠀⠑⢤⣀⣀⢀⣀⡤⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
;; Canvas is an immutable data structure
(let [canvas (bm/new-canvas 10 5)
canvas-with-line (bm/draw-line canvas [0 0] [20 20])]
;; Original canvas is unchanged
(bm/canvas->string canvas) ;; => blank canvas
(bm/canvas->string canvas-with-line)) ;; => canvas with line
(new-canvas width height) - Creates a new canvas. Dimensions are in “pixels” (braille characters), where each pixel is 2x4 sub-pixels.(bounds canvas) - Returns [width height] in sub-pixels.(canvas->string canvas) - Converts canvas to a string.(print-canvas! canvas) - Prints canvas to standard output (side-effecting).(draw-point canvas [x y]) - Draws a point at sub-pixel coordinates. Returns new canvas.(draw-point canvas [x y] false) - Clears a point. Returns new canvas.(draw-line canvas [x1 y1] [x2 y2]) - Draws a line using Bresenham’s algorithm. Returns new canvas.(plot canvas f & {:keys [axis x-scale y-scale]}) - Plots a function.(plot->string f [w h] x-scale y-scale & {:keys [axis]}) - Plots a function and returns the string representation.(print-plot! f [w h] x-scale y-scale & {:keys [axis]}) - Plots a function, prints to standard output, and returns nil.(braille byte-val) - Converts a byte (0–255) to a braille character.(bit-of-sub-pixel [x y]) - Maps sub-pixel coordinates to bit position.(set-sub-pixel num [x y] value) - Sets or clears a specific sub-pixel bit.Copyright © 2025–2026 Tom Waddington
Distributed under the MIT License. See LICENSE file for details.
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |