Skip to content

Commit 4e6e039

Browse files
committed
First commit
0 parents  commit 4e6e039

50 files changed

Lines changed: 13671 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.editorconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
root = true
2+
3+
[*.cr]
4+
charset = utf-8
5+
end_of_line = lf
6+
insert_final_newline = true
7+
indent_style = space
8+
indent_size = 2
9+
trim_trailing_whitespace = true

.github/dependabot.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "github-actions"
4+
directory: "/"
5+
schedule:
6+
interval: "weekly"

.github/workflows/docs.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: docs
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
jobs:
9+
build:
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- uses: actions/checkout@v6
14+
- uses: crystal-lang/install-crystal@v1
15+
- name: Install dependencies
16+
run: shards install
17+
- name: Generate document
18+
run: crystal docs
19+
- name: Deploy to GitHub Pages
20+
uses: peaceiris/actions-gh-pages@v4
21+
with:
22+
github_token: ${{ secrets.GITHUB_TOKEN }}
23+
publish_dir: ./docs

.github/workflows/test.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: Test
2+
3+
on:
4+
push:
5+
pull_request:
6+
workflow_dispatch:
7+
8+
jobs:
9+
test:
10+
strategy:
11+
fail-fast: false
12+
matrix:
13+
os: [ubuntu-latest, macos-latest]
14+
crystal: [latest]
15+
16+
runs-on: ${{ matrix.os }}
17+
18+
steps:
19+
- uses: actions/checkout@v6
20+
with:
21+
submodules: recursive
22+
23+
- name: Install Crystal
24+
uses: crystal-lang/install-crystal@v1
25+
with:
26+
crystal: ${{ matrix.crystal }}
27+
28+
- name: Install shards
29+
run: shards install --without-development
30+
31+
- name: Run specs
32+
run: crystal spec
33+
34+
- name: Build examples
35+
run: |
36+
find examples -name "*.cr" | sort | while read f; do
37+
echo "Building $f ..."
38+
crystal build --no-codegen "$f"
39+
done
40+
41+
- name: Check formatting
42+
run: crystal tool format --check

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/docs/
2+
/lib/
3+
/bin/
4+
/.shards/
5+
*.dwarf
6+
7+
# Libraries don't need dependency lock
8+
# Dependencies will be locked in applications that use them
9+
/shard.lock

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "UnicodePlots.jl"]
2+
path = UnicodePlots.jl
3+
url = https://github.com/JuliaPlots/UnicodePlots.jl

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 kojix2 <2xijok@gmail.com>
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# unicode_plot.cr
2+
3+
[![Test](https://github.com/kojix2/unicode_plot/actions/workflows/test.yml/badge.svg)](https://github.com/kojix2/unicode_plot/actions/workflows/test.yml)
4+
5+
Unicode terminal plots for Crystal — a port of Julia's [UnicodePlots.jl](https://github.com/JuliaPlots/UnicodePlots.jl).
6+
7+
The code was ported from Julia using an AI tool
8+
9+
## Installation
10+
11+
Add to your `shard.yml`:
12+
13+
```yaml
14+
dependencies:
15+
unicode_plot:
16+
github: kojix2/unicode_plot
17+
```
18+
19+
Then run `shards install`.
20+
21+
## Usage
22+
23+
```crystal
24+
require "unicode_plot"
25+
include UnicodePlot
26+
```
27+
28+
### Line plot
29+
30+
```crystal
31+
x = (0..62).map { |i| i * Math::PI / 31.0 }
32+
y = x.map { |v| Math.sin(v) }
33+
puts lineplot(x, y, title: "sin(x)", xlabel: "x", ylabel: "sin(x)", color: :blue)
34+
```
35+
36+
### Scatter plot
37+
38+
```crystal
39+
x1 = (1..15).map { Random.rand * 3.0 + 1.0 }
40+
y1 = (1..15).map { Random.rand * 3.0 + 1.0 }
41+
x2 = (1..15).map { Random.rand * 3.0 + 6.0 }
42+
y2 = (1..15).map { Random.rand * 3.0 + 6.0 }
43+
44+
p = scatterplot(x1, y1, name: "cluster A", color: :blue,
45+
title: "Two clusters", xlim: {0.0, 11.0}, ylim: {0.0, 11.0})
46+
scatterplot!(p, x2, y2, name: "cluster B", color: :red)
47+
puts p
48+
```
49+
50+
### Bar plot
51+
52+
```crystal
53+
cities = ["Tokyo", "Delhi", "Shanghai", "São Paulo", "Mexico City"]
54+
popmill = [13.96, 16.79, 24.18, 12.33, 9.21]
55+
puts barplot(cities, popmill, title: "City populations", xlabel: "population [mil]")
56+
```
57+
58+
You can also pass a `Hash(String, Float64)` directly (sorted by key):
59+
60+
```crystal
61+
puts barplot({"Ruby" => 95.0, "Python" => 98.0, "Crystal" => 72.0}, title: "Scores")
62+
```
63+
64+
### Histogram
65+
66+
```crystal
67+
data = (1..500).map { Random.rand * 10.0 }
68+
puts histogram(data, title: "Uniform [0, 10)", nbins: 15)
69+
```
70+
71+
### Multiple series / incremental plots
72+
73+
All plot types support a mutating `!` variant for adding series to an existing plot:
74+
75+
```crystal
76+
x = (1..20).map(&.to_f)
77+
p = lineplot(x, x.map { |v| Math.sqrt(v) }, name: "√x", color: :green, title: "Functions")
78+
lineplot!(p, x, x.map { |v| Math.log(v) }, name: "ln(x)", color: :red)
79+
puts p
80+
```
81+
82+
### Options
83+
84+
| Option | Description |
85+
|---|---|
86+
| `title` | Plot title |
87+
| `xlabel` / `ylabel` | Axis labels |
88+
| `xlim` / `ylim` | Axis limits as `{min, max}` tuple |
89+
| `color` | Line/point color (`:red`, `:blue`, `:green`, `:cyan`, `:magenta`, `:yellow`, `:normal`) |
90+
| `name` | Series name (shown in legend) |
91+
| `xscale` / `yscale` | Scale function (`:log2`, `:log10`, or a `Proc(Float64, Float64)`) |
92+
| `width` / `height` | Canvas size in characters |
93+
| `canvas` | Canvas type (`:braille`, `:block`, `:ascii`) |
94+
95+
See `examples/` for runnable demos.
96+
97+
## License
98+
99+
MIT — see [LICENSE](LICENSE).

UnicodePlots.jl

Submodule UnicodePlots.jl added at 09db003

examples/barplot.cr

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
require "../src/unicode_plot"
2+
3+
include UnicodePlot
4+
5+
# Basic bar plot
6+
cities = ["Tokyo", "Delhi", "Shanghai", "São Paulo", "Mexico City"]
7+
popmill = [13.96, 16.79, 24.18, 12.33, 9.21]
8+
9+
p = barplot(cities, popmill,
10+
title: "City populations", xlabel: "population [mil]")
11+
puts p
12+
puts
13+
14+
# From a Hash (sorted by key automatically)
15+
data = {"Ruby" => 95.0, "Python" => 98.0, "Crystal" => 72.0, "Julia" => 68.0, "Rust" => 85.0}
16+
p = barplot(data, title: "Language popularity index", xlabel: "score", color: :cyan)
17+
puts p
18+
puts
19+
20+
# Gradient bar symbols (sub-character resolution)
21+
langs = ["C", "Go", "Java", "JavaScript", "TypeScript"]
22+
vals = [100.0, 88.5, 75.2, 92.1, 89.4]
23+
p = barplot(langs, vals,
24+
title: "Benchmark scores",
25+
symbols: [' ', '▏', '▎', '▍', '▌', '▋', '▊', '▉', '█'],
26+
color: :green)
27+
puts p
28+
puts
29+
30+
# Adding bars to an existing plot with barplot!
31+
p = barplot(["Alpha"], [42.0], title: "Growing chart")
32+
barplot!(p, "Beta", 67.0)
33+
barplot!(p, "Gamma", 31.0, color: :yellow)
34+
puts p

0 commit comments

Comments
 (0)