refined language context: antiquotes;
authorwenzelm
Sat, 22 Feb 2014 15:07:33 +0100
changeset 57008cc350eb1087e
parent 57007 4381a2b622ea
child 57009 a99f9beba83a
refined language context: antiquotes;
support default completions, with move of caret position;
tuned signature;
src/Pure/Isar/completion.scala
src/Pure/Isar/outer_syntax.scala
src/Pure/PIDE/markup.ML
src/Pure/PIDE/markup.scala
src/Tools/jEdit/src/completion_popup.scala
src/Tools/jEdit/src/isabelle.scala
src/Tools/jEdit/src/rendering.scala
     1.1 --- a/src/Pure/Isar/completion.scala	Fri Feb 21 23:42:43 2014 +0100
     1.2 +++ b/src/Pure/Isar/completion.scala	Sat Feb 22 15:07:33 2014 +0100
     1.3 @@ -1,7 +1,7 @@
     1.4  /*  Title:      Pure/Isar/completion.scala
     1.5      Author:     Makarius
     1.6  
     1.7 -Completion of symbols and keywords.
     1.8 +Completion of keywords and symbols, with abbreviations.
     1.9  */
    1.10  
    1.11  package isabelle
    1.12 @@ -18,10 +18,13 @@
    1.13  
    1.14    object Context
    1.15    {
    1.16 -    val default = Context("", true)
    1.17 +    val outer = Context("", true, false)
    1.18 +    val inner = Context(Markup.Language.UNKNOWN, true, false)
    1.19 +    val ML_outer = Context(Markup.Language.ML, false, false)
    1.20 +    val ML_inner = Context(Markup.Language.ML, true, true)
    1.21    }
    1.22  
    1.23 -  sealed case class Context(language: String, symbols: Boolean)
    1.24 +  sealed case class Context(language: String, symbols: Boolean, antiquotes: Boolean)
    1.25    {
    1.26      def is_outer: Boolean = language == ""
    1.27    }
    1.28 @@ -31,10 +34,11 @@
    1.29  
    1.30    sealed case class Item(
    1.31      original: String,
    1.32 +    name: String,
    1.33      replacement: String,
    1.34 -    description: String,
    1.35 +    move: Int,
    1.36      immediate: Boolean)
    1.37 -  { override def toString: String = description }
    1.38 +  { override def toString: String = name }
    1.39  
    1.40    sealed case class Result(original: String, unique: Boolean, items: List[Item])
    1.41  
    1.42 @@ -92,8 +96,8 @@
    1.43        new Ordering[Item] {
    1.44          def compare(item1: Item, item2: Item): Int =
    1.45          {
    1.46 -          frequency(item1.replacement) compare frequency(item2.replacement) match {
    1.47 -            case 0 => item1.replacement compare item2.replacement
    1.48 +          frequency(item1.name) compare frequency(item2.name) match {
    1.49 +            case 0 => item1.name compare item2.name
    1.50              case ord => - ord
    1.51            }
    1.52          }
    1.53 @@ -122,7 +126,7 @@
    1.54      }
    1.55  
    1.56      def update(item: Item, freq: Int = 1): Unit = synchronized {
    1.57 -      history = history + (item.replacement -> freq)
    1.58 +      history = history + (item.name -> freq)
    1.59      }
    1.60    }
    1.61  
    1.62 @@ -154,6 +158,14 @@
    1.63        }
    1.64      }
    1.65    }
    1.66 +
    1.67 +
    1.68 +  /* abbreviations */
    1.69 +
    1.70 +  private val caret = '\007'
    1.71 +  private val antiquote = "@{"
    1.72 +  private val default_abbrs =
    1.73 +    Map("@{" -> "@{\007}", "`" -> "\\<open>\007\\<close>")
    1.74  }
    1.75  
    1.76  final class Completion private(
    1.77 @@ -182,9 +194,13 @@
    1.78        (for ((x, y) <- Symbol.names.toList) yield ("\\" + y, x)) :::
    1.79        (for ((x, y) <- Symbol.abbrevs.toList if Completion.Word_Parsers.is_word(y)) yield (y, x))
    1.80  
    1.81 +    val symbol_abbrs =
    1.82 +      (for ((x, y) <- Symbol.abbrevs.iterator if !Completion.Word_Parsers.is_word(y))
    1.83 +        yield (y, x)).toList
    1.84 +
    1.85      val abbrs =
    1.86 -      (for ((x, y) <- Symbol.abbrevs.iterator if !Completion.Word_Parsers.is_word(y))
    1.87 -        yield (y.reverse, (y, x))).toList
    1.88 +      for ((a, b) <- symbol_abbrs ::: Completion.default_abbrs.toList)
    1.89 +        yield (a.reverse, (a, b))
    1.90  
    1.91      new Completion(
    1.92        keywords,
    1.93 @@ -205,17 +221,19 @@
    1.94      context: Completion.Context): Option[Completion.Result] =
    1.95    {
    1.96      val abbrevs_result =
    1.97 -      if (context.symbols)
    1.98 -        Scan.Parsers.parse(Scan.Parsers.literal(abbrevs_lex), new Library.Reverse(text)) match {
    1.99 -          case Scan.Parsers.Success(reverse_a, _) =>
   1.100 -            val abbrevs = abbrevs_map.get_list(reverse_a)
   1.101 -            abbrevs match {
   1.102 -              case Nil => None
   1.103 -              case (a, _) :: _ => Some((a, abbrevs.map(_._2)))
   1.104 -            }
   1.105 -          case _ => None
   1.106 -        }
   1.107 -      else None
   1.108 +      Scan.Parsers.parse(Scan.Parsers.literal(abbrevs_lex), new Library.Reverse(text)) match {
   1.109 +        case Scan.Parsers.Success(reverse_a, _) =>
   1.110 +          val abbrevs = abbrevs_map.get_list(reverse_a)
   1.111 +          abbrevs match {
   1.112 +            case Nil => None
   1.113 +            case (a, _) :: _ =>
   1.114 +              val ok =
   1.115 +                if (a == Completion.antiquote) context.antiquotes
   1.116 +                else context.symbols || Completion.default_abbrs.isDefinedAt(a)
   1.117 +              if (ok) Some((a, abbrevs.map(_._2))) else None
   1.118 +          }
   1.119 +        case _ => None
   1.120 +      }
   1.121  
   1.122      val words_result =
   1.123        abbrevs_result orElse {
   1.124 @@ -241,7 +259,15 @@
   1.125            val immediate =
   1.126              !Completion.Word_Parsers.is_word(word) &&
   1.127              Character.codePointCount(word, 0, word.length) > 1
   1.128 -          val items = ds.map(s => Completion.Item(word, s, s, explicit || immediate))
   1.129 +          val items =
   1.130 +            ds.map(s => {
   1.131 +              val (s1, s2) =
   1.132 +                space_explode(Completion.caret, s) match {
   1.133 +                  case List(s1, s2) => (s1, s2)
   1.134 +                  case _ => (s, "")
   1.135 +                }
   1.136 +              Completion.Item(word, s, s1 + s2, - s2.length, explicit || immediate)
   1.137 +            })
   1.138            Some(Completion.Result(word, cs.length == 1, items.sorted(history.ordering)))
   1.139          }
   1.140        case None => None
     2.1 --- a/src/Pure/Isar/outer_syntax.scala	Fri Feb 21 23:42:43 2014 +0100
     2.2 +++ b/src/Pure/Isar/outer_syntax.scala	Sat Feb 22 15:07:33 2014 +0100
     2.3 @@ -43,7 +43,7 @@
     2.4    keywords: Map[String, (String, List[String])] = Map.empty,
     2.5    lexicon: Scan.Lexicon = Scan.Lexicon.empty,
     2.6    val completion: Completion = Completion.empty,
     2.7 -  val completion_context: Completion.Context = Completion.Context.default,
     2.8 +  val completion_context: Completion.Context = Completion.Context.outer,
     2.9    val has_tokens: Boolean = true)
    2.10  {
    2.11    override def toString: String =
     3.1 --- a/src/Pure/PIDE/markup.ML	Fri Feb 21 23:42:43 2014 +0100
     3.2 +++ b/src/Pure/PIDE/markup.ML	Sat Feb 22 15:07:33 2014 +0100
     3.3 @@ -21,7 +21,8 @@
     3.4    val kindN: string
     3.5    val instanceN: string
     3.6    val symbolsN: string
     3.7 -  val languageN: string val language: string -> bool -> T
     3.8 +  val languageN: string
     3.9 +  val language: {name: string, symbols: bool, antiquotes: bool} -> T
    3.10    val language_sort: T
    3.11    val language_type: T
    3.12    val language_term: T
    3.13 @@ -249,18 +250,22 @@
    3.14  (* embedded languages *)
    3.15  
    3.16  val symbolsN = "symbols";
    3.17 +val antiquotesN = "antiquotes";
    3.18  val languageN = "language";
    3.19 -fun language name symbols = (languageN, [(nameN, name), (symbolsN, print_bool symbols)]);
    3.20  
    3.21 -val language_sort = language "sort" true;
    3.22 -val language_type = language "type" true;
    3.23 -val language_term = language "term" true;
    3.24 -val language_prop = language "prop" true;
    3.25 -val language_ML = language "ML" false;
    3.26 -val language_document = language "document" false;
    3.27 -val language_antiquotation = language "antiquotation" true;
    3.28 -val language_text = language "text" true;
    3.29 -val language_rail = language "rail" true;
    3.30 +fun language {name, symbols, antiquotes} =
    3.31 +  (languageN,
    3.32 +    [(nameN, name), (symbolsN, print_bool symbols), (antiquotesN, print_bool antiquotes)]);
    3.33 +
    3.34 +val language_sort = language {name = "sort", symbols = true, antiquotes = false};
    3.35 +val language_type = language {name = "type", symbols = true, antiquotes = false};
    3.36 +val language_term = language {name = "term", symbols = true, antiquotes = false};
    3.37 +val language_prop = language {name = "prop", symbols = true, antiquotes = false};
    3.38 +val language_ML = language {name = "ML", symbols = false, antiquotes = true};
    3.39 +val language_document = language {name = "document", symbols = false, antiquotes = true};
    3.40 +val language_antiquotation = language {name = "antiquotation", symbols = true, antiquotes = false};
    3.41 +val language_text = language {name = "text", symbols = true, antiquotes = false};
    3.42 +val language_rail = language {name = "rail", symbols = true, antiquotes = true};
    3.43  
    3.44  
    3.45  (* formal entities *)
     4.1 --- a/src/Pure/PIDE/markup.scala	Fri Feb 21 23:42:43 2014 +0100
     4.2 +++ b/src/Pure/PIDE/markup.scala	Sat Feb 22 15:07:33 2014 +0100
     4.3 @@ -87,8 +87,8 @@
     4.4  
     4.5    /* embedded languages */
     4.6  
     4.7 -  val SYMBOLS = "symbols"
     4.8 -  val Symbols = new Properties.Boolean(SYMBOLS)
     4.9 +  val Symbols = new Properties.Boolean("symbols")
    4.10 +  val Antiquotes = new Properties.Boolean("antiquotes")
    4.11  
    4.12    val LANGUAGE = "language"
    4.13    object Language
    4.14 @@ -96,11 +96,12 @@
    4.15      val ML = "ML"
    4.16      val UNKNOWN = "unknown"
    4.17  
    4.18 -    def unapply(markup: Markup): Option[(String, Boolean)] =
    4.19 +    def unapply(markup: Markup): Option[(String, Boolean, Boolean)] =
    4.20        markup match {
    4.21          case Markup(LANGUAGE, props) =>
    4.22 -          (props, props) match {
    4.23 -            case (Name(name), Symbols(symbols)) => Some((name, symbols))
    4.24 +          (props, props, props) match {
    4.25 +            case (Name(name), Symbols(symbols), Antiquotes(antiquotes)) =>
    4.26 +              Some((name, symbols, antiquotes))
    4.27              case _ => None
    4.28            }
    4.29          case _ => None
     5.1 --- a/src/Tools/jEdit/src/completion_popup.scala	Fri Feb 21 23:42:43 2014 +0100
     5.2 +++ b/src/Tools/jEdit/src/completion_popup.scala	Sat Feb 22 15:07:33 2014 +0100
     5.3 @@ -87,6 +87,8 @@
     5.4              case Some(text) if text == item.original =>
     5.5                buffer.remove(caret - len, len)
     5.6                buffer.insert(caret - len, item.replacement)
     5.7 +              if (item.move != 0)
     5.8 +                text_area.moveCaretPosition(text_area.getCaretPosition + item.move)
     5.9              case _ =>
    5.10            }
    5.11          }
    5.12 @@ -265,7 +267,7 @@
    5.13                content.substring(0, caret - len) +
    5.14                item.replacement +
    5.15                content.substring(caret))
    5.16 -            text_field.getCaret.setDot(caret - len + item.replacement.length)
    5.17 +            text_field.getCaret.setDot(caret - len + item.replacement.length + item.move)
    5.18            case _ =>
    5.19          }
    5.20        }
     6.1 --- a/src/Tools/jEdit/src/isabelle.scala	Fri Feb 21 23:42:43 2014 +0100
     6.2 +++ b/src/Tools/jEdit/src/isabelle.scala	Sat Feb 22 15:07:33 2014 +0100
     6.3 @@ -33,7 +33,7 @@
     6.4  
     6.5    private lazy val ml_syntax: Outer_Syntax =
     6.6      Outer_Syntax.init().no_tokens.
     6.7 -      set_completion_context(Completion.Context(Markup.Language.ML, false))
     6.8 +      set_completion_context(Completion.Context.ML_outer)
     6.9  
    6.10    private lazy val news_syntax: Outer_Syntax =
    6.11      Outer_Syntax.init().no_tokens
     7.1 --- a/src/Tools/jEdit/src/rendering.scala	Fri Feb 21 23:42:43 2014 +0100
     7.2 +++ b/src/Tools/jEdit/src/rendering.scala	Sat Feb 22 15:07:33 2014 +0100
     7.3 @@ -278,11 +278,11 @@
     7.4            {
     7.5              case Text.Info(_, elem)
     7.6              if elem.name == Markup.ML_STRING || elem.name == Markup.ML_COMMENT =>
     7.7 -              Some(Completion.Context(Markup.Language.ML, true))
     7.8 -            case Text.Info(_, XML.Elem(Markup.Language(language, symbols), _)) =>
     7.9 -              Some(Completion.Context(language, symbols))
    7.10 -            case Text.Info(_, XML.Elem(markup, _)) =>
    7.11 -              Some(Completion.Context(Markup.Language.UNKNOWN, true))
    7.12 +              Some(Completion.Context.ML_inner)
    7.13 +            case Text.Info(_, XML.Elem(Markup.Language(language, symbols, antiquotes), _)) =>
    7.14 +              Some(Completion.Context(language, symbols, antiquotes))
    7.15 +            case Text.Info(_, _) =>
    7.16 +              Some(Completion.Context.inner)
    7.17            })
    7.18        result match {
    7.19          case Text.Info(_, context) :: _ => Some(context)
    7.20 @@ -500,7 +500,7 @@
    7.21              Some(add(prev, r, (true, pretty_typing("::", body))))
    7.22            case (prev, Text.Info(r, XML.Elem(Markup(Markup.ML_TYPING, _), body))) =>
    7.23              Some(add(prev, r, (false, pretty_typing("ML:", body))))
    7.24 -          case (prev, Text.Info(r, XML.Elem(Markup.Language(language, _), _))) =>
    7.25 +          case (prev, Text.Info(r, XML.Elem(Markup.Language(language, _, _), _))) =>
    7.26              Some(add(prev, r, (true, XML.Text("language: " + language))))
    7.27            case (prev, Text.Info(r, XML.Elem(Markup(name, _), _))) =>
    7.28              Rendering.tooltip_descriptions.get(name).