Scala DSL - realistic looking options Subscribe Pub Share

Consolidated - originally posted on 2011/01/21.

Trying to simulate the way options are passed to unix commands via '-'.

The idea is to define a set of applicable flags and an - operator. The end result is being able to write this beauty:

rm -r -f apply "gigi.file"

Without further ado, here's the sample code:

package razie.learn.dsl.fs1

case class Flag (val c:Char) 
object r extends Flag('r')
object f extends Flag('f')

class Cmd_rm (var flags:List[Flag]) { 
  def - (f:Flag) = { flags = f :: flags; this }
  def apply (s:String) = "removing " + s
}

trait Commands {
  def rm = new Cmd_rm (Nil)
}

object CmdOptions extends Application with Commands {
  rm -r -f apply "gigi.file"

  (((rm) - r) - f) apply "gigi.file"
  rm.-(r).-(f).apply("gigi.file")
}

Try it right now here bit.ly/hb93sH.

We're limiting the flags and making this type-safe with the Flag case class. If you had more types of commands, you could limit the actual flags for each of them with custom Flag classes (like RmFlag, CpFlag etc).

The main idea is counting on scala's infix notation. The different flags accumulate in sequence and in the end, the resulting command (now with flags) is applied.

The magic of the infix notation is revealed by this equivalent form:

rm.-(r).-(f).apply("gigi.file")

Further things to consider:

  • combining options
  • simplifying away the "apply" from the syntax

This sample is available here and I wrote it while playing with a unix-looking scala shell for file management: github.com/razie/scalafs.

Content assist

The power of DSL only comes alive if the users are guided via content assist, so for instance, if I type rm - the content assist options should include all the flags applicable to rm specifically, not all options - always pay attention to that when designing DSL.

Have fun!


Was this useful?    

By: Razie | 2014-05-21 .. 2016-05-13 | Tags: post , scala , dsl , programming


See more in: Cool Scala Subscribe

Viewed 1569 times ( | History | Print ) this page.

You need to log in to post a comment! There's 1 comment(s)...

By: Razie   Reply   Report    

You can try this right now here: bit.ly/hb93sH with www.tryscala.com.