src/Pure/System/isabelle_tool.scala
changeset 75393 87ebf5a50283
parent 75377 4ce7d95612cb
child 75394 42267c650205
equal deleted inserted replaced
75388:b3ca4a6ed74b 75393:87ebf5a50283
    10 import java.net.URLClassLoader
    10 import java.net.URLClassLoader
    11 import scala.reflect.runtime.universe
    11 import scala.reflect.runtime.universe
    12 import scala.tools.reflect.{ToolBox, ToolBoxError}
    12 import scala.tools.reflect.{ToolBox, ToolBoxError}
    13 
    13 
    14 
    14 
    15 object Isabelle_Tool
    15 object Isabelle_Tool {
    16 {
       
    17   /* Scala source tools */
    16   /* Scala source tools */
    18 
    17 
    19   abstract class Body extends Function[List[String], Unit]
    18   abstract class Body extends Function[List[String], Unit]
    20 
    19 
    21   private def compile(path: Path): Body =
    20   private def compile(path: Path): Body = {
    22   {
       
    23     def err(msg: String): Nothing =
    21     def err(msg: String): Nothing =
    24       cat_error(msg, "The error(s) above occurred in Isabelle/Scala tool " + path)
    22       cat_error(msg, "The error(s) above occurred in Isabelle/Scala tool " + path)
    25 
    23 
    26     val source = File.read(path)
    24     val source = File.read(path)
    27 
    25 
    56 
    54 
    57   /* external tools */
    55   /* external tools */
    58 
    56 
    59   private def dirs(): List[Path] = Path.split(Isabelle_System.getenv_strict("ISABELLE_TOOLS"))
    57   private def dirs(): List[Path] = Path.split(Isabelle_System.getenv_strict("ISABELLE_TOOLS"))
    60 
    58 
    61   private def is_external(dir: Path, file_name: String): Boolean =
    59   private def is_external(dir: Path, file_name: String): Boolean = {
    62   {
       
    63     val file = (dir + Path.explode(file_name)).file
    60     val file = (dir + Path.explode(file_name)).file
    64     try {
    61     try {
    65       file.isFile && file.canRead &&
    62       file.isFile && file.canRead &&
    66         (file_name.endsWith(".scala") || file.canExecute) &&
    63         (file_name.endsWith(".scala") || file.canExecute) &&
    67         !file_name.endsWith("~") && !file_name.endsWith(".orig")
    64         !file_name.endsWith("~") && !file_name.endsWith(".orig")
    72   private def find_external(name: String): Option[List[String] => Unit] =
    69   private def find_external(name: String): Option[List[String] => Unit] =
    73     dirs().collectFirst({
    70     dirs().collectFirst({
    74       case dir if is_external(dir, name + ".scala") =>
    71       case dir if is_external(dir, name + ".scala") =>
    75         compile(dir + Path.explode(name + ".scala"))
    72         compile(dir + Path.explode(name + ".scala"))
    76       case dir if is_external(dir, name) =>
    73       case dir if is_external(dir, name) =>
    77         (args: List[String]) =>
    74         (args: List[String]) => {
    78           {
    75           val tool = dir + Path.explode(name)
    79             val tool = dir + Path.explode(name)
    76           val result = Isabelle_System.bash(File.bash_path(tool) + " " + Bash.strings(args))
    80             val result = Isabelle_System.bash(File.bash_path(tool) + " " + Bash.strings(args))
    77           sys.exit(result.print_stdout.rc)
    81             sys.exit(result.print_stdout.rc)
    78         }
    82           }
       
    83     })
    79     })
    84 
    80 
    85 
    81 
    86   /* internal tools */
    82   /* internal tools */
    87 
    83 
    95       })
    91       })
    96 
    92 
    97 
    93 
    98   /* list tools */
    94   /* list tools */
    99 
    95 
   100   abstract class Entry
    96   abstract class Entry {
   101   {
       
   102     def name: String
    97     def name: String
   103     def position: Properties.T
    98     def position: Properties.T
   104     def description: String
    99     def description: String
   105     def print: String =
   100     def print: String =
   106       description match {
   101       description match {
   107         case "" => name
   102         case "" => name
   108         case descr => name + " - " + descr
   103         case descr => name + " - " + descr
   109       }
   104       }
   110   }
   105   }
   111 
   106 
   112   sealed case class External(name: String, path: Path) extends Entry
   107   sealed case class External(name: String, path: Path) extends Entry {
   113   {
       
   114     def position: Properties.T = Position.File(path.absolute.implode)
   108     def position: Properties.T = Position.File(path.absolute.implode)
   115     def description: String =
   109     def description: String = {
   116     {
       
   117       val Pattern = """.*\bDESCRIPTION: *(.*)""".r
   110       val Pattern = """.*\bDESCRIPTION: *(.*)""".r
   118       split_lines(File.read(path)).collectFirst({ case Pattern(s) => s }) getOrElse ""
   111       split_lines(File.read(path)).collectFirst({ case Pattern(s) => s }) getOrElse ""
   119     }
   112     }
   120   }
   113   }
   121 
   114 
   122   def external_tools(): List[External] =
   115   def external_tools(): List[External] = {
   123   {
       
   124     for {
   116     for {
   125       dir <- dirs() if dir.is_dir
   117       dir <- dirs() if dir.is_dir
   126       file_name <- File.read_dir(dir) if is_external(dir, file_name)
   118       file_name <- File.read_dir(dir) if is_external(dir, file_name)
   127     } yield {
   119     } yield {
   128       val path = dir + Path.explode(file_name)
   120       val path = dir + Path.explode(file_name)
   132   }
   124   }
   133 
   125 
   134   def isabelle_tools(): List[Entry] =
   126   def isabelle_tools(): List[Entry] =
   135     (external_tools() ::: internal_tools).sortBy(_.name)
   127     (external_tools() ::: internal_tools).sortBy(_.name)
   136 
   128 
   137   object Isabelle_Tools extends Scala.Fun_String("isabelle_tools")
   129   object Isabelle_Tools extends Scala.Fun_String("isabelle_tools") {
   138   {
       
   139     val here = Scala_Project.here
   130     val here = Scala_Project.here
   140     def apply(arg: String): String =
   131     def apply(arg: String): String =
   141       if (arg.nonEmpty) error("Bad argument: " + quote(arg))
   132       if (arg.nonEmpty) error("Bad argument: " + quote(arg))
   142       else {
   133       else {
   143         val result = isabelle_tools().map(entry => (entry.name, entry.position))
   134         val result = isabelle_tools().map(entry => (entry.name, entry.position))
   147   }
   138   }
   148 
   139 
   149 
   140 
   150   /* command line entry point */
   141   /* command line entry point */
   151 
   142 
   152   def main(args: Array[String]): Unit =
   143   def main(args: Array[String]): Unit = {
   153   {
       
   154     Command_Line.tool {
   144     Command_Line.tool {
   155       args.toList match {
   145       args.toList match {
   156         case Nil | List("-?") =>
   146         case Nil | List("-?") =>
   157           val tool_descriptions = isabelle_tools().map(_.print)
   147           val tool_descriptions = isabelle_tools().map(_.print)
   158           Getopts("""
   148           Getopts("""
   173 
   163 
   174 sealed case class Isabelle_Tool(
   164 sealed case class Isabelle_Tool(
   175   name: String,
   165   name: String,
   176   description: String,
   166   description: String,
   177   here: Scala_Project.Here,
   167   here: Scala_Project.Here,
   178   body: List[String] => Unit) extends Isabelle_Tool.Entry
   168   body: List[String] => Unit
   179 {
   169 ) extends Isabelle_Tool.Entry {
   180   def position: Position.T = here.position
   170   def position: Position.T = here.position
   181 }
   171 }
   182 
   172 
   183 class Isabelle_Scala_Tools(val tools: Isabelle_Tool*) extends Isabelle_System.Service
   173 class Isabelle_Scala_Tools(val tools: Isabelle_Tool*) extends Isabelle_System.Service
   184 
   174