| author | wenzelm | 
| Fri, 23 Aug 2024 20:21:04 +0200 | |
| changeset 80749 | 232a839ef8e6 | 
| parent 79656 | 10e560f2f580 | 
| child 81049 | 45ef41e823f7 | 
| 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 | |
| 51945 | 4 | System options with external string representation. | 
| 48365 
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 | |
| 75393 | 10 | object Options {
 | 
| 77624 | 11 | val empty: Options = new Options() | 
| 48421 | 12 | |
| 77626 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 13 |   object Spec {
 | 
| 78911 | 14 | val syntax: Outer_Syntax = Outer_Syntax.empty + "=" + "," | 
| 15 | ||
| 16 |     def parse(content: String): List[Spec] = {
 | |
| 17 |       val parser = Parsers.repsep(Parsers.option_spec, Parsers.$$$(","))
 | |
| 18 | val reader = Token.reader(Token.explode(syntax.keywords, content), Token.Pos.none) | |
| 19 |       Parsers.parse_all(parser, reader) match {
 | |
| 20 | case Parsers.Success(result, _) => result | |
| 21 | case bad => error(bad.toString) | |
| 22 | } | |
| 23 | } | |
| 24 | ||
| 78916 | 25 | def eq(a: String, b: String, permissive: Boolean = false): Spec = | 
| 26 | Spec(a, value = Some(b), permissive = permissive) | |
| 27 | ||
| 77626 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 28 | def make(s: String): Spec = | 
| 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 29 |       s match {
 | 
| 78916 | 30 | case Properties.Eq(a, b) => eq(a, b) | 
| 77626 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 31 | case _ => Spec(s) | 
| 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 32 | } | 
| 77628 | 33 | |
| 34 | def ISABELLE_BUILD_OPTIONS: List[Spec] = | |
| 35 |       Word.explode(Isabelle_System.getenv("ISABELLE_BUILD_OPTIONS")).map(make)
 | |
| 78560 | 36 | |
| 37 | def print_value(s: String): String = | |
| 38 |       s match {
 | |
| 39 | case Value.Boolean(_) => s | |
| 40 | case Value.Long(_) => s | |
| 41 | case Value.Double(_) => s | |
| 78911 | 42 | case _ => Token.quote_name(syntax.keywords, s) | 
| 78560 | 43 | } | 
| 44 | ||
| 45 | def print(name: String, value: String): String = Properties.Eq(name, print_value(value)) | |
| 78908 
f38153e58f21
proper Option.Spec.toString for bash script: avoid Token.quote_name of Options.Spec.print_value (amending 3d1746a716fa, see also 39f6f180008d);
 wenzelm parents: 
78614diff
changeset | 46 | |
| 78915 
90756ad4d8d7
more accurate treatment of surrounding whitespace;
 wenzelm parents: 
78911diff
changeset | 47 |     def bash_strings(opts: Iterable[Spec], bg: Boolean = false, en: Boolean = false): String = {
 | 
| 
90756ad4d8d7
more accurate treatment of surrounding whitespace;
 wenzelm parents: 
78911diff
changeset | 48 | val it = opts.iterator | 
| 
90756ad4d8d7
more accurate treatment of surrounding whitespace;
 wenzelm parents: 
78911diff
changeset | 49 | if (it.isEmpty) "" | 
| 
90756ad4d8d7
more accurate treatment of surrounding whitespace;
 wenzelm parents: 
78911diff
changeset | 50 |       else {
 | 
| 
90756ad4d8d7
more accurate treatment of surrounding whitespace;
 wenzelm parents: 
78911diff
changeset | 51 | it.map(opt => "-o " + Bash.string(opt.toString)) | 
| 
90756ad4d8d7
more accurate treatment of surrounding whitespace;
 wenzelm parents: 
78911diff
changeset | 52 | .mkString(if (bg) " " else "", " ", if (en) " " else "") | 
| 
90756ad4d8d7
more accurate treatment of surrounding whitespace;
 wenzelm parents: 
78911diff
changeset | 53 | } | 
| 
90756ad4d8d7
more accurate treatment of surrounding whitespace;
 wenzelm parents: 
78911diff
changeset | 54 | } | 
| 77626 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 55 | } | 
| 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 56 | |
| 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 57 |   sealed case class Spec(name: String, value: Option[String] = None, permissive: Boolean = false) {
 | 
| 77625 | 58 | override def toString: String = name + if_proper(value, "=" + value.get) | 
| 78909 | 59 | def print: String = | 
| 60 |       value match {
 | |
| 61 | case None => name | |
| 62 | case Some(v) => Spec.print(name, v) | |
| 63 | } | |
| 77625 | 64 | } | 
| 48421 | 65 | |
| 77623 | 66 |   sealed case class Change(name: String, value: String, unknown: Boolean) {
 | 
| 78916 | 67 | def spec: Spec = Spec.eq(name, value) | 
| 77626 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 68 | |
| 77623 | 69 | def print_prefs: String = | 
| 70 | name + " = " + Outer_Syntax.quote_string(value) + | |
| 71 | if_proper(unknown, " (* unknown *)") + "\n" | |
| 72 | } | |
| 73 | ||
| 48421 | 74 | |
| 75847 | 75 | /* typed access */ | 
| 75842 | 76 | |
| 75846 | 77 |   abstract class Access[A](val options: Options) {
 | 
| 75842 | 78 | def apply(name: String): A | 
| 79 | def update(name: String, x: A): Options | |
| 75847 | 80 | def change(name: String, f: A => A): Options = update(name, f(apply(name))) | 
| 75842 | 81 | } | 
| 82 | ||
| 75847 | 83 | class Access_Variable[A]( | 
| 84 | val options: Options_Variable, | |
| 85 | val pure_access: Options => Access[A] | |
| 86 |   ) {
 | |
| 87 | def apply(name: String): A = pure_access(options.value)(name) | |
| 88 | def update(name: String, x: A): Unit = | |
| 89 | options.change(options => pure_access(options).update(name, x)) | |
| 90 | def change(name: String, f: A => A): Unit = update(name, f(apply(name))) | |
| 75842 | 91 | } | 
| 92 | ||
| 93 | ||
| 48421 | 94 | /* representation */ | 
| 95 | ||
| 75393 | 96 |   sealed abstract class Type {
 | 
| 56599 | 97 | def print: String = Word.lowercase(toString) | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 98 | } | 
| 49246 | 99 | case object Bool extends Type | 
| 100 | case object Int extends Type | |
| 101 | case object Real extends Type | |
| 102 | case object String extends Type | |
| 103 | case object Unknown extends Type | |
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 104 | |
| 77611 | 105 | val TAG_CONTENT = "content" // formal theory content | 
| 106 | val TAG_DOCUMENT = "document" // document preparation | |
| 79526 
6e5397fcc41b
add build_sync tag to sync certain options (e.g., build_engine) across build processes;
 Fabian Huch <huch@in.tum.de> parents: 
78916diff
changeset | 107 | val TAG_BUILD = "build" // relevant for "isabelle build" | 
| 
6e5397fcc41b
add build_sync tag to sync certain options (e.g., build_engine) across build processes;
 Fabian Huch <huch@in.tum.de> parents: 
78916diff
changeset | 108 | val TAG_BUILD_SYNC = "build_sync" // relevant for distributed "isabelle build" | 
| 77611 | 109 | val TAG_UPDATE = "update" // relevant for "isabelle update" | 
| 110 | val TAG_CONNECTION = "connection" // private information about connections (password etc.) | |
| 77612 | 111 | val TAG_COLOR_DIALOG = "color_dialog" // special color selection dialog | 
| 77603 | 112 | |
| 77605 | 113 | case class Entry( | 
| 56465 | 114 | public: Boolean, | 
| 115 | pos: Position.T, | |
| 116 | name: String, | |
| 117 | typ: Type, | |
| 118 | value: String, | |
| 119 | default_value: String, | |
| 74827 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 120 | standard_value: Option[String], | 
| 77603 | 121 | tags: List[String], | 
| 56465 | 122 | description: String, | 
| 75393 | 123 | section: String | 
| 124 |   ) {
 | |
| 74827 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 125 | private def print_value(x: String): String = if (typ == Options.String) quote(x) else x | 
| 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 126 | private def print_standard: String = | 
| 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 127 |       standard_value match {
 | 
| 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 128 | case None => "" | 
| 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 129 | case Some(s) if s == default_value => " (standard)" | 
| 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 130 | case Some(s) => " (standard " + print_value(s) + ")" | 
| 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 131 | } | 
| 75393 | 132 |     private def print(default: Boolean): String = {
 | 
| 49289 | 133 | val x = if (default) default_value else value | 
| 74827 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 134 | "option " + name + " : " + typ.print + " = " + print_value(x) + print_standard + | 
| 77504 | 135 | if_proper(description, "\n -- " + quote(description)) | 
| 49289 | 136 | } | 
| 137 | ||
| 138 | def print: String = print(false) | |
| 139 | def print_default: String = print(true) | |
| 49247 | 140 | |
| 75393 | 141 |     def title(strip: String = ""): String = {
 | 
| 56600 | 142 |       val words = Word.explode('_', name)
 | 
| 49270 | 143 | val words1 = | 
| 144 |         words match {
 | |
| 145 | case word :: rest if word == strip => rest | |
| 146 | case _ => words | |
| 147 | } | |
| 78614 | 148 | Word.implode(words1.map(Word.perhaps_capitalized)) | 
| 49270 | 149 | } | 
| 76579 | 150 |     def title_jedit: String = title("jedit")
 | 
| 49270 | 151 | |
| 48860 | 152 | def unknown: Boolean = typ == Unknown | 
| 77603 | 153 | |
| 77617 | 154 | def for_tag(tag: String): Boolean = tags.contains(tag) | 
| 155 | def for_content: Boolean = for_tag(TAG_CONTENT) | |
| 156 | def for_document: Boolean = for_tag(TAG_DOCUMENT) | |
| 157 | def for_color_dialog: Boolean = for_tag(TAG_COLOR_DIALOG) | |
| 79526 
6e5397fcc41b
add build_sync tag to sync certain options (e.g., build_engine) across build processes;
 Fabian Huch <huch@in.tum.de> parents: 
78916diff
changeset | 158 | def for_build_sync: Boolean = for_tag(TAG_BUILD_SYNC) | 
| 77617 | 159 | |
| 160 | def session_content: Boolean = for_content || for_document | |
| 48860 | 161 | } | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 162 | |
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 163 | |
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 164 | /* parsing */ | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 165 | |
| 49270 | 166 | private val SECTION = "section" | 
| 52065 
78f2475aa126
explicit notion of public options, which are shown in the editor options dialog;
 wenzelm parents: 
51945diff
changeset | 167 | private val PUBLIC = "public" | 
| 48795 
bece259ee055
clarified format of etc/options: only declarations, not re-definitions;
 wenzelm parents: 
48718diff
changeset | 168 | private val OPTION = "option" | 
| 74827 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 169 | private val STANDARD = "standard" | 
| 77603 | 170 | private val FOR = "for" | 
| 48807 | 171 |   private val OPTIONS = Path.explode("etc/options")
 | 
| 67845 | 172 |   private val PREFS = Path.explode("$ISABELLE_HOME_USER/etc/preferences")
 | 
| 48713 
de26cf3191a3
more token markers, based on actual outer syntax;
 wenzelm parents: 
48693diff
changeset | 173 | |
| 71601 | 174 | val options_syntax: Outer_Syntax = | 
| 74827 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 175 |     Outer_Syntax.empty + ":" + "=" + "--" + "(" + ")" +
 | 
| 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 176 | Symbol.comment + Symbol.comment_decoded + | 
| 63441 | 177 | (SECTION, Keyword.DOCUMENT_HEADING) + | 
| 178 | (PUBLIC, Keyword.BEFORE_COMMAND) + | |
| 74827 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 179 | (OPTION, Keyword.THY_DECL) + | 
| 77603 | 180 | STANDARD + FOR | 
| 49270 | 181 | |
| 71601 | 182 | val prefs_syntax: Outer_Syntax = Outer_Syntax.empty + "=" | 
| 48713 
de26cf3191a3
more token markers, based on actual outer syntax;
 wenzelm parents: 
48693diff
changeset | 183 | |
| 75405 | 184 |   trait Parsers extends Parse.Parsers {
 | 
| 71601 | 185 |     val option_name: Parser[String] = atom("option name", _.is_name)
 | 
| 186 |     val option_type: Parser[String] = atom("option type", _.is_name)
 | |
| 187 | val option_value: Parser[String] = | |
| 48807 | 188 |       opt(token("-", tok => tok.is_sym_ident && tok.content == "-")) ~ atom("nat", _.is_nat) ^^
 | 
| 189 |         { case s ~ n => if (s.isDefined) "-" + n else n } |
 | |
| 190 |       atom("option value", tok => tok.is_name || tok.is_float)
 | |
| 74827 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 191 | val option_standard: Parser[Option[String]] = | 
| 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 192 |       $$$("(") ~! $$$(STANDARD) ~ opt(option_value) ~ $$$(")") ^^ { case _ ~ _ ~ a ~ _ => a }
 | 
| 77603 | 193 |     val option_tag: Parser[String] = atom("option tag", _.is_name)
 | 
| 194 | val option_tags: Parser[List[String]] = | |
| 195 |       $$$(FOR) ~! rep(option_tag) ^^ { case _ ~ x => x } | success(Nil)
 | |
| 78407 
b262ecc98319
more operations for independent "inline" options;
 wenzelm parents: 
77668diff
changeset | 196 | val option_spec: Parser[Spec] = | 
| 
b262ecc98319
more operations for independent "inline" options;
 wenzelm parents: 
77668diff
changeset | 197 |       option_name ~ opt($$$("=") ~! option_value ^^ { case _ ~ x => x }) ^^
 | 
| 78916 | 198 |         { case x ~ y => Options.Spec(x, value = y) }
 | 
| 62968 | 199 | } | 
| 48807 | 200 | |
| 75405 | 201 |   private object Parsers extends Parsers {
 | 
| 61579 | 202 | def comment_marker: Parser[String] = | 
| 203 |       $$$("--") | $$$(Symbol.comment) | $$$(Symbol.comment_decoded)
 | |
| 204 | ||
| 75393 | 205 |     val option_entry: Parser[Options => Options] = {
 | 
| 49270 | 206 | command(SECTION) ~! text ^^ | 
| 49295 | 207 |         { case _ ~ a => (options: Options) => options.set_section(a) } |
 | 
| 60133 
a90982bbe8b4
clarified keywords for quasi-command spans and Sidekick structure;
 wenzelm parents: 
59811diff
changeset | 208 |       opt($$$(PUBLIC)) ~ command(OPTION) ~! (position(option_name) ~ $$$(":") ~ option_type ~
 | 
| 77603 | 209 |       $$$("=") ~ option_value ~ opt(option_standard) ~ option_tags ~
 | 
| 74827 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 210 |         (comment_marker ~! text ^^ { case _ ~ x => x } | success(""))) ^^
 | 
| 77603 | 211 |         { case a ~ _ ~ ((b, pos) ~ _ ~ c ~ _ ~ d ~ e ~ f ~ g) =>
 | 
| 212 | (options: Options) => options.declare(a.isDefined, pos, b, c, d, e, f, g) } | |
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 213 | } | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 214 | |
| 75393 | 215 |     val prefs_entry: Parser[Options => Options] = {
 | 
| 58908 | 216 |       option_name ~ ($$$("=") ~! option_value) ^^
 | 
| 77626 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 217 |       { case a ~ (_ ~ b) => (options: Options) =>
 | 
| 78916 | 218 | options + Options.Spec.eq(a, b, permissive = true) } | 
| 48807 | 219 | } | 
| 220 | ||
| 75393 | 221 | def parse_file( | 
| 222 | options: Options, | |
| 223 | file_name: String, | |
| 224 | content: String, | |
| 67845 | 225 | syntax: Outer_Syntax = options_syntax, | 
| 75393 | 226 | parser: Parser[Options => Options] = option_entry | 
| 227 |     ): Options = {
 | |
| 67845 | 228 | val toks = Token.explode(syntax.keywords, content) | 
| 48807 | 229 | val ops = | 
| 67845 | 230 |         parse_all(rep(parser), Token.reader(toks, Token.Pos.file(file_name))) match {
 | 
| 48807 | 231 | case Success(result, _) => result | 
| 232 | case bad => error(bad.toString) | |
| 233 | } | |
| 73359 | 234 |       try { ops.foldLeft(options.set_section("")) { case (opts, op) => op(opts) } }
 | 
| 73166 | 235 |       catch { case ERROR(msg) => error(msg + Position.here(Position.File(file_name))) }
 | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 236 | } | 
| 67845 | 237 | |
| 238 | def parse_prefs(options: Options, content: String): Options = | |
| 69366 | 239 | parse_file(options, PREFS.file_name, content, syntax = prefs_syntax, parser = prefs_entry) | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 240 | } | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 241 | |
| 67845 | 242 | def read_prefs(file: Path = PREFS): String = | 
| 243 | if (file.is_file) File.read(file) else "" | |
| 64186 
49816908ae42
support for separate sub-system options, independent of main Isabelle options;
 wenzelm parents: 
64151diff
changeset | 244 | |
| 78407 
b262ecc98319
more operations for independent "inline" options;
 wenzelm parents: 
77668diff
changeset | 245 | def inline(content: String): Options = Parsers.parse_file(empty, "inline", content) | 
| 
b262ecc98319
more operations for independent "inline" options;
 wenzelm parents: 
77668diff
changeset | 246 | |
| 77628 | 247 |   def init(prefs: String = read_prefs(file = PREFS), specs: List[Spec] = Nil): Options = {
 | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 248 | var options = empty | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 249 |     for {
 | 
| 73815 | 250 | dir <- Components.directories() | 
| 48548 | 251 | file = dir + OPTIONS if file.is_file | 
| 75405 | 252 |     } { options = Parsers.parse_file(options, file.implode, File.read(file)) }
 | 
| 77628 | 253 | Parsers.parse_prefs(options, prefs) ++ specs | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 254 | } | 
| 48457 | 255 | |
| 77609 | 256 | def init0(): Options = init(prefs = "") | 
| 257 | ||
| 48457 | 258 | |
| 62832 | 259 | /* Isabelle tool wrapper */ | 
| 48693 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 260 | |
| 72763 | 261 |   val isabelle_tool = Isabelle_Tool("options", "print Isabelle system options",
 | 
| 75394 | 262 | Scala_Project.here, | 
| 263 |     { args =>
 | |
| 264 | var build_options = false | |
| 265 | var get_option = "" | |
| 266 | var list_options = false | |
| 77616 | 267 | var list_tags = List.empty[String] | 
| 75394 | 268 | var export_file = "" | 
| 62437 | 269 | |
| 75394 | 270 |       val getopts = Getopts("""
 | 
| 62437 | 271 | Usage: isabelle options [OPTIONS] [MORE_OPTIONS ...] | 
| 48693 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 272 | |
| 62437 | 273 | Options are: | 
| 274 | -b include $ISABELLE_BUILD_OPTIONS | |
| 275 | -g OPTION get value of OPTION | |
| 276 | -l list options | |
| 77616 | 277 | -t TAGS restrict list to given tags (comma-separated) | 
| 62437 | 278 | -x FILE export options to FILE in YXML format | 
| 279 | ||
| 280 | Report Isabelle system options, augmented by MORE_OPTIONS given as | |
| 281 | arguments NAME=VAL or NAME. | |
| 282 | """, | |
| 75394 | 283 | "b" -> (_ => build_options = true), | 
| 284 | "g:" -> (arg => get_option = arg), | |
| 285 | "l" -> (_ => list_options = true), | |
| 77616 | 286 |         "t:" -> (arg => list_tags = space_explode(',', arg)),
 | 
| 75394 | 287 | "x:" -> (arg => export_file = arg)) | 
| 52737 
7b396ef36af6
clarified meaning of options for "isabelle options";
 wenzelm parents: 
52735diff
changeset | 288 | |
| 75394 | 289 | val more_options = getopts(args) | 
| 290 | if (get_option == "" && !list_options && export_file == "") getopts.usage() | |
| 52737 
7b396ef36af6
clarified meaning of options for "isabelle options";
 wenzelm parents: 
52735diff
changeset | 291 | |
| 75394 | 292 |       val options = {
 | 
| 293 | val options0 = Options.init() | |
| 294 | val options1 = | |
| 77628 | 295 | if (build_options) options0 ++ Options.Spec.ISABELLE_BUILD_OPTIONS else options0 | 
| 75394 | 296 | more_options.foldLeft(options1)(_ + _) | 
| 297 | } | |
| 48693 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 298 | |
| 77613 | 299 |       if (get_option != "") {
 | 
| 75394 | 300 | Output.writeln(options.check_name(get_option).value, stdout = true) | 
| 77613 | 301 | } | 
| 62437 | 302 | |
| 77613 | 303 |       if (export_file != "") {
 | 
| 75394 | 304 | File.write(Path.explode(export_file), YXML.string_of_body(options.encode)) | 
| 77613 | 305 | } | 
| 62437 | 306 | |
| 77613 | 307 |       if (get_option == "" && export_file == "") {
 | 
| 77616 | 308 | val filter: Options.Entry => Boolean = | 
| 309 | if (list_tags.isEmpty) (_ => true) | |
| 77617 | 310 | else opt => list_tags.exists(opt.for_tag) | 
| 77616 | 311 | Output.writeln(options.print(filter = filter), stdout = true) | 
| 77613 | 312 | } | 
| 75394 | 313 | }) | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 314 | } | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 315 | |
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 316 | |
| 49270 | 317 | final class Options private( | 
| 77605 | 318 | options: Map[String, Options.Entry] = Map.empty, | 
| 75393 | 319 | val section: String = "" | 
| 320 | ) {
 | |
| 78407 
b262ecc98319
more operations for independent "inline" options;
 wenzelm parents: 
77668diff
changeset | 321 | def defined(name: String): Boolean = options.isDefinedAt(name) | 
| 
b262ecc98319
more operations for independent "inline" options;
 wenzelm parents: 
77668diff
changeset | 322 | |
| 77605 | 323 | def iterator: Iterator[Options.Entry] = options.valuesIterator | 
| 75844 
7d27944d7141
clarified signature: avoid public representation;
 wenzelm parents: 
75843diff
changeset | 324 | |
| 77605 | 325 |   override def toString: String = iterator.mkString("Options(", ",", ")")
 | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 326 | |
| 77605 | 327 | private def print_entry(opt: Options.Entry): String = | 
| 77614 | 328 | if_proper(opt.public, "public ") + opt.print | 
| 54347 | 329 | |
| 77616 | 330 | def print(filter: Options.Entry => Boolean = _ => true): String = | 
| 331 | cat_lines(iterator.filter(filter).toList.sortBy(_.name).map(print_entry)) | |
| 48693 
ceeea46bdeba
"isabelle options" prints Isabelle system options;
 wenzelm parents: 
48605diff
changeset | 332 | |
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 333 | 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 | 334 | |
| 78559 | 335 | def spec(name: String): Options.Spec = | 
| 78916 | 336 | Options.Spec.eq(name, check_name(name).value) | 
| 78559 | 337 | |
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 338 | |
| 48370 | 339 | /* check */ | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 340 | |
| 77605 | 341 | def get(name: String): Option[Options.Entry] = options.get(name) | 
| 75844 
7d27944d7141
clarified signature: avoid public representation;
 wenzelm parents: 
75843diff
changeset | 342 | |
| 77605 | 343 | def check_name(name: String): Options.Entry = | 
| 75844 
7d27944d7141
clarified signature: avoid public representation;
 wenzelm parents: 
75843diff
changeset | 344 |     get(name) match {
 | 
| 48860 | 345 | case Some(opt) if !opt.unknown => opt | 
| 346 |       case _ => error("Unknown option " + quote(name))
 | |
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 347 | } | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 348 | |
| 77605 | 349 |   private def check_type(name: String, typ: Options.Type): Options.Entry = {
 | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 350 | val opt = check_name(name) | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 351 | if (opt.typ == typ) opt | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 352 |     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 | 353 | } | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 354 | |
| 48370 | 355 | |
| 356 | /* basic operations */ | |
| 357 | ||
| 75843 | 358 |   private def put(name: String, typ: Options.Type, value: String): Options = {
 | 
| 48370 | 359 | val opt = check_type(name, typ) | 
| 49270 | 360 | new Options(options + (name -> opt.copy(value = value)), section) | 
| 48370 | 361 | } | 
| 362 | ||
| 75393 | 363 |   private def get[A](name: String, typ: Options.Type, parse: String => Option[A]): A = {
 | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 364 | val opt = check_type(name, typ) | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 365 |     parse(opt.value) match {
 | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 366 | case Some(x) => x | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 367 | case None => | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 368 |         error("Malformed value for option " + quote(name) +
 | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 369 | " : " + typ.print + " =\n" + quote(opt.value)) | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 370 | } | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 371 | } | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 372 | |
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 373 | |
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 374 | /* internal lookup and update */ | 
| 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 375 | |
| 75846 | 376 | val bool: Options.Access[Boolean] = | 
| 377 |     new Options.Access[Boolean](this) {
 | |
| 378 | def apply(name: String): Boolean = get(name, Options.Bool, Value.Boolean.unapply) | |
| 379 | def update(name: String, x: Boolean): Options = put(name, Options.Bool, Value.Boolean(x)) | |
| 380 | } | |
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 381 | |
| 75846 | 382 | val int: Options.Access[Int] = | 
| 383 |     new Options.Access[Int](this) {
 | |
| 384 | def apply(name: String): Int = get(name, Options.Int, Value.Int.unapply) | |
| 385 | def update(name: String, x: Int): Options = put(name, Options.Int, Value.Int(x)) | |
| 386 | } | |
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 387 | |
| 75846 | 388 | val real: Options.Access[Double] = | 
| 389 |     new Options.Access[Double](this) {
 | |
| 390 | def apply(name: String): Double = get(name, Options.Real, Value.Double.unapply) | |
| 391 | def update(name: String, x: Double): Options = put(name, Options.Real, Value.Double(x)) | |
| 392 | } | |
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 393 | |
| 75846 | 394 | val string: Options.Access[String] = | 
| 395 |     new Options.Access[String](this) {
 | |
| 396 | def apply(name: String): String = get(name, Options.String, Some(_)) | |
| 397 | def update(name: String, x: String): Options = put(name, Options.String, x) | |
| 398 | } | |
| 48370 | 399 | |
| 69073 | 400 | def seconds(name: String): Time = Time.seconds(real(name)) | 
| 50207 | 401 | |
| 79655 | 402 | def threads(default: => Int = Multithreading.num_processors()): Int = | 
| 403 |     Multithreading.max_threads(value = int("threads"), default = default)
 | |
| 404 | ||
| 79656 
10e560f2f580
more robust default: Scala imposes explicit "threads" value on ML, both the Poly/ML RTS and Isabelle/ML;
 wenzelm parents: 
79655diff
changeset | 405 |   def standard_ml(): Options = int.update("threads", threads())
 | 
| 
10e560f2f580
more robust default: Scala imposes explicit "threads" value on ML, both the Poly/ML RTS and Isabelle/ML;
 wenzelm parents: 
79655diff
changeset | 406 | |
| 48370 | 407 | |
| 48807 | 408 | /* external updates */ | 
| 48370 | 409 | |
| 75393 | 410 |   private def check_value(name: String): Options = {
 | 
| 48370 | 411 | val opt = check_name(name) | 
| 412 |     opt.typ match {
 | |
| 413 | case Options.Bool => bool(name); this | |
| 414 | case Options.Int => int(name); this | |
| 415 | case Options.Real => real(name); this | |
| 416 | case Options.String => string(name); this | |
| 48860 | 417 | case Options.Unknown => this | 
| 48370 | 418 | } | 
| 419 | } | |
| 420 | ||
| 56465 | 421 | def declare( | 
| 422 | public: Boolean, | |
| 423 | pos: Position.T, | |
| 424 | name: String, | |
| 425 | typ_name: String, | |
| 426 | value: String, | |
| 74827 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 427 | standard: Option[Option[String]], | 
| 77603 | 428 | tags: List[String], | 
| 75393 | 429 | description: String | 
| 430 |   ): Options = {
 | |
| 75844 
7d27944d7141
clarified signature: avoid public representation;
 wenzelm parents: 
75843diff
changeset | 431 |     get(name) match {
 | 
| 56465 | 432 | case Some(other) => | 
| 433 |         error("Duplicate declaration of option " + quote(name) + Position.here(pos) +
 | |
| 434 | Position.here(other.pos)) | |
| 48370 | 435 | case None => | 
| 436 | val typ = | |
| 437 |           typ_name match {
 | |
| 438 | case "bool" => Options.Bool | |
| 439 | case "int" => Options.Int | |
| 440 | case "real" => Options.Real | |
| 441 | case "string" => Options.String | |
| 56465 | 442 | case _ => | 
| 443 |               error("Unknown type for option " + quote(name) + " : " + quote(typ_name) +
 | |
| 444 | Position.here(pos)) | |
| 48370 | 445 | } | 
| 74827 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 446 | val standard_value = | 
| 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 447 |           standard match {
 | 
| 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 448 | case None => None | 
| 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 449 | case Some(_) if typ == Options.Bool => | 
| 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 450 |               error("Illegal standard value for option " + quote(name) + " : " + typ_name +
 | 
| 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 451 | Position.here) | 
| 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 452 | case Some(s) => Some(s.getOrElse(value)) | 
| 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 453 | } | 
| 
c1b5d6e6ff74
clarified system option standard values: avoid oddities like "isabelle build -o document_output" producing directories named "true";
 wenzelm parents: 
74144diff
changeset | 454 | val opt = | 
| 77605 | 455 | Options.Entry( | 
| 77603 | 456 | public, pos, name, typ, value, value, standard_value, tags, description, section) | 
| 49270 | 457 | (new Options(options + (name -> opt), section)).check_value(name) | 
| 48370 | 458 | } | 
| 459 | } | |
| 460 | ||
| 77626 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 461 |   def + (spec: Options.Spec): Options = {
 | 
| 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 462 | val name = spec.name | 
| 78407 
b262ecc98319
more operations for independent "inline" options;
 wenzelm parents: 
77668diff
changeset | 463 |     if (spec.permissive && !defined(name)) {
 | 
| 77626 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 464 |       val value = spec.value.getOrElse("")
 | 
| 77603 | 465 | val opt = | 
| 77605 | 466 | Options.Entry(false, Position.none, name, Options.Unknown, value, value, None, Nil, "", "") | 
| 56465 | 467 | new Options(options + (name -> opt), section) | 
| 468 | } | |
| 77626 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 469 |     else {
 | 
| 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 470 | val opt = check_name(name) | 
| 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 471 | def put(value: String): Options = | 
| 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 472 | (new Options(options + (name -> opt.copy(value = value)), section)).check_value(name) | 
| 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 473 |       spec.value orElse opt.standard_value match {
 | 
| 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 474 | case Some(value) => put(value) | 
| 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 475 |         case None if opt.typ == Options.Bool => put("true")
 | 
| 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 476 |         case None => error("Missing value for option " + quote(name) + " : " + opt.typ.print)
 | 
| 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 477 | } | 
| 48370 | 478 | } | 
| 479 | } | |
| 480 | ||
| 77626 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 481 | def + (s: String): Options = this + Options.Spec.make(s) | 
| 48456 
d8ff14f44a40
added ML version of stand-alone options, with XML.encode/decode operations (unidirectional from Scala to ML);
 wenzelm parents: 
48421diff
changeset | 482 | |
| 77626 
af8ac22d97f0
clarified signature: more explicit type Options.Spec, which incorporates all variants of Options.+;
 wenzelm parents: 
77625diff
changeset | 483 | def ++ (specs: List[Options.Spec]): Options = specs.foldLeft(this)(_ + _) | 
| 48807 | 484 | |
| 48456 
d8ff14f44a40
added ML version of stand-alone options, with XML.encode/decode operations (unidirectional from Scala to ML);
 wenzelm parents: 
48421diff
changeset | 485 | |
| 49270 | 486 | /* sections */ | 
| 487 | ||
| 488 | def set_section(new_section: String): Options = | |
| 489 | new Options(options, new_section) | |
| 490 | ||
| 77605 | 491 | def sections: List[(String, List[Options.Entry])] = | 
| 49270 | 492 |     options.groupBy(_._2.section).toList.map({ case (a, opts) => (a, opts.toList.map(_._2)) })
 | 
| 493 | ||
| 494 | ||
| 48456 
d8ff14f44a40
added ML version of stand-alone options, with XML.encode/decode operations (unidirectional from Scala to ML);
 wenzelm parents: 
48421diff
changeset | 495 | /* encode */ | 
| 
d8ff14f44a40
added ML version of stand-alone options, with XML.encode/decode operations (unidirectional from Scala to ML);
 wenzelm parents: 
48421diff
changeset | 496 | |
| 75393 | 497 |   def encode: XML.Body = {
 | 
| 48860 | 498 | val opts = | 
| 56465 | 499 | for ((_, opt) <- options.toList; if !opt.unknown) | 
| 500 | yield (opt.pos, (opt.name, (opt.typ.print, opt.value))) | |
| 48860 | 501 | |
| 56465 | 502 |     import XML.Encode.{string => string_, _}
 | 
| 503 | list(pair(properties, pair(string_, pair(string_, string_))))(opts) | |
| 48456 
d8ff14f44a40
added ML version of stand-alone options, with XML.encode/decode operations (unidirectional from Scala to ML);
 wenzelm parents: 
48421diff
changeset | 504 | } | 
| 48807 | 505 | |
| 506 | ||
| 77622 
f458547b4f0f
clarified signature (again, see also 8c64e51d9dde and 268bf61631ec);
 wenzelm parents: 
77621diff
changeset | 507 | /* changed options */ | 
| 
f458547b4f0f
clarified signature (again, see also 8c64e51d9dde and 268bf61631ec);
 wenzelm parents: 
77621diff
changeset | 508 | |
| 
f458547b4f0f
clarified signature (again, see also 8c64e51d9dde and 268bf61631ec);
 wenzelm parents: 
77621diff
changeset | 509 | def changed( | 
| 
f458547b4f0f
clarified signature (again, see also 8c64e51d9dde and 268bf61631ec);
 wenzelm parents: 
77621diff
changeset | 510 | defaults: Options = Options.init0(), | 
| 
f458547b4f0f
clarified signature (again, see also 8c64e51d9dde and 268bf61631ec);
 wenzelm parents: 
77621diff
changeset | 511 | filter: Options.Entry => Boolean = _ => true | 
| 77623 | 512 |   ): List[Options.Change] = {
 | 
| 77622 
f458547b4f0f
clarified signature (again, see also 8c64e51d9dde and 268bf61631ec);
 wenzelm parents: 
77621diff
changeset | 513 | List.from( | 
| 
f458547b4f0f
clarified signature (again, see also 8c64e51d9dde and 268bf61631ec);
 wenzelm parents: 
77621diff
changeset | 514 |       for {
 | 
| 
f458547b4f0f
clarified signature (again, see also 8c64e51d9dde and 268bf61631ec);
 wenzelm parents: 
77621diff
changeset | 515 | (name, opt2) <- options.iterator | 
| 
f458547b4f0f
clarified signature (again, see also 8c64e51d9dde and 268bf61631ec);
 wenzelm parents: 
77621diff
changeset | 516 | opt1 = defaults.get(name) | 
| 
f458547b4f0f
clarified signature (again, see also 8c64e51d9dde and 268bf61631ec);
 wenzelm parents: 
77621diff
changeset | 517 | if (opt1.isEmpty || opt1.get.value != opt2.value) && filter(opt2) | 
| 77668 
5cb7fd36223b
proper sorting of result (amending f458547b4f0f);
 wenzelm parents: 
77628diff
changeset | 518 | } yield Options.Change(name, opt2.value, opt1.isEmpty)).sortBy(_.name) | 
| 77622 
f458547b4f0f
clarified signature (again, see also 8c64e51d9dde and 268bf61631ec);
 wenzelm parents: 
77621diff
changeset | 519 | } | 
| 
f458547b4f0f
clarified signature (again, see also 8c64e51d9dde and 268bf61631ec);
 wenzelm parents: 
77621diff
changeset | 520 | |
| 
f458547b4f0f
clarified signature (again, see also 8c64e51d9dde and 268bf61631ec);
 wenzelm parents: 
77621diff
changeset | 521 | |
| 77608 | 522 | /* preferences */ | 
| 48807 | 523 | |
| 77603 | 524 | def make_prefs( | 
| 77609 | 525 | defaults: Options = Options.init0(), | 
| 77605 | 526 | filter: Options.Entry => Boolean = _ => true | 
| 77622 
f458547b4f0f
clarified signature (again, see also 8c64e51d9dde and 268bf61631ec);
 wenzelm parents: 
77621diff
changeset | 527 | ): String = changed(defaults = defaults, filter = filter).map(_.print_prefs).mkString | 
| 77374 
268bf61631ec
more robust options in "prefs" format: avoid odd control character;
 wenzelm parents: 
77366diff
changeset | 528 | |
| 77609 | 529 |   def save_prefs(file: Path = Options.PREFS, defaults: Options = Options.init0()): Unit = {
 | 
| 77374 
268bf61631ec
more robust options in "prefs" format: avoid odd control character;
 wenzelm parents: 
77366diff
changeset | 530 | val prefs = make_prefs(defaults = defaults) | 
| 72375 | 531 | Isabelle_System.make_directory(file.dir) | 
| 67845 | 532 | File.write_backup(file, "(* generated by Isabelle " + Date.now() + " *)\n\n" + prefs) | 
| 48807 | 533 | } | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: diff
changeset | 534 | } | 
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 535 | |
| 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 536 | |
| 75393 | 537 | class Options_Variable(init_options: Options) {
 | 
| 75846 | 538 | private var _options = init_options | 
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 539 | |
| 75846 | 540 |   def value: Options = synchronized { _options }
 | 
| 541 |   def change(f: Options => Options): Unit = synchronized { _options = f(_options) }
 | |
| 78916 | 542 | def += (name: String, x: String): Unit = change(options => options + Options.Spec.eq(name, x)) | 
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 543 | |
| 75846 | 544 | val bool: Options.Access_Variable[Boolean] = | 
| 75847 | 545 | new Options.Access_Variable[Boolean](this, _.bool) | 
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 546 | |
| 75846 | 547 | val int: Options.Access_Variable[Int] = | 
| 75847 | 548 | new Options.Access_Variable[Int](this, _.int) | 
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 549 | |
| 75846 | 550 | val real: Options.Access_Variable[Double] = | 
| 75847 | 551 | new Options.Access_Variable[Double](this, _.real) | 
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 552 | |
| 75846 | 553 | val string: Options.Access_Variable[String] = | 
| 75847 | 554 | new Options.Access_Variable[String](this, _.string) | 
| 50207 | 555 | |
| 69073 | 556 | def seconds(name: String): Time = value.seconds(name) | 
| 49245 
cb70157293c0
manage Isabelle/jEdit options as Isabelle/Scala options (with persistent preferences);
 wenzelm parents: 
48992diff
changeset | 557 | } |