🍵を作りました

🍵を作りました

表題の通りOchaを作りました。
この記事ではOchaを紹介したいと思います。

Ochaについて

OchaはSwiftで作ったライブラリです。 しかし、iOSmacOSのライブラリじゃなくてPCで動くプログラムになってます。 Ochaは指定した(1以上の)ファイルの変更を検知するプログラムです。 Ochaでできることはファイルの変更・保存・削除をもとに自分の任意のプログラムを走らせることができる。そういった役割のプログラムです。 たとえばファイル保存した時にインデントを整える。ファイル消した時に Delete file << FILE_PATH >>の形式のコミットメッセージでgit add, git commit する。 といったことの実現を補助するためのライブラリになっています。

使い方

Ochaの使い方を簡単に紹介します。 まず、FileSystemのイベント監視をするためのクラス。 Watcher クラスを作成します。この時に監視したいファイルパスも渡してあげましょう。

let watcher = Watcher(paths: [pathString])

次にFileSystemのイベントを検知を開始したい時にstartメソッドを呼んであげましょう。このstartメソッドの最後の引数のclosureはイベントを検知した時に実行されます。

watcher.start { (events) in ... }

具体例

上述したような ファイル消した時にDelete file << FILE_PATH >>の形式のコミットメッセージでgit add, git commitする。を実際に動かしている例をOchaリポジトリExampleとして載せています。

Exampleとして書かれているコードを下に載せます。こちらを見てもっと具体的な書き方を把握してみましょう。

import Foundation
import Ocha
import SwiftShell
import PathKit

print("You can confirm `Ocha.GitCommitExample` when removed file. Try rm -rf Package.swift and conform git history(e.g git show. You can got new commit for it message of 'Delete file [Package.swift] path'. ")

let path = Path(
    #file.components(separatedBy: "/")
        .dropLast() // main.swift
        .dropLast() // GitCommitExample
        .dropLast() // Sources
        .joined(separator: "/")
)
let pathString = path.absolute().string
main.currentdirectory = pathString

let watcher = Watcher(paths: [pathString])
watcher.start { (events) in
    let removedEventPaths = events
        .filter { $0.flag.contains(.removedFile) }
        .map { $0.path }
    removedEventPaths.forEach { path in
        main.run(bash: "git add \(path)")
        main.run(bash: "git commit -m \"Delete file \(path)\"")
    }
}

RunLoop.current.run()

なんとなく何がやりたいかは読めるのではないかと思います。後半のwatcher.startの内容を少し整理しながら見ていきましょう。
先程も説明したようにFileSystemを監視したいタイミングでwatcher.startを呼びます。
次にCLIrm -f Package.swift を実行します。この時に消すファイルは Package.swift である必要はありませんが、Watcherに渡しているディレクトリ配下である必要があります。ちなみにFinder上からのGUI上からの削除はゴミ箱の移動扱いになり、削除とはまた違う扱いになるためこのExampleはうまく機能しません。
rm -f Package.swiftを行ったにstartの最後の引数であるclosureが実行されます。この時にどのようなイベントが発生したか、どのファイルが対象か。といった情報を詰め込んだ構造体が引数として渡ってきます。このeventsをもとにどういったことを行いたいかを記述していきます。今回だとファイルが削除された場合にgit add << FILE_PATH >>, git commit -m "Delete file << FILE_PATH >>を実行をしたいです。
Eventにはflagがあり、これを用いてremovedFileのイベント対象となったファイルパスを取得しています。 そしてこのファイルパスの配列を用いてgitコマンドを実行する流れになっています。

モチベーション

Ochaを作ったモチベーションは主にファイル保存時に特定のコードフォーマッタかけたいなあ。かけれたらいいな。
ブログをローカルで書いているときにコミットメッセージはどうでもいいからファイル保存時にコミットとりあえず積んで安心感を得たい。ちょうどいいタイミングでsquash等を行ってきれいなログにする運用にしたい。などなど思ったのがきっかけでした。
Swiftのライブラリという点では、僕はSwiftを書くEditorとしてXcodeを使っているのですが、Xcodeではファイルイベントに応じてスクリプトを実行するような機能は用意されていません(僕の知る限りでは)。Compileの前後等のタイミングでScriptを挟めたりするのですが、このタイミングだとやりたいことに対してタイミングが遅いと感じる場合もあると思います。

そういった課題を感じたためOchaというライブラリを作りました。

なぜ 🍵 なのか

Watcher(監視者) の響きを日本語にしたときの アナグラム になっています。
うぉっちゃー → おっちゃー → おちゃ

以上。

技術について

Ochaの技術については本ブログでは紹介しません。代わりに(?)Ochaで使用されている技術の解説本を技術書典6で販売します。 SwiftKotlin愛好会というサークルで執筆者の一人としてSwiftでどのようにFileSystemを監視するか。と言ったことをOchaのコードベースに書いていきます。

サークル名: SwiftKotlin愛好会
URL: https://techbookfest.org/event/tbf06/circle/71750003

興味がある方は是非お越しください。複数人での共著なのでSwift・Kotlinネタが他にも載っている一冊となります。

素敵なロゴを描いてもらいました

OchaのREADMEを見るとわかるのですが素敵なロゴが載っています。
井上乃彩 / Noa Inoueさんに描いていただきました。とても可愛くて素敵なロゴをいただきました。見るたびに少し見とれてしまいます。 経緯を話すと Ochaにロゴが欲しい & 最近デザインツールを個人で触っていて他の人はどういう情報を元に作るんだろう。と気になりそれで声をかけて関わっていただきました。本当に素敵で感謝です。

噂のロゴです。

f:id:bannzai:20190405032805p:plain

まとめ

SwiftはまだAppleプラットフォーム、特にGUIアプリケーション開発に頻繁に用いられる開発言語と言えるでしょう。
Ochaも実はCocoa依存なのでmacOS上でのみ動くコマンドラインツールなのですが、それでも普段開発しているようなiOSアプリ等の開発とは毛色が違います。今回はFileSystemを監視する。というテーマのライブラリを作りました。Ochaは単体では機能せず処理内容は自分で記述する必要があります。が、 Ocha自体は小さなライブラリとなっておりExampleもシンプルで比較的応用例も浮かびやすいのかな。と思っています。普段GUIアプリケーションを開発している方でもCLIツール作成して便利なツールを作りたい方はOchaを利用するのも是非ご検討してください。

このライブラリが便利!最高!クール!ロゴかわいい!と思ったそこの貴方へ

スターください 🍵

おしまい \(^o^)/