はじめに
この記事は「言語実装 Advent Calendar 2021」 21日目の記事です。本記事は、2019 年末(GitHub への初コミットは 2019/11/28)頃から始めた Kinx という自作言語のアップデートの話題になります。
御多分に洩れず、本業の忙しさによりアップデートは細々と行っておりますが、太く短くではなく 細く長く 続けていこうと思っておりますので、今後ともよろしくお願いいたします。話題としては以下の構成になります。
- Kinx 2021年総括
- まずは Kinx 開発や主な活動に関して 2021 年を総括したいと思います。V1.0.0 を 3/16 にリリースし、Kinx パッケージをサポートした V1.1.0 をつい先日リリース(v1.1.0 Release)しました。
- Kinx アップデート状況
- 言語処理系そのもののアップデートの総括です。1年という期間ですので、細々とですが色々とアップデートはしました。大きくはパッケージ・システムをサポートしました。使い方をほとんど説明していない(日本語で)ので、今のところおそらく私しか使えません。
- Kinx パッケージの作り方・使い方
- 英語版は「ここ(パッケージ概要)」と「ここ(
kip
コマンド)」にありますが、使い方を日本語で説明していないのもアレなので、ちょっとだけ作り方と使い方を。これを読んだ誰かが何か試してくれるかも... という期待を込めて。恐らくバグもたくさん見つかるでしょう。そして、それこそが OSS のあるべき姿 ですね。
-
パッケージご紹介
- 一先ず最初の 1 歩ということでサポートしてみたパッケージのご紹介です。お試しパッケージを 2 つ紹介します。
- Kinx ドキュメント執筆開始
- Kinx をまとめてみようと思い、書籍の形式での文章を執筆し始めました。しかしながら、ドキュメント書きはご存知の通り一番時間がかかる作業です。したがってまだ完了していません。ので、ご紹介のみ。
【ご参考】Kinx
「見た目は JavaScript、頭脳(中身)は Ruby、(安定感は AC/DC)」 でお届けしているスクリプト言語 Kinx。ご存じない方は下記をご参照ください。
- 参考
- 最初の動機 ... スクリプト言語 KINX(ご紹介)
- 個別記事へのリンクは全てここに集約してあります。
- リポジトリ ... https://github.com/Kray-G/kinx
- Pull Request 等お待ちしております。
- Kinx 基礎文法最速マスター
- 最初の動機 ... スクリプト言語 KINX(ご紹介)
1. Kinx 2021年総括
全体を通して
2021年は前半は割と頑張ったところもありましたが、後半はやや低調でした。主に本業で激動があったせいですが、まあそういうことはままあると思うので、できるペースで今後も継続していきます。
GitHub Star 推移
さて、まずは GitHub でのスター数推移です。下記の図が推移を示していますが、2020年12月31日時点で 84 だったスター数は 2021年11月10日現在で 212 となっており、この 1 年で約 2.5 倍になりました。特に 1/16 に 92 → 114 と 22 個のスターが付いて大幅にアップし、一気に 100 の大台を超えました。後で色々確認してみると、この日に Hacker News で Kinx を紹介してくださった方がおり、一気に閲覧数が増えたのが要因です。
おかげさまでその後もじわじわと伸び続けており、200 の大台も今年中にクリアすることができました。ありがとうございました。
2022年の目標
2022年の目標は、まずは「使ってもらうこと」ですね。大きな目標としては GitHub でシンタックス・ハイライト してもらえて、一つの言語として 名前を認識してもらうこと なのですが、そのためには 「数百の(数多くの)」 リポジトリで使用されている実績が必要とのことです。いやぁハードル高いです。
色々と酔狂な方がいらっしゃれば、ぜひ何らかのリポジトリを作って使ってみていただければ幸いです。
2. Kinx アップデート状況
主なアップデート
主なアップデートをピックアップしてみました。以下の通りです。
- デバッガのサポート
-
switch-when
のサポート -
case-when
のサポート - 分割代入とパターンマッチ構文による代入のサポート
- パイプライン演算子と関数合成演算子のサポート
- SAT ソルバーのサポート
- Kinx パッケージのサポート
- その他バグフィックス
それでは一つ一つ軽くご紹介いたします。
デバッガ
簡単なデバッガをサポートしました。以下のような画面になります。--debug
でデバッガ機能を使えようになります。使い方に関しては「ここ(英語)」 を参照してみてください。
技術的なポイントを 1 つだけ。実は、デバッガでブレークポイントを仕込めるのですが、この処理を通常の VM 動作で実行させてしまうとパフォーマンスが急激に落ちます。そこで、デバッガ用 VM と通常用 VM は別にしています(といってもマクロで切り替えて別の関数として 2 つの実装が作られるようになっているだけですが)。しかし、この関数のコンパイルが Windows だと非常に遅いため、Windows 環境でのコンパイル時間がさらに長くなりました。。。Linux でのビルドは速いのですが。
switch-when
switch-when
をサポートしました。
とだけ言うと何のことやらと思いますが、まず元々 switch-case
がサポートされています。これが Fall Through で動作することに対して昔から賛否ありました(Kinx ではなく一般的な話として)。そして、Kinx では、switch-case
は Fall Through で動作します。これが「C like syntax」の精神から出てくる挙動です。C プログラマが switch-case
文を見た時、当然 Fall Through するだろう と認識することが期待されるからです。これが Fall Through でなければ逆に混乱するでしょう。なぜなら、break が無かったら次の文に自然に続きそうに見えるから です。
一方で、Fall Through ではない動作が求められる背景も理解できます。
そこで、構文を変えることで Fall Through ではない動作をさせる ことにしました。case
文の代わりに when
文を使えば、when
文の最後のステートメントの後で自動的に break
します。
代わりに、fallthrough
というキーワードを用意してあり、when
文で Fall Through 動作をさせたい場合は、任意の場所で fallthourgh
キーワードを挿入します。ただし、これは break
とは異なり静的に決定されるため、動的に Fall Through かどうかを決定するコードを書くことはできません。when
文のどこかで fallthrough
キーワードを書くと、case
を使ったのと同じになります。
もう一つ、default
に代わるキーワードは otherwise
になります。言い換えれば、otherwise
は自動的に break
する default
です。以下がサンプルです。
function test(a) {
var r;
switch (a) {
otherwise: // break するので when 1: にフォールスルーはしない。
when 1: r = a * 2;
when 2: r = a * 4;
when 3: r = a * 8;
when 4: r = a * 16;
}
return r ?? -1;
}
0.upto(8, &(n) => System.println("%d => %3d" % n % test(n)));
0 => -1
1 => 2
2 => 8
3 => 24
4 => 64
5 => -1
6 => -1
7 => -1
8 => -1
なお、switch
文の中で case
と when
は混在可能です。ただし、紛らわしいのでどちらかに統一したほうが良いとは思います。
case-when
case-when
もサポートしました。実は switch-when
よりも先に実装しました。case-when
は文ではなく 式 であり、評価に応じた値を持ちます。case-when
に関しては(switch-case
と後述の分割代入あたりの説明も一緒に)以下に詳しく説明していますのでご参照ください。
色々できるので、以下のサンプルコード(テストコード)を参照すると理解が深まるかもしれません。
分割代入とパターンマッチ代入
上記に書いた通り、分割代入とパターンマッチ代入をサポートしました。上記の記事を読むと分かるのですが、順番的に「分割代入とパターンマッチ代入」→「case-when
」→「switch-when
」の順で実装していますが説明の順が逆になってますね。「分割代入とパターンマッチ代入」に関しても、上記記事をご参照ください。
パイプライン演算子と関数合成演算子
パイプライン演算子と関数合成演算子をサポートしました。元々は JavaScript で議論されているものですが、早々に取り入れました。最終的には JavaScript 側は違う構文になっているかもしれませんが、元々完全互換でもないので特に問題はないでしょう。こんなことできます。
まずはパイプライン演算子です。
function doubleSay(str) {
return "%{str}, %{str}";
}
function capitalize(str) {
return str.toUpper(0, 1);
}
function exclaim(str) {
return str + '!';
}
var result = exclaim(capitalize(doubleSay("hello")));
System.println(result); // => "Hello, hello!"
var result = "hello"
|> doubleSay
|> capitalize
|> exclaim;
System.println(result); // => "Hello, hello!"
関数合成演算子を使うとこんな感じになります。
const double = &(n) => n * 2;
const increment = &(n) => n + 1;
// Normal case.
var r1 = double(increment(double(double(5)))); // 42
System.println(r1);
// By the function composition operator, it creates a new function.
var f = double +> double +> increment +> double;
var r2 = 5 |> f;
System.println(r2); // 42
SAT ソルバー
SAT ソルバーなるものをサポートしてみました。数独とか解けます。以下の記事をご参照ください。
解いてみた数独の回答例です。ピンク色の数字が、元々の問題の数字を表しています。
Kinx パッケージ
V1.1.0 で Kinx パッケージをサポートしました。今年の本命 です。まだ準備は完ぺきではありませんが、リリースこそが善 だという気合いでリリースさせました。どうぞバグでも見つけてやってください。
他の場所では全くまだ説明していないのですが、この機会に次の章で軽く説明します。
その他バグフィクス
2021年に直したバグは全部で 29 件(11/22現在)。色々ありました。現在は全て GitHub の Issues で管理していますので、何かありましたらここに Issue 登録していただければ感謝いたします。
3. Kinx パッケージの使い方/作り方
さて、今年の目玉であるパッケージ管理についてです。とは言っても、つい先日正式にリリースさせたのと、あまり使い方を説明していないので、ここで簡単に説明してみることにいたします。簡単な説明は以下にあります(英文)。
- パッケージ概要・使い方
-
kip
コマンド概要・使い方
Kinx パッケージは GitHub リポジトリで管理・配布
まず、Kinx パッケージの特長として、GitHub に依存します。パッケージのリポジトリは GitHub リポジトリそのものです。パッケージ・リポジトリの Release モジュールを使ってダウンロードし、インストールしますので、GitHub でリリースすることが所謂「パッケージの公開」になります。このパッケージのリポジトリを パッケージ・リポジトリ と呼びます。このパッケージ・リポジトリを管理するためのリポジトリとして、中央リポジトリ が存在します。
デフォルト中央リポジトリ
Kinx パッケージは中央リポジトリ方式です。デフォルトでは以下の中央リポジトリが登録されていますが、個人で追加の中央リポジトリを作成することも可能です。ここでは中央リポジトリの作り方には触れませんが、いずれ説明の機会を設けたいと思います。
- デフォルト中央リポジトリ
Kinx パッケージの使い方(kip
コマンド)
パッケージをコントロールするには kip
というコマンドを使用します。なぜ kip
か? そこには大きな理由が ... あるはずもなく、あまりいい名前が思いつかなかったため、Python のパッケージ管理コマンド pip
にあやかって kip
と名付けた、といった程度の理由になります。
さて kip
コマンドの使い方ですが、まずは -h
で表示されます。ここでは理解を容易にするために、全てを説明するのではなく、必要な主要なコマンドのみ説明することにしますのでご了承ください。
$ kip -h
Options
-h Display this help.
-v Verbose mode.
Configuration
config set <name> <value> Sets a value to a name.
config remove <name> Removes a name and a value.
config show [<name>] Lists up a name and a value.
Central Repository Access
repo add <repo> Adds a central repository.
repo remove <repo> Removes a central repository.
repo list Lists up a central repository.
Package Control
search <key> Searches a package.
install <key> [<ver>] Installs a specified package.
uninstall <key> <ver>|all Uninstalls a specified package.
devinst Installs a develpment package.
devuninst Uninstalls a develpment package.
list Lists up installed packages.
init <key> Creates and initializes a package.
help <key> [<ver>] Shows README.md of a package.
パッケージの検索
現時点では、パッケージのリストアップしかできません。今はまだこれで十分ですが、将来的にはパッケージ数を増やしていきたいので、パターンマッチなどでの検索・フィルタリング機能を追加したいと思っています。コマンドラインとしては kip search
コマンドを使用します。2021/12/21 時点では以下のように表示されます。既にインストールされているパッケージは - Installed
の表示もされます。
$ kip search
* kacc
- 0.0.1 (148.6 KB) [Pre-release] - Installed
* typesetting
- 0.0.1 ( 83.4 MB) [Pre-release] - Installed
- 0.0.0 ( 83.3 MB) [Pre-release]
このとき、上記で表示される kacc
や typesetting
がパッケージ名(キー <key>
)となります。この名前は全てのパッケージでユニークであり、重複させることはできません。
インストールパッケージの確認
上記では全てのパッケージが表示されますが、インストールされているパッケージを確認する目的には kip list
コマンドを使用します。
$ kip list
kacc: [0.0.1]
typesetting: [0.0.1]
複数のバージョンを共存させることが可能です。その場合、利用する側でバージョンを指定している場合はそのバージョンのパッケージが利用され、指定されていない場合はデフォルト有効バージョンが使われます。デフォルト有効バージョンは基本的に一番新しい版数のバージョンを示します。
パッケージのインストール
パッケージをインストールするには kip install <key> [<ver>]
コマンドを使います。<ver>
を省略すると、最新版数をインストールします。
$ kip install typesetting
[2021/12/05 11:35:31] Downloading the package typesetting(0.0.1) with 87423875 bytes.
[2021/12/05 11:35:31] from https://github.com/Kray-G/kinx-tiny-typesetting/releases/download/v0.0.1/package.zip
[2021/12/05 11:36:08] Received 87423875/87423875 (100%)
[2021/12/05 11:36:08] Created C:\Users\***********\AppData\Local\Temp/typesetting0.0.1.zip done.
[2021/12/05 11:36:11] Extracted 268/268 (100%)
[2021/12/05 11:36:11] Set the latest version of typesetting to 0.0.1
[2021/12/05 11:36:11] Made the file of phantomjs executable
[2021/12/05 11:36:11] Generated a command of kxkitty.exe
パッケージのアンインストール
パッケージのアンインストールは kip uninstall uninstall <key> <ver>|all
コマンドを使います。アンインストールの場合、<ver>
を省略することはできません。全てをアンインストールする場合は明示的に all
を指定します。
$ kip uninstall typesetting
[2021/12/05 11:35:23] No version for typesetting specified
[2021/12/05 11:35:23] If you want to uninstall all versions, specify 'all'
$ kip uninstall typesetting all
[2021/12/05 11:35:26] Removed an executable of kxkitty.exe
[2021/12/05 11:35:26] All versions of typesetting is successfully uninstalled
パッケージ内のファイルの参照方法
パッケージのライブラリを参照するには、使う側で以下のように using
指定を行います。この時、パッケージの lib
フォルダが参照の際のルート・ディレクトリになります。
using @packagekey.LibFile; // 最新バージョンの参照
using @packagekey(0.0.1).LibFile; // バージョン指定する場合
現在提供しているパッケージでも、Kacc (https://github.com/Kray-G/kacc) ではレキサ(字句解析器)を使用するのに以下のように指定させています。
using @kacc.Lexer;
Kinx パッケージの作り方(GitHub リポジトリ)
さて、ここからはパッケージの作り方です。パッケージを作る作業は大まかに以下に分解されます。
- パッケージ・リポジトリを作成する。
- 開発用インストールを行い、ローカルで動作検証を行う。
- パッケージ・リポジトリでリリースする。
- 中央リポジトリに登録する。
一旦中央リポジトリに登録できれば、あとはパッケージ・リポジトリ側でバージョンを上げてリリースすることで自動的に最新バージョンを更新することができます。
バージョンの付け方
バージョンは x.y.z
の形式です。基本的にはセマンティック・バージョニングに準しています。なお、開発用のバージョンは自動的に 99.99.99
と認識されます。
パッケージ・リポジトリの作成
ボイラープレート作成
パッケージ・リポジトリは、GitHub リポジトリです。従って、通常の GitHub リポジトリをまず作成します。その後、リポジトリ・フォルダ内で kip init <key>
コマンドを使用します。例えば、パッケージのキー名を pacname
とした場合、以下のように実行します。
$ kip init pacname
[2021/12/05 11:13:42] Created the directory of 'docs'.
[2021/12/05 11:13:42] Created a default README file of 'docs/README.md'.
[2021/12/05 11:13:42] Created the directory of 'src/bin'.
[2021/12/05 11:13:42] Created a hook script file of 'src/bin/pacname.kx'.
[2021/12/05 11:13:42] Created the directory of 'src/lib'.
[2021/12/05 11:13:42] Created an initial library file of 'src/lib/Pacname.kx'.
[2021/12/05 11:13:42] Created the directory of 'src/etc'.
[2021/12/05 11:13:42] Created an initial setting file of 'src/etc/pacname.json'.
[2021/12/05 11:13:42] Created the directory of '.github/workflows'.
[2021/12/05 11:13:42] Created a default CI file of '.github/workflows/main.yml'.
<key>
に指定する名前があらかじめ設定された package.json
ファイルを作成します。
{
"name": "pacname"
}
また、以下の各種テンプレート・ファイルが作成されます。
-
docs/README.md
ファイルが作成されます。 -
src/bin/packname.kx
というファイルを作成し、パッケージの実行ファイルのためのスクリプト・ファイルが作成されます。- 実行ファイルが不要なプロジェクト(ライブラリ提供など)の場合、不要であれば削除してください。
-
src/lib/Packname.kx
というファイルを作成し、パッケージのライブラリ・ファイルとして利用できるようにします。- 特に決まりはありませんが、ライブラリとして提供する場合、パッケージ・キーと同じだと分かりやすいとの理由です。デフォルトでは中身は空で作成されます。
-
src/etc/packname.json
というファイルを作成し、パッケージの設定ファイルとして利用できるようにします。- デフォルトでは空の Json オブジェクトが定義されています。
-
.github/workflows/main.yml
という GitHub Action のデフォルトワークフロー・ファイルが作成されます。-
vX.Y.Z
というバージョン番号に則したタグを打つと、vX.Y.Z
というリリースページを作成し、自動的にpackage.zip
ファイルを作成してアップロードします。必要に応じて[Publish]
するだけでリリースパッケージが公開できるようになります。
-
全体として、以下のようなフォルダツリーが作成されます。
.
│ package.json
├─.git
├─.github
│ └─workflows
│ main.yml
├─docs
│ README.md
└─src
├─bin
│ pacname.kx
├─lib
│ Pacname.kx
└─etc
pacname.json
リポジトリ構成とインストール時の構成の対応
リポジトリ上での構成とインストール後のディレクトリ構成の対応を以下に示します。
リポジトリ上の構成 | インストール先 | 例 |
---|---|---|
src/bin |
packagekey/ver/bin |
typesetting/0.0.1/bin |
src/lib |
packagekey/ver/lib |
typesetting/0.0.1/lib |
src/etc |
packagekey/ver/etc |
typesetting/0.0.1/etc |
docs |
packagekey/ver/docs |
typesetting/0.0.1/docs |
上記の 「リポジトリ上の構成」 の形でリポジトリ上にディレクトリを作成して配置してください。
src
配下
src
配下に以下のディレクトリを作成します。これは、基本的にはこのままの形でインストールされます。
-
bin
... 主に実行ファイル。後述する「特別な配慮」がなされます。 -
lib
... 主にライブラリファイル。ライブラリとして使われるファイルのルートになります。 -
etc
... 主に設定ファイルや必要な環境ファイルなど。
src/bin
配下における「特別な配慮」
展開した後のディレクトリ構成で、bin
配下は以下の特別な配慮がなされます。
-
bin
ディレクトリ直下のxxx.kx
ファイルは、Windows の場合xxx.exe
が、Linux の場合xxx
という executable なモジュールが作成され、セットアップされます。- 例えば、
kxkitty.kx
の場合、Windows であればkxkitty.exe
が作られ、Linux ではkxkitty
という実行コマンドが自動的に作成されます。 - ここで作成されたモジュールは、アンインストール時に不要となった場合、自動的に削除されます。
- 例えば、
- Linux の場合、
bin
ディレクトリ配下(直下でなくても良い)の実行モジュール(ELF ファイル、.sh
ファイル)は、全て自動的に実行可能フラグを付けることで実際に実行可能な状態にセットアップします。
docs
配下
主にドキュメントを配置します。docs/REAMDME.md
ファイルは特別で、kip help <key>
コマンドでコンソールに内容が表示される内容となります。Markdown ですが、コンソール用に簡易整形されます。
開発用インストールとデバッグ
開発用のインストールとアンインストールは kip devinst
および kip devunint
コマンドです。パッケージ・リポジトリのルートでこのコマンドを実行する必要がありますが、代わりにパッケージ名(キー)を指定する必要はありません。
例えば kacc パッケージのリポジトリ・ルートで実行すると以下のように出力されます。開発用バージョンは 99.99.99
で固定です。
$ kip devinst
[2021/12/05 11:55:46] $PKGPATH: /usr/bin/kinxlib/package/kacc/99.99.99
[2021/12/05 11:55:46] Copying a directory : bin
[2021/12/05 11:55:46] Copying a directory : bin/exec
[2021/12/05 11:55:46] Copying a file : bin/exec/kmyacc
[2021/12/05 11:55:46] Copying a file : bin/exec/kmyacc.exe
[2021/12/05 11:55:47] Copying a file : bin/kacc.kx
[2021/12/05 11:55:47] Copying a directory : etc
[2021/12/05 11:55:47] Copying a file : etc/kmyacc.kx.parser
[2021/12/05 11:55:47] Copying a directory : example
[2021/12/05 11:55:47] Copying a file : example/calc.y
[2021/12/05 11:55:47] Copying a file : example/calcjit.y
[2021/12/05 11:55:47] Copying a directory : lib
[2021/12/05 11:55:47] Copying a file : lib/Lexer.kx
[2021/12/05 11:55:47] Copying a directory : docs
[2021/12/05 11:55:47] Copying a file : docs/Lexer.md
[2021/12/05 11:55:47] Copying a file : docs/README.md
[2021/12/05 11:55:47] Made the file of kmyacc executable
[2021/12/05 11:55:47] Generated a command of kacc.exe
インストールパッケージを確認すると、以下のように <development>
表示が追加されます。
$ kip list
kacc: [0.0.1, <development>]
typesetting: [0.0.1]
インストールと同様に、パッケージ・リポジトリのルートで kip devuninst
とするとアンインストールできます。
パッケージ・リポジトリでのリリース
リリースも、通常の GitHub 上でのリリースと同様です。リリースページを作成します。その際のルールは以下の通りです。
- バージョン番号は
v0.0.1
といった形でvX.Y.Z
とする。 - Asset として
package.zip
という名前の ZIP ファイルを登録する。
例えば、kacc のバージョン 0.0.1 のリリースページは以下のようになっています。バージョン番号と package.zip
があることを確認してください。
なお、最初に kip init <key>
コマンドでボイラープレートを作成した場合、vX.Y.Z
の名前でタグをコミットして push すると、自動的に上記のようなページを作成してくれるよう事前に Workflow が定義されています。そのため、必要に応じて [Publish]
するだけでパッケージが公開できますので、ぜひご活用ください。
中央リポジトリへの登録
中央リポジトリへの登録は、現在自動的には行えません。以下の内容で GitHub の Issue からリクエストをお願いします。
- リクエスト: https://github.com/Kray-G/kinx-package-repository/issues
- 必要な情報
- リポジトリ・キー名:英数字、ハイフン
- パッケージ情報(JSON ファイル)
- 参考:typesetting のパッケージ情報は以下の通りです。参考にして記載してください。
こちらで確認でき次第、中央リポジトリをアップデートします。
4. パッケージご紹介
現在、サンプルのパッケージとして以下の 2 つのパッケージがあります。
- kacc - https://github.com/Kray-G/kacc
- Kacc - Kinx コードを出力する LALR(1) パーサージェネレータ。
- typesetting - https://github.com/Kray-G/kinx-tiny-typesetting
- Kinx Tiny Typesetting - Kinx による簡易組版ライブラリ。
- 本ライブラリに関しては、日本語のユーザーガイドが以下にあります。
- https://github.com/Kray-G/kinx-tiny-typesetting/raw/master/docs/userguide/KiTTy_jp.pdf
- 本ドキュメント自体も Kinx Tiny Typesetting ライブラリを使って作成されています。
5. Kinx ドキュメント執筆開始
最後に、Kinx を 1 冊にまとめたドキュメントを書いています。これは残念ながらまだ完成していません。ちょっとずつ完成させていきたいと思っています。ドキュメントは以下のリポジトリで作成しています(日英の両方を同時進行で作ってるので割と辛い...)。
-
https://github.com/Kray-G/kinx-books
- プログラミング言語 Kinx
- The Programming Language Kinx
本リポジトリは、今後 Kinx 関連のドキュメントを書く際の管理リポジトリとする予定です。その第一弾が「プログラミング言語 Kinx(The Programming Language Kinx)」になります。
おわりに
色々とペースダウンしてますが、まぁこういった作業には波がありますね。Kinx 自体はまだ続きます。もしご興味があるようであれば、ぜひ Kinx を使ったリポジトリを作って何か試してみていただいたり、軽く遊んだりしていただければ光栄です。
- Kinx リポジトリ
以上、ここまで読んでいただき、ありがとうございました。