| author | wenzelm | 
| Wed, 27 Mar 2013 17:58:07 +0100 | |
| changeset 51557 | 4e4b56b7a3a5 | 
| parent 50893 | d55eb82ae77b | 
| child 51620 | 7c39677f9ea0 | 
| permissions | -rw-r--r-- | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 1 | /* Title: Pure/System/options.scala | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 2 | Author: Makarius | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 3 | |
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 4 | Stand-alone options with external string representation. | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 5 | */ | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 6 | |
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 7 | package isabelle | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 8 | |
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 9 | |
| 48807 | 10 | import java.util.Calendar | 
| 11 | ||
| 12 | ||
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 13 | object Options | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 14 | {
 | 
| 48421 | 15 | type Spec = (String, Option[String]) | 
| 16 | ||
| 17 | val empty: Options = new Options() | |
| 18 | ||
| 19 | ||
| 20 | /* representation */ | |
| 21 | ||
| 22 | sealed abstract class Type | |
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 23 |   {
 | 
| 50299 | 24 | def print: String = Library.lowercase(toString) | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 25 | } | 
| 49246 | 26 | case object Bool extends Type | 
| 27 | case object Int extends Type | |
| 28 | case object Real extends Type | |
| 29 | case object String extends Type | |
| 30 | case object Unknown extends Type | |
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 31 | |
| 49289 | 32 | case class Opt(name: String, typ: Type, value: String, default_value: String, | 
| 33 | description: String, section: String) | |
| 48860 | 34 |   {
 | 
| 49289 | 35 | private def print(default: Boolean): String = | 
| 36 |     {
 | |
| 37 | val x = if (default) default_value else value | |
| 49247 | 38 | "option " + name + " : " + typ.print + " = " + | 
| 49289 | 39 | (if (typ == Options.String) quote(x) else x) + | 
| 40 | (if (description == "") "" else "\n -- " + quote(description)) | |
| 41 | } | |
| 42 | ||
| 43 | def print: String = print(false) | |
| 44 | def print_default: String = print(true) | |
| 49247 | 45 | |
| 49270 | 46 | def title(strip: String): String = | 
| 47 |     {
 | |
| 48 |       val words = space_explode('_', name)
 | |
| 49 | val words1 = | |
| 50 |         words match {
 | |
| 51 | case word :: rest if word == strip => rest | |
| 52 | case _ => words | |
| 53 | } | |
| 54 |       words1.map(Library.capitalize).mkString(" ")
 | |
| 55 | } | |
| 56 | ||
| 48860 | 57 | def unknown: Boolean = typ == Unknown | 
| 58 | } | |
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 59 | |
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 60 | |
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 61 | /* parsing */ | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 62 | |
| 49270 | 63 | private val SECTION = "section" | 
| 48795 
bece259ee055
clarified format of etc/options: only declarations, not re-definitions;
 wenzelm parents: 
48718diff
changeset | 64 | private val OPTION = "option" | 
| 48807 | 65 |   private val OPTIONS = Path.explode("etc/options")
 | 
| 50793 | 66 |   private val PREFS_DIR = Path.explode("$ISABELLE_HOME_USER/etc")
 | 
| 67 |   private val PREFS = PREFS_DIR + Path.basic("preferences")
 | |
| 68 |   private val PREFS_BACKUP = PREFS_DIR + Path.basic("preferences~")
 | |
| 48713 
de26cf3191a3
more token markers, based on actual outer syntax;
 wenzelm parents: 
48693diff
changeset | 69 | |
| 49270 | 70 | lazy val options_syntax = | 
| 71 | Outer_Syntax.init() + ":" + "=" + "--" + | |
| 72 | (SECTION, Keyword.THY_HEADING2) + (OPTION, Keyword.THY_DECL) | |
| 73 | ||
| 48807 | 74 | lazy val prefs_syntax = Outer_Syntax.init() + "=" | 
| 48713 
de26cf3191a3
more token markers, based on actual outer syntax;
 wenzelm parents: 
48693diff
changeset | 75 | |
| 48807 | 76 | object Parser extends Parse.Parser | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 77 |   {
 | 
| 48807 | 78 |     val option_name = atom("option name", _.is_xname)
 | 
| 79 |     val option_type = atom("option type", _.is_ident)
 | |
| 80 | val option_value = | |
| 81 |       opt(token("-", tok => tok.is_sym_ident && tok.content == "-")) ~ atom("nat", _.is_nat) ^^
 | |
| 82 |         { case s ~ n => if (s.isDefined) "-" + n else n } |
 | |
| 83 |       atom("option value", tok => tok.is_name || tok.is_float)
 | |
| 84 | ||
| 85 | val option_entry: Parser[Options => Options] = | |
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 86 |     {
 | 
| 49270 | 87 | command(SECTION) ~! text ^^ | 
| 49295 | 88 |         { case _ ~ a => (options: Options) => options.set_section(a) } |
 | 
| 48795 
bece259ee055
clarified format of etc/options: only declarations, not re-definitions;
 wenzelm parents: 
48718diff
changeset | 89 |       command(OPTION) ~! (option_name ~ keyword(":") ~ option_type ~
 | 
| 48580 | 90 |       keyword("=") ~ option_value ~ (keyword("--") ~! text ^^ { case _ ~ x => x } | success(""))) ^^
 | 
| 48795 
bece259ee055
clarified format of etc/options: only declarations, not re-definitions;
 wenzelm parents: 
48718diff
changeset | 91 |         { case _ ~ (a ~ _ ~ b ~ _ ~ c ~ d) => (options: Options) => options.declare(a, b, c, d) }
 | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 92 | } | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 93 | |
| 48807 | 94 | val prefs_entry: Parser[Options => Options] = | 
| 95 |     {
 | |
| 96 |       option_name ~ (keyword("=") ~! option_value) ^^
 | |
| 48860 | 97 |       { case a ~ (_ ~ b) => (options: Options) => options.add_permissive(a, b) }
 | 
| 48807 | 98 | } | 
| 99 | ||
| 100 | def parse_file(syntax: Outer_Syntax, parser: Parser[Options => Options], | |
| 101 | options: Options, file: Path): Options = | |
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 102 |     {
 | 
| 48807 | 103 | val toks = syntax.scan(File.read(file)) | 
| 104 | val ops = | |
| 105 |         parse_all(rep(parser), Token.reader(toks, file.implode)) match {
 | |
| 106 | case Success(result, _) => result | |
| 107 | case bad => error(bad.toString) | |
| 108 | } | |
| 49270 | 109 |       try { (options.set_section("") /: ops) { case (opts, op) => op(opts) } }
 | 
| 48992 | 110 |       catch { case ERROR(msg) => error(msg + Position.here(file.position)) }
 | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 111 | } | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 112 | } | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 113 | |
| 48807 | 114 | def init_defaults(): Options = | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 115 |   {
 | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 116 | var options = empty | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 117 |     for {
 | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 118 | dir <- Isabelle_System.components() | 
| 48548 | 119 | file = dir + OPTIONS if file.is_file | 
| 48807 | 120 |     } { options = Parser.parse_file(options_syntax, Parser.option_entry, options, file) }
 | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 121 | options | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 122 | } | 
| 48457 | 123 | |
| 48807 | 124 | def init(): Options = init_defaults().load_prefs() | 
| 125 | ||
| 48457 | 126 | |
| 127 | /* encode */ | |
| 128 | ||
| 129 | val encode: XML.Encode.T[Options] = (options => options.encode) | |
| 48693 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 130 | |
| 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 131 | |
| 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 132 | /* command line entry point */ | 
| 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 133 | |
| 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 134 | def main(args: Array[String]) | 
| 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 135 |   {
 | 
| 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 136 |     Command_Line.tool {
 | 
| 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 137 |       args.toList match {
 | 
| 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 138 | case export_file :: more_options => | 
| 48807 | 139 | val options = (Options.init() /: more_options)(_ + _) | 
| 48693 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 140 | |
| 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 141 | if (export_file == "") java.lang.System.out.println(options.print) | 
| 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 142 | else File.write(Path.explode(export_file), YXML.string_of_body(options.encode)) | 
| 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 143 | |
| 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 144 | 0 | 
| 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 145 |         case _ => error("Bad arguments:\n" + cat_lines(args))
 | 
| 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 146 | } | 
| 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 147 | } | 
| 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 148 | } | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 149 | } | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 150 | |
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 151 | |
| 49270 | 152 | final class Options private( | 
| 49296 | 153 | val options: Map[String, Options.Opt] = Map.empty, | 
| 49270 | 154 | val section: String = "") | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 155 | {
 | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 156 |   override def toString: String = options.iterator.mkString("Options (", ",", ")")
 | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 157 | |
| 49247 | 158 | def print: String = cat_lines(options.toList.sortBy(_._1).map(p => p._2.print)) | 
| 48693 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 159 | |
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 160 | def description(name: String): String = check_name(name).description | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 161 | |
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 162 | |
| 48370 | 163 | /* check */ | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 164 | |
| 49246 | 165 | def check_name(name: String): Options.Opt = | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 166 |     options.get(name) match {
 | 
| 48860 | 167 | case Some(opt) if !opt.unknown => opt | 
| 168 |       case _ => error("Unknown option " + quote(name))
 | |
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 169 | } | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 170 | |
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 171 | private def check_type(name: String, typ: Options.Type): Options.Opt = | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 172 |   {
 | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 173 | val opt = check_name(name) | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 174 | if (opt.typ == typ) opt | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 175 |     else error("Ill-typed option " + quote(name) + " : " + opt.typ.print + " vs. " + typ.print)
 | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 176 | } | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 177 | |
| 48370 | 178 | |
| 179 | /* basic operations */ | |
| 180 | ||
| 181 | private def put[A](name: String, typ: Options.Type, value: String): Options = | |
| 182 |   {
 | |
| 183 | val opt = check_type(name, typ) | |
| 49270 | 184 | new Options(options + (name -> opt.copy(value = value)), section) | 
| 48370 | 185 | } | 
| 186 | ||
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 187 | private def get[A](name: String, typ: Options.Type, parse: String => Option[A]): A = | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 188 |   {
 | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 189 | val opt = check_type(name, typ) | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 190 |     parse(opt.value) match {
 | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 191 | case Some(x) => x | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 192 | case None => | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 193 |         error("Malformed value for option " + quote(name) +
 | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 194 | " : " + typ.print + " =\n" + quote(opt.value)) | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 195 | } | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 196 | } | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 197 | |
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 198 | |
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 199 | /* internal lookup and update */ | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 200 | |
| 49954 
44658062d822
more explicit auxiliary classes to avoid warning "reflective access of structural type member method" of scala-2.10.0-RC1;
 wenzelm parents: 
49296diff
changeset | 201 | class Bool_Access | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 202 |   {
 | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 203 | def apply(name: String): Boolean = get(name, Options.Bool, Properties.Value.Boolean.unapply) | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 204 | def update(name: String, x: Boolean): Options = | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 205 | put(name, Options.Bool, Properties.Value.Boolean(x)) | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 206 | } | 
| 49954 
44658062d822
more explicit auxiliary classes to avoid warning "reflective access of structural type member method" of scala-2.10.0-RC1;
 wenzelm parents: 
49296diff
changeset | 207 | val bool = new Bool_Access | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 208 | |
| 49954 
44658062d822
more explicit auxiliary classes to avoid warning "reflective access of structural type member method" of scala-2.10.0-RC1;
 wenzelm parents: 
49296diff
changeset | 209 | class Int_Access | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 210 |   {
 | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 211 | def apply(name: String): Int = get(name, Options.Int, Properties.Value.Int.unapply) | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 212 | def update(name: String, x: Int): Options = | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 213 | put(name, Options.Int, Properties.Value.Int(x)) | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 214 | } | 
| 49954 
44658062d822
more explicit auxiliary classes to avoid warning "reflective access of structural type member method" of scala-2.10.0-RC1;
 wenzelm parents: 
49296diff
changeset | 215 | val int = new Int_Access | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 216 | |
| 49954 
44658062d822
more explicit auxiliary classes to avoid warning "reflective access of structural type member method" of scala-2.10.0-RC1;
 wenzelm parents: 
49296diff
changeset | 217 | class Real_Access | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 218 |   {
 | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 219 | def apply(name: String): Double = get(name, Options.Real, Properties.Value.Double.unapply) | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 220 | def update(name: String, x: Double): Options = | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 221 | put(name, Options.Real, Properties.Value.Double(x)) | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 222 | } | 
| 49954 
44658062d822
more explicit auxiliary classes to avoid warning "reflective access of structural type member method" of scala-2.10.0-RC1;
 wenzelm parents: 
49296diff
changeset | 223 | val real = new Real_Access | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 224 | |
| 49954 
44658062d822
more explicit auxiliary classes to avoid warning "reflective access of structural type member method" of scala-2.10.0-RC1;
 wenzelm parents: 
49296diff
changeset | 225 | class String_Access | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 226 |   {
 | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 227 | def apply(name: String): String = get(name, Options.String, s => Some(s)) | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 228 | def update(name: String, x: String): Options = put(name, Options.String, x) | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 229 | } | 
| 49954 
44658062d822
more explicit auxiliary classes to avoid warning "reflective access of structural type member method" of scala-2.10.0-RC1;
 wenzelm parents: 
49296diff
changeset | 230 | val string = new String_Access | 
| 48370 | 231 | |
| 50207 | 232 | class Seconds_Access | 
| 233 |   {
 | |
| 234 | def apply(name: String): Time = Time.seconds(real(name)) | |
| 235 | } | |
| 236 | val seconds = new Seconds_Access | |
| 237 | ||
| 48370 | 238 | |
| 48807 | 239 | /* external updates */ | 
| 48370 | 240 | |
| 241 | private def check_value(name: String): Options = | |
| 242 |   {
 | |
| 243 | val opt = check_name(name) | |
| 244 |     opt.typ match {
 | |
| 245 | case Options.Bool => bool(name); this | |
| 246 | case Options.Int => int(name); this | |
| 247 | case Options.Real => real(name); this | |
| 248 | case Options.String => string(name); this | |
| 48860 | 249 | case Options.Unknown => this | 
| 48370 | 250 | } | 
| 251 | } | |
| 252 | ||
| 253 | def declare(name: String, typ_name: String, value: String, description: String = ""): Options = | |
| 254 |   {
 | |
| 255 |     options.get(name) match {
 | |
| 256 |       case Some(_) => error("Duplicate declaration of option " + quote(name))
 | |
| 257 | case None => | |
| 258 | val typ = | |
| 259 |           typ_name match {
 | |
| 260 | case "bool" => Options.Bool | |
| 261 | case "int" => Options.Int | |
| 262 | case "real" => Options.Real | |
| 263 | case "string" => Options.String | |
| 48456 
d8ff14f44a40
added ML version of stand-alone options, with XML.encode/decode operations (unidirectional from Scala to ML);
 wenzelm parents: 
48421diff
changeset | 264 |             case _ => error("Unknown type for option " + quote(name) + " : " + quote(typ_name))
 | 
| 48370 | 265 | } | 
| 49289 | 266 | val opt = Options.Opt(name, typ, value, value, description, section) | 
| 49270 | 267 | (new Options(options + (name -> opt), section)).check_value(name) | 
| 48370 | 268 | } | 
| 269 | } | |
| 270 | ||
| 48860 | 271 | def add_permissive(name: String, value: String): Options = | 
| 272 |   {
 | |
| 273 | if (options.isDefinedAt(name)) this + (name, value) | |
| 49289 | 274 | else | 
| 275 | new Options( | |
| 276 | options + (name -> Options.Opt(name, Options.Unknown, value, value, "", "")), section) | |
| 48860 | 277 | } | 
| 278 | ||
| 48807 | 279 | def + (name: String, value: String): Options = | 
| 48370 | 280 |   {
 | 
| 281 | val opt = check_name(name) | |
| 49270 | 282 | (new Options(options + (name -> opt.copy(value = value)), section)).check_value(name) | 
| 48370 | 283 | } | 
| 284 | ||
| 48807 | 285 | def + (name: String, opt_value: Option[String]): Options = | 
| 48370 | 286 |   {
 | 
| 287 | val opt = check_name(name) | |
| 288 |     opt_value match {
 | |
| 48807 | 289 | case Some(value) => this + (name, value) | 
| 290 | case None if opt.typ == Options.Bool => this + (name, "true") | |
| 48370 | 291 |       case None => error("Missing value for option " + quote(name) + " : " + opt.typ.print)
 | 
| 292 | } | |
| 293 | } | |
| 294 | ||
| 48807 | 295 | def + (str: String): Options = | 
| 48370 | 296 |   {
 | 
| 297 |     str.indexOf('=') match {
 | |
| 48807 | 298 | case -1 => this + (str, None) | 
| 299 | case i => this + (str.substring(0, i), str.substring(i + 1)) | |
| 48370 | 300 | } | 
| 301 | } | |
| 48456 
d8ff14f44a40
added ML version of stand-alone options, with XML.encode/decode operations (unidirectional from Scala to ML);
 wenzelm parents: 
48421diff
changeset | 302 | |
| 48807 | 303 | def ++ (specs: List[Options.Spec]): Options = | 
| 304 |     (this /: specs)({ case (x, (y, z)) => x + (y, z) })
 | |
| 305 | ||
| 48456 
d8ff14f44a40
added ML version of stand-alone options, with XML.encode/decode operations (unidirectional from Scala to ML);
 wenzelm parents: 
48421diff
changeset | 306 | |
| 49270 | 307 | /* sections */ | 
| 308 | ||
| 309 | def set_section(new_section: String): Options = | |
| 310 | new Options(options, new_section) | |
| 311 | ||
| 312 | def sections: List[(String, List[Options.Opt])] = | |
| 313 |     options.groupBy(_._2.section).toList.map({ case (a, opts) => (a, opts.toList.map(_._2)) })
 | |
| 314 | ||
| 315 | ||
| 48456 
d8ff14f44a40
added ML version of stand-alone options, with XML.encode/decode operations (unidirectional from Scala to ML);
 wenzelm parents: 
48421diff
changeset | 316 | /* encode */ | 
| 
d8ff14f44a40
added ML version of stand-alone options, with XML.encode/decode operations (unidirectional from Scala to ML);
 wenzelm parents: 
48421diff
changeset | 317 | |
| 
d8ff14f44a40
added ML version of stand-alone options, with XML.encode/decode operations (unidirectional from Scala to ML);
 wenzelm parents: 
48421diff
changeset | 318 | def encode: XML.Body = | 
| 
d8ff14f44a40
added ML version of stand-alone options, with XML.encode/decode operations (unidirectional from Scala to ML);
 wenzelm parents: 
48421diff
changeset | 319 |   {
 | 
| 48860 | 320 | val opts = | 
| 321 | for ((name, opt) <- options.toList; if !opt.unknown) | |
| 322 | yield (name, opt.typ.print, opt.value) | |
| 323 | ||
| 48456 
d8ff14f44a40
added ML version of stand-alone options, with XML.encode/decode operations (unidirectional from Scala to ML);
 wenzelm parents: 
48421diff
changeset | 324 |     import XML.Encode.{string => str, _}
 | 
| 48860 | 325 | list(triple(str, str, str))(opts) | 
| 48456 
d8ff14f44a40
added ML version of stand-alone options, with XML.encode/decode operations (unidirectional from Scala to ML);
 wenzelm parents: 
48421diff
changeset | 326 | } | 
| 48807 | 327 | |
| 328 | ||
| 329 | /* user preferences */ | |
| 330 | ||
| 331 | def load_prefs(): Options = | |
| 332 | if (Options.PREFS.is_file) | |
| 333 | Options.Parser.parse_file( | |
| 334 | Options.prefs_syntax, Options.Parser.prefs_entry, this, Options.PREFS) | |
| 335 | else this | |
| 336 | ||
| 337 | def save_prefs() | |
| 338 |   {
 | |
| 48860 | 339 | val defaults = Options.init_defaults() | 
| 48807 | 340 | val changed = | 
| 341 |       (for {
 | |
| 48860 | 342 | (name, opt2) <- options.iterator | 
| 343 | opt1 = defaults.options.get(name) | |
| 344 | if (opt1.isEmpty || opt1.get.value != opt2.value) | |
| 345 | } yield (name, opt2.value, if (opt1.isEmpty) " (* unknown *)" else "")).toList | |
| 346 | ||
| 48807 | 347 | val prefs = | 
| 348 | changed.sortBy(_._1) | |
| 48860 | 349 |         .map({ case (x, y, z) => x + " = " + Outer_Syntax.quote_string(y) + z + "\n" }).mkString
 | 
| 48807 | 350 | |
| 50893 
d55eb82ae77b
Isabelle_System.mkdirs with explicit error checking (in accordance to ML version), e.g. relevant with read-only DMG file-system on Mac OS X;
 wenzelm parents: 
50793diff
changeset | 351 | Isabelle_System.mkdirs(Options.PREFS_DIR) | 
| 48807 | 352 | Options.PREFS.file renameTo Options.PREFS_BACKUP.file | 
| 353 | File.write(Options.PREFS, | |
| 354 | "(* generated by Isabelle " + Calendar.getInstance.getTime + " *)\n\n" + prefs) | |
| 355 | } | |
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 356 | } | 
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 357 | |
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 358 | |
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 359 | class Options_Variable | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 360 | {
 | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 361 | // owned by Swing thread | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 362 | @volatile private var options = Options.empty | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 363 | |
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 364 | def value: Options = options | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 365 | def update(new_options: Options) | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 366 |   {
 | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 367 | Swing_Thread.require() | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 368 | options = new_options | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 369 | } | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 370 | |
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 371 | def + (name: String, x: String) | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 372 |   {
 | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 373 | Swing_Thread.require() | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 374 | options = options + (name, x) | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 375 | } | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 376 | |
| 49954 
44658062d822
more explicit auxiliary classes to avoid warning "reflective access of structural type member method" of scala-2.10.0-RC1;
 wenzelm parents: 
49296diff
changeset | 377 | class Bool_Access | 
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 378 |   {
 | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 379 | def apply(name: String): Boolean = options.bool(name) | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 380 | def update(name: String, x: Boolean) | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 381 |     {
 | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 382 | Swing_Thread.require() | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 383 | options = options.bool.update(name, x) | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 384 | } | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 385 | } | 
| 49954 
44658062d822
more explicit auxiliary classes to avoid warning "reflective access of structural type member method" of scala-2.10.0-RC1;
 wenzelm parents: 
49296diff
changeset | 386 | val bool = new Bool_Access | 
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 387 | |
| 49954 
44658062d822
more explicit auxiliary classes to avoid warning "reflective access of structural type member method" of scala-2.10.0-RC1;
 wenzelm parents: 
49296diff
changeset | 388 | class Int_Access | 
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 389 |   {
 | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 390 | def apply(name: String): Int = options.int(name) | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 391 | def update(name: String, x: Int) | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 392 |     {
 | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 393 | Swing_Thread.require() | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 394 | options = options.int.update(name, x) | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 395 | } | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 396 | } | 
| 49954 
44658062d822
more explicit auxiliary classes to avoid warning "reflective access of structural type member method" of scala-2.10.0-RC1;
 wenzelm parents: 
49296diff
changeset | 397 | val int = new Int_Access | 
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 398 | |
| 49954 
44658062d822
more explicit auxiliary classes to avoid warning "reflective access of structural type member method" of scala-2.10.0-RC1;
 wenzelm parents: 
49296diff
changeset | 399 | class Real_Access | 
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 400 |   {
 | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 401 | def apply(name: String): Double = options.real(name) | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 402 | def update(name: String, x: Double) | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 403 |     {
 | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 404 | Swing_Thread.require() | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 405 | options = options.real.update(name, x) | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 406 | } | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 407 | } | 
| 49954 
44658062d822
more explicit auxiliary classes to avoid warning "reflective access of structural type member method" of scala-2.10.0-RC1;
 wenzelm parents: 
49296diff
changeset | 408 | val real = new Real_Access | 
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 409 | |
| 49954 
44658062d822
more explicit auxiliary classes to avoid warning "reflective access of structural type member method" of scala-2.10.0-RC1;
 wenzelm parents: 
49296diff
changeset | 410 | class String_Access | 
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 411 |   {
 | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 412 | def apply(name: String): String = options.string(name) | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 413 | def update(name: String, x: String) | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 414 |     {
 | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 415 | Swing_Thread.require() | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 416 | options = options.string.update(name, x) | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 417 | } | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 418 | } | 
| 49954 
44658062d822
more explicit auxiliary classes to avoid warning "reflective access of structural type member method" of scala-2.10.0-RC1;
 wenzelm parents: 
49296diff
changeset | 419 | val string = new String_Access | 
| 50207 | 420 | |
| 421 | class Seconds_Access | |
| 422 |   {
 | |
| 423 | def apply(name: String): Time = options.seconds(name) | |
| 424 | } | |
| 425 | val seconds = new Seconds_Access | |
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 426 | } | 
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 427 |