1 /* Title: Tools/jEdit/src/isabelle.scala
4 Global configuration and convenience operations for Isabelle/jEdit.
12 import scala.swing.CheckBox
13 import scala.swing.event.ButtonClicked
15 import org.gjt.sp.jedit.{jEdit, View, Buffer}
16 import org.gjt.sp.jedit.textarea.JEditTextArea
17 import org.gjt.sp.jedit.gui.{DockableWindowManager, CompleteWord}
26 "isabelle", // theory source
27 "isabelle-ml", // ML source
28 "isabelle-markup", // SideKick markup tree
29 "isabelle-news", // NEWS
30 "isabelle-options", // etc/options
31 "isabelle-output", // pretty text area output
32 "isabelle-root", // session ROOT
33 "sml") // Standard ML (not Isabelle/ML)
35 private lazy val ml_syntax: Outer_Syntax =
36 Outer_Syntax.init().no_tokens.
37 set_language_context(Completion.Language_Context.ML_outer)
39 private lazy val sml_syntax: Outer_Syntax =
40 Outer_Syntax.init().no_tokens.
41 set_language_context(Completion.Language_Context.SML_outer)
43 private lazy val news_syntax: Outer_Syntax =
44 Outer_Syntax.init().no_tokens
46 def mode_syntax(name: String): Option[Outer_Syntax] =
48 case "isabelle" | "isabelle-markup" =>
49 PIDE.session.recent_syntax match {
50 case syntax: Outer_Syntax if syntax != Outer_Syntax.empty => Some(syntax)
53 case "isabelle-options" => Some(Options.options_syntax)
54 case "isabelle-root" => Some(Build.root_syntax)
55 case "isabelle-ml" => Some(ml_syntax)
56 case "isabelle-news" => Some(news_syntax)
57 case "isabelle-output" => None
58 case "sml" => Some(sml_syntax)
66 Map(modes.map(name => (name, new Token_Markup.Marker(name))): _*)
68 def token_marker(name: String): Option[Token_Markup.Marker] = markers.get(name)
71 /* dockable windows */
73 private def wm(view: View): DockableWindowManager = view.getDockableWindowManager
75 def documentation_dockable(view: View): Option[Documentation_Dockable] =
76 wm(view).getDockableWindow("isabelle-documentation") match {
77 case dockable: Documentation_Dockable => Some(dockable)
81 def find_dockable(view: View): Option[Find_Dockable] =
82 wm(view).getDockableWindow("isabelle-find") match {
83 case dockable: Find_Dockable => Some(dockable)
87 def monitor_dockable(view: View): Option[Monitor_Dockable] =
88 wm(view).getDockableWindow("isabelle-monitor") match {
89 case dockable: Monitor_Dockable => Some(dockable)
93 def output_dockable(view: View): Option[Output_Dockable] =
94 wm(view).getDockableWindow("isabelle-output") match {
95 case dockable: Output_Dockable => Some(dockable)
99 def protocol_dockable(view: View): Option[Protocol_Dockable] =
100 wm(view).getDockableWindow("isabelle-protocol") match {
101 case dockable: Protocol_Dockable => Some(dockable)
105 def raw_output_dockable(view: View): Option[Raw_Output_Dockable] =
106 wm(view).getDockableWindow("isabelle-raw-output") match {
107 case dockable: Raw_Output_Dockable => Some(dockable)
111 def simplifier_trace_dockable(view: View): Option[Simplifier_Trace_Dockable] =
112 wm(view).getDockableWindow("isabelle-simplifier-trace") match {
113 case dockable: Simplifier_Trace_Dockable => Some(dockable)
117 def sledgehammer_dockable(view: View): Option[Sledgehammer_Dockable] =
118 wm(view).getDockableWindow("isabelle-sledgehammer") match {
119 case dockable: Sledgehammer_Dockable => Some(dockable)
123 def symbols_dockable(view: View): Option[Symbols_Dockable] =
124 wm(view).getDockableWindow("isabelle-symbols") match {
125 case dockable: Symbols_Dockable => Some(dockable)
129 def syslog_dockable(view: View): Option[Syslog_Dockable] =
130 wm(view).getDockableWindow("isabelle-syslog") match {
131 case dockable: Syslog_Dockable => Some(dockable)
135 def theories_dockable(view: View): Option[Theories_Dockable] =
136 wm(view).getDockableWindow("isabelle-theories") match {
137 case dockable: Theories_Dockable => Some(dockable)
141 def timing_dockable(view: View): Option[Timing_Dockable] =
142 wm(view).getDockableWindow("isabelle-timing") match {
143 case dockable: Timing_Dockable => Some(dockable)
148 /* continuous checking */
150 private val CONTINUOUS_CHECKING = "editor_continuous_checking"
152 def continuous_checking: Boolean = PIDE.options.bool(CONTINUOUS_CHECKING)
154 def continuous_checking_=(b: Boolean)
156 Swing_Thread.require()
158 if (continuous_checking != b) {
159 PIDE.options.bool(CONTINUOUS_CHECKING) = b
160 PIDE.options_changed()
165 def set_continuous_checking() { continuous_checking = true }
166 def reset_continuous_checking() { continuous_checking = false }
167 def toggle_continuous_checking() { continuous_checking = !continuous_checking }
169 class Continuous_Checking extends CheckBox("Continuous checking")
171 tooltip = "Continuous checking of proof document (visible and required parts)"
172 reactions += { case ButtonClicked(_) => continuous_checking = selected }
173 def load() { selected = continuous_checking }
178 /* required document nodes */
180 private def node_required_update(view: View, toggle: Boolean = false, set: Boolean = false)
182 Swing_Thread.require()
183 PIDE.document_model(view.getBuffer) match {
185 model.node_required = (if (toggle) !model.node_required else set)
190 def set_node_required(view: View) { node_required_update(view, set = true) }
191 def reset_node_required(view: View) { node_required_update(view, set = false) }
192 def toggle_node_required(view: View) { node_required_update(view, toggle = true) }
197 def reset_font_size() {
198 Font_Info.main_change.reset(PIDE.options.int("jedit_reset_font_size").toFloat)
200 def increase_font_size() { Font_Info.main_change.step(1) }
201 def decrease_font_size() { Font_Info.main_change.step(-1) }
204 /* structured edits */
206 def insert_line_padding(text_area: JEditTextArea, text: String)
208 val buffer = text_area.getBuffer
209 JEdit_Lib.buffer_edit(buffer) {
211 if (text_area.getSelectionCount == 0) {
212 def pad(range: Text.Range): String =
213 if (JEdit_Lib.try_get_text(buffer, range) == Some("\n")) "" else "\n"
215 val caret = JEdit_Lib.point_range(buffer, text_area.getCaretPosition)
216 val before_caret = JEdit_Lib.point_range(buffer, caret.start - 1)
217 pad(before_caret) + text + pad(caret)
220 text_area.setSelectedText(text1)
225 snapshot: Document.Snapshot,
228 id: Document_ID.Generic,
231 if (!snapshot.is_outdated) {
232 snapshot.state.find_command(snapshot.version, id) match {
233 case Some((node, command)) =>
234 node.command_start(command) match {
236 JEdit_Lib.buffer_edit(buffer) {
237 val range = command.proper_range + start
239 buffer.insert(start + range.length, "\n" + s)
242 buffer.remove(start, range.length)
243 buffer.insert(start, s)
256 def complete(view: View)
258 if (!Completion_Popup.Text_Area.action(view.getTextArea))
259 CompleteWord.completeWord(view)
265 def control_sub(text_area: JEditTextArea)
266 { Token_Markup.edit_control_style(text_area, Symbol.sub_decoded) }
268 def control_sup(text_area: JEditTextArea)
269 { Token_Markup.edit_control_style(text_area, Symbol.sup_decoded) }
271 def control_bold(text_area: JEditTextArea)
272 { Token_Markup.edit_control_style(text_area, Symbol.bold_decoded) }
274 def control_reset(text_area: JEditTextArea)
275 { Token_Markup.edit_control_style(text_area, "") }
280 private def enclose_input(text_area: JEditTextArea, s1: String, s2: String)
282 s1.foreach(text_area.userInput(_))
283 s2.foreach(text_area.userInput(_))
284 s2.foreach(_ => text_area.goToPrevCharacter(false))
287 def input_bsub(text_area: JEditTextArea)
288 { enclose_input(text_area, Symbol.bsub_decoded, Symbol.esub_decoded) }
290 def input_bsup(text_area: JEditTextArea)
291 { enclose_input(text_area, Symbol.bsup_decoded, Symbol.esup_decoded) }
294 /* spell-checker dictionary */
296 def update_dictionary(text_area: JEditTextArea, include: Boolean, permanent: Boolean)
299 spell_checker <- PIDE.spell_checker.get
300 doc_view <- PIDE.document_view(text_area)
301 Text.Info(_, word) <- Spell_Checker.current_word(text_area, doc_view.get_rendering())
302 } spell_checker.update(word, include, permanent)
305 def reset_dictionary(): Unit = PIDE.spell_checker.get.foreach(_.reset())