p5rb_cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.standard.yml +3 -0
- data/CHANGELOG.md +5 -0
- data/README.ja.md +59 -0
- data/README.md +59 -0
- data/Rakefile +14 -0
- data/exe/p5rb +5 -0
- data/lib/p5rb_cli/static/index.html +60 -0
- data/lib/p5rb_cli/static/p5editor.js +79 -0
- data/lib/p5rb_cli/static/p5editor.rb +285 -0
- data/lib/p5rb_cli/static/style.css +30 -0
- data/lib/p5rb_cli/version.rb +5 -0
- data/lib/p5rb_cli/web_app.rb +51 -0
- data/lib/p5rb_cli.rb +82 -0
- data/sig/p5rb_cli.rbs +4 -0
- metadata +90 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f7e4ff0549fb0d7163d03434b1a7efd3b8e4f00819280797ce04154f021a19af
|
4
|
+
data.tar.gz: 3cc537a3d241257aaaa20ea4561a130513b02a24e3d8ecd08abc3a3be40ef44c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3f4c9b07797c32db5235cff71b016ec001956b8028e8971435c65e854cd24931f4809b07d9cab5815b1c3fb09d4b64e3136e612b53d7223577a818f79a916910
|
7
|
+
data.tar.gz: b635d263e7964d9e9e7805846aa14de3c4f2623392d180ad1bb9e68374dce747bc74cdfdcfe360db05fa90a9a272cb030abbdf89eca4f18dbbbfddc72eb0b6ae
|
data/.standard.yml
ADDED
data/CHANGELOG.md
ADDED
data/README.ja.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# p5.rb CLI
|
2
|
+
|
3
|
+
p5.rb CLIは、Rubyを使ってp5.jsのようなクリエイティブコーディングを手軽に始められるコマンドラインツールです。インタラクティブなアニメーションやビジュアルアートを、Rubyのシンプルな文法で作成できます。
|
4
|
+
|
5
|
+
## インストール
|
6
|
+
|
7
|
+
```bash
|
8
|
+
gem install p5rb_cli
|
9
|
+
```
|
10
|
+
|
11
|
+
## 使い方
|
12
|
+
|
13
|
+
インストール後、以下のコマンドが使用できます:
|
14
|
+
|
15
|
+
### 新しいスケッチの作成
|
16
|
+
|
17
|
+
```bash
|
18
|
+
p5rb new <NAME>
|
19
|
+
```
|
20
|
+
|
21
|
+
このコマンドは指定したディレクトリに新しいp5.rbスケッチを生成します。生成されるスケッチには、基本的なセットアップとサンプルコードが含まれています。
|
22
|
+
|
23
|
+
### スケッチの実行
|
24
|
+
|
25
|
+
```bash
|
26
|
+
p5rb run <SCRIPT_FILE>
|
27
|
+
```
|
28
|
+
|
29
|
+
このコマンドは指定したスケッチをローカルサーバーで実行し、ブラウザで表示します。変更を加えると自動的にブラウザが更新されます。
|
30
|
+
|
31
|
+
### その他のコマンド
|
32
|
+
|
33
|
+
詳細な使い方を確認するには:
|
34
|
+
|
35
|
+
```bash
|
36
|
+
p5rb help
|
37
|
+
```
|
38
|
+
|
39
|
+
## サンプルコード
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
def setup
|
43
|
+
createCanvas(400, 400)
|
44
|
+
background(220)
|
45
|
+
end
|
46
|
+
|
47
|
+
def draw
|
48
|
+
fill(255, 0, 0)
|
49
|
+
circle(mouseX, mouseY, 50)
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
## 開発に参加する
|
54
|
+
|
55
|
+
バグ報告やプルリクエストは大歓迎です。GitHubの[p5rb_cliリポジトリ](https://github.com/ongaeshi/p5rb_cli)でお願いします。
|
56
|
+
|
57
|
+
## ライセンス
|
58
|
+
|
59
|
+
このプロジェクトは[MITライセンス](https://opensource.org/licenses/MIT)の下でオープンソースとして公開されています。
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# p5.rb CLI
|
2
|
+
|
3
|
+
p5.rb CLI is a command-line tool that makes it easy to start creative coding with Ruby, inspired by p5.js. Create interactive animations and visual art using Ruby's simple and elegant syntax.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```bash
|
8
|
+
gem install p5rb_cli
|
9
|
+
```
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
After installation, you can use the following commands:
|
14
|
+
|
15
|
+
### Create a New Sketch
|
16
|
+
|
17
|
+
```bash
|
18
|
+
p5rb new <NAME>
|
19
|
+
```
|
20
|
+
|
21
|
+
This command generates a new p5.rb sketch in the specified directory. The generated sketch includes basic setup and sample code.
|
22
|
+
|
23
|
+
### Run a Sketch
|
24
|
+
|
25
|
+
```bash
|
26
|
+
p5rb run <SCRIPT_FILE>
|
27
|
+
```
|
28
|
+
|
29
|
+
This command runs the specified sketch on a local server and displays it in your browser. The browser automatically updates when you make changes to your code.
|
30
|
+
|
31
|
+
### Other Commands
|
32
|
+
|
33
|
+
To see detailed usage information:
|
34
|
+
|
35
|
+
```bash
|
36
|
+
p5rb help
|
37
|
+
```
|
38
|
+
|
39
|
+
## Sample Code
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
def setup
|
43
|
+
createCanvas(400, 400)
|
44
|
+
background(220)
|
45
|
+
end
|
46
|
+
|
47
|
+
def draw
|
48
|
+
fill(255, 0, 0)
|
49
|
+
circle(mouseX, mouseY, 50)
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
## Contributing
|
54
|
+
|
55
|
+
Bug reports and pull requests are welcome on GitHub at the [p5rb_cli repository](https://github.com/ongaeshi/p5rb_cli).
|
56
|
+
|
57
|
+
## License
|
58
|
+
|
59
|
+
This project is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rake/testtask"
|
5
|
+
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
7
|
+
t.libs << "test"
|
8
|
+
t.libs << "lib"
|
9
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
10
|
+
end
|
11
|
+
|
12
|
+
require "standard/rake"
|
13
|
+
|
14
|
+
task default: %i[test standard]
|
data/exe/p5rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html>
|
3
|
+
|
4
|
+
<head>
|
5
|
+
<meta charset="utf-8">
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
7
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
|
8
|
+
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
|
9
|
+
<link rel="icon" href="https://i.gyazo.com/0aa7908931f32799b49503d24ea1456f.png">
|
10
|
+
|
11
|
+
<title>p5.rb</title>
|
12
|
+
</head>
|
13
|
+
|
14
|
+
<body>
|
15
|
+
<nav class="navbar navbar-expand-md navbar-light rob-navbar">
|
16
|
+
<div class="container-fluid">
|
17
|
+
<div class="navbar-brand rob-navbar">
|
18
|
+
<img src="https://i.gyazo.com/0aa7908931f32799b49503d24ea1456f.png" alt="" width="24"
|
19
|
+
class="d-inline-block align-text-top">
|
20
|
+
p5.rb
|
21
|
+
</div>
|
22
|
+
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
|
23
|
+
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
24
|
+
<span class="navbar-toggler-icon"></span>
|
25
|
+
</button>
|
26
|
+
<div class="collapse navbar-collapse" id="navbarNav">
|
27
|
+
<ul class="navbar-nav">
|
28
|
+
<li class="nav-item">
|
29
|
+
<a class="nav-link active rob-navbar" aria-current="page" href="https://p5js.org/reference/"
|
30
|
+
target="_blank">Reference</a>
|
31
|
+
</li>
|
32
|
+
<li class="nav-item">
|
33
|
+
<a class="nav-link active rob-navbar" aria-current="page" href="https://github.com/ongaeshi/p5rb_cli/"
|
34
|
+
target="_blank">GitHub</a>
|
35
|
+
</li>
|
36
|
+
</ul>
|
37
|
+
</div>
|
38
|
+
</div>
|
39
|
+
</nav>
|
40
|
+
<div class="container-fluid py-2">
|
41
|
+
<div class="row">
|
42
|
+
<div class="col-lg">
|
43
|
+
<main></main>
|
44
|
+
<button id="run" type="button" class="btn btn-primary mb-1">Run</button>
|
45
|
+
<button id="save-button" type="button" class="btn btn-secondary mb-1 float-end">Save</button>
|
46
|
+
<textarea id="error-console" class="form-control font-monospace" rows="5" readonly></textarea>
|
47
|
+
</div>
|
48
|
+
</div>
|
49
|
+
|
50
|
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
|
51
|
+
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
|
52
|
+
crossorigin="anonymous"></script>
|
53
|
+
<script src="https://bundle.run/buffer@6.0.3"></script>
|
54
|
+
<script src="https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.7.1/dist/browser.umd.js"></script>
|
55
|
+
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
|
56
|
+
<script src="p5editor.js"></script>
|
57
|
+
<link rel="stylesheet" href="style.css">
|
58
|
+
</body>
|
59
|
+
|
60
|
+
</html>
|
@@ -0,0 +1,79 @@
|
|
1
|
+
const { DefaultRubyVM } = window["ruby-wasm-wasi"];
|
2
|
+
const globalData = {};
|
3
|
+
let myP5 = null;
|
4
|
+
|
5
|
+
const main = async () => {
|
6
|
+
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.4-wasm-wasi@2.7.1/dist/ruby.wasm");
|
7
|
+
// const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.4-wasm-wasi@2.7.1/dist/ruby+stdlib.wasm");
|
8
|
+
const module = await WebAssembly.compileStreaming(response);
|
9
|
+
globalData.module = module;
|
10
|
+
document.getElementById("run").onclick = runScript;
|
11
|
+
runScript();
|
12
|
+
};
|
13
|
+
|
14
|
+
main();
|
15
|
+
|
16
|
+
const runScript = async () => {
|
17
|
+
const { vm } = await DefaultRubyVM(globalData.module);
|
18
|
+
globalData.vm = vm;
|
19
|
+
|
20
|
+
{
|
21
|
+
const p5rb = await fetch("p5editor.rb");
|
22
|
+
const t = await p5rb.text();
|
23
|
+
vm.eval(t);
|
24
|
+
}
|
25
|
+
|
26
|
+
document.getElementById("error-console").value = "";
|
27
|
+
|
28
|
+
try {
|
29
|
+
const main = await fetch("main.rb");
|
30
|
+
const t = await main.text();
|
31
|
+
vm.eval(t);
|
32
|
+
} catch (e) {
|
33
|
+
document.getElementById("error-console").value += e.message + "\n"
|
34
|
+
throw e
|
35
|
+
}
|
36
|
+
|
37
|
+
function registerRubyMethod(p5, name) {
|
38
|
+
let isDefined = vm.eval(`defined?(${name}) == "method"`).toJS()
|
39
|
+
if (!isDefined) {
|
40
|
+
return
|
41
|
+
}
|
42
|
+
p5[name] = function () {
|
43
|
+
try {
|
44
|
+
vm.eval(name)
|
45
|
+
} catch (e) {
|
46
|
+
document.getElementById("error-console").value += e.message + "\n"
|
47
|
+
throw e
|
48
|
+
}
|
49
|
+
};
|
50
|
+
}
|
51
|
+
|
52
|
+
// Initialize p5.js
|
53
|
+
function sketch(p5) {
|
54
|
+
vm.eval("P5").call("init", vm.wrap(p5))
|
55
|
+
registerRubyMethod(p5, "preload");
|
56
|
+
registerRubyMethod(p5, "setup");
|
57
|
+
registerRubyMethod(p5, "draw");
|
58
|
+
registerRubyMethod(p5, "mouseMoved");
|
59
|
+
registerRubyMethod(p5, "mouseDragged");
|
60
|
+
registerRubyMethod(p5, "mousePressed");
|
61
|
+
registerRubyMethod(p5, "mouseReleased");
|
62
|
+
registerRubyMethod(p5, "mouseClicked");
|
63
|
+
registerRubyMethod(p5, "doubleClicked");
|
64
|
+
registerRubyMethod(p5, "mouseWheel");
|
65
|
+
registerRubyMethod(p5, "keyPressed");
|
66
|
+
registerRubyMethod(p5, "keyReleased");
|
67
|
+
registerRubyMethod(p5, "keyTyped");
|
68
|
+
}
|
69
|
+
|
70
|
+
myP5 && myP5.remove();
|
71
|
+
myP5 = new p5(sketch, 'main');
|
72
|
+
document.getElementById("save-button").onclick = () => {
|
73
|
+
const date = new Date();
|
74
|
+
const dateString = date.toISOString().split('T')[0].replace(/-/g, ''); // YYYYMMDD format
|
75
|
+
const timeString = date.toTimeString().split(' ')[0].replace(/:/g, ''); // HHMMSS format
|
76
|
+
myP5.saveCanvas(`p5rb_${dateString}_${timeString}`, 'png');
|
77
|
+
};
|
78
|
+
}
|
79
|
+
|
@@ -0,0 +1,285 @@
|
|
1
|
+
require 'js'
|
2
|
+
|
3
|
+
# --------------------------------------------
|
4
|
+
# Constants
|
5
|
+
#
|
6
|
+
# Copyright: p5.js(https://p5js.org/copyright.html)
|
7
|
+
# The p5.js library is free software;
|
8
|
+
# you can redistribute it and/or modify it under the terms of
|
9
|
+
# the GNU Lesser General Public License as published
|
10
|
+
# by the Free Software Foundation, version 2.1.
|
11
|
+
# --------------------------------------------
|
12
|
+
_PI = Math::PI
|
13
|
+
|
14
|
+
# The default, two-dimensional renderer.
|
15
|
+
P2D = 'p2d'
|
16
|
+
|
17
|
+
# One of the two render modes in p5.js: P2D (default renderer) and WEBGL
|
18
|
+
# Enables 3D render by introducing the third dimension: Z
|
19
|
+
WEBGL = 'webgl'
|
20
|
+
|
21
|
+
# ENVIRONMENT
|
22
|
+
ARROW = 'default'
|
23
|
+
CROSS = 'crosshair'
|
24
|
+
HAND = 'pointer'
|
25
|
+
MOVE = 'move'
|
26
|
+
TEXT = 'text'
|
27
|
+
WAIT = 'wait'
|
28
|
+
|
29
|
+
# TRIGONOMETRY
|
30
|
+
|
31
|
+
# HALF_PI is a mathematical constant with the value
|
32
|
+
# 1.57079632679489661923. It is half the ratio of the
|
33
|
+
# circumference of a circle to its diameter. It is useful in
|
34
|
+
# combination with the trigonometric functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>.
|
35
|
+
HALF_PI = _PI / 2
|
36
|
+
|
37
|
+
# PI is a mathematical constant with the value
|
38
|
+
# 3.14159265358979323846. It is the ratio of the circumference
|
39
|
+
# of a circle to its diameter. It is useful in combination with
|
40
|
+
# the trigonometric functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>.
|
41
|
+
PI = _PI
|
42
|
+
|
43
|
+
# QUARTER_PI is a mathematical constant with the value 0.7853982.
|
44
|
+
# It is one quarter the ratio of the circumference of a circle to
|
45
|
+
# its diameter. It is useful in combination with the trigonometric
|
46
|
+
# functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>.
|
47
|
+
QUARTER_PI = _PI / 4
|
48
|
+
|
49
|
+
# TAU is an alias for TWO_PI, a mathematical constant with the
|
50
|
+
# value 6.28318530717958647693. It is twice the ratio of the
|
51
|
+
# circumference of a circle to its diameter. It is useful in
|
52
|
+
# combination with the trigonometric functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>.
|
53
|
+
TAU = _PI * 2
|
54
|
+
|
55
|
+
# TWO_PI is a mathematical constant with the value
|
56
|
+
# 6.28318530717958647693. It is twice the ratio of the
|
57
|
+
# circumference of a circle to its diameter. It is useful in
|
58
|
+
# combination with the trigonometric functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>.
|
59
|
+
TWO_PI = _PI * 2
|
60
|
+
|
61
|
+
# Constant to be used with the <a href="#/p5/angleMode">angleMode()</a> function, to set the mode in
|
62
|
+
# which p5.js interprets and calculates angles (either DEGREES or RADIANS).
|
63
|
+
DEGREES = 'degrees'
|
64
|
+
|
65
|
+
# Constant to be used with the <a href="#/p5/angleMode">angleMode()</a> function, to set the mode
|
66
|
+
# in which p5.js interprets and calculates angles (either RADIANS or DEGREES).
|
67
|
+
RADIANS = 'radians'
|
68
|
+
DEG_TO_RAD = _PI / 180.0
|
69
|
+
RAD_TO_DEG = 180.0 / _PI
|
70
|
+
|
71
|
+
CORNER = 'corner'
|
72
|
+
CORNERS = 'corners'
|
73
|
+
RADIUS = 'radius'
|
74
|
+
RIGHT = 'right'
|
75
|
+
LEFT = 'left'
|
76
|
+
CENTER = 'center'
|
77
|
+
TOP = 'top'
|
78
|
+
BOTTOM = 'bottom'
|
79
|
+
BASELINE = 'alphabetic'
|
80
|
+
|
81
|
+
POINTS = 0x0000
|
82
|
+
LINES = 0x0001
|
83
|
+
LINE_STRIP = 0x0003
|
84
|
+
LINE_LOOP = 0x0002
|
85
|
+
TRIANGLES = 0x0004
|
86
|
+
TRIANGLE_FAN = 0x0006
|
87
|
+
TRIANGLE_STRIP = 0x0005
|
88
|
+
|
89
|
+
QUADS = 'quads'
|
90
|
+
QUAD_STRIP = 'quad_strip'
|
91
|
+
TESS = 'tess'
|
92
|
+
CLOSE = 'close'
|
93
|
+
OPEN = 'open'
|
94
|
+
CHORD = 'chord'
|
95
|
+
PIE = 'pie'
|
96
|
+
PROJECT = 'square' # PEND: careful this is counterintuitive
|
97
|
+
SQUARE = 'butt'
|
98
|
+
ROUND = 'round'
|
99
|
+
BEVEL = 'bevel'
|
100
|
+
MITER = 'miter'
|
101
|
+
|
102
|
+
# COLOR
|
103
|
+
RGB = 'rgb'
|
104
|
+
# HSB (hue, saturation, brightness) is a type of color model.
|
105
|
+
# You can learn more about it at
|
106
|
+
# <a href="https://learnui.design/blog/the-hsb-color-system-practicioners-primer.html">HSB</a>.
|
107
|
+
HSB = 'hsb'
|
108
|
+
HSL = 'hsl'
|
109
|
+
|
110
|
+
# DOM EXTENSION
|
111
|
+
|
112
|
+
# AUTO allows us to automatically set the width or height of an element (but not both),
|
113
|
+
# based on the current height and width of the element. Only one parameter can
|
114
|
+
# be passed to the <a href="/#/p5.Element/size">size</a> function as AUTO, at a time.
|
115
|
+
AUTO = 'auto'
|
116
|
+
|
117
|
+
# INPUT
|
118
|
+
ALT = 18
|
119
|
+
BACKSPACE = 8
|
120
|
+
CONTROL = 17
|
121
|
+
DELETE = 46
|
122
|
+
DOWN_ARROW = 40
|
123
|
+
ENTER = 13
|
124
|
+
ESCAPE = 27
|
125
|
+
LEFT_ARROW = 37
|
126
|
+
OPTION = 18
|
127
|
+
RETURN = 13
|
128
|
+
RIGHT_ARROW = 39
|
129
|
+
SHIFT = 16
|
130
|
+
TAB = 9
|
131
|
+
UP_ARROW = 38
|
132
|
+
|
133
|
+
# RENDERING
|
134
|
+
BLEND = 'source-over'
|
135
|
+
REMOVE = 'destination-out'
|
136
|
+
ADD = 'lighter'
|
137
|
+
#ADD: 'add', #
|
138
|
+
#SUBTRACT: 'subtract', #
|
139
|
+
DARKEST = 'darken'
|
140
|
+
LIGHTEST = 'lighten'
|
141
|
+
DIFFERENCE = 'difference'
|
142
|
+
SUBTRACT = 'subtract'
|
143
|
+
EXCLUSION = 'exclusion'
|
144
|
+
MULTIPLY = 'multiply'
|
145
|
+
SCREEN = 'screen'
|
146
|
+
REPLACE = 'copy'
|
147
|
+
OVERLAY = 'overlay'
|
148
|
+
HARD_LIGHT = 'hard-light'
|
149
|
+
SOFT_LIGHT = 'soft-light'
|
150
|
+
DODGE = 'color-dodge'
|
151
|
+
BURN = 'color-burn'
|
152
|
+
|
153
|
+
# FILTERS
|
154
|
+
THRESHOLD = 'threshold'
|
155
|
+
GRAY = 'gray'
|
156
|
+
OPAQUE = 'opaque'
|
157
|
+
INVERT = 'invert'
|
158
|
+
POSTERIZE = 'posterize'
|
159
|
+
DILATE = 'dilate'
|
160
|
+
ERODE = 'erode'
|
161
|
+
BLUR = 'blur'
|
162
|
+
|
163
|
+
# TYPOGRAPHY
|
164
|
+
NORMAL = 'normal'
|
165
|
+
ITALIC = 'italic'
|
166
|
+
BOLD = 'bold'
|
167
|
+
BOLDITALIC = 'bold italic'
|
168
|
+
CHAR = 'CHAR'
|
169
|
+
WORD = 'WORD'
|
170
|
+
|
171
|
+
# TYPOGRAPHY-INTERNAL
|
172
|
+
_DEFAULT_TEXT_FILL = '#000000'
|
173
|
+
_DEFAULT_LEADMULT = 1.25
|
174
|
+
_CTX_MIDDLE = 'middle'
|
175
|
+
|
176
|
+
# VERTICES
|
177
|
+
LINEAR = 'linear'
|
178
|
+
QUADRATIC = 'quadratic'
|
179
|
+
BEZIER = 'bezier'
|
180
|
+
CURVE = 'curve'
|
181
|
+
|
182
|
+
# WEBGL DRAWMODES
|
183
|
+
STROKE = 'stroke'
|
184
|
+
FILL = 'fill'
|
185
|
+
TEXTURE = 'texture'
|
186
|
+
IMMEDIATE = 'immediate'
|
187
|
+
|
188
|
+
# WEBGL TEXTURE MODE
|
189
|
+
# NORMAL already exists for typography
|
190
|
+
IMAGE = 'image'
|
191
|
+
|
192
|
+
# WEBGL TEXTURE WRAP AND FILTERING
|
193
|
+
# LINEAR already exists above
|
194
|
+
NEAREST = 'nearest'
|
195
|
+
REPEAT = 'repeat'
|
196
|
+
CLAMP = 'clamp'
|
197
|
+
MIRROR = 'mirror'
|
198
|
+
|
199
|
+
# DEVICE-ORIENTATION
|
200
|
+
LANDSCAPE = 'landscape'
|
201
|
+
PORTRAIT = 'portrait'
|
202
|
+
|
203
|
+
# DEFAULTS
|
204
|
+
_DEFAULT_STROKE = '#000000'
|
205
|
+
_DEFAULT_FILL = '#FFFFFF'
|
206
|
+
|
207
|
+
GRID = 'grid'
|
208
|
+
AXES = 'axes'
|
209
|
+
LABEL = 'label'
|
210
|
+
FALLBACK = 'fallback'
|
211
|
+
CONTAIN = 'contain'
|
212
|
+
COVER = 'cover'
|
213
|
+
|
214
|
+
# --------------------------------------------
|
215
|
+
# Library
|
216
|
+
# --------------------------------------------
|
217
|
+
# JS::Object can call property via function style
|
218
|
+
class JS::Object
|
219
|
+
def method_missing(sym, *args, &block)
|
220
|
+
ret = self[sym]
|
221
|
+
|
222
|
+
case ret.typeof
|
223
|
+
when "undefined"
|
224
|
+
str = sym.to_s
|
225
|
+
if str[-1] == "="
|
226
|
+
self[str.chop.to_sym] = args.first
|
227
|
+
return args.first
|
228
|
+
end
|
229
|
+
|
230
|
+
super
|
231
|
+
when "function"
|
232
|
+
self.call(sym, *args, &block).to_r
|
233
|
+
else
|
234
|
+
ret.to_r
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def respond_to_missing?(sym, include_private)
|
239
|
+
return true if super
|
240
|
+
self[sym].typeof != "undefined"
|
241
|
+
end
|
242
|
+
|
243
|
+
def to_r
|
244
|
+
case self.typeof
|
245
|
+
when "number"
|
246
|
+
self.to_f
|
247
|
+
when "string"
|
248
|
+
self.to_s
|
249
|
+
else
|
250
|
+
self
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
# Call p5.js global functions
|
256
|
+
$p5 = nil
|
257
|
+
|
258
|
+
def method_missing(sym, *args, &block)
|
259
|
+
return super unless $p5.respond_to?(:[])
|
260
|
+
ret = $p5[sym]
|
261
|
+
|
262
|
+
case ret.typeof
|
263
|
+
when "undefined"
|
264
|
+
# str = sym.to_s
|
265
|
+
# if str[-1] == "="
|
266
|
+
# $p5[str.chop.to_sym] = args.first
|
267
|
+
# return args.first
|
268
|
+
# end
|
269
|
+
super
|
270
|
+
when "function"
|
271
|
+
$p5.call(sym, *args, &block).to_r
|
272
|
+
else
|
273
|
+
ret.to_r
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
module P5
|
278
|
+
Vector = JS.global[:p5][:Vector]
|
279
|
+
|
280
|
+
module_function
|
281
|
+
|
282
|
+
def init(p5)
|
283
|
+
$p5 = p5
|
284
|
+
end
|
285
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
nav {
|
2
|
+
outline: solid 1px #a2a5a8;
|
3
|
+
}
|
4
|
+
|
5
|
+
.rob-navbar {
|
6
|
+
background-color: #f8f9fa !important;
|
7
|
+
color: #25292e !important;
|
8
|
+
}
|
9
|
+
|
10
|
+
.navbar-brand {
|
11
|
+
font-size: 1.1rem;
|
12
|
+
}
|
13
|
+
|
14
|
+
@media (min-width: 768px) { /* Medium(md) */
|
15
|
+
.CodeMirror {
|
16
|
+
height: 320px;
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
@media (min-width: 992px) { /* Large(lg) */
|
21
|
+
.CodeMirror {
|
22
|
+
height: 540px;
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
@media (min-width: 1200px) { /* Extra Large(xl) */
|
27
|
+
.CodeMirror {
|
28
|
+
height: 800px;
|
29
|
+
}
|
30
|
+
}
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'webrick'
|
2
|
+
|
3
|
+
def run_web_app(script_file)
|
4
|
+
if script_file.nil? || !File.exist?(script_file)
|
5
|
+
puts "Not found script file: #{script_file}"
|
6
|
+
return
|
7
|
+
end
|
8
|
+
|
9
|
+
root = File.join(File.dirname(script_file))
|
10
|
+
server = WEBrick::HTTPServer.new(
|
11
|
+
Port: 8000,
|
12
|
+
DocumentRoot: root
|
13
|
+
)
|
14
|
+
|
15
|
+
static_root = File.join(File.dirname(__FILE__), "static")
|
16
|
+
server.mount_proc '/' do |req, res|
|
17
|
+
case req.path
|
18
|
+
when "/" || "/index.html"
|
19
|
+
res.body = File.read(File.join(static_root, 'index.html'))
|
20
|
+
res.content_type = 'text/html'
|
21
|
+
when "/p5editor.js"
|
22
|
+
res.body = File.read(File.join(static_root, 'p5editor.js'))
|
23
|
+
res.content_type = 'application/javascript'
|
24
|
+
when "/p5editor.rb"
|
25
|
+
res.body = File.read(File.join(static_root, 'p5editor.rb'))
|
26
|
+
res.content_type = 'application/ruby'
|
27
|
+
when "/style.css"
|
28
|
+
res.body = File.read(File.join(static_root, 'style.css'))
|
29
|
+
res.content_type = 'text/css'
|
30
|
+
when "/main.rb"
|
31
|
+
res.body = File.read(script_file)
|
32
|
+
res.content_type = 'application/ruby'
|
33
|
+
else
|
34
|
+
path = File.join(File.dirname(script_file), req.path)
|
35
|
+
if File.exist?(path)
|
36
|
+
res.body = File.binread(path)
|
37
|
+
res.content_type = case File.extname(path)
|
38
|
+
when ".png" then 'image/png'
|
39
|
+
when ".jpg" then 'image/jpeg'
|
40
|
+
else 'application/octet-stream'
|
41
|
+
end
|
42
|
+
else
|
43
|
+
res.body = "Not Found"
|
44
|
+
res.status = 404
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
trap('INT') { server.shutdown }
|
49
|
+
puts "Serving at http://localhost:8000/"
|
50
|
+
server.start
|
51
|
+
end
|
data/lib/p5rb_cli.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "p5rb_cli/version"
|
4
|
+
require_relative "p5rb_cli/web_app"
|
5
|
+
require "thor"
|
6
|
+
require "fileutils"
|
7
|
+
|
8
|
+
module P5rbCli
|
9
|
+
class Cli < Thor
|
10
|
+
def self.exit_on_failure?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "new NAME", "Create a new p5.rb script"
|
15
|
+
def new(name)
|
16
|
+
name += ".rb" unless name.end_with?(".rb")
|
17
|
+
|
18
|
+
if FileTest.exist?(name)
|
19
|
+
raise Thor::Error, "ERROR: '#{File.absolute_path(name)}' already exists"
|
20
|
+
end
|
21
|
+
|
22
|
+
File.write(name, <<~CODE)
|
23
|
+
# p5.rb - A Ruby implementation of p5.js
|
24
|
+
#
|
25
|
+
# This library allows you to create sketches using Ruby, similar to p5.js.
|
26
|
+
#
|
27
|
+
# - Define `setup` and `draw` method to create a sketch.
|
28
|
+
# - API is compatible with p5.js.
|
29
|
+
# - API naming follows PascalCase for consistency with p5.js.
|
30
|
+
#
|
31
|
+
# Example:
|
32
|
+
# def setup
|
33
|
+
# createCanvas(400, 400)
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# def draw
|
37
|
+
# background(220)
|
38
|
+
# ellipse(200, 200, 50, 50)
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# --- Major Methods ---
|
42
|
+
#
|
43
|
+
# - createCanvas(width, height) -> Creates a drawing canvas.
|
44
|
+
# - background(color) -> Sets the background color.
|
45
|
+
# - fill(color) -> Sets the fill color for shapes.
|
46
|
+
# - stroke(color) -> Sets the outline color for shapes.
|
47
|
+
# - noStroke() -> Disables shape outlines.
|
48
|
+
# - ellipse(x, y, w, h) -> Draws an ellipse at (x, y) with width w and height h.
|
49
|
+
# - rect(x, y, w, h) -> Draws a rectangle at (x, y) with width w and height h.
|
50
|
+
# - line(x1, y1, x2, y2) -> Draws a line from (x1, y1) to (x2, y2).
|
51
|
+
# - text(str, x, y) -> Draws text at (x, y).
|
52
|
+
# - push() -> Saves the current drawing state (transformation, styles, etc.).
|
53
|
+
# - pop() -> Restores the last saved drawing state.
|
54
|
+
# - width, height -> Returns the canvas dimensions.
|
55
|
+
# - frameCount -> Returns the number of frames elapsed.
|
56
|
+
# - mouseX, mouseY -> Returns the current mouse position.
|
57
|
+
# - keyPressed? -> Returns true if a key is pressed.
|
58
|
+
# - mousePressed? -> Returns true if the mouse button is pressed.
|
59
|
+
|
60
|
+
def setup
|
61
|
+
createCanvas(400, 400)
|
62
|
+
background(200)
|
63
|
+
end
|
64
|
+
|
65
|
+
def draw
|
66
|
+
background(200)
|
67
|
+
(0..width).step(50) do |x|
|
68
|
+
(0..height).step(50) do |y|
|
69
|
+
ellipse(x, y, 40, 40)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
CODE
|
74
|
+
end
|
75
|
+
|
76
|
+
desc "run SCRIPT_FILE", "Run p5.rb script on server"
|
77
|
+
def run_command(script_file)
|
78
|
+
run_web_app(script_file)
|
79
|
+
end
|
80
|
+
map "run" => "run_command"
|
81
|
+
end
|
82
|
+
end
|
data/sig/p5rb_cli.rbs
ADDED
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: p5rb_cli
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- ongaeshi
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-03-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: webrick
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.9'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.9'
|
41
|
+
description: p5.rb CLI is a command-line tool that allows you to create p5.js-like
|
42
|
+
sketches using Ruby. It provides commands to generate new sketches and run them
|
43
|
+
in a local web server.
|
44
|
+
email:
|
45
|
+
- ongaeshi0621@gmail.com
|
46
|
+
executables:
|
47
|
+
- p5rb
|
48
|
+
extensions: []
|
49
|
+
extra_rdoc_files: []
|
50
|
+
files:
|
51
|
+
- ".standard.yml"
|
52
|
+
- CHANGELOG.md
|
53
|
+
- README.ja.md
|
54
|
+
- README.md
|
55
|
+
- Rakefile
|
56
|
+
- exe/p5rb
|
57
|
+
- lib/p5rb_cli.rb
|
58
|
+
- lib/p5rb_cli/static/index.html
|
59
|
+
- lib/p5rb_cli/static/p5editor.js
|
60
|
+
- lib/p5rb_cli/static/p5editor.rb
|
61
|
+
- lib/p5rb_cli/static/style.css
|
62
|
+
- lib/p5rb_cli/version.rb
|
63
|
+
- lib/p5rb_cli/web_app.rb
|
64
|
+
- sig/p5rb_cli.rbs
|
65
|
+
homepage: https://github.com/ongaeshi/p5rb_cli
|
66
|
+
licenses: []
|
67
|
+
metadata:
|
68
|
+
homepage_uri: https://github.com/ongaeshi/p5rb_cli
|
69
|
+
source_code_uri: https://github.com/ongaeshi/p5rb_cli
|
70
|
+
changelog_uri: https://github.com/ongaeshi/p5rb_cli/blob/master/CHANGELOG.md
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 3.0.0
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
requirements: []
|
86
|
+
rubygems_version: 3.5.22
|
87
|
+
signing_key:
|
88
|
+
specification_version: 4
|
89
|
+
summary: A CLI tool for creating p5.js-like sketches using Ruby.
|
90
|
+
test_files: []
|