src/Pure/PIDE/resources.scala
changeset 56208 06cc31dff138
parent 55879 ac979f750c1a
child 56209 3c89e21d9be2
equal deleted inserted replaced
56207:52d5067ca06a 56208:06cc31dff138
       
     1 /*  Title:      Pure/PIDE/resources.scala
       
     2     Author:     Makarius
       
     3 
       
     4 Resources for theories and auxiliary files.
       
     5 */
       
     6 
       
     7 package isabelle
       
     8 
       
     9 
       
    10 import scala.annotation.tailrec
       
    11 
       
    12 import java.io.{File => JFile}
       
    13 
       
    14 
       
    15 object Resources
       
    16 {
       
    17   /* paths */
       
    18 
       
    19   def thy_path(path: Path): Path = path.ext("thy")
       
    20 
       
    21   def is_wellformed_thy_path(str: String): Boolean =
       
    22     try { thy_path(Path.explode(str)); true }
       
    23     catch { case ERROR(_) => false }
       
    24 }
       
    25 
       
    26 
       
    27 class Resources(val loaded_theories: Set[String] = Set.empty, val base_syntax: Outer_Syntax)
       
    28 {
       
    29   /* document node names */
       
    30 
       
    31   def node_name(raw_path: Path): Document.Node.Name =
       
    32   {
       
    33     val path = raw_path.expand
       
    34     val node = path.implode
       
    35     val theory = Thy_Header.thy_name(node).getOrElse("")
       
    36     val master_dir = if (theory == "") "" else path.dir.implode
       
    37     Document.Node.Name(node, master_dir, theory)
       
    38   }
       
    39 
       
    40 
       
    41   /* file-system operations */
       
    42 
       
    43   def append(dir: String, source_path: Path): String =
       
    44     (Path.explode(dir) + source_path).expand.implode
       
    45 
       
    46   def with_thy_text[A](name: Document.Node.Name, f: CharSequence => A): A =
       
    47   {
       
    48     val path = Path.explode(name.node)
       
    49     if (!path.is_file) error("No such file: " + path.toString)
       
    50 
       
    51     val text = File.read(path)
       
    52     Symbol.decode_strict(text)
       
    53     f(text)
       
    54   }
       
    55 
       
    56 
       
    57   /* theory files */
       
    58 
       
    59   def body_files_test(syntax: Outer_Syntax, text: String): Boolean =
       
    60     syntax.thy_load_commands.exists({ case (cmd, _) => text.containsSlice(cmd) })
       
    61 
       
    62   def body_files(syntax: Outer_Syntax, text: String): List[String] =
       
    63   {
       
    64     val spans = Thy_Syntax.parse_spans(syntax.scan(text))
       
    65     spans.iterator.map(Thy_Syntax.span_files(syntax, _)).flatten.toList
       
    66   }
       
    67 
       
    68   def import_name(master: Document.Node.Name, s: String): Document.Node.Name =
       
    69   {
       
    70     val theory = Thy_Header.base_name(s)
       
    71     if (loaded_theories(theory)) Document.Node.Name(theory + ".thy", "", theory)
       
    72     else {
       
    73       val path = Path.explode(s)
       
    74       val node = append(master.master_dir, Resources.thy_path(path))
       
    75       val master_dir = append(master.master_dir, path.dir)
       
    76       Document.Node.Name(node, master_dir, theory)
       
    77     }
       
    78   }
       
    79 
       
    80   def check_thy_text(name: Document.Node.Name, text: CharSequence): Document.Node.Header =
       
    81   {
       
    82     try {
       
    83       val header = Thy_Header.read(text)
       
    84 
       
    85       val name1 = header.name
       
    86       if (name.theory != name1)
       
    87         error("Bad file name " + Resources.thy_path(Path.basic(name.theory)) +
       
    88           " for theory " + quote(name1))
       
    89 
       
    90       val imports = header.imports.map(import_name(name, _))
       
    91       Document.Node.Header(imports, header.keywords, Nil)
       
    92     }
       
    93     catch { case exn: Throwable => Document.Node.bad_header(Exn.message(exn)) }
       
    94   }
       
    95 
       
    96   def check_thy(name: Document.Node.Name): Document.Node.Header =
       
    97     with_thy_text(name, check_thy_text(name, _))
       
    98 
       
    99 
       
   100   /* theory text edits */
       
   101 
       
   102   def text_edits(
       
   103     reparse_limit: Int,
       
   104     previous: Document.Version,
       
   105     doc_blobs: Document.Blobs,
       
   106     edits: List[Document.Edit_Text]): (Boolean, List[Document.Edit_Command], Document.Version) =
       
   107     Thy_Syntax.text_edits(this, reparse_limit, previous, doc_blobs, edits)
       
   108 
       
   109   def syntax_changed() { }
       
   110 }
       
   111