Common Lispでの開発時に使う補助ツールを作った話

# Common Lispでの開発時に使う補助ツールを作った話

## はじめに

劣化した車輪の再発明かもしれませんが、私の私による私のための簡単な開発補助ツール的な何かを作ってみたのでその話。

## 抱えている問題

Embeddable Common Lispを触りはじめて一ヶ月くらい経ったのですが、Quicklisp & ASDF & Common Lisp & Emacs & SLIMEな環境で、いくつか面倒で嫌なことがありました。

- QuicklispからパッケージをインストールするにはREPLを起動しておかないと駄目
- Quicklispを使うには処理系の設定ファイルにQuicklispを読み込むコードを書いておかないと駄目
- パッケージのロードはASDFのみで問題ないので、毎回Quicklispを読み込むのは嫌
- ASDFのmake-buildを使ってバイナリ実行形式を作るには、自分の作ったプログラムもパッケージ化、asdファイルを作っておく必要がある。
- asdファイルを作ってパッケージを作る際のファイル構成は複雑で、いくつもの小さな練習用プログラムを作るときに面倒
- 自分で書いたC言語のコードも同じプロジェクトで管理して、ビルドした共有ライブラリを呼び出したい
- 自分で作ったパッケージを入れ子構造にして管理して呼び出したい
- 実行もテストもREPLからコマンドを呼び出さないと駄目
- Debianが提供しているパッケージのECL、Emacsを使いたい
- 既存のEmacsの設定は引き継ぎたくない

みたいなものがうーんという感じだったので、これらの問題を解決するため、C言語とシェルスクリプトでコマンドラインインターフェースを作成しました。

## 解決するためのツールの仕様

### 仕様

- 好きな場所にインストールできること
- 後でインストール場所を変更しても環境変数を変更すれば対応できる
- Quicklispのインストールと設定
- ASDFのインストールとsource-registry-parameterなどの設定
- Emacs、ECLの設定ファイルをセットアップ
- ECL Readlineのインストールと設定
- SLIMEのセットアップ
- 既存のQuicklisp、Emacs、ASDF、SLIME、ECLの設定などに影響を与えない
- シェルから色々な操作ができること
- このツールを途中で使わなくなった時に、ツール削除に起因する面倒なことが起きないこと

### ツールでできること

以下の操作をシェルから実行できるようにしました

- Quicklispを使ったパッケージの検索、インストール、削除
- プロジェクトのファイルとディレクトリの自動作成
- テスト用のファイルとディレクトリの自動作成
- Lispプログラムの実行、ビルド、テスト
- 独自に用意した設定を読み込み、REPLやEmacs&SLIMEを起動

## Deepspace

[deepspace](https://gitlab.com/hu.moonstone/deepspace)という名前でGitLab上で管理しています。Debian 10.2上でのみ動作を確認しています。

### インストール

#### 必要なパッケージのインストール

```bash
$ sudo apt install gcc make ecl emacs libreadline-dev
```

#### 環境変数の設定

インストール先として環境変数`DEEPSPACE_HOME`を設定し、bin以下にパスを通して置きます。

```bash:.bashrc
export DEEPSPACE_HOME=$HOME/deepspace
export PATH=$PATH:$DEEPSPACE_HOME/bin
```

```bash
$ source ~/.bashrc
```

ダウンロード、解凍後、`install.sh`を実行するとインストールを開始します。

```bash
$ wget https://gitlab.com/hu.moonstone/deepspace/-/archive/master/deepspace-master.tar.gz
$ tar xf deepspace-master.tar.gz
$ cd deepspace-master
$ ./install.sh
```

インストールが完了すると、`~/deepspace`以下にコマンドが設置されます。

```bash
$ which deepspace
/home/username/deepspace/bin/deepspace
```

### パッケージの操作

#### 検索

```
$ deepspace -t package -o search -n package-name
```

#### インストール

```
$ deepspace -t package -o install -n package-name
```

#### 削除

```
$ deepspace -t package -o remove -n package-name
```


### プロジェクトの作成とファイル、ディレクトリ構成

-nオプションに渡す値がプロジェクト名、パッケージ名になり、その名前で新しくディレクトリが作成されます。

```bash
$ deepspace -t project -o create -n sdl-window
```

```bash
$ tree
.
|-- build # ビルド済みバイナリファイルの出力先
|-- doc # ドキュメント設置場所
|-- lib # この中に置いたパッケージは自動でASDFのsource-registryに登録される
|-- resources
|   |-- data
|   |-- images
|   `-- sounds
|-- sdl-window-test.asd # テスト用パッケージASDFファイル
|-- sdl-window.asd #パッケージASDファイル
|-- src #ソースコード
|   |-- c # Cのソースコード
|   `-- lisp
|       |-- package.lisp
|       `-- sdl-window.lisp
`-- test # テストコード
    |-- c
    `-- lisp
        |-- package.lisp
        `-- sdl-window-test.lisp
```


### 実行、ビルド、テスト

#### 実行

project-nameパッケージ内のmain関数を呼び出します。

```
$ deepspace -t project -o execute -n project-name
```

#### ビルド

project-nameパッケージ内のmain関数を呼び出す形で実行バイナリをbuildディレクトリ以下に出力します。

```
$ deepspace -t project -o build -n project-name
```

#### テスト

fivamを使うため、

```
$ deepspace -t package -o install -n fiveam
```

でfiveamをインストールした上で、

```
$ deepspace -t project -o test -n project-name
```

を実行します。

### REPL、SLIME REPLの起動

```
$ deepspace --repl
```

```
$ deepspace --slime
```

### Quicklisp

#### インストール済みパッケージの更新

```
$ deepspace -t quicklisp -o update
```

#### Quicklisp自体の更新

```
$ deepspace -t quicklisp -o self-update
```

### 各種設定ファイルの場所

#### Emacsの設定

$DEEPSPACE_HOME/share/deepspace/.emacs.d/init.el

#### ECLの設定
$DEEPSPACE_HOME/share/deepspace/.eclrc

#### プロジェクト作成時の処理
$DEEPSPACE_HOME/share/deepspace/scripts/create-project.sh


## TODO

- ファイル、ディレクトリ構成の雛形を用意して選択式に
- パッケージ検索時、パッケージの詳細情報を表示
- 他の場所にあるパッケージを即座に組み込んで実行、ビルド、テスト
- GUIフロントエンド
- ソースコード内とASDファイルのパッケージ名を一括変更
- ソースコードのファイルを追加時、asdファイルのcomponentに自動追加