src/Pure/System/options.scala
changeset 67845 46fa8c2c142a
parent 67178 70576478bda9
child 67847 c61acb4855b6
equal deleted inserted replaced
67844:7f82445e8f0e 67845:46fa8c2c142a
    66 
    66 
    67   private val SECTION = "section"
    67   private val SECTION = "section"
    68   private val PUBLIC = "public"
    68   private val PUBLIC = "public"
    69   private val OPTION = "option"
    69   private val OPTION = "option"
    70   private val OPTIONS = Path.explode("etc/options")
    70   private val OPTIONS = Path.explode("etc/options")
    71   private val PREFS_DIR = Path.explode("$ISABELLE_HOME_USER/etc")
    71   private val PREFS = Path.explode("$ISABELLE_HOME_USER/etc/preferences")
    72   private val PREFS = PREFS_DIR + Path.basic("preferences")
       
    73 
    72 
    74   val options_syntax =
    73   val options_syntax =
    75     Outer_Syntax.empty + ":" + "=" + "--" + Symbol.comment + Symbol.comment_decoded +
    74     Outer_Syntax.empty + ":" + "=" + "--" + Symbol.comment + Symbol.comment_decoded +
    76       (SECTION, Keyword.DOCUMENT_HEADING) +
    75       (SECTION, Keyword.DOCUMENT_HEADING) +
    77       (PUBLIC, Keyword.BEFORE_COMMAND) +
    76       (PUBLIC, Keyword.BEFORE_COMMAND) +
   108     {
   107     {
   109       option_name ~ ($$$("=") ~! option_value) ^^
   108       option_name ~ ($$$("=") ~! option_value) ^^
   110       { case a ~ (_ ~ b) => (options: Options) => options.add_permissive(a, b) }
   109       { case a ~ (_ ~ b) => (options: Options) => options.add_permissive(a, b) }
   111     }
   110     }
   112 
   111 
   113     def parse_file(syntax: Outer_Syntax, parser: Parser[Options => Options],
   112     def parse_file(options: Options, file_name: String, content: String,
   114       options: Options, file: Path): Options =
   113       syntax: Outer_Syntax = options_syntax,
   115     {
   114       parser: Parser[Options => Options] = option_entry): Options =
   116       val toks = Token.explode(syntax.keywords, File.read(file))
   115     {
       
   116       val toks = Token.explode(syntax.keywords, content)
   117       val ops =
   117       val ops =
   118         parse_all(rep(parser), Token.reader(toks, Token.Pos.file(file.implode))) match {
   118         parse_all(rep(parser), Token.reader(toks, Token.Pos.file(file_name))) match {
   119           case Success(result, _) => result
   119           case Success(result, _) => result
   120           case bad => error(bad.toString)
   120           case bad => error(bad.toString)
   121         }
   121         }
   122       try { (options.set_section("") /: ops) { case (opts, op) => op(opts) } }
   122       try { (options.set_section("") /: ops) { case (opts, op) => op(opts) } }
   123       catch { case ERROR(msg) => error(msg + Position.here(file.position)) }
   123       catch { case ERROR(msg) => error(msg + Position.File(file_name)) }
   124     }
   124     }
   125   }
   125 
   126 
   126     def parse_prefs(options: Options, content: String): Options =
   127   def load(file: Path): Options =
   127       parse_file(options, PREFS.base_name, content, syntax = prefs_syntax, parser = prefs_entry)
   128     Parser.parse_file(options_syntax, Parser.option_entry, empty, file)
   128   }
   129 
   129 
   130   def init_defaults(): Options =
   130   def read_prefs(file: Path = PREFS): String =
       
   131     if (file.is_file) File.read(file) else ""
       
   132 
       
   133   def init(prefs: String = read_prefs(PREFS)): Options =
   131   {
   134   {
   132     var options = empty
   135     var options = empty
   133     for {
   136     for {
   134       dir <- Isabelle_System.components()
   137       dir <- Isabelle_System.components()
   135       file = dir + OPTIONS if file.is_file
   138       file = dir + OPTIONS if file.is_file
   136     } { options = Parser.parse_file(options_syntax, Parser.option_entry, options, file) }
   139     } { options = Parser.parse_file(options, file.implode, File.read(file)) }
   137     options
   140     Options.Parser.parse_prefs(options, prefs)
   138   }
   141   }
   139 
       
   140   def init(): Options = init_defaults().load_prefs()
       
   141 
   142 
   142 
   143 
   143   /* encode */
   144   /* encode */
   144 
   145 
   145   val encode: XML.Encode.T[Options] = (options => options.encode)
   146   val encode: XML.Encode.T[Options] = (options => options.encode)
   385     import XML.Encode.{string => string_, _}
   386     import XML.Encode.{string => string_, _}
   386     list(pair(properties, pair(string_, pair(string_, string_))))(opts)
   387     list(pair(properties, pair(string_, pair(string_, string_))))(opts)
   387   }
   388   }
   388 
   389 
   389 
   390 
   390   /* user preferences */
   391   /* save preferences */
   391 
   392 
   392   def load_prefs(): Options =
   393   def save_prefs(file: Path = Options.PREFS)
   393     if (Options.PREFS.is_file)
   394   {
   394       Options.Parser.parse_file(
   395     val defaults: Options = Options.init(prefs = "")
   395         Options.prefs_syntax, Options.Parser.prefs_entry, this, Options.PREFS)
       
   396     else this
       
   397 
       
   398   def save_prefs()
       
   399   {
       
   400     val defaults = Options.init_defaults()
       
   401     val changed =
   396     val changed =
   402       (for {
   397       (for {
   403         (name, opt2) <- options.iterator
   398         (name, opt2) <- options.iterator
   404         opt1 = defaults.options.get(name)
   399         opt1 = defaults.options.get(name)
   405         if opt1.isEmpty || opt1.get.value != opt2.value
   400         if opt1.isEmpty || opt1.get.value != opt2.value
   407 
   402 
   408     val prefs =
   403     val prefs =
   409       changed.sortBy(_._1)
   404       changed.sortBy(_._1)
   410         .map({ case (x, y, z) => x + " = " + Outer_Syntax.quote_string(y) + z + "\n" }).mkString
   405         .map({ case (x, y, z) => x + " = " + Outer_Syntax.quote_string(y) + z + "\n" }).mkString
   411 
   406 
   412     Isabelle_System.mkdirs(Options.PREFS_DIR)
   407     Isabelle_System.mkdirs(file.dir)
   413     File.write_backup(Options.PREFS, "(* generated by Isabelle " + Date.now() + " *)\n\n" + prefs)
   408     File.write_backup(file, "(* generated by Isabelle " + Date.now() + " *)\n\n" + prefs)
   414   }
   409   }
   415 }
   410 }
   416 
   411 
   417 
   412 
   418 class Options_Variable(init_options: Options)
   413 class Options_Variable(init_options: Options)