decadence

個人のメモ帳

sbtのCommand.processあたり

コマンドを実行するとこ

殆ど内容無い

sbt.State.Next

個々のコマンドを実行するとstateが返却される。このstate.next: sbt.State.Nextの結果により、次のコマンドが実行されるかが決まる - sbt.State.Nextはsealed traitで、以下4つの直和 - Continue - 普通に終わって、次のコマンドを正常に実行させる - Return(xsbti.MainResult) - ClearGlobalLog - KeepLastLog

Stateは、再帰して実行されるため、最終的にContinue以外の3つのいずれかに収束する。

  • Return(xsbti.MainResult)
    • 終了を表すもの
    • xsbti.MainResultは、interfaceであり、以下の3つで実装されている
      • xsbti.Continue
      • xsbti.Exit: exit codeを持つ
      • xsbti.Reboot: 新たな設定(ディレクトリ、app, 引数等)を持つ
    • これらは、Launch.launchで処理され、名前通りの処理が行われる
  • ClearGlobalLog
    • 1つ前のログファイルを削除し、現在のログファイルを1つ前のログファイルとし、新たなログファイルを用いて再帰に戻る。
  • KeepLastLog
    • 現在のログファイルを破棄し、1つ前のログファイルを用いて再帰に戻る。

Command.processの話あたり

def process(command: String, state: State): State

文字列として与えられたコマンドを実行し、新しく(更新した)Stateを返す。

  • state.definedCommands: Seq[Command]から新たにstateを引数に取り、コマンドを実行可能な形式にしたParserを作成
    • definedCommandsは、TODO以前に見たinitialDefinitionsの事
    • CommandSimpleCommandArbitraryCommandのいずれかなので、初めに分離させる
      • SimpleCommandが普通のコマンドで、ArbitraryCommandは名前を持たないコマンド
  • コマンド名を基に、コマンドを取得し、実行(s())
    • 後述
  • もしコマンドが見つからなければ、エラーログを出して、tate.fail

コマンドを実行するって話はこの辺まで

state.fail

コマンドが失敗したりした際に呼ばれるもので、以下の処理が行われる。

  • state.remainingCommandsの先頭からresumeFromFailureコマンドか---コマンドまで削除する
  • もしremainingCommandsがなくなれば...(ここでstate.onFailure: Stringで、失敗時に実行するコマンドが含まれてる前提)
    • state.onFailureが定義されて無ければ、exit code = 1でReturnを返すようなnextを持つStateを返す
    • state.onFailureが定義されてれば、そのコマンドが次に実行されるようにして、onFailureを消したStateを返す
  • remainingCommandsが残っていれば
    • 同じように、onFailureがあればそれを次に実行させるようにするStateを返す
    • なければ、remainingCommandsをさっき削ったのにしたStateを返す

コマンドを実行するってとこ

SimpleCommand(普通の名前ついたCommand)?

  • 定義するのは以下らへんが用いられる
    • Command.command
    • Comamnd.make
    • Command.apply
    • Command.args
    • Command.single
    • ...
    • ArbitraryCommandを定義するときはCommand.arbなど
  • 結局Command.makeからSimpleCommandが生成される
    • 引数の数とかパーサーとかで使い分ける
    • 定義する際の(f: State => State)などが実行される内容になる