296 case None => None |
296 case None => None |
297 } |
297 } |
298 |
298 |
299 def hyperlink(range: Text.Range): Option[Text.Info[PIDE.editor.Hyperlink]] = |
299 def hyperlink(range: Text.Range): Option[Text.Info[PIDE.editor.Hyperlink]] = |
300 { |
300 { |
301 snapshot.cumulate_markup[List[Text.Info[PIDE.editor.Hyperlink]]]( |
301 snapshot.cumulate_markup[Vector[Text.Info[PIDE.editor.Hyperlink]]]( |
302 range, Nil, hyperlink_elements, _ => |
302 range, Vector.empty, hyperlink_elements, _ => |
303 { |
303 { |
304 case (links, Text.Info(info_range, XML.Elem(Markup.Path(name), _))) |
304 case (links, Text.Info(info_range, XML.Elem(Markup.Path(name), _))) |
305 if Path.is_ok(name) => |
305 if Path.is_ok(name) => |
306 val jedit_file = PIDE.thy_load.append(snapshot.node_name.master_dir, Path.explode(name)) |
306 val jedit_file = PIDE.thy_load.append(snapshot.node_name.master_dir, Path.explode(name)) |
307 val link = PIDE.editor.hyperlink_file(jedit_file) |
307 val link = PIDE.editor.hyperlink_file(jedit_file) |
308 Some(Text.Info(snapshot.convert(info_range), link) :: links) |
308 Some(links :+ Text.Info(snapshot.convert(info_range), link)) |
309 |
309 |
310 case (links, Text.Info(info_range, XML.Elem(Markup.Url(name), _))) => |
310 case (links, Text.Info(info_range, XML.Elem(Markup.Url(name), _))) => |
311 val link = PIDE.editor.hyperlink_url(name) |
311 val link = PIDE.editor.hyperlink_url(name) |
312 Some(Text.Info(snapshot.convert(info_range), link) :: links) |
312 Some(links :+ Text.Info(snapshot.convert(info_range), link)) |
313 |
313 |
314 case (links, Text.Info(info_range, XML.Elem(Markup(Markup.ENTITY, props), _))) |
314 case (links, Text.Info(info_range, XML.Elem(Markup(Markup.ENTITY, props), _))) |
315 if !props.exists( |
315 if !props.exists( |
316 { case (Markup.KIND, Markup.ML_OPEN) => true |
316 { case (Markup.KIND, Markup.ML_OPEN) => true |
317 case (Markup.KIND, Markup.ML_STRUCT) => true |
317 case (Markup.KIND, Markup.ML_STRUCT) => true |
321 props match { |
321 props match { |
322 case Position.Def_Line_File(line, name) => hyperlink_file(line, name) |
322 case Position.Def_Line_File(line, name) => hyperlink_file(line, name) |
323 case Position.Def_Id_Offset(id, offset) => hyperlink_command(id, offset) |
323 case Position.Def_Id_Offset(id, offset) => hyperlink_command(id, offset) |
324 case _ => None |
324 case _ => None |
325 } |
325 } |
326 opt_link.map(link => (Text.Info(snapshot.convert(info_range), link) :: links)) |
326 opt_link.map(link => (links :+ Text.Info(snapshot.convert(info_range), link))) |
327 |
327 |
328 case (links, Text.Info(info_range, XML.Elem(Markup(Markup.POSITION, props), _))) => |
328 case (links, Text.Info(info_range, XML.Elem(Markup(Markup.POSITION, props), _))) => |
329 val opt_link = |
329 val opt_link = |
330 props match { |
330 props match { |
331 case Position.Line_File(line, name) => hyperlink_file(line, name) |
331 case Position.Line_File(line, name) => hyperlink_file(line, name) |
332 case Position.Id_Offset(id, offset) => hyperlink_command(id, offset) |
332 case Position.Id_Offset(id, offset) => hyperlink_command(id, offset) |
333 case _ => None |
333 case _ => None |
334 } |
334 } |
335 opt_link.map(link => (Text.Info(snapshot.convert(info_range), link) :: links)) |
335 opt_link.map(link => links :+ (Text.Info(snapshot.convert(info_range), link))) |
336 |
336 |
337 case _ => None |
337 case _ => None |
338 }) match { case Text.Info(_, info :: _) :: _ => Some(info) case _ => None } |
338 }) match { case Text.Info(_, _ :+ info) :: _ => Some(info) case _ => None } |
339 } |
339 } |
340 |
340 |
341 |
341 |
342 private val active_elements = |
342 private val active_elements = |
343 Set(Markup.BROWSER, Markup.GRAPHVIEW, Markup.SENDBACK, Markup.DIALOG, Markup.SIMP_TRACE) |
343 Set(Markup.DIALOG, Markup.BROWSER, Markup.GRAPHVIEW, Markup.SENDBACK, Markup.SIMP_TRACE) |
344 |
344 |
345 def active(range: Text.Range): Option[Text.Info[XML.Elem]] = |
345 def active(range: Text.Range): Option[Text.Info[XML.Elem]] = |
346 snapshot.select_markup(range, active_elements, command_state => |
346 snapshot.select_markup(range, active_elements, command_state => |
347 { |
347 { |
348 case Text.Info(info_range, elem @ Protocol.Dialog(_, serial, _)) |
348 case Text.Info(info_range, elem @ Protocol.Dialog(_, serial, _)) |
349 if !command_state.results.defined(serial) => |
349 if !command_state.results.defined(serial) => |
350 Some(Text.Info(snapshot.convert(info_range), elem)) |
350 Some(Text.Info(snapshot.convert(info_range), elem)) |
|
351 |
351 case Text.Info(info_range, elem) => |
352 case Text.Info(info_range, elem) => |
352 if (elem.name == Markup.BROWSER || |
353 if (elem.name == Markup.BROWSER || |
353 elem.name == Markup.GRAPHVIEW || |
354 elem.name == Markup.GRAPHVIEW || |
354 elem.name == Markup.SENDBACK || |
355 elem.name == Markup.SENDBACK || |
355 elem.name == Markup.SIMP_TRACE) |
356 elem.name == Markup.SIMP_TRACE) |
418 |
419 |
419 private val timing_threshold: Double = options.real("jedit_timing_threshold") |
420 private val timing_threshold: Double = options.real("jedit_timing_threshold") |
420 |
421 |
421 def tooltip(range: Text.Range): Option[Text.Info[XML.Body]] = |
422 def tooltip(range: Text.Range): Option[Text.Info[XML.Body]] = |
422 { |
423 { |
423 def add(prev: Text.Info[(Timing, List[(Boolean, XML.Tree)])], |
424 def add(prev: Text.Info[(Timing, Vector[(Boolean, XML.Tree)])], |
424 r0: Text.Range, p: (Boolean, XML.Tree)): Text.Info[(Timing, List[(Boolean, XML.Tree)])] = |
425 r0: Text.Range, p: (Boolean, XML.Tree)): Text.Info[(Timing, Vector[(Boolean, XML.Tree)])] = |
425 { |
426 { |
426 val r = snapshot.convert(r0) |
427 val r = snapshot.convert(r0) |
427 val (t, info) = prev.info |
428 val (t, info) = prev.info |
428 if (prev.range == r) Text.Info(r, (t, p :: info)) else Text.Info(r, (t, List(p))) |
429 if (prev.range == r) |
|
430 Text.Info(r, (t, info :+ p)) |
|
431 else Text.Info(r, (t, Vector(p))) |
429 } |
432 } |
430 |
433 |
431 val results = |
434 val results = |
432 snapshot.cumulate_markup[Text.Info[(Timing, List[(Boolean, XML.Tree)])]]( |
435 snapshot.cumulate_markup[Text.Info[(Timing, Vector[(Boolean, XML.Tree)])]]( |
433 range, Text.Info(range, (Timing.zero, Nil)), tooltip_elements, _ => |
436 range, Text.Info(range, (Timing.zero, Vector.empty)), tooltip_elements, _ => |
434 { |
437 { |
435 case (Text.Info(r, (t1, info)), Text.Info(_, XML.Elem(Markup.Timing(t2), _))) => |
438 case (Text.Info(r, (t1, info)), Text.Info(_, XML.Elem(Markup.Timing(t2), _))) => |
436 Some(Text.Info(r, (t1 + t2, info))) |
439 Some(Text.Info(r, (t1 + t2, info))) |
437 case (prev, Text.Info(r, XML.Elem(Markup.Entity(kind, name), _))) => |
440 case (prev, Text.Info(r, XML.Elem(Markup.Entity(kind, name), _))) => |
438 val kind1 = space_explode('_', kind).mkString(" ") |
441 val kind1 = space_explode('_', kind).mkString(" ") |
460 if (tooltips.isDefinedAt(name)) |
463 if (tooltips.isDefinedAt(name)) |
461 Some(add(prev, r, (true, XML.Text(tooltips(name))))) |
464 Some(add(prev, r, (true, XML.Text(tooltips(name))))) |
462 else None |
465 else None |
463 }).map(_.info) |
466 }).map(_.info) |
464 |
467 |
465 results.map(_.info).flatMap(_._2) match { |
468 results.map(_.info).flatMap(res => res._2.toList) match { |
466 case Nil => None |
469 case Nil => None |
467 case tips => |
470 case tips => |
468 val r = Text.Range(results.head.range.start, results.last.range.stop) |
471 val r = Text.Range(results.head.range.start, results.last.range.stop) |
469 val all_tips = (tips.filter(_._1) ++ tips.filter(!_._1).lastOption.toList).map(_._2) |
472 val all_tips = (tips.filter(_._1) ++ tips.filter(!_._1).lastOption.toList).map(_._2) |
470 Some(Text.Info(r, Library.separate(Pretty.FBreak, all_tips))) |
473 Some(Text.Info(r, Library.separate(Pretty.FBreak, all_tips))) |