2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JuliaAdvent Calendar 2021

Day 6

PkgTemplates.jl をベースに VSCode と Docker を組み合わせる自作テンプレートを作ります

Last updated at Posted at 2021-12-06

本日は

Julia アドベントカレンダーネタです.
本日は MyTemplate.jl というPkgTemplates.jl をベースに自分好みのテンプレートを作成する方法を紹介します.

背景

MyWorkflow.jl というリポジトリで Julia + Docker + Jupyter Notebook の組み合わせをする心地いいワークフローを開発していました.MyWorkflow.jl 自身は 別の Qiita でも書いています.

個人の自作パッケージを作る際や Julia に限らず Python で(個人的な)開発するときにもこのリポジトリで用いていたファイルをよく愛用していました.

とりあえず make コマンドを叩けば環境が構築でき,docker-compose up lab で Jupyter 環境を立ち上げることができるのはとても便利です(と思っています)

さて,問題だったのは新しい Julia のプロジェクトを行う際に, MyWorkflow.jl から DockerfileMakefile, docker-compose.yml, .devcontainer/devcontainer.json をいちいちコピペするという作業が必要でした.そしてイメージ名を変更したりとか...置換作業が必要でした.

なければテンプレートを作ればいいじゃない!

そもそも MyWorkflow.jl 自身が PkgTemplates.jl から作られたのでした.

PkgTemplates.jl は Julia プロジェクトを開発する時のテンプレートを作ってくれる Julia のパッケージです.

さて本題(MyTemplate.jl の使い方)

例えば YourPkg.jl を作りたいとします. ひとまず下記のようにするとテンプレートができます.

$ git config --global github.user "あなたのGitHubアカウント名を入力" # これは初回のみ
$ git clone https://github.com/terasakisatoshi/MyTemplate.jl.git # コードをクローン
$ cd MyTemplate.jl
$ julia --project=@. -e 'using Pkg; Pkg.instantiate()' # `generate.jl` を使うための依存関係を追加
$ julia --project=@. generate.jl YourPkg --with-jupyter # YourPkg という名前のパッケージ名を作る

このようにすると YourPkg.jl というディレクトリができます. tree コマンドでディレクトリ構造を眺めてみましょう

$ cd YourPkg.jl
$ tree
.
├── Dockerfile
├── LICENSE
├── Makefile
├── Manifest.toml
├── Project.toml
├── README.md
├── docker-compose.yml
├── docs
│   ├── Manifest.toml
│   ├── Project.toml
│   ├── make.jl
│   └── src
│       └── index.md
├── jupytext.toml
├── playground
│   ├── notebook
│   └── pluto
├── src
│   └── YourPkg.jl
└── test
    └── runtests.jl

jupytext.tomlDockerfile, docker-compose.yml, Makefile, playground/ などが含まれています.これがオレオレテンプレートで,それ以外は PkgTemplates.jl がよしなに作成したものです.

テンプレートから作成できたら

作業する場所を YourPkg.jl に移動して make コマンドを叩きます

$ cd YourPkg.jl
$ make
...
ちょっと時間がかかる

make コマンドで Jupyter 環境をコンテナ内で立ち上げるためのDockerイメージをビルドします(M1 Mac 環境だと JupyterLab 関連の extension のビルドが失敗するかもしれないです. 実機持ってないので GitHub Sponsor とかで経済的支援していただけると対応します)

イメージがビルドできたら docker-compose up lab とすると docker-compose.yml で定義したサービスを立ち上げることができます.

$ docker-compose up lab
...
... (色々ログが出力される)
...
       |     To access the server, open this file in a browser:
       |         file:///root/.local/share/jupyter/runtime/jpserver-1-open.html
       |     Or copy and paste one of these URLs:
       |         http://320812028b46:8888/lab?token=xxxxxxxx
       |      or http://127.0.0.1:8888/lab?token=xxxxxxxx

こういうログが出てきたらブラウザを開いて http://127.0.0.1:8888/lab?token=xxxxxxxx にアクセスするとカスタマイズされた JupyterLab 環境が得られます.

Jupyter が不要な場合

とりあえず VSCode と組み合わせるだけに興味があって Jupyter 環境が不要な場合は上記で使用した generate.jl のオプションでつけていた with-jupyter を使わずに generate.jl を実行してください:

$ https://github.com/terasakisatoshi/MyTemplate.jl.git # コードをクローン
$ cd MyTemplate.jl
$ julia --project=@. -e 'using Pkg; Pkg.instantiate()' # `generate.jl` を使うための依存関係を追加
$ julia --project=@. generate.jl YourPkg # YourPkg という名前のパッケージ名を作る
$ cd YourPkg
$ docker-compose run --rm julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.6.4 (2021-11-19)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> # あとはお好きにどうぞ

