Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Continuation monad and generalizations #302

Closed
wants to merge 3 commits into from

2 participants

@pthariensflame

This pull request implements the indexed multi-continuation monad transformer IndexedContsT, as well as providing type synonyms for common specializations.

Unfortunately, I was unable to provide a MonadTrans instance and still maintain variance in the type parameters, and a Hoist instance is completely out of the question. liftM is, at least, implemented with the necessary additional variance annotations in IndexedContsTFunctions.

@larsrh

Could you please rebase this pull request to the latest HEAD so that we can get rid of the merge commit?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
148 core/src/main/scala/scalaz/IndexedContsT.scala
@@ -0,0 +1,148 @@
+package scalaz
+
+sealed trait IndexedContsT[W[+_], M[+_], +R, -O, +A] {
+ def run(wamo: W[A => M[O]]): M[R]
+
+ def apply(wamo: W[A => M[O]]): M[R] = run(wamo)
+
+ def run_(implicit W: Applicative[W], M: Applicative[M], ev: A <:< O): M[R] = run(W.point(x => M.point(x)))
+
+ def map[B](f: A => B)(implicit W: Functor[W]): IndexedContsT[W, M, R, O, B] = IndexedContsT { wbmo =>
+ run(W.map(wbmo)(f andThen _))
+ }
+
+ def flatten[E, B](implicit ev: A <:< IndexedContsT[W, M, O, E, B], W: Cobind[W]): IndexedContsT[W, M, R, E, B] = flatMap(ev)
+
+ def flatMap[E, B](f: A => IndexedContsT[W, M, O, E, B])(implicit W: Cobind[W]): IndexedContsT[W, M, R, E, B] = IndexedContsT { wbme =>
+ run(W.cobind(wbme) { wk => { a =>
+ f(a).run(wk)
+ } })
+ }
+
+ def contramap[I](f: I => O)(implicit M: Functor[M], W: Functor[W]): IndexedContsT[W, M, R, I, A] = IndexedContsT { wami =>
+ run(W.map(wami) { ami => { a => M.map(ami(a))(f) } })
+ }
+
+ def imap[E](f: R => E)(implicit M: Functor[M]): IndexedContsT[W, M, E, O, A] = IndexedContsT { wamo =>
+ M.map(run(wamo))(f)
+ }
+
+ def bimap[E, B](f: R => E, g: A => B)(implicit M: Functor[M], W: Functor[W]): IndexedContsT[W, M, E, O, B] = IndexedContsT { wbmo =>
+ M.map(run(W.map(wbmo)(g andThen _)))(f)
+ }
+
+ def xmap[E, I](f: R => E, g: I => O)(implicit M: Functor[M], W: Functor[W]): IndexedContsT[W, M, E, I, A] = IndexedContsT { wami =>
+ M.map(run(W.map(wami) { ami => { a => M.map(ami(a))(g) } }))(f)
+ }
+
+ import BijectionT._
+
+ def bmap[X >: R <: O, Z](f: Bijection[X, Z])(implicit M: Functor[M], W: Functor[W]): ContsT[W, M, Z, A] = IndexedContsT { wami =>
+ M.map(run(W.map(wami) { ami => { a => M.map(ami(a))(f from _) } }))(f to _)
+ }
+}
+
+object IndexedContsT extends IndexedContsTFunctions with IndexedContsTInstances {
+ def apply[W[+_], M[+_], R, O, A](f: W[A => M[O]] => M[R]): IndexedContsT[W, M, R, O, A] = new IndexedContsT[W, M, R, O, A] {
+ def run(wamo: W[A => M[O]]): M[R] = f(wamo)
+ }
+}
+
+trait IndexedContsTFunctions {
+ def point[W[+_], M[+_], R, A](a: => A)(implicit W: Comonad[W]): ContsT[W, M, R, A] = ContsT { k => W.copoint(k)(a) }
+
+ def liftM[W[+_], M[+_], R, O, A](a: => M[A])(implicit W: Comonad[W], M: Bind[M]): ContsT[W, M, R, A] = ContsT { k => M.bind(a)(W.copoint(k)) }
+
+ def shift[W[+_], M[+_], I, R, J, O, A](f: (A => IndexedContsT[W, M, I, I, O]) => IndexedContsT[W, M, R, J, J])(implicit W: Comonad[W], WA: Applicative[W], M: Monad[M]): IndexedContsT[W, M, R, O, A] =
+ IndexedContsT { k0 =>
+ (f { a =>
+ IndexedContsT { k1 =>
+ M.bind(W.copoint(k0)(a))(W.copoint(k1))
+ }
+ }).run_
+ }
+
+ def reset[W[+_], M[+_], R, O, A](v: IndexedContsT[W, M, A, O, O])(implicit W: Comonad[W], WA: Applicative[W], M: Monad[M]): IndexedContsT[W, M, R, R, A] =
+ IndexedContsT { k =>
+ M.bind(v.run_)(W.copoint(k))
+ }
+
+ def callCC[W[+_], M[+_], R, O, A](f: (A => IndexedContsT[W, M, Any, O, Nothing]) => IndexedContsT[W, M, R, O, A])(implicit W: Comonad[W]): IndexedContsT[W, M, R, O, A] =
+ IndexedContsT { k =>
+ (f { a =>
+ IndexedContsT { u =>
+ W.copoint(k)(a)
+ }
+ }).run(k)
+ }
+}
+
+trait IndexedContsTInstances0 {
+ implicit def IndexedContsTFunctorRight[W[+_], M[+_], R, O](implicit W0: Functor[W]): Functor[({type f[+a]=IndexedContsT[W, M, R, O, a]})#f] = new IndexedContsTFunctorRight[W, M, R, O] {
+ implicit val W: Functor[W] = W0
+ }
+}
+
+trait IndexedContsTInstances extends IndexedContsTInstances0 {
+ implicit def IndexedContsTFunctorLeft[W[+_], M[+_], O, A](implicit M0: Functor[M]): Functor[({type f[+r]=IndexedContsT[W, M, r, O, A]})#f] = new IndexedContsTFunctorLeft[W, M, O, A] {
+ implicit val M: Functor[M] = M0
+ }
+
+ implicit def IndexedContsTContravariant[W[+_], M[+_], R, A](implicit W0: Functor[W], M0: Functor[M]): Contravariant[({type f[-o]=IndexedContsT[W, M, R, o, A]})#f] = new IndexedContsTContravariant[W, M, R, A] {
+ implicit val W: Functor[W] = W0
+ implicit val M: Functor[M] = M0
+ }
+
+ implicit def IndexedContsTBifunctor[W[+_], M[+_], O](implicit W0: Functor[W], M0: Functor[M]): Bifunctor[({type f[+r, +a]=IndexedContsT[W, M, r, O, a]})#f] = new IndexedContsTBifunctor[W, M, O] {
+ implicit val W: Functor[W] = W0
+ implicit val M: Functor[M] = M0
+ }
+
+ implicit def ContsTMonad[W[+_], M[+_], R](implicit W0: Comonad[W]): Monad[({type f[+a]=ContsT[W, M, R, a]})#f] = new ContsTMonad[W, M, R] {
+ implicit val W: Comonad[W] = W0
+ }
+}
+
+private[scalaz] sealed trait IndexedContsTFunctorLeft[W[+_], M[+_], O, A0] extends Functor[({type f[+r]=IndexedContsT[W, M, r, O, A0]})#f] {
+ implicit val M: Functor[M]
+
+ def map[A, B](fa: IndexedContsT[W, M, A, O, A0])(f: A => B): IndexedContsT[W, M, B, O, A0] = fa.imap(f)
+}
+
+private[scalaz] sealed trait IndexedContsTFunctorRight[W[+_], M[+_], R, O] extends Functor[({type f[+a]=IndexedContsT[W, M, R, O, a]})#f] {
+ implicit val W: Functor[W]
+
+ override def map[A, B](fa: IndexedContsT[W, M, R, O, A])(f: A => B): IndexedContsT[W, M, R, O, B] = fa.map(f)
+}
+
+private[scalaz] sealed trait IndexedContsTContravariant[W[+_], M[+_], R, A0] extends Contravariant[({type f[-o]=IndexedContsT[W, M, R, o, A0]})#f] {
+ implicit val W: Functor[W]
+ implicit val M: Functor[M]
+
+ def contramap[A, B](fa: IndexedContsT[W, M, R, A, A0])(f: B => A): IndexedContsT[W, M, R, B, A0] = fa.contramap(f)
+}
+
+private[scalaz] sealed trait IndexedContsTBifunctor[W[+_], M[+_], O] extends Bifunctor[({type f[+r, +a]=IndexedContsT[W, M, r, O, a]})#f] {
+ implicit val W: Functor[W]
+ implicit val M: Functor[M]
+
+ def bimap[A, B, C, D](fab: IndexedContsT[W, M, A, O, B])(f: A => C, g: B => D): IndexedContsT[W, M, C, O, D] = fab.bimap(f, g)
+
+ override def leftFunctor[X]: Functor[({type f[+r]=IndexedContsT[W, M, r, O, X]})#f] = IndexedContsT.IndexedContsTFunctorLeft
+
+ override def leftMap[A, B, C](fa: IndexedContsT[W, M, A, O, B])(f: A => C): IndexedContsT[W, M, C, O, B] = fa.imap(f)
+
+ override def rightFunctor[X]: Functor[({type f[+a]=IndexedContsT[W, M, X, O, a]})#f] = IndexedContsT.IndexedContsTFunctorRight
+
+ override def rightMap[A, B, D](fa: IndexedContsT[W, M, A, O, B])(f: B => D): IndexedContsT[W, M, A, O, D] = fa.map(f)
+}
+
+private[scalaz] sealed trait ContsTMonad[W[+_], M[+_], R] extends Monad[({type f[+a]=ContsT[W, M, R, a]})#f] with IndexedContsTFunctorRight[W, M, R, R] {
+ implicit val W: Comonad[W]
+
+ def point[A](a: => A): ContsT[W, M, R, A] = IndexedContsT.point(a)
+
+ def bind[A, B](fa: ContsT[W, M, R, A])(f: A => ContsT[W, M, R, B]): ContsT[W, M, R, B] = fa.flatMap(f)
+
+ override def join[A](ffa: ContsT[W, M, R, ContsT[W, M, R, A]]): ContsT[W, M, R, A] = ffa.flatten
+}
View
29 core/src/main/scala/scalaz/package.scala
@@ -240,4 +240,33 @@ package object scalaz {
type PIndexedState[-S1, +S2, +A] = PIndexedStateT[Id, S1, S2, A]
type PState[S, +A] = PStateT[Id, S, A]
+
+ type IndexedConts[W[+_], +R, -O, +A] = IndexedContsT[W, Id, R, O, A]
+ object IndexedConts extends IndexedContsTFunctions with IndexedContsTInstances {
+ def apply[W[+_], R, O, A](f: W[A => O] => R): IndexedConts[W, R, O, A] = IndexedContsT[W, Id, R, O, A](f)
+ }
+ type IndexedContT[M[+_], +R, -O, +A] = IndexedContsT[Id, M, R, O, A]
+ object IndexedContT extends IndexedContsTFunctions with IndexedContsTInstances {
+ def apply[M[+_], R, O, A](f: (A => M[O]) => M[R]): IndexedContT[M, R, O, A] = IndexedContsT[Id, M, R, O, A](f)
+ }
+ type IndexedCont[+R, -O, +A] = IndexedContT[Id, R, O, A]
+ object IndexedCont extends IndexedContsTFunctions with IndexedContsTInstances {
+ def apply[W[+_], R, O, A](f: (A => O) => R): IndexedCont[R, O, A] = IndexedContsT[Id, Id, R, O, A](f)
+ }
+ type ContsT[W[+_], M[+_], R, +A] = IndexedContsT[W, M, R, R, A]
+ object ContsT extends IndexedContsTFunctions with IndexedContsTInstances {
+ def apply[W[+_], M[+_], R, A](f: W[A => M[R]] => M[R]): ContsT[W, M, R, A] = IndexedContsT[W, M, R, R, A](f)
+ }
+ type Conts[W[+_], R, +A] = ContsT[W, Id, R, A]
+ object Conts extends IndexedContsTFunctions with IndexedContsTInstances {
+ def apply[W[+_], R, A](f: W[A => R] => R): Conts[W, R, A] = IndexedContsT[W, Id, R, R, A](f)
+ }
+ type ContT[M[+_], R, +A] = ContsT[Id, M, R, A]
+ object ContT extends IndexedContsTFunctions with IndexedContsTInstances {
+ def apply[M[+_], R, A](f: (A => M[R]) => M[R]): ContT[M, R, A] = IndexedContsT[Id, M, R, R, A](f)
+ }
+ type Cont[R, +A] = ContT[Id, R, A]
+ object Cont extends IndexedContsTFunctions with IndexedContsTInstances {
+ def apply[R, A](f: (A => R) => R): Cont[R, A] = IndexedContsT[Id, Id, R, R, A](f)
+ }
}
View
175 sbt
@@ -7,9 +7,9 @@
declare -r sbt_release_version=0.12.2
declare -r sbt_snapshot_version=0.13.0-SNAPSHOT
-unset sbt_jar sbt_dir sbt_create sbt_snapshot sbt_launch_dir
-unset scala_version java_home sbt_explicit_version
-unset verbose debug quiet noshare trace_level log_level
+declare sbt_jar sbt_dir sbt_create sbt_snapshot sbt_launch_dir
+declare scala_version java_home sbt_explicit_version
+declare verbose debug quiet noshare batch trace_level log_level
for arg in "$@"; do
case $arg in
@@ -19,7 +19,7 @@ for arg in "$@"; do
done
build_props_sbt () {
- if [[ -f project/build.properties ]]; then
+ if [[ -r project/build.properties ]]; then
versionLine=$(grep ^sbt.version project/build.properties)
versionString=${versionLine##sbt.version=}
echo "$versionString"
@@ -32,7 +32,7 @@ update_build_props_sbt () {
if [[ $ver == $old ]]; then
return
- elif [[ -f project/build.properties ]]; then
+ elif [[ -r project/build.properties ]]; then
perl -pi -e "s/^sbt\.version=.*\$/sbt.version=${ver}/" project/build.properties
grep -q '^sbt.version=' project/build.properties || echo "sbt.version=${ver}" >> project/build.properties
@@ -80,18 +80,6 @@ get_script_path () {
fi
}
-# a ham-fisted attempt to move some memory settings in concert
-# so they need not be dicked around with individually.
-get_mem_opts () {
- local mem=${1:-1536}
- local perm=$(( $mem / 4 ))
- (( $perm > 256 )) || perm=256
- (( $perm < 1024 )) || perm=1024
- local codecache=$(( $perm / 2 ))
-
- echo "-Xms${mem}m -Xmx${mem}m -XX:MaxPermSize=${perm}m -XX:ReservedCodeCacheSize=${codecache}m"
-}
-
die() {
echo "Aborting: $@"
exit 1
@@ -105,15 +93,10 @@ make_url () {
echo "http://typesafe.artifactoryonline.com/typesafe/ivy-$category/$groupid/sbt-launch/$version/sbt-launch.jar"
}
-declare -r default_jvm_opts="-Dfile.encoding=UTF8"
-declare -r default_sbt_opts="-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC"
-declare -r default_sbt_mem=1536
-declare -r default_trace_level=15
+declare -r default_jvm_opts="-Dfile.encoding=UTF8 -XX:MaxPermSize=256m -Xms512m -Xmx1g -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC"
declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy"
-declare -r sbt_opts_file=".sbtopts"
-declare -r jvm_opts_file=".jvmopts"
declare -r latest_28="2.8.2"
-declare -r latest_29="2.9.2"
+declare -r latest_29="2.9.3"
declare -r latest_210="2.10.0"
declare -r script_path=$(get_script_path "$BASH_SOURCE")
@@ -124,9 +107,9 @@ declare -r script_name="$(basename $script_path)"
declare java_cmd=java
declare sbt_launch_dir="$script_dir/.lib"
declare sbt_universal_launcher="$script_dir/lib/sbt-launch.jar"
-declare sbt_mem=$default_sbt_mem
declare sbt_jar=$sbt_universal_launcher
-declare trace_level=$default_trace_level
+declare sbt_opts_file=.sbtopts
+declare jvm_opts_file=.jvmopts
# pull -J and -D options to give to java.
declare -a residual_args
@@ -134,11 +117,17 @@ declare -a java_args
declare -a scalac_args
declare -a sbt_commands
+# args to jvm/sbt via files or environment variables
+declare -a extra_jvm_opts extra_sbt_opts
+
# if set, use JAVA_HOME over java found in path
[[ -e "$JAVA_HOME/bin/java" ]] && java_cmd="$JAVA_HOME/bin/java"
+# use ~/.sbt/launch to store sbt jars if script_dir is not writable
+[[ -w "$sbt_launch_dir" ]] || sbt_launch_dir="$HOME/.sbt/launch"
+
build_props_scala () {
- if [[ -f project/build.properties ]]; then
+ if [[ -r project/build.properties ]]; then
versionLine=$(grep ^build.scala.versions project/build.properties)
versionString=${versionLine##build.scala.versions=}
echo ${versionString%% .*}
@@ -149,16 +138,26 @@ execRunner () {
# print the arguments one to a line, quoting any containing spaces
[[ $verbose || $debug ]] && echo "# Executing command line:" && {
for arg; do
- if printf "%s\n" "$arg" | grep -q ' '; then
- printf "\"%s\"\n" "$arg"
- else
- printf "%s\n" "$arg"
+ if [[ -n "$arg" ]]; then
+ if printf "%s\n" "$arg" | grep -q ' '; then
+ printf "\"%s\"\n" "$arg"
+ else
+ printf "%s\n" "$arg"
+ fi
fi
done
echo ""
}
- exec "$@"
+ if [[ -n $batch ]]; then
+ # the only effective way I've found to avoid sbt hanging when backgrounded.
+ exec 0<&-
+ ( "$@" & )
+ # I'm sure there's some way to get our hands on the pid and wait for it
+ # but it exceeds my present level of ambition.
+ else
+ exec "$@"
+ fi
}
sbt_groupid () {
@@ -225,14 +224,14 @@ download_url () {
elif which wget >/dev/null; then
wget --quiet -O "$jar" "$url"
fi
- } && [[ -f "$jar" ]]
+ } && [[ -r "$jar" ]]
}
acquire_sbt_jar () {
sbt_url="$(jar_url)"
sbt_jar="$(jar_file $(sbt_version))"
- [[ -f "$sbt_jar" ]] || download_url "$sbt_url" "$sbt_jar"
+ [[ -r "$sbt_jar" ]] || download_url "$sbt_url" "$sbt_jar"
}
usage () {
@@ -243,14 +242,12 @@ Usage: $script_name [options]
-v | -verbose this runner is chattier
-d | -debug set sbt log level to Debug
-q | -quiet set sbt log level to Error
- -trace <level> display stack traces with a max of <level> frames (default: $default_trace_level)
+ -trace <level> display stack traces with a max of <level> frames (default: -1, traces suppressed)
-no-colors disable ANSI color codes
-sbt-create start sbt even if current directory contains no sbt project
-sbt-dir <path> path to global settings/plugins directory (default: ~/.sbt/<version>)
-sbt-boot <path> path to shared boot directory (default: ~/.sbt/boot in 0.11+)
-ivy <path> path to local Ivy repository (default: ~/.ivy2)
- -mem <integer> set memory options (default: $sbt_mem, which is
- $(get_mem_opts $sbt_mem) )
-no-share use all local caches; no sharing
-offline put sbt in offline mode
-jvm-debug <port> Turn on JVM debugging, open at the given port.
@@ -276,17 +273,18 @@ Usage: $script_name [options]
# java version (default: java from PATH, currently $(java -version |& grep version))
-java-home <path> alternate JAVA_HOME
- # jvm options and output control
- JAVA_OPTS environment variable holding jvm args, if unset uses "$default_jvm_opts"
- SBT_OPTS environment variable holding jvm args, if unset uses "$default_sbt_opts"
- .jvmopts if file is in sbt root, it is prepended to the args given to the jvm
- .sbtopts if file is in sbt root, it is prepended to the args given to **sbt**
- -Dkey=val pass -Dkey=val directly to the jvm
- -J-X pass option -X directly to the jvm (-J is stripped)
- -S-X add -X to sbt's scalacOptions (-S is stripped)
-
-In the case of duplicated or conflicting options, the order above
-shows precedence: JAVA_OPTS lowest, command line options highest.
+ # passing options to the jvm - note it does NOT use JAVA_OPTS due to pollution
+ # The default set is used if JVM_OPTS is unset and no -jvm-opts file is found
+ <default> $default_jvm_opts
+ JVM_OPTS environment variable holding jvm args
+ -jvm-opts <path> file containing jvm args (if not given, .jvmopts in project root is used if present)
+ -Dkey=val pass -Dkey=val directly to the jvm
+ -J-X pass option -X directly to the jvm (-J is stripped)
+
+ # passing options to sbt, OR to this runner
+ SBT_OPTS environment variable holding sbt args
+ -sbt-opts <path> file containing sbt args (if not given, .sbtopts in project root is used if present)
+ -S-X add -X to sbt's scalacOptions (-S is stripped)
EOM
}
@@ -319,13 +317,6 @@ setScalaVersion () {
fi
}
-get_jvm_opts () {
- # echo "${JAVA_OPTS:-$default_jvm_opts}"
- # echo "${SBT_OPTS:-$default_sbt_opts}"
-
- [[ -f "$jvm_opts_file" ]] && cat "$jvm_opts_file"
-}
-
process_args ()
{
require_arg () {
@@ -346,7 +337,6 @@ process_args ()
-trace) require_arg integer "$1" "$2" && trace_level=$2 && shift 2 ;;
-ivy) require_arg path "$1" "$2" && addJava "-Dsbt.ivy.home=$2" && shift 2 ;;
- -mem) require_arg integer "$1" "$2" && sbt_mem="$2" && shift 2 ;;
-no-colors) addJava "-Dsbt.log.noformat=true" && shift ;;
-no-share) noshare=true && shift ;;
-sbt-boot) require_arg path "$1" "$2" && addJava "-Dsbt.boot.directory=$2" && shift 2 ;;
@@ -354,7 +344,7 @@ process_args ()
-debug-inc) addJava "-Dxsbt.inc.debug=true" && shift ;;
-offline) addSbt "set offline := true" && shift ;;
-jvm-debug) require_arg port "$1" "$2" && addDebugger $2 && shift 2 ;;
- -batch) exec </dev/null && shift ;;
+ -batch) batch=true && shift ;;
-prompt) require_arg "expr" "$1" "$2" && addSbt "set shellPrompt in ThisBuild := (s => { val e = Project.extract(s) ; $2 })" && shift 2 ;;
-sbt-create) sbt_create=true && shift ;;
@@ -366,6 +356,8 @@ process_args ()
-binary-version) require_arg version "$1" "$2" && addSbt "set scalaBinaryVersion in ThisBuild := \"$2\"" && shift 2 ;;
-scala-home) require_arg path "$1" "$2" && addSbt "set every scalaHome := Some(file(\"$2\"))" && shift 2 ;;
-java-home) require_arg path "$1" "$2" && java_cmd="$2/bin/java" && shift 2 ;;
+ -sbt-opts) require_arg path "$1" "$2" && sbt_opts_file="$2" && shift 2 ;;
+ -jvm-opts) require_arg path "$1" "$2" && jvm_opts_file="$2" && shift 2 ;;
-D*) addJava "$1" && shift ;;
-J*) addJava "${1:2}" && shift ;;
@@ -379,28 +371,31 @@ process_args ()
done
}
-# if .sbtopts exists, prepend its contents to $@ so it can be processed by this runner
-[[ -f "$sbt_opts_file" ]] && {
- sbtargs=()
- while IFS= read -r arg; do
- sbtargs=( "${sbtargs[@]}" "$arg" )
- done <"$sbt_opts_file"
-
- set -- "${sbtargs[@]}" "$@"
-}
-# process the combined args, then reset "$@" to the residuals
+# process the direct command line arguments
process_args "$@"
+
+# if there are file/environment sbt_opts, process again so we
+# can supply args to this runner
+if [[ -r "$sbt_opts_file" ]]; then
+ readarray -t extra_sbt_opts < "$sbt_opts_file"
+elif [[ -n "$SBT_OPTS" ]]; then
+ extra_sbt_opts=( $SBT_OPTS )
+fi
+
+[[ -n $extra_sbt_opts ]] && process_args "${extra_sbt_opts[@]}"
+
+# reset "$@" to the residual args
set -- "${residual_args[@]}"
argumentCount=$#
-# set sbt version specific options
-case $(sbt_version) in
- 0.7.*) ;;
- 0.10.*) ;;
- 0.11.*) ;;
- *) addSbt "set every traceLevel := $trace_level" ;;
-esac
+# only exists in 0.12+
+setTraceLevel() {
+ case $(sbt_version) in
+ 0.{7,10,11}.*) echoerr "Cannot set trace level in sbt version $(sbt_version)" ;;
+ *) addSbt "set every traceLevel := $trace_level" ;;
+ esac
+}
# set scalacOptions if we were given any -S opts
[[ ${#scalac_args[@]} -eq 0 ]] || addSbt "set scalacOptions in ThisBuild += \"${scalac_args[@]}\""
@@ -415,7 +410,7 @@ echoerr "Detected sbt version $(sbt_version)"
(( $argumentCount > 0 )) || echo "Starting $script_name: invoke with -help for other options"
# verify this is an sbt dir or -create was given
-[[ -f ./build.sbt || -d ./project || -n "$sbt_create" ]] || {
+[[ -r ./build.sbt || -d ./project || -n "$sbt_create" ]] || {
cat <<EOM
$(pwd) doesn't appear to be an sbt project.
If you want to start sbt anyway, run:
@@ -426,37 +421,45 @@ EOM
}
# pick up completion if present; todo
-[[ -f .sbt_completion.sh ]] && source .sbt_completion.sh
+[[ -r .sbt_completion.sh ]] && source .sbt_completion.sh
# no jar? download it.
-[[ -f "$sbt_jar" ]] || acquire_sbt_jar || {
+[[ -r "$sbt_jar" ]] || acquire_sbt_jar || {
# still no jar? uh-oh.
echo "Download failed. Obtain the jar manually and place it at $sbt_jar"
exit 1
}
-if [[ "$noshare" -eq 1 ]]; then
+if [[ -n $noshare ]]; then
addJava "$noshare_opts"
else
[[ -n "$sbt_dir" ]] || {
sbt_dir=~/.sbt/$(sbt_version)
- echoerr "Using $sbt_dir as sbt dir, -sbt-dir to override."
+ vlog "Using $sbt_dir as sbt dir, -sbt-dir to override."
}
addJava "-Dsbt.global.base=$sbt_dir"
fi
+if [[ -r "$jvm_opts_file" ]]; then
+ readarray -t extra_jvm_opts < "$jvm_opts_file"
+elif [[ -n "$JVM_OPTS" ]]; then
+ extra_jvm_opts=( $JVM_OPTS )
+else
+ extra_jvm_opts=( $default_jvm_opts )
+fi
+
# since sbt 0.7 doesn't understand iflast
-(( ${#residual_args[@]} == 0 )) && residual_args=( "shell" )
+[[ ${#residual_args[@]} -eq 0 ]] && [[ -z "$batch" ]] && residual_args=( "shell" )
+
+# traceLevel is 0.12+
+[[ -n $trace_level ]] && setTraceLevel
-# -shell \
-# "set every traceLevel := $trace_level" \
-[[ -n $log_level ]] && logLevalArg="set logLevel in Global := Level.$log_level"
+[[ -n $log_level ]] && [[ $log_level != Info ]] && logLevalArg="set logLevel in Global := Level.$log_level"
# run sbt
execRunner "$java_cmd" \
- $(get_mem_opts $sbt_mem) \
- $(get_jvm_opts) \
- ${java_args[@]} \
+ "${extra_jvm_opts[@]}" \
+ "${java_args[@]}" \
-jar "$sbt_jar" \
"$logLevalArg" \
"${sbt_commands[@]}" \
Something went wrong with that request. Please try again.