merged
authorwenzelm
Fri, 30 Aug 2013 13:46:32 +0200
changeset 53327 d0e4c8f73541
parent 53312 a1cf42366cea (current diff)
parent 53326 d8ad101cc684 (diff)
child 53328 9228c575d67d
merged
NEWS
--- a/NEWS	Fri Aug 30 13:23:23 2013 +0200
+++ b/NEWS	Fri Aug 30 13:46:32 2013 +0200
@@ -90,18 +90,41 @@
 according to Isabelle/Scala plugin option "jedit_font_reset_size"
 (cf. keyboard shortcut C+0).
 
-* More reactive and less intrusive completion, managed by
-Isabelle/jEdit instead of SideKick.  Plain words need to be at least 3
-characters long to be completed (was 2 before).  Symbols are only
-completed in backslash forms, e.g. \forall or \<forall> that both
-produce the Isabelle symbol \<forall> in its Unicode rendering.
-
-* Standard jEdit completion via C+b uses action isabelle.complete
-with fall-back on complete-word for non-Isabelle buffers.
-
 * Improved support for Linux look-and-feel "GTK+", see also "Utilities
 / Global Options / Appearance".
 
+* Improved completion mechanism, which is now managed by the
+Isabelle/jEdit plugin instead of SideKick.
+
+  - Various Isabelle plugin options to control popup behaviour and
+    immediate insertion into buffer.
+
+  - Light-weight popup, which avoids explicit window (more reactive
+    and more robust).  Interpreted key events: TAB, ESCAPE, UP, DOWN,
+    PAGE_UP, PAGE_DOWN.  All other key events are passed to the jEdit
+    text area unchanged.
+
+  - Explicit completion via standard jEdit shortcut C+b, which has
+    been remapped to action "isabelle.complete" (fall-back on regular
+    "complete-word" for non-Isabelle buffers).
+
+  - Implicit completion via keyboard input on text area, with popup or
+    immediate insertion into buffer.
+
+  - Implicit completion of plain words requires at least 3 characters
+    (was 2 before).
+
+  - Immediate completion ignores plain words; it requires > 1
+    characters of symbol abbreviation to complete, otherwise fall-back
+    on completion popup.
+
+  - Isabelle Symbols are only completed in backslashed forms,
+    e.g. \forall or \<forall> that both produce the Isabelle symbol
+    \<forall> in its Unicode rendering.
+
+  - Refined table of Isabelle symbol abbreviations (see
+    $ISABELLE_HOME/etc/symbols).
+
 
 *** Pure ***
 
--- a/etc/symbols	Fri Aug 30 13:23:23 2013 +0200
+++ b/etc/symbols	Fri Aug 30 13:46:32 2013 +0200
@@ -161,11 +161,11 @@
 \<Leftarrow>            code: 0x0021d0  group: arrow
 \<Longleftarrow>        code: 0x0027f8  group: arrow
 \<Rightarrow>           code: 0x0021d2  group: arrow  abbrev: =>
-\<Longrightarrow>       code: 0x0027f9  group: arrow  abbrev: ==>
-\<leftrightarrow>       code: 0x002194  group: arrow
-\<longleftrightarrow>   code: 0x0027f7  group: arrow  abbrev: <->
+\<Longrightarrow>       code: 0x0027f9  group: arrow  abbrev: ==>  abbrev: ≡>
+\<leftrightarrow>       code: 0x002194  group: arrow  abbrev: <->
+\<longleftrightarrow>   code: 0x0027f7  group: arrow  abbrev: <->  abbrev: <-->
 \<Leftrightarrow>       code: 0x0021d4  group: arrow
-\<Longleftrightarrow>   code: 0x0027fa  group: arrow  abbrev: <=>
+\<Longleftrightarrow>   code: 0x0027fa  group: arrow
 \<mapsto>               code: 0x0021a6  group: arrow  abbrev: |->
 \<longmapsto>           code: 0x0027fc  group: arrow  abbrev: |-->
 \<midarrow>             code: 0x002500  group: arrow
@@ -190,42 +190,42 @@
 \<Down>                 code: 0x0021d3  group: arrow
 \<updown>               code: 0x002195  group: arrow
 \<Updown>               code: 0x0021d5  group: arrow
-\<langle>               code: 0x0027e8  group: punctuation  abbrev: <.
-\<rangle>               code: 0x0027e9  group: punctuation  abbrev: .>
-\<lceil>                code: 0x002308  group: punctuation
-\<rceil>                code: 0x002309  group: punctuation
-\<lfloor>               code: 0x00230a  group: punctuation
-\<rfloor>               code: 0x00230b  group: punctuation
+\<langle>               code: 0x0027e8  group: punctuation  abbrev: <<
+\<rangle>               code: 0x0027e9  group: punctuation  abbrev: >>
+\<lceil>                code: 0x002308  group: punctuation  abbrev: [.
+\<rceil>                code: 0x002309  group: punctuation  abbrev: .]
+\<lfloor>               code: 0x00230a  group: punctuation  abbrev: [.
+\<rfloor>               code: 0x00230b  group: punctuation  abbrev: .]
 \<lparr>                code: 0x002987  group: punctuation  abbrev: (|
 \<rparr>                code: 0x002988  group: punctuation  abbrev: |)
 \<lbrakk>               code: 0x0027e6  group: punctuation  abbrev: [|
 \<rbrakk>               code: 0x0027e7  group: punctuation  abbrev: |]
-\<lbrace>               code: 0x002983  group: punctuation  abbrev: {.
-\<rbrace>               code: 0x002984  group: punctuation  abbrev: .}
+\<lbrace>               code: 0x002983  group: punctuation  abbrev: {|
+\<rbrace>               code: 0x002984  group: punctuation  abbrev: |}
 \<guillemotleft>        code: 0x0000ab  group: punctuation  abbrev: <<
 \<guillemotright>       code: 0x0000bb  group: punctuation  abbrev: >>
 \<bottom>               code: 0x0022a5  group: logic
 \<top>                  code: 0x0022a4  group: logic