こんな感じで楽にできるので使ってみてください.

VSCode との連携

VSCode の Remote Containers の機能を利用するだけです. いろんな設定は .devcontainer/devcontainer.json で設定されているのでよしなにDockerによるコンテナ環境の中で作業できるようになります.

をインストールすると使えるようになります. そのあとは作成した YourPkg.jl ディレクトリで code . で開いたディレクトリをプロジェクトとしてみなしながら VSCode を立ち上げます. 画面左下に >< というマークがあるのでそれをクリックして ReOpen in Container をクリックするとコンテナ内部で作業することができます. 具体的な操作方法は Julia と関係ないので VSCode Docker などでググって調べてください.例えば
外部のブログ VS Code + Remote Containers で快適な Dev ライフを がとてもわかりやすいです.

自作テンプレートを追加する方法

例えば自作パッケージを作るときに自分が使う定型ファイル oreorefile.txt も入れ込んでおきたい!とします.そのテンプレートはパッケージ名に依存しているとしましょう. なんでもいいので例えば下記のようなテンプレートを作っておきます:

templates/oreorefile.txt
Hi, I'm {{name}}. {{{PKG}}} is my julia package.

{{name}}{{{PKG}}} の部分が動的に変わってほしい部分です. 例えば David さんが YourPkg を作るのであれば Hi, I'm David. YourPkg is my julia package というファイルができて欲しいとしましょう.

FilePlugin のサブタイプを作る

ここでは Julia コードを持ってきて説明します. PkgTemplates.jl ではファイルのテンプレートをハンドリングするために FilePlugin という抽象型を定義しています. この型のサブタイプとして oreorefile.txt を操作するための構造体(ここでは OreOreFile という自作型)と対応する構造体に対して幾つかのメソッドを定義することになります. あまりJuliaに慣れてない,でもオブジェクト指向なら知っているよ!って読者なら,FilePlugin というのは基底クラスで OreOreFileFilePlugin を継承するというノリで読んでください. 幾つかのメソッドを定義するのは FilePlugin を継承するクラスが持っているべきメソッドをオーバライドするものと解釈してください.

メソッドは source, destination, view というメソッド(関数の具体的な手続き)を OreOreFile 構造体に対して実装することになります.

  • source はテンプレートファイルのパスを返す
  • destination はテンプレートから作られたファイルを配置するパス(作成されるパッケージのディレクトリからの相対パス)を返す
  • view {{name}}{{{PKG}}} となっているところに何を代入するかを指定するために必要な対応表(Juliaの辞書オブジェクトして使う)

PKG はPkgTemplates.jl の中ではパッケージ名を表す特別なキーワードになっています. ですので {{{PKG}}} と3重カッコが必要ですが,自作の変数であればカッコは2つで良いみたいです.

基本的に下記をそのままコピペすれば良いでしょう:

oreorefile.jl
Base.@kwdef struct OreOreFile <: FilePlugin
    file::String = "templates/oreorefile.txt"
    destination::String = "oreorefile.txt"
    name::String = "David"
end

source(p::OreOreFile) = p.file
destination(p::OreOreFile) = p.destination
view(of::OreOreFile, ::Template, pkg::AbstractString) = Dict("PKG" => pkg, "name"=>of.name)

OreOreFile 構造体のインスタンスを plugins 変数に渡す

あとは PkgTemplates.jl のお作法に則ればOKです. PkgTemplates.Template のインスタンスに渡す plugins 引数に先ほど定義した OreOreFile 構造体のインスタンスを含めればOKです. 下記のように generate.jl というスクリプト(名前はJuliaのスクリプトであればなんでも良い)を作ります.

generate.jl
using PkgTemplates
t = Template(;
    dir = pwd(),
    julia = v"1",
    plugins = [
        License(; name = "MIT"),
        Git(; manifest = false, ssh = true),
        OreOreFile(;name="あなたの名前を入れてね♪"),
    ]
)

t("YourPkg")

julia generate.jl とすると無事にテンプレートから必要な情報が穴埋めされた oreorefile.txt が完成します.

まとめ

こんな感じで Julia の型システムを使うと外部パッケージの機能と同等の機能を実現するオレオレ機能を実装し組み込むことができるようになります.
テンプレート作成だけでなく,Julia の型システムの一部も学ぶことができました.

2
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?