diff --git a/etc/build.props b/etc/build.props --- a/etc/build.props +++ b/etc/build.props @@ -1,302 +1,301 @@ title = Isabelle/Scala module = $ISABELLE_HOME/lib/classes/isabelle.jar main = isabelle.jedit.Main resources = \ lib/services/java.nio.charset.spi.CharsetProvider:META-INF/services/ \ lib/logo/isabelle_transparent-32.gif:isabelle/ \ lib/logo/isabelle_transparent.gif:isabelle/ sources = \ src/HOL/SPARK/Tools/spark.scala \ src/HOL/Tools/ATP/system_on_tptp.scala \ src/HOL/Tools/Mirabelle/mirabelle.scala \ src/HOL/Tools/Nitpick/kodkod.scala \ src/Pure/Admin/afp.scala \ src/Pure/Admin/build_csdp.scala \ src/Pure/Admin/build_cygwin.scala \ src/Pure/Admin/build_doc.scala \ src/Pure/Admin/build_e.scala \ src/Pure/Admin/build_fonts.scala \ src/Pure/Admin/build_history.scala \ src/Pure/Admin/build_jcef.scala \ src/Pure/Admin/build_jdk.scala \ src/Pure/Admin/build_jedit.scala \ src/Pure/Admin/build_log.scala \ src/Pure/Admin/build_minisat.scala \ src/Pure/Admin/build_pdfjs.scala \ src/Pure/Admin/build_polyml.scala \ src/Pure/Admin/build_release.scala \ src/Pure/Admin/build_spass.scala \ src/Pure/Admin/build_sqlite.scala \ src/Pure/Admin/build_status.scala \ src/Pure/Admin/build_vampire.scala \ src/Pure/Admin/build_verit.scala \ src/Pure/Admin/build_zipperposition.scala \ src/Pure/Admin/check_sources.scala \ src/Pure/Admin/ci_profile.scala \ src/Pure/Admin/isabelle_cronjob.scala \ src/Pure/Admin/isabelle_devel.scala \ src/Pure/Admin/jenkins.scala \ src/Pure/Admin/other_isabelle.scala \ src/Pure/Concurrent/consumer_thread.scala \ src/Pure/Concurrent/counter.scala \ src/Pure/Concurrent/delay.scala \ src/Pure/Concurrent/event_timer.scala \ src/Pure/Concurrent/future.scala \ src/Pure/Concurrent/isabelle_thread.scala \ src/Pure/Concurrent/mailbox.scala \ src/Pure/Concurrent/par_list.scala \ src/Pure/Concurrent/synchronized.scala \ src/Pure/GUI/color_value.scala \ src/Pure/GUI/desktop_app.scala \ src/Pure/GUI/gui.scala \ src/Pure/GUI/gui_thread.scala \ src/Pure/GUI/popup.scala \ src/Pure/GUI/wrap_panel.scala \ src/Pure/General/antiquote.scala \ src/Pure/General/bytes.scala \ src/Pure/General/cache.scala \ src/Pure/General/codepoint.scala \ src/Pure/General/comment.scala \ src/Pure/General/completion.scala \ src/Pure/General/csv.scala \ src/Pure/General/date.scala \ src/Pure/General/exn.scala \ src/Pure/General/file.scala \ src/Pure/General/file_watcher.scala \ src/Pure/General/graph.scala \ src/Pure/General/graph_display.scala \ src/Pure/General/graphics_file.scala \ src/Pure/General/http.scala \ src/Pure/General/json.scala \ src/Pure/General/json_api.scala \ src/Pure/General/linear_set.scala \ src/Pure/General/logger.scala \ src/Pure/General/long_name.scala \ src/Pure/General/mailman.scala \ src/Pure/General/mercurial.scala \ src/Pure/General/multi_map.scala \ src/Pure/General/output.scala \ src/Pure/General/path.scala \ src/Pure/General/position.scala \ src/Pure/General/pretty.scala \ src/Pure/General/properties.scala \ src/Pure/General/rdf.scala \ src/Pure/General/scan.scala \ src/Pure/General/sha1.scala \ src/Pure/General/sql.scala \ src/Pure/General/ssh.scala \ src/Pure/General/symbol.scala \ src/Pure/General/time.scala \ src/Pure/General/timing.scala \ src/Pure/General/untyped.scala \ src/Pure/General/url.scala \ src/Pure/General/utf8.scala \ src/Pure/General/uuid.scala \ src/Pure/General/value.scala \ src/Pure/General/word.scala \ src/Pure/General/xz.scala \ src/Pure/Isar/document_structure.scala \ src/Pure/Isar/keyword.scala \ src/Pure/Isar/line_structure.scala \ src/Pure/Isar/outer_syntax.scala \ src/Pure/Isar/parse.scala \ src/Pure/Isar/token.scala \ src/Pure/ML/ml_console.scala \ src/Pure/ML/ml_lex.scala \ src/Pure/ML/ml_process.scala \ src/Pure/ML/ml_profiling.scala \ src/Pure/ML/ml_statistics.scala \ src/Pure/ML/ml_syntax.scala \ src/Pure/PIDE/byte_message.scala \ src/Pure/PIDE/command.scala \ src/Pure/PIDE/command_span.scala \ src/Pure/PIDE/document.scala \ src/Pure/PIDE/document_id.scala \ src/Pure/PIDE/document_status.scala \ src/Pure/PIDE/editor.scala \ src/Pure/PIDE/headless.scala \ src/Pure/PIDE/line.scala \ src/Pure/PIDE/markup.scala \ src/Pure/PIDE/markup_tree.scala \ src/Pure/PIDE/protocol.scala \ src/Pure/PIDE/protocol_handlers.scala \ src/Pure/PIDE/protocol_message.scala \ src/Pure/PIDE/prover.scala \ src/Pure/PIDE/query_operation.scala \ src/Pure/PIDE/rendering.scala \ src/Pure/PIDE/resources.scala \ src/Pure/PIDE/session.scala \ src/Pure/PIDE/text.scala \ src/Pure/PIDE/xml.scala \ src/Pure/PIDE/yxml.scala \ src/Pure/ROOT.scala \ src/Pure/System/bash.scala \ src/Pure/System/command_line.scala \ src/Pure/System/components.scala \ src/Pure/System/executable.scala \ src/Pure/System/getopts.scala \ src/Pure/System/isabelle_charset.scala \ src/Pure/System/isabelle_fonts.scala \ src/Pure/System/isabelle_platform.scala \ src/Pure/System/isabelle_process.scala \ src/Pure/System/isabelle_system.scala \ src/Pure/System/isabelle_tool.scala \ src/Pure/System/java_statistics.scala \ src/Pure/System/linux.scala \ src/Pure/System/mingw.scala \ src/Pure/System/numa.scala \ src/Pure/System/options.scala \ src/Pure/System/platform.scala \ src/Pure/System/posix_interrupt.scala \ src/Pure/System/process_result.scala \ src/Pure/System/progress.scala \ src/Pure/System/scala.scala \ src/Pure/System/system_channel.scala \ src/Pure/System/tty_loop.scala \ src/Pure/Thy/bibtex.scala \ src/Pure/Thy/document_build.scala \ src/Pure/Thy/export.scala \ src/Pure/Thy/export_theory.scala \ src/Pure/Thy/file_format.scala \ src/Pure/Thy/html.scala \ src/Pure/Thy/latex.scala \ src/Pure/Thy/presentation.scala \ src/Pure/Thy/sessions.scala \ src/Pure/Thy/thy_element.scala \ src/Pure/Thy/thy_header.scala \ src/Pure/Thy/thy_syntax.scala \ src/Pure/Tools/build.scala \ src/Pure/Tools/build_docker.scala \ src/Pure/Tools/build_job.scala \ src/Pure/Tools/check_keywords.scala \ src/Pure/Tools/debugger.scala \ src/Pure/Tools/doc.scala \ src/Pure/Tools/dump.scala \ src/Pure/Tools/flarum.scala \ src/Pure/Tools/fontforge.scala \ src/Pure/Tools/java_monitor.scala \ src/Pure/Tools/logo.scala \ src/Pure/Tools/mkroot.scala \ src/Pure/Tools/phabricator.scala \ src/Pure/Tools/print_operation.scala \ src/Pure/Tools/profiling_report.scala \ src/Pure/Tools/scala_build.scala \ src/Pure/Tools/scala_project.scala \ src/Pure/Tools/server.scala \ src/Pure/Tools/server_commands.scala \ src/Pure/Tools/simplifier_trace.scala \ src/Pure/Tools/spell_checker.scala \ src/Pure/Tools/task_statistics.scala \ src/Pure/Tools/update.scala \ src/Pure/Tools/update_cartouches.scala \ src/Pure/Tools/update_comments.scala \ src/Pure/Tools/update_header.scala \ src/Pure/Tools/update_then.scala \ src/Pure/Tools/update_theorems.scala \ src/Pure/library.scala \ src/Pure/pure_thy.scala \ src/Pure/term.scala \ src/Pure/term_xml.scala \ src/Pure/thm_name.scala \ src/Tools/Graphview/graph_file.scala \ src/Tools/Graphview/graph_panel.scala \ src/Tools/Graphview/graphview.scala \ src/Tools/Graphview/layout.scala \ src/Tools/Graphview/main_panel.scala \ src/Tools/Graphview/metrics.scala \ src/Tools/Graphview/model.scala \ src/Tools/Graphview/mutator.scala \ src/Tools/Graphview/mutator_dialog.scala \ src/Tools/Graphview/mutator_event.scala \ src/Tools/Graphview/popups.scala \ src/Tools/Graphview/shapes.scala \ src/Tools/Graphview/tree_panel.scala \ src/Tools/VSCode/src/build_vscode_extension.scala \ src/Tools/VSCode/src/build_vscodium.scala \ src/Tools/VSCode/src/channel.scala \ src/Tools/VSCode/src/dynamic_output.scala \ src/Tools/VSCode/src/language_server.scala \ src/Tools/VSCode/src/lsp.scala \ src/Tools/VSCode/src/preview_panel.scala \ src/Tools/VSCode/src/state_panel.scala \ - src/Tools/VSCode/src/textmate_grammar.scala \ src/Tools/VSCode/src/vscode_model.scala \ src/Tools/VSCode/src/vscode_rendering.scala \ src/Tools/VSCode/src/vscode_resources.scala \ src/Tools/VSCode/src/vscode_setup.scala \ src/Tools/VSCode/src/vscode_spell_checker.scala \ src/Tools/jEdit/src/active.scala \ src/Tools/jEdit/src/base_plugin.scala \ src/Tools/jEdit/src/completion_popup.scala \ src/Tools/jEdit/src/context_menu.scala \ src/Tools/jEdit/src/debugger_dockable.scala \ src/Tools/jEdit/src/dockable.scala \ src/Tools/jEdit/src/document_model.scala \ src/Tools/jEdit/src/document_view.scala \ src/Tools/jEdit/src/documentation_dockable.scala \ src/Tools/jEdit/src/fold_handling.scala \ src/Tools/jEdit/src/font_info.scala \ src/Tools/jEdit/src/graphview_dockable.scala \ src/Tools/jEdit/src/info_dockable.scala \ src/Tools/jEdit/src/isabelle.scala \ src/Tools/jEdit/src/isabelle_encoding.scala \ src/Tools/jEdit/src/isabelle_export.scala \ src/Tools/jEdit/src/isabelle_options.scala \ src/Tools/jEdit/src/isabelle_session.scala \ src/Tools/jEdit/src/isabelle_vfs.scala \ src/Tools/jEdit/src/jedit_bibtex.scala \ src/Tools/jEdit/src/jedit_editor.scala \ src/Tools/jEdit/src/jedit_lib.scala \ src/Tools/jEdit/src/jedit_options.scala \ src/Tools/jEdit/src/jedit_plugins.scala \ src/Tools/jEdit/src/jedit_rendering.scala \ src/Tools/jEdit/src/jedit_resources.scala \ src/Tools/jEdit/src/jedit_sessions.scala \ src/Tools/jEdit/src/jedit_spell_checker.scala \ src/Tools/jEdit/src/keymap_merge.scala \ src/Tools/jEdit/src/main.scala \ src/Tools/jEdit/src/main_plugin.scala \ src/Tools/jEdit/src/monitor_dockable.scala \ src/Tools/jEdit/src/output_dockable.scala \ src/Tools/jEdit/src/pide_docking_framework.scala \ src/Tools/jEdit/src/pretty_text_area.scala \ src/Tools/jEdit/src/pretty_tooltip.scala \ src/Tools/jEdit/src/process_indicator.scala \ src/Tools/jEdit/src/protocol_dockable.scala \ src/Tools/jEdit/src/query_dockable.scala \ src/Tools/jEdit/src/raw_output_dockable.scala \ src/Tools/jEdit/src/rich_text_area.scala \ src/Tools/jEdit/src/session_build.scala \ src/Tools/jEdit/src/simplifier_trace_dockable.scala \ src/Tools/jEdit/src/simplifier_trace_window.scala \ src/Tools/jEdit/src/sledgehammer_dockable.scala \ src/Tools/jEdit/src/state_dockable.scala \ src/Tools/jEdit/src/status_widget.scala \ src/Tools/jEdit/src/symbols_dockable.scala \ src/Tools/jEdit/src/syntax_style.scala \ src/Tools/jEdit/src/syslog_dockable.scala \ src/Tools/jEdit/src/text_overview.scala \ src/Tools/jEdit/src/text_structure.scala \ src/Tools/jEdit/src/theories_dockable.scala \ src/Tools/jEdit/src/timing_dockable.scala \ src/Tools/jEdit/src/token_markup.scala services = \ isabelle.Bash$Handler \ isabelle.Bibtex$File_Format \ isabelle.Document_Build$Build_Engine \ isabelle.Document_Build$LuaLaTeX_Engine \ isabelle.Document_Build$PDFLaTeX_Engine \ isabelle.ML_Statistics$Handler \ isabelle.Print_Operation$Handler \ isabelle.Scala$Handler \ isabelle.Scala_Functions \ isabelle.Server_Commands \ isabelle.Sessions$File_Format \ isabelle.Simplifier_Trace$Handler \ isabelle.Tools \ isabelle.jedit.JEdit_Plugin0 \ isabelle.jedit.JEdit_Plugin1 \ isabelle.nitpick.Kodkod$Handler \ isabelle.nitpick.Scala_Functions \ isabelle.spark.SPARK$Load_Command1 \ isabelle.spark.SPARK$Load_Command2 diff --git a/src/Pure/System/isabelle_tool.scala b/src/Pure/System/isabelle_tool.scala --- a/src/Pure/System/isabelle_tool.scala +++ b/src/Pure/System/isabelle_tool.scala @@ -1,240 +1,239 @@ /* Title: Pure/System/isabelle_tool.scala Author: Makarius Author: Lars Hupel Isabelle system tools: external executables or internal Scala functions. */ package isabelle import java.net.URLClassLoader import scala.reflect.runtime.universe import scala.tools.reflect.{ToolBox, ToolBoxError} object Isabelle_Tool { /* Scala source tools */ abstract class Body extends Function[List[String], Unit] private def compile(path: Path): Body = { def err(msg: String): Nothing = cat_error(msg, "The error(s) above occurred in Isabelle/Scala tool " + path) val source = File.read(path) val class_loader = new URLClassLoader(Array(), getClass.getClassLoader) val tool_box = universe.runtimeMirror(class_loader).mkToolBox() try { val tree = tool_box.parse(source) val module = try { tree.asInstanceOf[universe.ModuleDef] } catch { case _: java.lang.ClassCastException => err("Source does not describe a module (Scala object)") } tool_box.compile(universe.Ident(tool_box.define(module)))() match { case body: Body => body case _ => err("Ill-typed source: Isabelle_Tool.Body expected") } } catch { case e: ToolBoxError => if (tool_box.frontEnd.hasErrors) { val infos = tool_box.frontEnd.infos.toList val msgs = infos.map(info => "Error in line " + info.pos.line + ":\n" + info.msg) err(msgs.mkString("\n")) } else err(e.toString) } } /* external tools */ private def dirs(): List[Path] = Path.split(Isabelle_System.getenv_strict("ISABELLE_TOOLS")) private def is_external(dir: Path, file_name: String): Boolean = { val file = (dir + Path.explode(file_name)).file try { file.isFile && file.canRead && (file_name.endsWith(".scala") || file.canExecute) && !file_name.endsWith("~") && !file_name.endsWith(".orig") } catch { case _: SecurityException => false } } private def find_external(name: String): Option[List[String] => Unit] = dirs().collectFirst({ case dir if is_external(dir, name + ".scala") => compile(dir + Path.explode(name + ".scala")) case dir if is_external(dir, name) => (args: List[String]) => { val tool = dir + Path.explode(name) val result = Isabelle_System.bash(File.bash_path(tool) + " " + Bash.strings(args)) sys.exit(result.print_stdout.rc) } }) /* internal tools */ private lazy val internal_tools: List[Isabelle_Tool] = Isabelle_System.make_services(classOf[Isabelle_Scala_Tools]).flatMap(_.tools) private def find_internal(name: String): Option[List[String] => Unit] = internal_tools.collectFirst({ case tool if tool.name == name => args => Command_Line.tool { tool.body(args) } }) /* list tools */ abstract class Entry { def name: String def position: Properties.T def description: String def print: String = description match { case "" => name case descr => name + " - " + descr } } sealed case class External(name: String, path: Path) extends Entry { def position: Properties.T = Position.File(path.absolute.implode) def description: String = { val Pattern = """.*\bDESCRIPTION: *(.*)""".r split_lines(File.read(path)).collectFirst({ case Pattern(s) => s }) getOrElse "" } } def external_tools(): List[External] = { for { dir <- dirs() if dir.is_dir file_name <- File.read_dir(dir) if is_external(dir, file_name) } yield { val path = dir + Path.explode(file_name) val name = Library.perhaps_unsuffix(".scala", file_name) External(name, path) } } def isabelle_tools(): List[Entry] = (external_tools() ::: internal_tools).sortBy(_.name) object Isabelle_Tools extends Scala.Fun_String("isabelle_tools") { val here = Scala_Project.here def apply(arg: String): String = if (arg.nonEmpty) error("Bad argument: " + quote(arg)) else { val result = isabelle_tools().map(entry => (entry.name, entry.position)) val body = { import XML.Encode._; list(pair(string, properties))(result) } YXML.string_of_body(body) } } /* command line entry point */ def main(args: Array[String]): Unit = { Command_Line.tool { args.toList match { case Nil | List("-?") => val tool_descriptions = isabelle_tools().map(_.print) Getopts(""" Usage: isabelle TOOL [ARGS ...] Start Isabelle TOOL with ARGS; pass "-?" for tool-specific help. Available tools:""" + tool_descriptions.mkString("\n ", "\n ", "\n")).usage() case tool_name :: tool_args => find_external(tool_name) orElse find_internal(tool_name) match { case Some(tool) => tool(tool_args) case None => error("Unknown Isabelle tool: " + quote(tool_name)) } } } } } sealed case class Isabelle_Tool( name: String, description: String, here: Scala_Project.Here, body: List[String] => Unit) extends Isabelle_Tool.Entry { def position: Position.T = here.position } class Isabelle_Scala_Tools(val tools: Isabelle_Tool*) extends Isabelle_System.Service class Tools extends Isabelle_Scala_Tools( Build.isabelle_tool, Build_Docker.isabelle_tool, Build_Job.isabelle_tool, Doc.isabelle_tool, Document_Build.isabelle_tool, Dump.isabelle_tool, Export.isabelle_tool, ML_Process.isabelle_tool, Mercurial.isabelle_tool, Mkroot.isabelle_tool, Logo.isabelle_tool, Options.isabelle_tool, Phabricator.isabelle_tool1, Phabricator.isabelle_tool2, Phabricator.isabelle_tool3, Phabricator.isabelle_tool4, Profiling_Report.isabelle_tool, Server.isabelle_tool, Sessions.isabelle_tool, Scala_Project.isabelle_tool, Update.isabelle_tool, Update_Cartouches.isabelle_tool, Update_Comments.isabelle_tool, Update_Header.isabelle_tool, Update_Then.isabelle_tool, Update_Theorems.isabelle_tool, isabelle.mirabelle.Mirabelle.isabelle_tool, - isabelle.vscode.TextMate_Grammar.isabelle_tool, isabelle.vscode.Language_Server.isabelle_tool) class Admin_Tools extends Isabelle_Scala_Tools( Build_CSDP.isabelle_tool, Build_Cygwin.isabelle_tool, Build_Doc.isabelle_tool, Build_E.isabelle_tool, Build_Fonts.isabelle_tool, Build_JCEF.isabelle_tool, Build_JDK.isabelle_tool, Build_JEdit.isabelle_tool, Build_Minisat.isabelle_tool, Build_PDFjs.isabelle_tool, Build_PolyML.isabelle_tool1, Build_PolyML.isabelle_tool2, Build_SPASS.isabelle_tool, Build_SQLite.isabelle_tool, Build_Status.isabelle_tool, Build_Vampire.isabelle_tool, Build_VeriT.isabelle_tool, Build_Zipperposition.isabelle_tool, Check_Sources.isabelle_tool, Components.isabelle_tool, isabelle.vscode.Build_VSCode.isabelle_tool, isabelle.vscode.Build_VSCodium.isabelle_tool1, isabelle.vscode.Build_VSCodium.isabelle_tool2, isabelle.vscode.VSCode_Setup.isabelle_tool) diff --git a/src/Tools/VSCode/src/build_vscode_extension.scala b/src/Tools/VSCode/src/build_vscode_extension.scala --- a/src/Tools/VSCode/src/build_vscode_extension.scala +++ b/src/Tools/VSCode/src/build_vscode_extension.scala @@ -1,98 +1,213 @@ /* Title: Tools/VSCode/src/build_vscode_extension.scala Author: Makarius Build the Isabelle/VSCode extension. */ package isabelle.vscode import isabelle._ object Build_VSCode { - val extension_dir = Path.explode("$ISABELLE_VSCODE_HOME/extension") + val extension_dir: Path = Path.explode("$ISABELLE_VSCODE_HOME/extension") - /* grammar */ + /* build grammar */ - def build_grammar(options: Options, progress: Progress = new Progress): Unit = + def default_logic: String = Isabelle_System.getenv("ISABELLE_LOGIC") + + def build_grammar(options: Options, + logic: String = default_logic, + dirs: List[Path] = Nil, + progress: Progress = new Progress): Unit = { - val logic = TextMate_Grammar.default_logic - val keywords = Sessions.base_info(options, logic).check.base.overall_syntax.keywords + val keywords = + Sessions.base_info(options, logic, dirs = dirs).check.base.overall_syntax.keywords - val output_path = extension_dir + Path.explode(TextMate_Grammar.default_output(logic)) + val output_path = extension_dir + Path.explode("isabelle-grammar.json") progress.echo(output_path.expand.implode) - File.write_backup(output_path, TextMate_Grammar.generate(keywords)) + + val (minor_keywords, operators) = + keywords.minor.iterator.toList.partition(Symbol.is_ascii_identifier) + + def major_keywords(pred: String => Boolean): List[String] = + (for { + k <- keywords.major.iterator + kind <- keywords.kinds.get(k) + if pred(kind) + } yield k).toList + + val keywords1 = + major_keywords(k => k != Keyword.THY_END && k != Keyword.PRF_ASM && k != Keyword.PRF_ASM_GOAL) + val keywords2 = minor_keywords ::: major_keywords(Set(Keyword.THY_END)) + val keywords3 = major_keywords(Set(Keyword.PRF_ASM, Keyword.PRF_ASM_GOAL)) + + def grouped_names(as: List[String]): String = + JSON.Format("\\b(" + as.sorted.map(Library.escape_regex).mkString("|") + ")\\b") + + File.write_backup(output_path, """{ + "name": "Isabelle", + "scopeName": "source.isabelle", + "fileTypes": ["thy"], + "uuid": """ + JSON.Format(UUID.random().toString) + """, + "repository": { + "comment": { + "patterns": [ + { + "name": "comment.block.isabelle", + "begin": "\\(\\*", + "patterns": [{ "include": "#comment" }], + "end": "\\*\\)" + } + ] + }, + "cartouche": { + "patterns": [ + { + "name": "string.quoted.other.multiline.isabelle", + "begin": "(?:\\\\|‹)", + "patterns": [{ "include": "#cartouche" }], + "end": "(?:\\\\|›)" + } + ] + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#cartouche" + }, + { + "name": "keyword.control.isabelle", + "match": """ + grouped_names(keywords1) + """ + }, + { + "name": "keyword.other.unit.isabelle", + "match": """ + grouped_names(keywords2) + """ + }, + { + "name": "keyword.operator.isabelle", + "match": """ + grouped_names(operators) + """ + }, + { + "name": "entity.name.type.isabelle", + "match": """ + grouped_names(keywords3) + """ + }, + { + "name": "constant.numeric.isabelle", + "match": "\\b\\d*\\.?\\d+\\b" + }, + { + "name": "string.quoted.double.isabelle", + "begin": "\"", + "patterns": [ + { + "name": "constant.character.escape.isabelle", + "match": """ + JSON.Format("""\\[\"]|\\\d\d\d""") + """ + } + ], + "end": "\"" + }, + { + "name": "string.quoted.backtick.isabelle", + "begin": "`", + "patterns": [ + { + "name": "constant.character.escape.isabelle", + "match": """ + JSON.Format("""\\[\`]|\\\d\d\d""") + """ + } + ], + "end": "`" + }, + { + "name": "string.quoted.verbatim.isabelle", + "begin": """ + JSON.Format("""\{\*""") + """, + "patterns": [ + { "match": """ + JSON.Format("""[^*]+|\*(?!\})""") + """ } + ], + "end": """ + JSON.Format("""\*\}""") + """ + } + ] +} +""") } /* extension */ def uninstall_extension(progress: Progress = new Progress): Unit = progress.bash("isabelle vscode --uninstall-extension Isabelle.isabelle").check def install_extension(vsix_path: Path, progress: Progress = new Progress): Unit = progress.bash("isabelle vscode --install-extension " + File.bash_platform_path(vsix_path)).check def build_extension(progress: Progress = new Progress): Path = { Isabelle_System.require_command("node") Isabelle_System.require_command("yarn") Isabelle_System.require_command("vsce") val output_path = extension_dir + Path.explode("out") Isabelle_System.rm_tree(output_path) Isabelle_System.make_directory(output_path) progress.echo(output_path.expand.implode) val result = progress.bash("yarn && vsce package", cwd = extension_dir.file, echo = true).check val Pattern = """.*Packaged:.*(isabelle-.*\.vsix).*""".r result.out_lines.collectFirst( { case Pattern(vsix_name) => extension_dir + Path.basic(vsix_name) }) .getOrElse(error("Failed to guess resulting .vsix file name")) } /* Isabelle tool wrapper */ val isabelle_tool = Isabelle_Tool("build_vscode_extension", "build Isabelle/VSCode extension module", Scala_Project.here, args => { + var dirs: List[Path] = Nil + var logic = default_logic var install = false var uninstall = false val getopts = Getopts(""" Usage: isabelle build_vscode_extension Options are: -I install resulting extension -U uninstall extension (no build) + -l NAME logic session name (default ISABELLE_LOGIC=""" + quote(default_logic) + """) Build Isabelle/VSCode extension module in directory """ + extension_dir.expand + """ """, + "d:" -> (arg => dirs = dirs ::: List(Path.explode(arg))), + "l:" -> (arg => logic = arg), "I" -> (_ => install = true), "U" -> (_ => uninstall = true)) val more_args = getopts(args) if (more_args.nonEmpty) getopts.usage() val options = Options.init() val progress = new Console_Progress() if (uninstall) { uninstall_extension(progress = progress) } else { - build_grammar(options, progress = progress) + build_grammar(options, logic = logic, dirs = dirs, progress = progress) val path = build_extension(progress = progress) if (install) install_extension(path, progress = progress) } }) } diff --git a/src/Tools/VSCode/src/textmate_grammar.scala b/src/Tools/VSCode/src/textmate_grammar.scala deleted file mode 100644 --- a/src/Tools/VSCode/src/textmate_grammar.scala +++ /dev/null @@ -1,167 +0,0 @@ -/* Title: Tools/VSCode/src/textmate_grammar.scala - Author: Makarius - -Generate static TextMate grammar for VSCode editor. -*/ - -package isabelle.vscode - - -import isabelle._ - - -object TextMate_Grammar -{ - /* generate grammar */ - - lazy val default_logic = Isabelle_System.getenv("ISABELLE_LOGIC") - - def default_output(logic: String = ""): String = - if (logic == "" || logic == default_logic) "isabelle-grammar.json" - else "isabelle-" + logic + "-grammar.json" - - def generate(keywords: Keyword.Keywords): JSON.S = - { - val (minor_keywords, operators) = - keywords.minor.iterator.toList.partition(Symbol.is_ascii_identifier) - - def major_keywords(pred: String => Boolean): List[String] = - (for { - k <- keywords.major.iterator - kind <- keywords.kinds.get(k) - if pred(kind) - } yield k).toList - - val keywords1 = - major_keywords(k => k != Keyword.THY_END && k != Keyword.PRF_ASM && k != Keyword.PRF_ASM_GOAL) - val keywords2 = minor_keywords ::: major_keywords(Set(Keyword.THY_END)) - val keywords3 = major_keywords(Set(Keyword.PRF_ASM, Keyword.PRF_ASM_GOAL)) - - - def grouped_names(as: List[String]): String = - JSON.Format("\\b(" + as.sorted.map(Library.escape_regex).mkString("|") + ")\\b") - - """{ - "name": "Isabelle", - "scopeName": "source.isabelle", - "fileTypes": ["thy"], - "uuid": """ + JSON.Format(UUID.random().toString) + """, - "repository": { - "comment": { - "patterns": [ - { - "name": "comment.block.isabelle", - "begin": "\\(\\*", - "patterns": [{ "include": "#comment" }], - "end": "\\*\\)" - } - ] - }, - "cartouche": { - "patterns": [ - { - "name": "string.quoted.other.multiline.isabelle", - "begin": "(?:\\\\|‹)", - "patterns": [{ "include": "#cartouche" }], - "end": "(?:\\\\|›)" - } - ] - } - }, - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#cartouche" - }, - { - "name": "keyword.control.isabelle", - "match": """ + grouped_names(keywords1) + """ - }, - { - "name": "keyword.other.unit.isabelle", - "match": """ + grouped_names(keywords2) + """ - }, - { - "name": "keyword.operator.isabelle", - "match": """ + grouped_names(operators) + """ - }, - { - "name": "entity.name.type.isabelle", - "match": """ + grouped_names(keywords3) + """ - }, - { - "name": "constant.numeric.isabelle", - "match": "\\b\\d*\\.?\\d+\\b" - }, - { - "name": "string.quoted.double.isabelle", - "begin": "\"", - "patterns": [ - { - "name": "constant.character.escape.isabelle", - "match": """ + JSON.Format("""\\[\"]|\\\d\d\d""") + """ - } - ], - "end": "\"" - }, - { - "name": "string.quoted.backtick.isabelle", - "begin": "`", - "patterns": [ - { - "name": "constant.character.escape.isabelle", - "match": """ + JSON.Format("""\\[\`]|\\\d\d\d""") + """ - } - ], - "end": "`" - }, - { - "name": "string.quoted.verbatim.isabelle", - "begin": """ + JSON.Format("""\{\*""") + """, - "patterns": [ - { "match": """ + JSON.Format("""[^*]+|\*(?!\})""") + """ } - ], - "end": """ + JSON.Format("""\*\}""") + """ - } - ] -} -""" - } - - - /* Isabelle tool wrapper */ - - val isabelle_tool = Isabelle_Tool("vscode_grammar", - "generate static TextMate grammar for VSCode editor", Scala_Project.here, args => - { - var dirs: List[Path] = Nil - var logic = default_logic - var output: Option[Path] = None - - val getopts = Getopts(""" -Usage: isabelle vscode_grammar [OPTIONS] - - Options are: - -d DIR include session directory - -l NAME logic session name (default ISABELLE_LOGIC=""" + quote(default_logic) + """) - -o FILE output file name (default """ + default_output() + """) - - Generate static TextMate grammar for VSCode editor. -""", - "d:" -> (arg => dirs = dirs ::: List(Path.explode(arg))), - "l:" -> (arg => logic = arg), - "o:" -> (arg => output = Some(Path.explode(arg)))) - - val more_args = getopts(args) - if (more_args.nonEmpty) getopts.usage() - - val keywords = - Sessions.base_info(Options.init(), logic, dirs = dirs).check.base.overall_syntax.keywords - val output_path = output getOrElse Path.explode(default_output(logic)) - - Output.writeln(output_path.implode) - File.write_backup(output_path, generate(keywords)) - }) -}