-\<and>                  code: 0x002227  group: logic  abbrev: /\
+\<and>                  code: 0x002227  group: logic  abbrev: /\  abbrev: &
 \<And>                  code: 0x0022c0  group: logic  abbrev: !!
-\<or>                   code: 0x002228  group: logic  abbrev: \/
+\<or>                   code: 0x002228  group: logic  abbrev: \/  abbrev: |
 \<Or>                   code: 0x0022c1  group: logic  abbrev: ??
-\<forall>               code: 0x002200  group: logic  abbrev: !
-\<exists>               code: 0x002203  group: logic  abbrev: ?
+\<forall>               code: 0x002200  group: logic  abbrev: !  abbrev: ALL
+\<exists>               code: 0x002203  group: logic  abbrev: ?  abbrev: EX
 \<nexists>              code: 0x002204  group: logic  abbrev: ~?
 \<not>                  code: 0x0000ac  group: logic  abbrev: ~
 \<box>                  code: 0x0025a1  group: logic
 \<diamond>              code: 0x0025c7  group: logic
 \<turnstile>            code: 0x0022a2  group: relation  abbrev: |-
 \<Turnstile>            code: 0x0022a8  group: relation  abbrev: |=
-\<tturnstile>           code: 0x0022a9  group: relation  abbrev: ||-
-\<TTurnstile>           code: 0x0022ab  group: relation  abbrev: ||=
+\<tturnstile>           code: 0x0022a9  group: relation  abbrev: |-
+\<TTurnstile>           code: 0x0022ab  group: relation  abbrev: |=
 \<stileturn>            code: 0x0022a3  group: relation  abbrev: -|
 \<surd>                 code: 0x00221a  group: relation
 \<le>                   code: 0x002264  group: relation  abbrev: <=
 \<ge>                   code: 0x002265  group: relation  abbrev: >=
-\<lless>                code: 0x00226a  group: relation
-\<ggreater>             code: 0x00226b  group: relation
+\<lless>                code: 0x00226a  group: relation  abbrev: <<
+\<ggreater>             code: 0x00226b  group: relation  abbrev: >>
 \<lesssim>              code: 0x002272  group: relation
 \<greatersim>           code: 0x002273  group: relation
 \<lessapprox>           code: 0x002a85  group: relation
@@ -240,21 +240,21 @@
 \<sqsupset>             code: 0x002290  group: relation
 \<sqsubseteq>           code: 0x002291  group: relation  abbrev: [=
 \<sqsupseteq>           code: 0x002292  group: relation  abbrev: =]
-\<inter>                code: 0x002229  group: operator
-\<Inter>                code: 0x0022c2  group: operator
-\<union>                code: 0x00222a  group: operator
-\<Union>                code: 0x0022c3  group: operator
+\<inter>                code: 0x002229  group: operator  abbrev: Int
+\<Inter>                code: 0x0022c2  group: operator  abbrev: Inter
+\<union>                code: 0x00222a  group: operator  abbrev: Un
+\<Union>                code: 0x0022c3  group: operator  abbrev: Union
 \<squnion>              code: 0x002294  group: operator
-\<Squnion>              code: 0x002a06  group: operator
+\<Squnion>              code: 0x002a06  group: operator  abbrev: SUP
 \<sqinter>              code: 0x002293  group: operator
-\<Sqinter>              code: 0x002a05  group: operator
+\<Sqinter>              code: 0x002a05  group: operator  abbrev: INF
 \<setminus>             code: 0x002216  group: operator
 \<propto>               code: 0x00221d  group: operator
 \<uplus>                code: 0x00228e  group: operator
 \<Uplus>                code: 0x002a04  group: operator
 \<noteq>                code: 0x002260  group: relation  abbrev: ~=
 \<sim>                  code: 0x00223c  group: relation
-\<doteq>                code: 0x002250  group: relation
+\<doteq>                code: 0x002250  group: relation  abbrev: .=
 \<simeq>                code: 0x002243  group: relation
 \<approx>               code: 0x002248  group: relation
 \<asymp>                code: 0x00224d  group: relation
@@ -269,10 +269,10 @@
 \<preceq>               code: 0x00227c  group: relation
 \<succeq>               code: 0x00227d  group: relation
 \<parallel>             code: 0x002225  group: punctuation  abbrev: ||
-\<bar>                  code: 0x0000a6  group: punctuation
+\<bar>                  code: 0x0000a6  group: punctuation  abbrev: ||
 \<plusminus>            code: 0x0000b1  group: operator
 \<minusplus>            code: 0x002213  group: operator
-\<times>                code: 0x0000d7  group: operator
+\<times>                code: 0x0000d7  group: operator  abbrev: *
 \<div>                  code: 0x0000f7  group: operator
 \<cdot>                 code: 0x0022c5  group: operator
 \<star>                 code: 0x0022c6  group: operator
--- a/lib/Tools/components	Fri Aug 30 13:23:23 2013 +0200
+++ b/lib/Tools/components	Fri Aug 30 13:46:32 2013 +0200
@@ -134,7 +134,7 @@
       fi
       if [ -e "${FULL_NAME}.tar.gz" ]; then
         echo "Unpacking \"${FULL_NAME}.tar.gz\""
-        tar -C "$(dirname "$FULL_NAME")" -x -f "${FULL_NAME}.tar.gz"
+        tar -C "$(dirname "$FULL_NAME")" -x -f "${FULL_NAME}.tar.gz" || exit 2
       fi
     fi
   done
--- a/src/Pure/General/symbol.scala	Fri Aug 30 13:23:23 2013 +0200
+++ b/src/Pure/General/symbol.scala	Fri Aug 30 13:46:32 2013 +0200
@@ -216,27 +216,28 @@
     private val No_Decl = new Regex("""(?xs) ^\s* (?: \#.* )? $ """)
     private val Key = new Regex("""(?xs) (.+): """)
 
