summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/cmd/FromString.scala
blob: ab49c7507c616bb804c1f102d2bf24f01db19ba6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/* NSC -- new Scala compiler
 * Copyright 2005-2013 LAMP/EPFL
 * @author  Paul Phillips
 */

package scala.tools
package cmd

import nsc.io.Directory
import scala.reflect.OptManifest

/** A general mechanism for defining how a command line argument
 *  (always a String) is transformed into an arbitrary type.  A few
 *  example instances are in the companion object, but in general
 *  either IntFromString will suffice or you'll want custom transformers.
 */
abstract class FromString[+T](implicit m: OptManifest[T]) extends PartialFunction[String, T] {
  def apply(s: String): T
  def isDefinedAt(s: String): Boolean = true
  def zero: T = apply("")

  def targetString: String = m.toString
}

object FromString {
  // We need this because we clash with the String => Path implicits.
  private def toDir(s: String)  = new Directory(new java.io.File(s))

  /** Path related stringifiers.
   */
  val ExistingDir: FromString[Directory] = new FromString[Directory] {
    override def isDefinedAt(s: String) = toDir(s).isDirectory
    def apply(s: String): Directory =
      if (isDefinedAt(s)) toDir(s)
      else cmd.runAndExit(println("'%s' is not an existing directory." format s))
  }
  def ExistingDirRelativeTo(root: Directory) = new FromString[Directory] {
    private def resolve(s: String) = (toDir(s) toAbsoluteWithRoot root).toDirectory
    override def isDefinedAt(s: String) = resolve(s).isDirectory
    def apply(s: String): Directory =
      if (isDefinedAt(s)) resolve(s)
      else cmd.runAndExit(println("'%s' is not an existing directory." format resolve(s)))
  }

  /** Argument expander, i.e. turns single argument "foo bar baz" into argument
   *  list "foo", "bar", "baz".
   */
  val ArgumentsFromString: FromString[List[String]] = new FromString[List[String]] {
    def apply(s: String) = toArgs(s)
  }

  /** Identity.
   */
  implicit val StringFromString: FromString[String] = new FromString[String] {
    def apply(s: String): String = s
  }

  /** Implicit as the most likely to be useful as-is.
   */
  implicit val IntFromString: FromString[Int] = new FromString[Int] {
    override def isDefinedAt(s: String)   = safeToInt(s).isDefined
    def apply(s: String)                  = safeToInt(s).get
    def safeToInt(s: String): Option[Int] = try Some(java.lang.Integer.parseInt(s)) catch { case _: NumberFormatException => None }
  }
}