# HG changeset patch # User wenzelm # Date 1393183473 -3600 # Node ID 93ba0085e888048ebaabb210f4734c1b07c20174 # Parent 19e8b00684f782286c9f22fa9e05bb2276811fef try explicit semantic completion before syntax completion; diff -r 19e8b00684f7 -r 93ba0085e888 src/Pure/General/completion.scala --- a/src/Pure/General/completion.scala Sun Feb 23 19:29:27 2014 +0100 +++ b/src/Pure/General/completion.scala Sun Feb 23 20:24:33 2014 +0100 @@ -32,6 +32,23 @@ } sealed case class Names(range: Text.Range, total: Int, names: List[String]) + { + def complete( + history: Completion.History, + decode: Boolean, + original: String): Option[Completion.Result] = + { + val items = + for { + raw_name <- names + name = (if (decode) Symbol.decode(raw_name) else raw_name) + if name != original + } yield Item(range, original, name, name, 0, true) + + if (items.isEmpty) None + else Some(Result(range, original, names.length == 1, items)) + } + } @@ -64,7 +81,11 @@ immediate: Boolean) { override def toString: String = name } - sealed case class Result(original: String, unique: Boolean, items: List[Item]) + sealed case class Result( + range: Text.Range, + original: String, + unique: Boolean, + items: List[Item]) /* init */ @@ -278,6 +299,7 @@ words_result match { case Some((word, cs)) => + val range = Text.Range(- word.length, 0) + (text_start + text.length) val ds = (if (decode) cs.map(Symbol.decode(_)) else cs).filter(_ != word) if (ds.isEmpty) None else { @@ -291,10 +313,9 @@ case List(s1, s2) => (s1, s2) case _ => (s, "") } - val range = Text.Range(- word.length, 0) + (text_start + text.length) Completion.Item(range, word, s, s1 + s2, - s2.length, explicit || immediate) }) - Some(Completion.Result(word, cs.length == 1, items.sorted(history.ordering))) + Some(Completion.Result(range, word, cs.length == 1, items.sorted(history.ordering))) } case None => None } diff -r 19e8b00684f7 -r 93ba0085e888 src/Tools/jEdit/src/completion_popup.scala --- a/src/Tools/jEdit/src/completion_popup.scala Sun Feb 23 19:29:27 2014 +0100 +++ b/src/Tools/jEdit/src/completion_popup.scala Sun Feb 23 20:24:33 2014 +0100 @@ -99,17 +99,70 @@ val layered = view.getLayeredPane val buffer = text_area.getBuffer val painter = text_area.getPainter + val caret = text_area.getCaretPosition - if (buffer.isEditable) { + val history = PIDE.completion_history.value + val decode = Isabelle_Encoding.is_active(buffer) + + def open_popup(result: Completion.Result) + { + val font = + painter.getFont.deriveFont(Rendering.font_size("jedit_popup_font_scale")) + + val loc1 = text_area.offsetToXY(result.range.start) + if (loc1 != null) { + val loc2 = + SwingUtilities.convertPoint(painter, + loc1.x, loc1.y + painter.getFontMetrics.getHeight, layered) + + val completion = + new Completion_Popup(layered, loc2, font, result.items) { + override def complete(item: Completion.Item) { + PIDE.completion_history.update(item) + insert(item) + } + override def propagate(evt: KeyEvent) { + JEdit_Lib.propagate_key(view, evt) + input(evt) + } + override def refocus() { text_area.requestFocus } + } + completion_popup = Some(completion) + completion.show_popup() + } + } + + def semantic_completion(): Boolean = + explicit && { + PIDE.document_view(text_area) match { + case Some(doc_view) => + val rendering = doc_view.get_rendering() + rendering.completion_names(JEdit_Lib.stretch_point_range(buffer, caret)) match { + case None => false + case Some(names) => + JEdit_Lib.try_get_text(buffer, names.range) match { + case Some(original) => + names.complete(history, decode, original) match { + case Some(result) if !result.items.isEmpty => + open_popup(result) + true + case _ => false + } + case None => false + } + } + case _ => false + } + } + + def syntax_completion(): Boolean = + { Isabelle.mode_syntax(JEdit_Lib.buffer_mode(buffer)) match { case Some(syntax) => - val caret = text_area.getCaretPosition val line = buffer.getLineOfOffset(caret) val start = buffer.getLineStartOffset(line) val text = buffer.getSegment(start, caret - start) - val history = PIDE.completion_history.value - val decode = Isabelle_Encoding.is_active(buffer) val context = (PIDE.document_view(text_area) match { case None => None @@ -120,39 +173,23 @@ syntax.completion.complete(history, decode, explicit, start, text, context) match { case Some(result) => - if (result.unique && result.items.head.immediate && immediate) - insert(result.items.head) - else { - val font = - painter.getFont.deriveFont(Rendering.font_size("jedit_popup_font_scale")) - - val loc1 = text_area.offsetToXY(caret - result.original.length) - if (loc1 != null) { - val loc2 = - SwingUtilities.convertPoint(painter, - loc1.x, loc1.y + painter.getFontMetrics.getHeight, layered) - - val completion = - new Completion_Popup(layered, loc2, font, result.items) { - override def complete(item: Completion.Item) { - PIDE.completion_history.update(item) - insert(item) - } - override def propagate(evt: KeyEvent) { - JEdit_Lib.propagate_key(view, evt) - input(evt) - } - override def refocus() { text_area.requestFocus } - } - completion_popup = Some(completion) - completion.show_popup() - } + result.items match { + case List(item) if result.unique && item.immediate && immediate => + insert(item) + true + case _ :: _ => + open_popup(result) + true + case _ => false } - case None => + case None => false } - case None => + case None => false } } + + if (buffer.isEditable) + semantic_completion() || syntax_completion() }