TUI ベースの RDS クライアントツール gobang を試してみる。
こんにちは k-jun です。今日は約一週間ほど前に登場し、またたく間に 1000 star を獲得した TUI ベースの RDS クライアントツール gobang を試してみようと思います。
https://github.com/TaKO8Ki/gobang
Rust で記述されており、Sequal Ace 等の各種 GUI ベースのクライアントツールがサポートしている挙動をほとんど行えるようで、そりゃ star も集まるよなという印象です。
Install
インストールも扱いやすく、brew で提供されています。
$ brew install tako8ki/tap/gobang
Run
ひとまず適当に、MySQL を起動して試してみます。
$ docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -e MYSQL_USER=test -e MYSQL_PASSWORD=test -e MYSQL_DATABASE=test -d mysql:5.7
config ファイルを生成して gobang の引数に渡します。
$ cat /tmp/config.toml [[conn]] type = "mysql" user = "test" password = "test" host = "localhost" port = 3306 $ gobang -c /tmp/config.toml
いい感じですね。database test には何も table を生成していないので、ここを作ってみます。 readme 勝手に SQL が直で打てるものかと思っていましたがどうも違うようです。WHERE の条件を簡単に検索出来るぐらいみたいですね。
適当に table と row を生成したので、改めて中身を見てみます。
簡易的な検索も聞くようです。検索というよりは Filter に近いですね。
結構いい感じに使えそうです。何より TUI でここまで出来るというのがすごい !!! 自分も見習って何かしら便利なものを作りたいです !! それでは今回はこのへんで。
認証情報の漏洩をシステム的に検知する gitleaks を試してみる。
こんにちは k-jun です。今回は git 管理下にある現在のコード、過去のコミット履歴などから包括的に認証情報が漏洩していないかを確認できるツール gitleaks を試してみようと思います。
https://github.com/zricethezav/gitleaks
基本的には gitactions で CI/CD としてセットすることが想定されているみたいですね。 一度 github にあげてしまうと手遅れ感はあるので、それよりは未然に防ぐために手元で git push のエイリアスに設定されていると良いかもしれませんね。
Install
$ brew install gitleak
brew で簡単にインストールできます。
Run
$ gitleaks INFO[0000] opening . INFO[0000] scan time: 35 milliseconds 632 microseconds INFO[0000] No leaks found
適当に実行してみると何やらチェックらしきものが走っています。ではでは検証として適当にパスワードっぽいものを生成して .env
なんかに貼り付けてみます。
$ echo "kJutbFnW52aB8C4Al1ph0LuMOvYIYzSP4GZfXXXXX" > .env ~/ghq/github.com/k-jun/playground-pulumi master* $ gitleaks INFO[0000] opening . INFO[0000] scan time: 14 milliseconds 168 microseconds INFO[0000] No leaks found
あれ...? なにも反応しない...??
$ echo AWS_ACCESS_KEY='XXXXXXbFnW52aB8C4Al1ph0LuMOvYIYzSP4GZfvksdnv/dsa' > .env ~/ghq/github.com/k-jun/playground-pulumi master* $ gitleaks INFO[0000] opening . INFO[0000] scan time: 13 milliseconds 264 microseconds INFO[0000] No leaks found
うーんこれでも反応しない...。リポジトリの url を直接指定できるようなのでそれで試してみる。
$ gitleaks --repo-url https://github.com/zricethezav/gronit -v INFO[0000] cloning... https://github.com/zricethezav/gronit Enumerating objects: 228, done. Counting objects: 100% (78/78), done. Compressing objects: 100% (51/51), done. Total 228 (delta 34), reused 17 (delta 9), pack-reused 150 { "line": "const AWSKEY string = \"AKIAIO5FODNN7EXAMPLE\"", "lineNumber": 12, "offender": "AKIAIO5FODNN7EXAMPLE", "offenderEntropy": -1, "commit": "034344be2227771ae9f020358ad68230debfbb9d", "repo": "gronit", "repoURL": "https://github.com/zricethezav/gronit", "leakURL": "https://github.com/zricethezav/gronit/blob/034344be2227771ae9f020358ad68230debfbb9d/main.go#L12", "rule": "AWS Access Key", "commitMessage": "secret\n", "author": "Zach Rice", "email": "zricer@protonmail.com", "file": "main.go", "date": "2021-04-20T09:04:44-04:00", "tags": "key, AWS" }
おおお!!! こんな感じに出るのね。リポジトリレベルで指定できるのはかなり有り難いですね。CI がどこで動くかを考えるまもなく、同じコマンドを実行しておけば良いので。
.git/hooks/pre-commit
に書き込むとこのように、commit 前にチェックしてくれます。認証情報を万が一 commit した際に備えて設定しておくと良いかもしれませんね。
$ git commit -m 'feat(docs): update readme' INFO[0000] opening ./ INFO[0000] scan time: 69 milliseconds 727 microseconds INFO[0000] commits scanned: 62 WARN[0000] leaks found: 7
これでローカルの環境が少しだけ安全になりました。それでは今日はこのへんで...!
Wireshark の CLI 版 TShark を試してみる。
こんにちは k-jun です。今回は、Wireshark より簡易的に使用できて高速な TShark を試してみようと思います。
https://github.com/wireshark/wireshark
The Wireshark distribution also comes with TShark
記載の通り、Wireshark にくっついて来るみたいですね。今回は tpcdump でキャプチャしたパケットを閲覧してみたいと思います。
Install
$ brew install wireshark
$ which tshark
/usr/local/bin/tshark
Run
まずは tcpdump でパケットをキャプチャします。-w でファイル名を指定することで対象ファイルへのパケットがキャプチャされます。 今回は適当に EC2 インスタンスを AWS 環境に立ち上げ、Nginx を起動させておきます。EC2インスタンス に対してローカルから cURL を発行し、インスタンス上で tcpdump を打っておきパケットを確認してみます。
$ sudo apt update -y $ sudo apt install -y nginx $ sudo tcpdump -w /tmp/tcpdump -i any port 80
rsync で手元に持ってきてから tshark で中身を見てみます。port は 80 に限定します。
$ rsync -azv ubuntu@XX.XXX.XX.XXX:/tmp/tcpdump /tmp/tcpdump $ tshark -r /tmp/tcpdump 'tcp.dstport==80' 1 0.000000 106.165.44.175 → 10.1.101.115 TCP 80 55327 → 80 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 WS=64 TSval=597833747 TSecr=0 SACK_PERM=1 2 0.000023 10.1.101.115 → 106.165.44.175 TCP 76 80 → 55327 [SYN, ACK] Seq=0 Ack=1 Win=62643 Len=0 MSS=8961 SACK_PERM=1 TSval=2055342097 TSecr=597833747 WS=128 3 0.015210 106.165.44.175 → 10.1.101.115 TCP 68 55327 → 80 [ACK] Seq=1 Ack=1 Win=131712 Len=0 TSval=597833762 TSecr=2055342097 4 0.015233 106.165.44.175 → 10.1.101.115 HTTP 144 GET / HTTP/1.1 5 0.015237 10.1.101.115 → 106.165.44.175 TCP 68 80 → 55327 [ACK] Seq=1 Ack=77 Win=62592 Len=0 TSval=2055342112 TSecr=597833762 6 0.015388 10.1.101.115 → 106.165.44.175 HTTP 927 HTTP/1.1 200 OK (text/html) 7 0.029359 106.165.44.175 → 10.1.101.115 TCP 68 55327 → 80 [ACK] Seq=77 Ack=860 Win=130880 Len=0 TSval=597833777 TSecr=2055342113 8 0.029629 106.165.44.175 → 10.1.101.115 TCP 68 55327 → 80 [FIN, ACK] Seq=77 Ack=860 Win=131072 Len=0 TSval=597833777 TSecr=2055342113 9 0.029649 10.1.101.115 → 106.165.44.175 TCP 68 80 → 55327 [FIN, ACK] Seq=860 Ack=78 Win=62592 Len=0 TSval=2055342127 TSecr=597833777 10 0.043834 106.165.44.175 → 10.1.101.115 TCP 68 55327 → 80 [ACK] Seq=78 Ack=861 Win=131072 Len=0 TSval=597833791 TSecr=2055342127
tshark で中身は見れましたが、これ EC2 インスタンスの Private の IP Address ですね..。106.165.44.175 は自分の IP っぽいですが...。 どうも不思議ですね..。手元でも tcpdump を取ってみます。
$ tshark -r /tmp/tcpdump_send 'tcp.port==80' 1 0.000000 192.168.0.24 → 35.75.22.116 TCP 78 56004 → 80 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 WS=64 TSval=598576611 TSecr=0 SACK_PERM=1 2 0.016389 35.75.22.116 → 192.168.0.24 TCP 74 80 → 56004 [SYN, ACK] Seq=0 Ack=1 Win=62643 Len=0 MSS=1460 SACK_PERM=1 TSval=2056091860 TSecr=598576611 WS=128 3 0.016430 192.168.0.24 → 35.75.22.116 TCP 66 56004 → 80 [ACK] Seq=1 Ack=1 Win=131712 Len=0 TSval=598576627 TSecr=2056091860 4 0.016518 192.168.0.24 → 35.75.22.116 HTTP 142 GET / HTTP/1.1 5 0.032305 35.75.22.116 → 192.168.0.24 TCP 66 80 → 56004 [ACK] Seq=1 Ack=77 Win=62592 Len=0 TSval=2056091876 TSecr=598576627 6 0.032305 35.75.22.116 → 192.168.0.24 TCP 66 [TCP Dup ACK 5#1] 80 → 56004 [ACK] Seq=1 Ack=77 Win=62592 Len=0 TSval=2056091876 TSecr=598576627 7 0.032466 35.75.22.116 → 192.168.0.24 HTTP 925 HTTP/1.1 200 OK (text/html) 8 0.032501 192.168.0.24 → 35.75.22.116 TCP 66 56004 → 80 [ACK] Seq=77 Ack=860 Win=130880 Len=0 TSval=598576642 TSecr=2056091876 9 0.032723 192.168.0.24 → 35.75.22.116 TCP 66 56004 → 80 [FIN, ACK] Seq=77 Ack=860 Win=131072 Len=0 TSval=598576642 TSecr=2056091876 10 0.048712 35.75.22.116 → 192.168.0.24 TCP 66 80 → 56004 [FIN, ACK] Seq=860 Ack=78 Win=62592 Len=0 TSval=2056091892 TSecr=598576642 11 0.048769 192.168.0.24 → 35.75.22.116 TCP 66 56004 → 80 [ACK] Seq=78 Ack=861 Win=131072 Len=0 TSval=598576658 TSecr=2056091892
手元からは 35.75.22.116 に http request を送信しているように見えています。こちらの Source IP も Private IP になっていますしそういうものということですかね。
内容的には しっかり SYN -> SYN,ACK -> ACK の 3way ハンドシェイクや切断時の FIN,ACK -> FIN,ACK -> ACK も確認できます。
また TShark は実は直接 パケットキャプチャを行うことができます。tcpdump で取得だけを行ったのは TShark をインストールできないリモートサーバーを想定していたためでした。 できることを試さないのも怠慢なのでやってみます。
$ sudo apt install -y tshark $ sudo tshark -Y 'tcp.port==80' Running as user "root" and group "root". This could be dangerous. Capturing on 'ens5' 1 0.000000000 106.165.44.175 → 10.1.101.115 TCP 78 56799 → 80 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 WS=64 TSval=599940646 TSecr=0 SACK_PERM=1 2 0.000021621 10.1.101.115 → 106.165.44.175 TCP 74 80 → 56799 [SYN, ACK] Seq=0 Ack=1 Win=62643 Len=0 MSS=8961 SACK_PERM=1 TSval=2057468236 TSecr=599940646 WS=128 3 0.014247052 106.165.44.175 → 10.1.101.115 HTTP 142 GET / HTTP/1.1 4 0.014262153 10.1.101.115 → 106.165.44.175 TCP 66 80 → 56799 [ACK] Seq=1 Ack=77 Win=62592 Len=0 TSval=2057468251 TSecr=599940660 5 0.014275806 106.165.44.175 → 10.1.101.115 TCP 66 56799 → 80 [ACK] Seq=1 Ack=1 Win=131712 Len=0 TSval=599940660 TSecr=2057468236 6 0.014278135 10.1.101.115 → 106.165.44.175 TCP 66 [TCP Dup ACK 4#1] 80 → 56799 [ACK] Seq=1 Ack=77 Win=62592 Len=0 TSval=2057468251 TSecr=599940660 7 0.014423231 10.1.101.115 → 106.165.44.175 HTTP 925 HTTP/1.1 200 OK (text/html) 8 0.028525676 106.165.44.175 → 10.1.101.115 TCP 66 56799 → 80 [ACK] Seq=77 Ack=860 Win=130880 Len=0 TSval=599940673 TSecr=2057468251 9 0.028532464 106.165.44.175 → 10.1.101.115 TCP 66 56799 → 80 [FIN, ACK] Seq=77 Ack=860 Win=131072 Len=0 TSval=599940673 TSecr=2057468251 10 0.028558085 10.1.101.115 → 106.165.44.175 TCP 66 80 → 56799 [FIN, ACK] Seq=860 Ack=78 Win=62592 Len=0 TSval=2057468265 TSecr=599940673 11 0.042741897 106.165.44.175 → 10.1.101.115 TCP 66 56799 → 80 [ACK] Seq=78 Ack=861 Win=131072 Len=0 TSval=599940687 TSecr=2057468265
いい感じですね。tcpdump と同じような内容が観測できました。CLI であるがゆえに簡単に環境に入れられ見たいものも見れたので満足です。 今後必要に応じて使っていこうと思います。それでは今回はこのへんで。
Postman の代替ツール Ain を触ってみる。
こんにちは k-jun です。今回は Postman のように API サーバーにリクエストを投げる Ain を試してみます。
https://github.com/jonaslu/ain
Postman との差別点は Cli で完結している点ですね。意外と便利で 設定ファイルに格納できれば、確認 URL として GitHub に収めることも可能になります。 他 Postman に似たツールとして paw、insomnia. も存在するようですね。知りませんでした...。
Install
$ go install github.com/jonaslu/ain/cmd/ain@latest
Run
ではでは、早速試してみます。
$ ain -b basic_template.ain
テンプレートを生成。中身を見てみます。
$ cat basic_template.ain [Host] http://localhost:${PORT} [Headers] Content-Type: application/json # [Method] # POST # [Body] # { # "some": "json" # } [Config] Timeout=3 [Backend] curl # wget [BackendOptions] -sS # Makes curl suppress its progress bar in a pipe # -q # Makes wget suppress its progress output # Short help: # Comments start with hash-sign (#) and are ignored. # ${VARIABLES} are replaced with the .env-file or environment variable value # $(executables.sh) are replaced with the output of that executable
うーむ... なんか横に長いですね...。toml 形式の設定方法は単発では見やすいと思いますが、複数 API を定義するのには冗長になりそうだなと言う印象を受けました。 これ複数定義して GitHub 管理してもどれを使うかわからなくなりそうですね...。
利用用途は Load Balancer ですが drill のほうが簡易的で好きでした...。Header の Content-Type とかも Postman であればよしなに判断して付与してくれますし...。
認証系統は以下のようにコマンドを利用できるのである程度やりやすそうですが、設定のわかりやすさとしては、自分の中では Drill の勝ちですね。
[Headers] Authorization: Bearer $(bash -c "./get-login.sh | jq -r '.token'")
というか、これぐらいであれば Makefile に curl を列挙して実行したほうがマシな気がします。無駄なファイルが増えませんし。
それでは今回はこのへんで。
HTML を jq like にパースする htmlq を試してみる。
こんにちは k-jun です。今回は jq inspire の htmlq を試してみようと思います。
前に jq の yaml 版 yq を試してみましたが、それと似たような感じでしょうか。yq は 先に yaml を json へ変換した後に jq に流しているだけでしたが 笑。 htmlq は果たして。
Install
$ cargo install htmlq
Run
以前弟用に英語の単語集を作成する機会があり、単語のリストをスクレイピングで取得したことがあったので、これを htmlq を用いて簡略化してみます。
$ curl -s https://www.eigo-duke.com/tango/eiken3.html | htmlq --text 'div.eng' | head find decide seem forget plan see think believe grow talk
$ curl -s https://www.eigo-duke.com/tango/eiken3.html | htmlq --text 'div.jap' | head 見つける 決心する、決める ~のように思われる(見える) 忘れる 計画する 見る、わかる 考える 信じる 成長する,になる 話す
BeautifulSoup などを噛ませなくて良いので結構楽ですね...! 出力をパイプすると以下のエラーに引っかかることだけ気になりました。
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 32, kind: BrokenPipe, message: "Broken pipe" }', /Users/k-jun/.cargo/registry/src/github.com-1ecc6299db9ec823/htmlq-0.1.0/src/main.rs:159:65 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
内部の HTML のパースには html5ever が使われているようです。中身を少しだけ見て見ましたが、普通に構文解析をして Token 化しているだけみたいですね。
これで スクレイピング時に BeautifulSoup とはおさらばできそうです! それでは今回はこのへんで。
TUI (Text User Interface) のライブラリ tui-rs で CLI を作ってみる。
こんにちは k-jun です。今回は Rust 製の TUI ライブラリ tui-rs を作ってみます。
https://github.com/fdehau/tui-rs
Golang 製のtermui と JavaScript 製の blessed-contrib に影響されているとのこと。 tui-rs が面白かったらこれらも触ってみようと思います!
デモがあるようなので、まずはそれを見てみます。
Demo
$ git clone https://github.com/fdehau/tui-rs.git $ cd tui-rs $ cargo run --example termion_demo --release -- --tick-rate 200
うーん、うねうねしててヤバす。今回はこの左のグラフを用いて、vm_stat の結果を表示するものを作ってみたいと思います。
Install
$ cargo add tui@0.16 $ cargo add termion@1.5
Run
サンプルコードをひとまず実行してみます。どうやら出力を単にボックスで囲うことになる様子。
use std::io; use termion::raw::IntoRawMode; use tui::backend::TermionBackend; use tui::layout::{Constraint, Direction, Layout}; use tui::widgets::{Block, Borders, Widget}; use tui::Terminal; fn main() -> Result<(), io::Error> { let stdout = io::stdout().into_raw_mode()?; let backend = TermionBackend::new(stdout); let mut terminal = Terminal::new(backend)?; terminal.draw(|f| { let size = f.size(); let block = Block::default().title("Block").borders(Borders::ALL); f.render_widget(block, size); })?; Ok(()) }
コードの出力箇所が罫線で囲まれました。少しだけコードが読めるようになったので、サンプルを見ていきます。 今回実装しようとしている chart は以下の example が参考になりそうなものは以下。
https://github.com/fdehau/tui-rs/blob/master/examples/chart.rs
データを生成している正体はこの構造体なので、こいつを vm_stat のデータを取得するように書き換えます。
impl App { fn new() -> App { let mut signal1 = SinSignal::new(0.2, 3.0, 18.0); let mut signal2 = SinSignal::new(0.1, 2.0, 10.0); let data1 = signal1.by_ref().take(200).collect::<Vec<(f64, f64)>>(); let data2 = signal2.by_ref().take(200).collect::<Vec<(f64, f64)>>(); App { signal1, data1, signal2, data2, window: [0.0, 20.0], } } fn update(&mut self) { for _ in 0..5 { self.data1.remove(0); } self.data1.extend(self.signal1.by_ref().take(5)); for _ in 0..10 { self.data2.remove(0); } self.data2.extend(self.signal2.by_ref().take(10)); self.window[0] += 1.0; self.window[1] += 1.0; } }
書き換え。main 関数の中身もいい感じに調整しておきました。
struct App { data: HashMap<String, Vec<(f64, f64)>>, window: [f64; 2], } impl App { fn new() -> App { let mut data = HashMap::new(); let mut a = App { data, window: [0.0, 180.0], }; a.update(); return a; } fn update(&mut self) { let output = Command::new("vm_stat").output().unwrap(); let raw = String::from_utf8(output.stdout).unwrap(); let v = raw.split("\n").collect::<Vec<&str>>(); let r = Regex::new(r"^Pages (free|active|inactive|speculative)").unwrap(); for i in 1..v.len() { if !r.is_match(v[i]) { continue; } let x = v[i].split(":").collect::<Vec<&str>>(); let key = x[0].trim().to_string(); let value = x[1].trim(); let value = &value[..value.len() - 1]; let value: i64 = value.parse::<i64>().unwrap(); let mut current = self.data.entry(key).or_insert(vec![]); if current.len() > self.window[1] as usize { current.remove(0); self.window[0] += 1.0; self.window[1] += 1.0; } current.push((current.len() as f64, value as f64)); } } fn xbound(&self) -> [f64; 2] { return self.window; } fn ybound(&self) -> [f64; 2] { let mut max = 0.0; self.data.keys(); for (_, v) in &self.data { let maxv = v.iter().map(|x| x.1 as i64).max().unwrap(); max = std::cmp::max(max as i64, maxv) as f64; } return [0.0, max * 1.1]; } }
結果!
それなりに見やすくはなりました。グラフにすることはやっぱり大事ですね...。 メモリの値を表示させているので、もう少し上下する様子がみたいなー。といろいろと頑張ってみましたが動きませんでした.. orz。 画面切り替えの機能などまだまだ試していない機能も多いので、別で監視ツールを作成する際に試してみようと思います。それでは今回はこの辺で!
コードでコードを奏でる! alda を試してみた。
こんにちは k-jun です。今回は何とも異色な音を出す cli ツール。alda を試してみようと思います。
https://github.com/alda-lang/alda
さらっと見た感じ、楽譜のようなものを入力するとそれに応じて演奏してくれるみたいです。どんな有能便利なコマンドよりもワクワクするのはなぜでしょうか...!
Install
直接ダウンロードする形式なので、多少めんどくさいですがインストールしていきます。
$ wget -o /tmp/alda https://alda-releases.nyc3.digitaloceanspaces.com/2.0.5/client/darwin-amd64/alda $ wget -o /tmp/alda-player https://alda-releases.nyc3.digitaloceanspaces.com/2.0.5/player/non-windows/alda-player $ chmod +x /tmp/{alda,alda-player} $ mv /tmp/{alda,alda-player} /usr/loca/bin
Run
おおお!確かに音がなりました!
alda play -c "(tempo! 160) trumpet: (quant 60) f12 b- > d f6 d12 f1"
もっと色々とやってみたいのでチュートリアルに進みます。
alda repl と入力することで repl モードに入ります。ここに種々の文法で定義された "コード" を打ち込むことで音を鳴らします。
$ alda repl nREPL server started on port 60519 on host localhost - nrepl://localhost:60519 █████╗ ██╗ ██████╗ █████╗ ██╔══██╗██║ ██╔══██╗██╔══██╗ ███████║██║ ██║ ██║███████║ ██╔══██║██║ ██║ ██║██╔══██║ ██║ ██║███████╗██████╔╝██║ ██║ ╚═╝ ╚═╝╚══════╝╚═════╝ ╚═╝ ╚═╝ Client version: 2.0.5 Server version: 2.0.5 Type :help for a list of available commands.
piano で演奏する場合は piano と prefix をつけます。以降 piano が デフォルトの楽器になります。
alda> piano: c d e f
ド〜レ〜ミ〜ファ〜 というわけです。まさにコードでコードを奏でている状態ですね ♪
alda> g a b > c
オクターブ上げる場合には > を追加。
alda> o4 c < b- a g f+ alda> o4 c++++-+-+-+
半音の上げ下げもできます。+ と - の合計値が参照されるところはプログラムっぽいですね 笑。
alda> o4 c4 c8 c c16 c c c c32 c c c c c c c | c1 alda> r2 c | r4 c r8 c r4
4分音符、8分音符などもできますできます。休符は r で表現し、| は2つのコードのまとまりを意味的に区切ります。
alda> trombone: o2 c4.. d16 e-8 r c r alda> o4 c1/e-/g/b
突然のトロンボーン。そして和音。
ということで、一通り機能することがわかりました。repl だけでなくテキストファイルを渡すことで音を出すことも可能なので、最後にリポジトリに存在する楽譜を一通りやってみて終わろうと思います。
$ alda play --file examples/across_the_sea.alda $ alda play --file examples/alternate-endings.alda $ alda play --file examples/awobmolg.alda $ alda play --file examples/bach_cello_suite_no_1.alda $ alda play --file examples/debussy_quartet.alda $ alda play --file examples/dot_accessor.alda $ alda play --file examples/dynamics.alda $ alda play --file examples/gau.alda $ alda play --file examples/hello_world.alda $ alda play --file examples/jimenez-divertimento.alda $ alda play --file examples/key_signature.alda $ alda play --file examples/modes.alda $ alda play --file examples/multi-poly.alda $ alda play --file examples/nesting.alda $ alda play --file examples/nicechord-alda-demo.alda $ alda play --file examples/nicechord-transposed-variable.alda $ alda play --file examples/overriding-a-global-attribute.alda $ alda play --file examples/panning.alda $ alda play --file examples/percussion.alda $ alda play --file examples/phase.alda $ alda play --file examples/poly.alda $ alda play --file examples/rachmaninoff_piano_concerto_2_mvmt_2.alda $ alda play --file examples/seconds_and_milliseconds.alda $ alda play --file examples/track-volume.alda $ alda play --file examples/variables-2.alda $ alda play --file examples/variables.alda
癒やされますね...。
試しながら気づきましたが、これ同時発火もできますね笑。1個1個やっていけばオーケストラも再現できそうな 笑。誰か UnderTale の楽譜作ってくれええええ。それでは今回はこのへんで。