-    private def read_decl(decl: String): (Symbol, Map[String, String]) =
+    private def read_decl(decl: String): (Symbol, Properties.T) =
     {
       def err() = error("Bad symbol declaration: " + decl)
 
-      def read_props(props: List[String]): Map[String, String] =
+      def read_props(props: List[String]): Properties.T =
       {
         props match {
-          case Nil => Map()
+          case Nil => Nil
           case _ :: Nil => err()
-          case Key(x) :: y :: rest => read_props(rest) + (x -> y)
+          case Key(x) :: y :: rest => (x -> y) :: read_props(rest)
           case _ => err()
         }
       }
       decl.split("\\s+").toList match {
-        case sym :: props if sym.length > 1 && !is_malformed(sym) => (sym, read_props(props))
+        case sym :: props if sym.length > 1 && !is_malformed(sym) =>
+          (sym, read_props(props))
         case _ => err()
       }
     }
 
-    private val symbols: List[(Symbol, Map[String, String])] =
-      (((List.empty[(Symbol, Map[String, String])], Set.empty[Symbol]) /:
+    private val symbols: List[(Symbol, Properties.T)] =
+      (((List.empty[(Symbol, Properties.T)], Set.empty[Symbol]) /:
           split_lines(symbols_spec).reverse)
         { case (res, No_Decl()) => res
           case ((list, known), decl) =>
@@ -255,28 +256,35 @@
     }
 
     val groups: List[(String, List[Symbol])] =
-      symbols.map({ case (sym, props) => (sym, props.getOrElse("group", "unsorted")) })
+      symbols.map({ case (sym, props) =>
+        val gs = for (("group", g) <- props) yield g
+        if (gs.isEmpty) List(sym -> "unsorted") else gs.map(sym -> _)
+      }).flatten
         .groupBy(_._2).toList.map({ case (group, list) => (group, list.map(_._1)) })
         .sortBy(_._1)
 
-    val abbrevs: Map[Symbol, String] =
-      Map((
-        for ((sym, props) <- symbols if props.isDefinedAt("abbrev"))
-          yield (sym -> props("abbrev"))): _*)
+    val abbrevs: Multi_Map[Symbol, String] =
+      Multi_Map((
+        for {
+          (sym, props) <- symbols
+          ("abbrev", a) <- props.reverse
+        } yield (sym -> a)): _*)
 
 
     /* recoding */
 
+    private val Code = new Properties.String("code")
     private val (decoder, encoder) =
     {
       val mapping =
         for {
           (sym, props) <- symbols
           code =
-            try { Integer.decode(props("code")).intValue }
-            catch {
-              case _: NoSuchElementException => error("Missing code for symbol " + sym)
-              case _: NumberFormatException => error("Bad code for symbol " + sym)
+            props match {
+              case Code(s) =>
+                try { Integer.decode(s).intValue }
+                catch { case _: NumberFormatException => error("Bad code for symbol " + sym) }
+              case _ => error("Missing code for symbol " + sym)
             }
           ch = new String(Character.toChars(code))
         } yield {
@@ -305,10 +313,9 @@
 
     /* user fonts */
 
+    private val Font = new Properties.String("font")
     val fonts: Map[Symbol, String] =
-      recode_map((
-        for ((sym, props) <- symbols if props.isDefinedAt("font"))
-          yield (sym -> props("font"))): _*)
+      recode_map((for ((sym, Font(font)) <- symbols) yield (sym -> font)): _*)
 
     val font_names: List[String] = Set(fonts.toList.map(_._2): _*).toList
     val font_index: Map[String, Int] = Map((font_names zip (0 until font_names.length).toList): _*)
@@ -376,7 +383,7 @@
 
   def names: Map[Symbol, String] = symbols.names
   def groups: List[(String, List[Symbol])] = symbols.groups
-  def abbrevs: Map[Symbol, String] = symbols.abbrevs
+  def abbrevs: Multi_Map[Symbol, String] = symbols.abbrevs
 
   def decode(text: String): String = symbols.decode(text)
   def encode(text: String): String = symbols.encode(text)
--- a/src/Pure/Isar/completion.scala	Fri Aug 30 13:23:23 2013 +0200
+++ b/src/Pure/Isar/completion.scala	Fri Aug 30 13:46:32 2013 +0200
@@ -11,7 +11,7 @@
 
 object Completion
 {
-  /* items */
+  /* result */
 
   sealed case class Item(
     original: String,
@@ -20,6 +20,8 @@
     immediate: Boolean)
   { override def toString: String = description }
 
+  sealed case class Result(original: String, unique: Boolean, items: List[Item])
+
 
   /* init */
 
@@ -39,12 +41,14 @@
     def reverse_symbol: Parser[String] = """>[A-Za-z0-9_']+\^?<\\""".r
     def reverse_symb: Parser[String] = """[A-Za-z0-9_']{2,}\^?<\\""".r
     def escape: Parser[String] = """[a-zA-Z0-9_']+\\""".r
-    def word: Parser[String] = """[a-zA-Z0-9_']{3,}""".r
+    def word: Parser[String] = word_regex
+    def word3: Parser[String] = """[a-zA-Z0-9_']{3,}""".r
 
-    def read(in: CharSequence): Option[String] =
+    def read(explicit: Boolean, in: CharSequence): Option[String] =
     {
+      val parse_word = if (explicit) word else word3
       val reverse_in = new Library.Reverse(in)
-      parse((reverse_symbol | reverse_symb | escape | word) ^^ (_.reverse), reverse_in) match {
+      parse((reverse_symbol | reverse_symb | escape | parse_word) ^^ (_.reverse), reverse_in) match {
         case Success(result, _) => Some(result)
         case _ => None
       }
@@ -54,9 +58,9 @@
 
 final class Completion private(
   words_lex: Scan.Lexicon = Scan.Lexicon.empty,
-  words_map: Map[String, String] = Map.empty,
+  words_map: Multi_Map[String, String] = Multi_Map.empty,
   abbrevs_lex: Scan.Lexicon = Scan.Lexicon.empty,
-  abbrevs_map: Map[String, (String, String)] = Map.empty)
+  abbrevs_map: Multi_Map[String, (String, String)] = Multi_Map.empty)
 {
   /* adding stuff */
 
@@ -74,10 +78,10 @@
     val words =
       (for ((x, _) <- Symbol.names) yield (x, x)).toList :::
       (for ((x, y) <- Symbol.names) yield ("\\" + y, x)).toList :::
-      (for ((x, y) <- Symbol.abbrevs if Completion.is_word(y)) yield (y, x)).toList
+      (for ((x, y) <- Symbol.abbrevs.iterator if Completion.is_word(y)) yield (y, x)).toList
 
     val abbrs =
-      (for ((x, y) <- Symbol.abbrevs if !Completion.is_word(y))
+      (for ((x, y) <- Symbol.abbrevs.iterator if !Completion.is_word(y))
         yield (y.reverse.toString, (y, x))).toList
 
     new Completion(
@@ -90,17 +94,20 @@
 
   /* complete */
 
-  def complete(decode: Boolean, line: CharSequence): Option[(String, List[Completion.Item])] =
+  def complete(decode: Boolean, explicit: Boolean, line: CharSequence): Option[Completion.Result] =
   {
     val raw_result =
       abbrevs_lex.parse(abbrevs_lex.keyword, new Library.Reverse(line)) match {
         case abbrevs_lex.Success(reverse_a, _) =>
-          val (word, c) = abbrevs_map(reverse_a)
-          Some(word, List(c))
+          val abbrevs = abbrevs_map.get_list(reverse_a)
+          abbrevs match {
+            case Nil => None
+            case (a, _) :: _ => Some((a, abbrevs.map(_._2)))
+          }
         case _ =>
-          Completion.Parse.read(line) match {
+          Completion.Parse.read(explicit, line) match {
             case Some(word) =>
-              words_lex.completions(word).map(words_map(_)) match {
+              words_lex.completions(word).map(words_map.get_list(_)).flatten match {
                 case Nil => None
                 case cs => Some(word, cs.sorted)
               }
@@ -109,11 +116,14 @@
       }
     raw_result match {
       case Some((word, cs)) =>
-        val ds = (if (decode) cs.map(Symbol.decode(_)).sorted else cs)
+        val ds = (if (decode) cs.map(Symbol.decode(_)).sorted else cs).filter(_ != word)
         if (ds.isEmpty) None
         else {
-          val immediate = !Completion.is_word(word)
-          Some((word, ds.map(s => Completion.Item(word, s, s, immediate))))
+          val immediate =
+            !Completion.is_word(word) &&
+            Character.codePointCount(word, 0, word.length) > 1
+          val items = ds.map(s => Completion.Item(word, s, s, explicit || immediate))
+          Some(Completion.Result(word, cs.length == 1, items))
         }
       case None => None
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/WWW_Find/etc/symbols	Fri Aug 30 13:46:32 2013 +0200
@@ -0,0 +1,357 @@
+# Default interpretation of some Isabelle symbols
+
+\<zero>                 code: 0x01d7ec  group: digit
+\<one>                  code: 0x01d7ed  group: digit
+\<two>                  code: 0x01d7ee  group: digit
+\<three>                code: 0x01d7ef  group: digit
+\<four>                 code: 0x01d7f0  group: digit
+\<five>                 code: 0x01d7f1  group: digit
+\<six>                  code: 0x01d7f2  group: digit
+\<seven>                code: 0x01d7f3  group: digit
+\<eight>                code: 0x01d7f4  group: digit
+\<nine>                 code: 0x01d7f5  group: digit
+\<A>                    code: 0x01d49c  group: letter
+\<B>                    code: 0x00212c  group: letter
+\<C>                    code: 0x01d49e  group: letter
+\<D>                    code: 0x01d49f  group: letter
+\<E>                    code: 0x002130  group: letter
+\<F>                    code: 0x002131  group: letter
+\<G>                    code: 0x01d4a2  group: letter
+\<H>                    code: 0x00210b  group: letter
+\<I>                    code: 0x002110  group: letter
+\<J>                    code: 0x01d4a5  group: letter
+\<K>                    code: 0x01d4a6  group: letter
+\<L>                    code: 0x002112  group: letter
+\<M>                    code: 0x002133  group: letter
+\<N>                    code: 0x01d4a9  group: letter
+\<O>                    code: 0x01d4aa  group: letter
+\<P>                    code: 0x01d4ab  group: letter
+\<Q>                    code: 0x01d4ac  group: letter
+\<R>                    code: 0x00211b  group: letter
+\<S>                    code: 0x01d4ae  group: letter
+\<T>                    code: 0x01d4af  group: letter
+\<U>                    code: 0x01d4b0  group: letter
+\<V>                    code: 0x01d4b1  group: letter
+\<W>                    code: 0x01d4b2  group: letter
+\<X>                    code: 0x01d4b3  group: letter
+\<Y>                    code: 0x01d4b4  group: letter
+\<Z>                    code: 0x01d4b5  group: letter
+\<a>                    code: 0x01d5ba  group: letter
+\<b>                    code: 0x01d5bb  group: letter
+\<c>                    code: 0x01d5bc  group: letter
+\<d>                    code: 0x01d5bd  group: letter
+\<e>                    code: 0x01d5be  group: letter
+\<f>                    code: 0x01d5bf  group: letter
+\<g>                    code: 0x01d5c0  group: letter
+\<h>                    code: 0x01d5c1  group: letter
+\<i>                    code: 0x01d5c2  group: letter
+\<j>                    code: 0x01d5c3  group: letter
+\<k>                    code: 0x01d5c4  group: letter
+\<l>                    code: 0x01d5c5  group: letter
+\<m>                    code: 0x01d5c6  group: letter
+\<n>                    code: 0x01d5c7  group: letter
+\<o>                    code: 0x01d5c8  group: letter
+\<p>                    code: 0x01d5c9  group: letter
+\<q>                    code: 0x01d5ca  group: letter
+\<r>                    code: 0x01d5cb  group: letter
+\<s>                    code: 0x01d5cc  group: letter
+\<t>                    code: 0x01d5cd  group: letter
+\<u>                    code: 0x01d5ce  group: letter
+\<v>                    code: 0x01d5cf  group: letter
+\<w>                    code: 0x01d5d0  group: letter
+\<x>                    code: 0x01d5d1  group: letter
+\<y>                    code: 0x01d5d2  group: letter
+\<z>                    code: 0x01d5d3  group: letter
+\<AA>                   code: 0x01d504  group: letter
+\<BB>                   code: 0x01d505  group: letter
+\<CC>                   code: 0x00212d  group: letter
+\<DD>                   code: 0x01d507  group: letter
+\<EE>                   code: 0x01d508  group: letter
+\<FF>                   code: 0x01d509  group: letter
+\<GG>                   code: 0x01d50a  group: letter
+\<HH>                   code: 0x00210c  group: letter
+\<II>                   code: 0x002111  group: letter
+\<JJ>                   code: 0x01d50d  group: letter
+\<KK>                   code: 0x01d50e  group: letter
+\<LL>                   code: 0x01d50f  group: letter
+\<MM>                   code: 0x01d510  group: letter
+\<NN>                   code: 0x01d511  group: letter
+\<OO>                   code: 0x01d512  group: letter
+\<PP>                   code: 0x01d513  group: letter
+\<QQ>                   code: 0x01d514  group: letter
+\<RR>                   code: 0x00211c  group: letter
+\<SS>                   code: 0x01d516  group: letter
+\<TT>                   code: 0x01d517  group: letter
+\<UU>                   code: 0x01d518  group: letter
+\<VV>                   code: 0x01d519  group: letter
+\<WW>                   code: 0x01d51a  group: letter
+\<XX>                   code: 0x01d51b  group: letter
+\<YY>                   code: 0x01d51c  group: letter
+\<ZZ>                   code: 0x002128  group: letter
+\<aa>                   code: 0x01d51e  group: letter
+\<bb>                   code: 0x01d51f  group: letter
+\<cc>                   code: 0x01d520  group: letter
+\<dd>                   code: 0x01d521  group: letter
+\<ee>                   code: 0x01d522  group: letter
+\<ff>                   code: 0x01d523  group: letter
+\<gg>                   code: 0x01d524  group: letter
+\<hh>                   code: 0x01d525  group: letter
+\<ii>                   code: 0x01d526  group: letter
+\<jj>                   code: 0x01d527  group: letter
+\<kk>                   code: 0x01d528  group: letter
+\<ll>                   code: 0x01d529  group: letter
+\<mm>                   code: 0x01d52a  group: letter
+\<nn>                   code: 0x01d52b  group: letter
+\<oo>                   code: 0x01d52c  group: letter
+\<pp>                   code: 0x01d52d  group: letter
+\<qq>                   code: 0x01d52e  group: letter
+\<rr>                   code: 0x01d52f  group: letter
+\<ss>                   code: 0x01d530  group: letter
+\<tt>                   code: 0x01d531  group: letter
+\<uu>                   code: 0x01d532  group: letter
+\<vv>                   code: 0x01d533  group: letter
+\<ww>                   code: 0x01d534  group: letter
+\<xx>                   code: 0x01d535  group: letter
+\<yy>                   code: 0x01d536  group: letter
+\<zz>                   code: 0x01d537  group: letter
+\<alpha>                code: 0x0003b1  group: greek
+\<beta>                 code: 0x0003b2  group: greek
+\<gamma>                code: 0x0003b3  group: greek
+\<delta>                code: 0x0003b4  group: greek
+\<epsilon>              code: 0x0003b5  group: greek
+\<zeta>                 code: 0x0003b6  group: greek
+\<eta>                  code: 0x0003b7  group: greek
+\<theta>                code: 0x0003b8  group: greek
+\<iota>                 code: 0x0003b9  group: greek
+\<kappa>                code: 0x0003ba  group: greek
+\<lambda>               code: 0x0003bb  group: greek  abbrev: %
+\<mu>                   code: 0x0003bc  group: greek
+\<nu>                   code: 0x0003bd  group: greek
+\<xi>                   code: 0x0003be  group: greek
+\<pi>                   code: 0x0003c0  group: greek
+\<rho>                  code: 0x0003c1  group: greek
+\<sigma>                code: 0x0003c3  group: greek
+\<tau>                  code: 0x0003c4  group: greek
+\<upsilon>              code: 0x0003c5  group: greek
+\<phi>                  code: 0x0003c6  group: greek
+\<chi>                  code: 0x0003c7  group: greek
+\<psi>                  code: 0x0003c8  group: greek
+\<omega>                code: 0x0003c9  group: greek
+\<Gamma>                code: 0x000393  group: greek
+\<Delta>                code: 0x000394  group: greek
+\<Theta>                code: 0x000398  group: greek
+\<Lambda>               code: 0x00039b  group: greek
+\<Xi>                   code: 0x00039e  group: greek
+\<Pi>                   code: 0x0003a0  group: greek
+\<Sigma>                code: 0x0003a3  group: greek
+\<Upsilon>              code: 0x0003a5  group: greek
+\<Phi>                  code: 0x0003a6  group: greek
+\<Psi>                  code: 0x0003a8  group: greek
+\<Omega>                code: 0x0003a9  group: greek
+\<bool>                 code: 0x01d539  group: letter
+\<complex>              code: 0x002102  group: letter
+\<nat>                  code: 0x002115  group: letter
+\<rat>                  code: 0x00211a  group: letter
+\<real>                 code: 0x00211d  group: letter
+\<int>                  code: 0x002124  group: letter
+\<leftarrow>            code: 0x002190  group: arrow
+\<longleftarrow>        code: 0x0027f5  group: arrow
+\<rightarrow>           code: 0x002192  group: arrow  abbrev: ->
+\<longrightarrow>       code: 0x0027f6  group: arrow  abbrev: -->
+\<Leftarrow>            code: 0x0021d0  group: arrow
+\<Longleftarrow>        code: 0x0027f8  group: arrow
+\<Rightarrow>           code: 0x0021d2  group: arrow  abbrev: =>
+\<Longrightarrow>       code: 0x0027f9  group: arrow  abbrev: ==>
+\<leftrightarrow>       code: 0x002194  group: arrow
+\<longleftrightarrow>   code: 0x0027f7  group: arrow  abbrev: <->
+\<Leftrightarrow>       code: 0x0021d4  group: arrow
+\<Longleftrightarrow>   code: 0x0027fa  group: arrow  abbrev: <=>
+\<mapsto>               code: 0x0021a6  group: arrow  abbrev: |->
+\<longmapsto>           code: 0x0027fc  group: arrow  abbrev: |-->
+\<midarrow>             code: 0x002500  group: arrow
+\<Midarrow>             code: 0x002550  group: arrow
+\<hookleftarrow>        code: 0x0021a9  group: arrow
+\<hookrightarrow>       code: 0x0021aa  group: arrow
+\<leftharpoondown>      code: 0x0021bd  group: arrow
+\<rightharpoondown>     code: 0x0021c1  group: arrow
+\<leftharpoonup>        code: 0x0021bc  group: arrow
+\<rightharpoonup>       code: 0x0021c0  group: arrow
+\<rightleftharpoons>    code: 0x0021cc  group: arrow
+\<leadsto>              code: 0x00219d  group: arrow  abbrev: ~>
+\<downharpoonleft>      code: 0x0021c3  group: arrow
+\<downharpoonright>     code: 0x0021c2  group: arrow
+\<upharpoonleft>        code: 0x0021bf  group: arrow
+#\<upharpoonright>       code: 0x0021be  group: arrow
+\<restriction>          code: 0x0021be  group: punctuation
+\<Colon>                code: 0x002237  group: punctuation
+\<up>                   code: 0x002191  group: arrow
+\<Up>                   code: 0x0021d1  group: arrow
+\<down>                 code: 0x002193  group: arrow
+\<Down>                 code: 0x0021d3  group: arrow
+\<updown>               code: 0x002195  group: arrow
+\<Updown>               code: 0x0021d5  group: arrow
+\<langle>               code: 0x0027e8  group: punctuation  abbrev: <.
+\<rangle>               code: 0x0027e9  group: punctuation  abbrev: .>
+\<lceil>                code: 0x002308  group: punctuation
+\<rceil>                code: 0x002309  group: punctuation
+\<lfloor>               code: 0x00230a  group: punctuation
+\<rfloor>               code: 0x00230b  group: punctuation
+\<lparr>                code: 0x002987  group: punctuation  abbrev: (|
+\<rparr>                code: 0x002988  group: punctuation  abbrev: |)
+\<lbrakk>               code: 0x0027e6  group: punctuation  abbrev: [|
+\<rbrakk>               code: 0x0027e7  group: punctuation  abbrev: |]
+\<lbrace>               code: 0x002983  group: punctuation  abbrev: {.
+\<rbrace>               code: 0x002984  group: punctuation  abbrev: .}
+\<guillemotleft>        code: 0x0000ab  group: punctuation  abbrev: <<
+\<guillemotright>       code: 0x0000bb  group: punctuation  abbrev: >>
+\<bottom>               code: 0x0022a5  group: logic
+\<top>                  code: 0x0022a4  group: logic
+\<and>                  code: 0x002227  group: logic  abbrev: /\
+\<And>                  code: 0x0022c0  group: logic  abbrev: !!
+\<or>                   code: 0x002228  group: logic  abbrev: \/
+\<Or>                   code: 0x0022c1  group: logic  abbrev: ??
+\<forall>               code: 0x002200  group: logic  abbrev: !
+\<exists>               code: 0x002203  group: logic  abbrev: ?
+\<nexists>              code: 0x002204  group: logic  abbrev: ~?
+\<not>                  code: 0x0000ac  group: logic  abbrev: ~
+\<box>                  code: 0x0025a1  group: logic
+\<diamond>              code: 0x0025c7  group: logic
+\<turnstile>            code: 0x0022a2  group: relation  abbrev: |-
+\<Turnstile>            code: 0x0022a8  group: relation  abbrev: |=
+\<tturnstile>           code: 0x0022a9  group: relation  abbrev: ||-
+\<TTurnstile>           code: 0x0022ab  group: relation  abbrev: ||=
+\<stileturn>            code: 0x0022a3  group: relation  abbrev: -|
+\<surd>                 code: 0x00221a  group: relation
+\<le>                   code: 0x002264  group: relation  abbrev: <=
+\<ge>                   code: 0x002265  group: relation  abbrev: >=
+\<lless>                code: 0x00226a  group: relation
+\<ggreater>             code: 0x00226b  group: relation
+\<lesssim>              code: 0x002272  group: relation
+\<greatersim>           code: 0x002273  group: relation
+\<lessapprox>           code: 0x002a85  group: relation
+\<greaterapprox>        code: 0x002a86  group: relation
+\<in>                   code: 0x002208  group: relation  abbrev: :
+\<notin>                code: 0x002209  group: relation  abbrev: ~:
+\<subset>               code: 0x002282  group: relation
+\<supset>               code: 0x002283  group: relation
+\<subseteq>             code: 0x002286  group: relation  abbrev: (=
+\<supseteq>             code: 0x002287  group: relation  abbrev: =)
+\<sqsubset>             code: 0x00228f  group: relation
+\<sqsupset>             code: 0x002290  group: relation
+\<sqsubseteq>           code: 0x002291  group: relation  abbrev: [=
+\<sqsupseteq>           code: 0x002292  group: relation  abbrev: =]
+\<inter>                code: 0x002229  group: operator
+\<Inter>                code: 0x0022c2  group: operator
+\<union>                code: 0x00222a  group: operator
+\<Union>                code: 0x0022c3  group: operator
+\<squnion>              code: 0x002294  group: operator
+\<Squnion>              code: 0x002a06  group: operator
+\<sqinter>              code: 0x002293  group: operator
+\<Sqinter>              code: 0x002a05  group: operator
+\<setminus>             code: 0x002216  group: operator
+\<propto>               code: 0x00221d  group: operator
+\<uplus>                code: 0x00228e  group: operator
+\<Uplus>                code: 0x002a04  group: operator
+\<noteq>                code: 0x002260  group: relation  abbrev: ~=
+\<sim>                  code: 0x00223c  group: relation
+\<doteq>                code: 0x002250  group: relation
+\<simeq>                code: 0x002243  group: relation
+\<approx>               code: 0x002248  group: relation
+\<asymp>                code: 0x00224d  group: relation
+\<cong>                 code: 0x002245  group: relation
+\<smile>                code: 0x002323  group: relation
+\<equiv>                code: 0x002261  group: relation  abbrev: ==
+\<frown>                code: 0x002322  group: relation
+\<Join>                 code: 0x0022c8
+\<bowtie>               code: 0x002a1d
+\<prec>                 code: 0x00227a  group: relation
+\<succ>                 code: 0x00227b  group: relation
+\<preceq>               code: 0x00227c  group: relation
+\<succeq>               code: 0x00227d  group: relation
+\<parallel>             code: 0x002225  group: punctuation  abbrev: ||
+\<bar>                  code: 0x0000a6  group: punctuation
+\<plusminus>            code: 0x0000b1  group: operator
+\<minusplus>            code: 0x002213  group: operator
+\<times>                code: 0x0000d7  group: operator
+\<div>                  code: 0x0000f7  group: operator
+\<cdot>                 code: 0x0022c5  group: operator
+\<star>                 code: 0x0022c6  group: operator
+\<bullet>               code: 0x002219  group: operator
+\<circ>                 code: 0x002218  group: operator
+\<dagger>               code: 0x002020
+\<ddagger>              code: 0x002021
+\<lhd>                  code: 0x0022b2  group: relation
+\<rhd>                  code: 0x0022b3  group: relation
+\<unlhd>                code: 0x0022b4  group: relation
+\<unrhd>                code: 0x0022b5  group: relation
+\<triangleleft>         code: 0x0025c3  group: relation
+\<triangleright>        code: 0x0025b9  group: relation
+\<triangle>             code: 0x0025b3  group: relation
+\<triangleq>            code: 0x00225c  group: relation
+\<oplus>                code: 0x002295  group: operator  abbrev: +o
+\<Oplus>                code: 0x002a01  group: operator  abbrev: +O
+\<otimes>               code: 0x002297  group: operator  abbrev: *o
+\<Otimes>               code: 0x002a02  group: operator  abbrev: *O
+\<odot>                 code: 0x002299  group: operator  abbrev: .o
+\<Odot>                 code: 0x002a00  group: operator  abbrev: .O
+\<ominus>               code: 0x002296  group: operator  abbrev: -o
+\<oslash>               code: 0x002298  group: operator  abbrev: /o
+\<dots>                 code: 0x002026  group: punctuation abbrev: ...
+\<cdots>                code: 0x0022ef  group: punctuation
+\<Sum>                  code: 0x002211  group: operator  abbrev: SUM
+\<Prod>                 code: 0x00220f  group: operator  abbrev: PROD
+\<Coprod>               code: 0x002210  group: operator
+\<infinity>             code: 0x00221e
+\<integral>             code: 0x00222b  group: operator
+\<ointegral>            code: 0x00222e  group: operator
+\<clubsuit>             code: 0x002663
+\<diamondsuit>          code: 0x002662
+\<heartsuit>            code: 0x002661
+\<spadesuit>            code: 0x002660
+\<aleph>                code: 0x002135
+\<emptyset>             code: 0x002205
+\<nabla>                code: 0x002207
+\<partial>              code: 0x002202
+\<flat>                 code: 0x00266d
+\<natural>              code: 0x00266e
+\<sharp>                code: 0x00266f
+\<angle>                code: 0x002220
+\<copyright>            code: 0x0000a9
+\<registered>           code: 0x0000ae
+\<hyphen>               code: 0x0000ad  group: punctuation
+\<inverse>              code: 0x0000af  group: punctuation
+\<onequarter>           code: 0x0000bc  group: digit
+\<onehalf>              code: 0x0000bd  group: digit
+\<threequarters>        code: 0x0000be  group: digit
+\<ordfeminine>          code: 0x0000aa
+\<ordmasculine>         code: 0x0000ba
+\<section>              code: 0x0000a7
+\<paragraph>            code: 0x0000b6
+\<exclamdown>           code: 0x0000a1
+\<questiondown>         code: 0x0000bf
+\<euro>                 code: 0x0020ac
+\<pounds>               code: 0x0000a3
+\<yen>                  code: 0x0000a5
+\<cent>                 code: 0x0000a2
+\<currency>             code: 0x0000a4
+\<degree>               code: 0x0000b0
+\<amalg>                code: 0x002a3f  group: operator
+\<mho>                  code: 0x002127  group: operator
+\<lozenge>              code: 0x0025ca
+\<wp>                   code: 0x002118
+\<wrong>                code: 0x002240  group: relation
+\<struct>               code: 0x0022c4
+\<acute>                code: 0x0000b4
+\<index>                code: 0x000131
+\<dieresis>             code: 0x0000a8
+\<cedilla>              code: 0x0000b8
+\<hungarumlaut>         code: 0x0002dd
+\<some>                 code: 0x0003f5
+\<^sub>                 code: 0x0021e9  group: control  font: IsabelleText
+\<^sup>                 code: 0x0021e7  group: control  font: IsabelleText
+\<^bold>                code: 0x002759  group: control  font: IsabelleText
+\<^bsub>                code: 0x0021d8  group: control_block  font: IsabelleText  abbrev: =_(
+\<^esub>                code: 0x0021d9  group: control_block  font: IsabelleText  abbrev: =_)
+\<^bsup>                code: 0x0021d7  group: control_block  font: IsabelleText  abbrev: =^(
+\<^esup>                code: 0x0021d6  group: control_block  font: IsabelleText  abbrev: =^)
+
--- a/src/Tools/WWW_Find/unicode_symbols.ML	Fri Aug 30 13:23:23 2013 +0200
+++ b/src/Tools/WWW_Find/unicode_symbols.ML	Fri Aug 30 13:46:32 2013 +0200
@@ -1,7 +1,7 @@
 (*  Title:      Tools/WWW_Find/unicode_symbols.ML
     Author:     Timothy Bourke, NICTA
 
-Ad-hoc parsing of ~~/etc/symbols.
+Parsing of private etc/symbols.
 *)
 
 signature UNICODE_SYMBOLS =
@@ -176,7 +176,8 @@
 end;
 
 local
-val (fromsym, fromabbr, tosym, toabbr) = read_symbols (Path.explode "~~/etc/symbols");
+val (fromsym, fromabbr, tosym, toabbr) =
+  read_symbols (Path.explode "~~/src/Tools/WWW_Find/etc/symbols");
 in
 val symbol_to_unicode = Symtab.lookup fromsym;
 val abbrev_to_unicode = Symtab.lookup fromabbr;
--- a/src/Tools/jEdit/src/completion_popup.scala	Fri Aug 30 13:23:23 2013 +0200
+++ b/src/Tools/jEdit/src/completion_popup.scala	Fri Aug 30 13:46:32 2013 +0200
@@ -91,7 +91,7 @@
       }
     }
 
-    def action(immediate: Boolean)
+    def action(immediate: Boolean = false, explicit: Boolean = false)
     {
       val view = text_area.getView
       val layered = view.getLayeredPane
@@ -106,31 +106,33 @@
             val start = buffer.getLineStartOffset(line)
             val text = buffer.getSegment(start, caret - start)
 
-            syntax.completion.complete(Isabelle_Encoding.is_active(buffer), text) match {
-              case Some((_, List(item))) if item.immediate && immediate =>
-                insert(item)
-
-              case Some((original, items)) =>
-                val font =
-                  painter.getFont.deriveFont(Rendering.font_size("jedit_popup_font_scale"))
+            val decode = Isabelle_Encoding.is_active(buffer)
+            syntax.completion.complete(decode, explicit, text) 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 - original.length)
-                if (loc1 != null) {
-                  val loc2 =
-                    SwingUtilities.convertPoint(painter,
-                      loc1.x, loc1.y + painter.getFontMetrics.getHeight, layered)
+                  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, items) {
-                      override def complete(item: Completion.Item) { insert(item) }
-                      override def propagate(evt: KeyEvent) {
-                        JEdit_Lib.propagate_key(view, evt)
-                        input(evt)
+                    val completion =
+                      new Completion_Popup(layered, loc2, font, result.items) {
+                        override def complete(item: Completion.Item) { insert(item) }
+                        override def propagate(evt: KeyEvent) {
+                          JEdit_Lib.propagate_key(view, evt)
+                          input(evt)
+                        }
+                        override def refocus() { text_area.requestFocus }
                       }
-                      override def refocus() { text_area.requestFocus }
-                    }
-                  completion_popup = Some(completion)
-                  completion.show_popup()
+                    completion_popup = Some(completion)
+                    completion.show_popup()
+                  }
                 }
               case None =>
             }
@@ -161,7 +163,7 @@
 
           if (PIDE.options.seconds("jedit_completion_delay").is_zero && !special) {
             input_delay.revoke()
-            action(PIDE.options.bool("jedit_completion_immediate"))
+            action(immediate = PIDE.options.bool("jedit_completion_immediate"))
           }
           else input_delay.invoke()
         }
@@ -170,7 +172,7 @@
 
     private val input_delay =
       Swing_Thread.delay_last(PIDE.options.seconds("jedit_completion_delay")) {
-        action(false)
+        action()
       }
 
 
--- a/src/Tools/jEdit/src/isabelle.scala	Fri Aug 30 13:23:23 2013 +0200
+++ b/src/Tools/jEdit/src/isabelle.scala	Fri Aug 30 13:46:32 2013 +0200
@@ -168,7 +168,8 @@
   def complete(view: View)
   {
     Completion_Popup.Text_Area(view.getTextArea) match {
-      case Some(text_area_completion) => text_area_completion.action(true)
+      case Some(text_area_completion) =>
+        text_area_completion.action(immediate = true, explicit = true)
       case None => CompleteWord.completeWord(view)
     }
   }
--- a/src/Tools/jEdit/src/symbols_dockable.scala	Fri Aug 30 13:23:23 2013 +0200
+++ b/src/Tools/jEdit/src/symbols_dockable.scala	Fri Aug 30 13:46:32 2013 +0200
@@ -43,8 +43,7 @@
       }
     tooltip =
       JEdit_Lib.wrap_tooltip(
-        symbol +
-          (if (Symbol.abbrevs.isDefinedAt(symbol)) "\nabbrev: " + Symbol.abbrevs(symbol) else ""))
+        cat_lines(symbol :: Symbol.abbrevs.get_list(symbol).map(a => "abbrev: " + a)))
   }
 
   private class Reset_Component extends Button