LoginSignup
4
1

More than 5 years have passed since last update.

プロジェクト配下の任意のディレクトリからsbtを起動できるようにする

Last updated at Posted at 2017-06-12

普段 Scala でプログラミングをするときにビルドツールとして sbt を使用していて不便に感じることのひとつが
build.sbt のあるディレクトリ(=プロジェクトのルートディレクトリ)で sbt を起動しないといけない こと。

プロジェクト配下のサブディレクトリに移動して作業していたりすると、
いちいちルートディレクトリに移動してから sbt を起動しないといけなくてめんどくさい。

Python のコマンドラインツール Fabric なんかだと、カレントディレクトリから親ディレクトリに向かって
fabfile.py を探してくれて便利なので、同じようなことを sbt でもできるようにしたい。

sbt 自体にはそのようなオプションはないようなので、ちょっとしたシェルスクリプトを書いて実現しました。

  1. あるファイルを、カレントディレクトリから親ディレクトリに向かって再帰的に探すシェルスクリプトを作成。
  2. そのシェルスクリプトを使って build.sbt を探し、見つかったディレクトリで sbt を起動するシェル関数を定義。
  3. 定義したシェル関数で sbt を起動。

親ディレクトリからファイルを探すスクリプトを作成

まずは、カレントディレクトリから親ディレクトリに向かって再帰的にファイルを探すシェルスクリプトを作成し、
パスが通っている場所(/usr/local/binとか)にお好みの名前で置いて実行権限を付けておきます。

ここでは /usr/local/bin/pfind(Parent FIND) と言う名前で、↓な感じでシェルスクリプトを作ります。
特に特定のライブラリなどは使ってないので、Bashさえ動く環境であれば使えるはずです。
ちなみに、このシェルスクリプトは sbt 専用でもないので汎用的に使えます。

シェルプログラミングが得意な方ならもっとシンプルに書けると思いますが...
と言うか親ディレクトリからファイルを探すコマンドってないのかな

#!/bin/bash

find_in_parents () {
  slashes=${PWD//[^\/]/}
  directory=$BASE_DIR
  for (( n=${#slashes}; n>0; --n ))
  do
    test -e "$directory/$FILE" && echo "$directory" && return
    directory="$directory../"
  done

  # Not found.
  exit -1
}

show_usage() {
  echo "Find file recursively in the parent directory."
  echo ""
  echo "Usage: "
  echo "  pfind -f FILE -b BASE_DIR -p"
  echo "    -f: Target file name."
  echo "    -b: Base directory for starting search. (OPTIONAL Default current directory)"
  echo "    -p: With file name.(OPTIONAL Default direcotry only)"
  echo "Exampe:"
  echo " pfind -f foobar.txt"
  echo " pfind -f foobar.txt -b /foo/bar"
  echo " pfind -f foobar.txt -b /foo/bar -p"
  echo ""

  exit -1
}

while getopts f:b:p OPT
do
  case $OPT in
    f) FILE=$OPTARG
      ;;
    b) BASE_DIR=$OPTARG
       ;;
    p) WITH_FILE=true
  esac
done
[ "$FILE" == "" ] && show_usage
[ "$BASE_DIR" == "" ] && BASE_DIR=`pwd`/
[ "$WITH_FILE" == "" ] && WITH_FILE=false

FOUND_DIR=`find_in_parents`
RC=$?
if [ $RC == 0 ]; then
  if $WITH_FILE ; then
    echo `(cd $FOUND_DIR; pwd)`/$FILE
  else
    echo `(cd $FOUND_DIR; pwd)`
  fi
else
  echo "$FILE not found." >&2
  exit $RC
fi

使い方はこんな感じになります。(/Users/xxxx/work/example/build.sbtがある例)

$ pwd
/Users/xxxx/work/example/src/main/resources

$ pfind -f build.sbt
/Users/xxxx/work/example

$ pfind -f build.sbt -p
/Users/xxxx/work/example/build.sbt

build.sbtを探してsbtを起動するシェル関数を定義

↑で作成したシェルスクリプトを使って build.sbt を探し、見つかったディレクトリで sbt を起動するシェル関数を定義します。
これまた関数名はお好みで。ここでは ssbt(特に意味なし) って名前にしています。

エイリアスでも良いですが、エイリアスだと sbt にパラメタを渡すことができないのでシェル関数にしておくのが吉です。

~/.bashrc
function ssbt() {
  BUILDSBT_IN_DIR=`pfind -f build.sbt`
  RC=$?
  if [ $RC == 0 ]; then
    (cd $BUILDSBT_IN_DIR; echo "build.sbt found in `pwd`"; sbt $@)
  else
    echo "build.sbt not found."
  fi
}
  • cdしてからsbt起動は、( )で囲んで書いておけば build.sbt の場所にカレントディレクトリが移動しないので使いやすいと思います。
  • $@ でパラメタを sbt に渡します。

zshな人はこんな感じ。(ifの構文が違う)

~/.zshrc
function ssbt() {
  BUILDSBT_IN_DIR=`pfind -f build.sbt`
  RC=$?
  if [[ $RC -eq 0 ]]; then
    (cd $BUILDSBT_IN_DIR; echo "build.sbt found in `pwd`"; sbt $@)
  else
    echo "build.sbt not found."
  fi
}

sbtを起動

これで build.sbt を置いてあるディレクトリの下からであれば、どこからでも sbt を起動できます。

$ pwd
/Users/xxxx/work/example/src/main/resources

$ ssbt
build.sbt found in /Users/xxxx/work/example
[info] Loading global plugins from /Users/xxxx/.sbt/0.13/plugins
[info] Loading project definition from /Users/xxxx/work/example/project
> 

# パラメタを指定することもできます
$ ssbt clean compile

以上です。

4
1
0

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
4
1