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) |