A Scala implementation of a very small subset of the widely known TCL expect.
Scala Expect comes with three different flavors: core
, fluent
and dsl
.
libraryDependencies += "work.martins.simon" %% "scala-expect" % "6.0.0"
- Closer to metal / basis for the other flavors.
- Immutable and therefore thread-safe.
- Most errors will be caught at compile time (eg. you won't be able to use a
SendWithRegex
inside aStringWhen
).
- Verbose syntax.
- Can't cleanly add expect blocks/whens/actions based on a condition.
import work.martins.simon.core._
import scala.concurrent.ExecutionContext.Implicits.global
val e = new Expect("bc -i", defaultValue = 5)(
ExpectBlock(
StringWhen("For details type `warranty'.")(
Sendln("1 + 2")
)
),
ExpectBlock(
RegexWhen("""\n(\d+)\n""".r)(
SendlnWithRegex { m =>
val previousAnswer = m.group(1)
println(s"Got $previousAnswer")
s"$previousAnswer + 3"
}
)
),
ExpectBlock(
RegexWhen("""\n(\d+)\n""".r)(
ReturningWithRegex(_.group(1).toInt)
)
)
)
e.run() //Returns 6 inside a Future[Int]
- Less verbose syntax:
- StringWhen, RegexWhen, etc is just
when
. - Returning, ReturningWithRegex, etc is just
returning
. - Less commas and parenthesis.
- StringWhen, RegexWhen, etc is just
- Most errors will be caught at compile time.
- Easy to add expect blocks/whens/actions based on a condition.
- Easy to refactor the creation of expects.
- Can be called from Java easily.
- Some overhead since the fluent expect is just a builder for a core expect.
- Mutable - the fluent expect has to maintain a state of the objects that have been built.
- IDE's will easily mess the custom indentation.
import work.martins.simon.fluent._
import scala.concurrent.ExecutionContext.Implicits.global
val e = new Expect("bc -i", defaultValue = 5) {
expect
.when("For details type `warranty'.")
.sendln("1 + 2")
expect
.when("""\n(\d+)\n""".r)
.sendln { m =>
val previousAnswer = m.group(1)
println(s"Got $previousAnswer")
s"$previousAnswer + 3"
}
//This is a shortcut. It works just like the previous expect block.
expect("""\n(\d+)\n""".r)
.returning(_.group(1).toInt)
}
e.run() //Returns 6 inside a Future[Int]
- Code will be indented in blocks so IDE's won't mess the indentation.
- Syntax more close to the TCL expect.
- Easy to add expect blocks/whens/actions based on a condition.
- Easy to refactor the creation of expects.
- Most errors will only be caught at runtime as opposed to compile time.
- More overhead than the fluent expect since it's just a wrapper arround fluent expect.
- Mutable - it uses a fluent expect as the backing expect and a mutable stack to keep track of the current context.
import work.martins.simon.dsl._
import scala.concurrent.ExecutionContext.Implicits.global
val e = new Expect("bc -i", defaultValue = 5) {
expect {
when("For details type `warranty'.") {
sendln("1 + 2")
}
}
expect {
when("""\n(\d+)\n""".r) {
sendln { m =>
val previousAnswer = m.group(1)
println(s"Got $previousAnswer")
s"$previousAnswer + 3"
}
}
}
//This is a shortcut. It works just like the previous expect block.
expect("""\n(\d+)\n""".r) {
returning(_.group(1).toInt)
}
}
e.run() //Returns 6 inside a Future[Int]
Scala Expect is open source and available under the MIT license.