src/Pure/General/completion.scala
author wenzelm
Fri, 07 Mar 2014 14:37:25 +0100
changeset 55977 ec4830499634
parent 55914 c5b752d549e3
child 55978 56645c447ee9
permissions -rw-r--r--
more detailed description of completion items;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
55673
0286219c1261 clarified module location (again, see 763d35697338);
wenzelm
parents: 55666
diff changeset
     1
/*  Title:      Pure/General/completion.scala
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
     3
55687
78c83cd477c1 clarified completion names;
wenzelm
parents: 55674
diff changeset
     4
Semantic completion within the formal context (reported names).
55674
8a213ab0e78a support for semantic completion on Scala side;
wenzelm
parents: 55673
diff changeset
     5
Syntactic completion of keywords and symbols, with abbreviations
55687
78c83cd477c1 clarified completion names;
wenzelm
parents: 55674
diff changeset
     6
(based on language context).  */
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
     7
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
     8
package isabelle
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
     9
55618
995162143ef4 tuned imports;
wenzelm
parents: 55615
diff changeset
    10
53337
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    11
import scala.collection.immutable.SortedMap
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
    12
import scala.util.parsing.combinator.RegexParsers
53337
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    13
import scala.math.Ordering
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
    14
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
    15
46624
dc4c72092088 streamlined abstract datatype;
wenzelm
parents: 45900
diff changeset
    16
object Completion
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
    17
{
55694
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
    18
  /** completion result **/
53275
b34aac6511ab tuned signature;
wenzelm
parents: 53251
diff changeset
    19
53296
65c60c782da5 less aggressive immediate completion, based on input and text;
wenzelm
parents: 53295
diff changeset
    20
  sealed case class Item(
55692
19e8b00684f7 more explicit Completion.Item.range, independently of caret;
wenzelm
parents: 55687
diff changeset
    21
    range: Text.Range,
53296
65c60c782da5 less aggressive immediate completion, based on input and text;
wenzelm
parents: 53295
diff changeset
    22
    original: String,
55666
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
    23
    name: String,
55694
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
    24
    description: String,
53296
65c60c782da5 less aggressive immediate completion, based on input and text;
wenzelm
parents: 53295
diff changeset
    25
    replacement: String,
55666
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
    26
    move: Int,
53296
65c60c782da5 less aggressive immediate completion, based on input and text;
wenzelm
parents: 53295
diff changeset
    27
    immediate: Boolean)
55694
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
    28
  { override def toString: String = description }
53275
b34aac6511ab tuned signature;
wenzelm
parents: 53251
diff changeset
    29
55914
c5b752d549e3 clarified init_assignable: make double-sure that initial values are reset;
wenzelm
parents: 55813
diff changeset
    30
  object Result
c5b752d549e3 clarified init_assignable: make double-sure that initial values are reset;
wenzelm
parents: 55813
diff changeset
    31
  {
c5b752d549e3 clarified init_assignable: make double-sure that initial values are reset;
wenzelm
parents: 55813
diff changeset
    32
    def empty(range: Text.Range): Result = Result(range, "", false, Nil)
c5b752d549e3 clarified init_assignable: make double-sure that initial values are reset;
wenzelm
parents: 55813
diff changeset
    33
  }
c5b752d549e3 clarified init_assignable: make double-sure that initial values are reset;
wenzelm
parents: 55813
diff changeset
    34
55693
93ba0085e888 try explicit semantic completion before syntax completion;
wenzelm
parents: 55692
diff changeset
    35
  sealed case class Result(
93ba0085e888 try explicit semantic completion before syntax completion;
wenzelm
parents: 55692
diff changeset
    36
    range: Text.Range,
93ba0085e888 try explicit semantic completion before syntax completion;
wenzelm
parents: 55692
diff changeset
    37
    original: String,
93ba0085e888 try explicit semantic completion before syntax completion;
wenzelm
parents: 55692
diff changeset
    38
    unique: Boolean,
93ba0085e888 try explicit semantic completion before syntax completion;
wenzelm
parents: 55692
diff changeset
    39
    items: List[Item])
53325
ffabc0083786 more explicit indication of unique result (see also 45be26b98ca6, 3d654643cf56);
wenzelm
parents: 53324
diff changeset
    40
53275
b34aac6511ab tuned signature;
wenzelm
parents: 53251
diff changeset
    41
46624
dc4c72092088 streamlined abstract datatype;
wenzelm
parents: 45900
diff changeset
    42
53337
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    43
  /** persistent history **/
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    44
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    45
  private val COMPLETION_HISTORY = Path.explode("$ISABELLE_HOME_USER/etc/completion_history")
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    46
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    47
  object History
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    48
  {
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    49
    val empty: History = new History()
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    50
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    51
    def load(): History =
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    52
    {
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    53
      def ignore_error(msg: String): Unit =
55618
995162143ef4 tuned imports;
wenzelm
parents: 55615
diff changeset
    54
        System.err.println("### Ignoring bad content of file " + COMPLETION_HISTORY +
53337
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    55
          (if (msg == "") "" else "\n" + msg))
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    56
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    57
      val content =
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    58
        if (COMPLETION_HISTORY.is_file) {
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    59
          try {
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    60
            import XML.Decode._
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    61
            list(pair(Symbol.decode_string, int))(
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    62
              YXML.parse_body(File.read(COMPLETION_HISTORY)))
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    63
          }
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    64
          catch {
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    65
            case ERROR(msg) => ignore_error(msg); Nil
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    66
            case _: XML.Error => ignore_error(""); Nil
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    67
          }
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    68
        }
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    69
        else Nil
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    70
      (empty /: content)(_ + _)
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    71
    }
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    72
  }
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    73
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    74
  final class History private(rep: SortedMap[String, Int] = SortedMap.empty)
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    75
  {
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    76
    override def toString: String = rep.mkString("Completion.History(", ",", ")")
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    77
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    78
    def frequency(name: String): Int = rep.getOrElse(name, 0)
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    79
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    80
    def + (entry: (String, Int)): History =
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    81
    {
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    82
      val (name, freq) = entry
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    83
      new History(rep + (name -> (frequency(name) + freq)))
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    84
    }
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    85
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    86
    def ordering: Ordering[Item] =
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    87
      new Ordering[Item] {
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    88
        def compare(item1: Item, item2: Item): Int =
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    89
        {
55666
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
    90
          frequency(item1.name) compare frequency(item2.name) match {
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
    91
            case 0 => item1.name compare item2.name
53337
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    92
            case ord => - ord
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    93
          }
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    94
        }
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    95
      }
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    96
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    97
    def save()
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    98
    {
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
    99
      Isabelle_System.mkdirs(COMPLETION_HISTORY.dir)
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   100
      File.write_backup(COMPLETION_HISTORY,
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   101
        {
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   102
          import XML.Encode._
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   103
          YXML.string_of_body(list(pair(Symbol.encode_string, int))(rep.toList))
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   104
        })
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   105
    }
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   106
  }
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   107
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   108
  class History_Variable
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   109
  {
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   110
    private var history = History.empty
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   111
    def value: History = synchronized { history }
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   112
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   113
    def load()
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   114
    {
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   115
      val h = History.load()
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   116
      synchronized { history = h }
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   117
    }
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   118
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   119
    def update(item: Item, freq: Int = 1): Unit = synchronized {
55666
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   120
      history = history + (item.name -> freq)
53337
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   121
    }
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   122
  }
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   123
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   124
55694
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   125
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   126
  /** semantic completion **/
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   127
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   128
  object Names
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   129
  {
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   130
    object Info
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   131
    {
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   132
      def unapply(info: Text.Markup): Option[Names] =
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   133
        info.info match {
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   134
          case XML.Elem(Markup(Markup.COMPLETION, _), body) =>
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   135
            try {
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   136
              val (total, names) =
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   137
              {
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   138
                import XML.Decode._
55977
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   139
                pair(int, list(pair(string, pair(string, string))))(body)
55694
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   140
              }
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   141
              Some(Names(info.range, total, names))
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   142
            }
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   143
            catch { case _: XML.Error => None }
55914
c5b752d549e3 clarified init_assignable: make double-sure that initial values are reset;
wenzelm
parents: 55813
diff changeset
   144
          case XML.Elem(Markup(Markup.NO_COMPLETION, _), _) =>
c5b752d549e3 clarified init_assignable: make double-sure that initial values are reset;
wenzelm
parents: 55813
diff changeset
   145
            Some(Names(info.range, 0, Nil))
55694
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   146
          case _ => None
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   147
        }
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   148
    }
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   149
  }
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   150
55977
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   151
  sealed case class Names(
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   152
    range: Text.Range, total: Int, names: List[(String, (String, String))])
55694
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   153
  {
55914
c5b752d549e3 clarified init_assignable: make double-sure that initial values are reset;
wenzelm
parents: 55813
diff changeset
   154
    def no_completion: Boolean = total == 0 && names.isEmpty
c5b752d549e3 clarified init_assignable: make double-sure that initial values are reset;
wenzelm
parents: 55813
diff changeset
   155
55694
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   156
    def complete(
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   157
      history: Completion.History,
55977
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   158
      do_decode: Boolean,
55694
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   159
      original: String): Option[Completion.Result] =
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   160
    {
55977
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   161
      def decode(s: String): String = if (do_decode) Symbol.decode(s) else s
55694
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   162
      val items =
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   163
        for {
55977
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   164
          (xname, (kind, name)) <- names
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   165
          xname1 = decode(xname)
55694
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   166
          if xname1 != original
55977
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   167
          (full_name, descr_name) =
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   168
            if (kind == "") (name, quote(decode(name)))
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   169
            else (kind + "." + name, Library.plain_words(kind) + " " + quote(decode(name)))
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   170
          description = xname1 + "   (" + descr_name + ")"
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   171
        } yield Item(range, original, full_name, description, xname1, 0, true)
55694
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   172
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   173
      if (items.isEmpty) None
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   174
      else Some(Result(range, original, names.length == 1, items.sorted(history.ordering)))
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   175
    }
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   176
  }
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   177
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   178
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   179
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   180
  /** syntactic completion **/
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   181
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   182
  /* language context */
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   183
55749
75a48dc4383e tuned signature;
wenzelm
parents: 55748
diff changeset
   184
  object Language_Context
55694
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   185
  {
55749
75a48dc4383e tuned signature;
wenzelm
parents: 55748
diff changeset
   186
    val outer = Language_Context("", true, false)
75a48dc4383e tuned signature;
wenzelm
parents: 55748
diff changeset
   187
    val inner = Language_Context(Markup.Language.UNKNOWN, true, false)
75a48dc4383e tuned signature;
wenzelm
parents: 55748
diff changeset
   188
    val ML_outer = Language_Context(Markup.Language.ML, false, true)
75a48dc4383e tuned signature;
wenzelm
parents: 55748
diff changeset
   189
    val ML_inner = Language_Context(Markup.Language.ML, true, false)
55694
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   190
  }
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   191
55749
75a48dc4383e tuned signature;
wenzelm
parents: 55748
diff changeset
   192
  sealed case class Language_Context(language: String, symbols: Boolean, antiquotes: Boolean)
55694
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   193
  {
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   194
    def is_outer: Boolean = language == ""
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   195
  }
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   196
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   197
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   198
  /* init */
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   199
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   200
  val empty: Completion = new Completion()
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   201
  def init(): Completion = empty.add_symbols()
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   202
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   203
a1184dfb8e00 clarified semantic completion: retain kind.full_name as official item name for history;
wenzelm
parents: 55693
diff changeset
   204
  /* word parsers */
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   205
55615
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   206
  private object Word_Parsers extends RegexParsers
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   207
  {
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   208
    override val whiteSpace = "".r
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   209
55615
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   210
    private def reverse_symbol: Parser[String] = """>[A-Za-z0-9_']+\^?<\\""".r
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   211
    private def reverse_symb: Parser[String] = """[A-Za-z0-9_']{2,}\^?<\\""".r
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   212
    private def escape: Parser[String] = """[a-zA-Z0-9_']+\\""".r
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   213
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   214
    private val word_regex = "[a-zA-Z0-9_']+".r
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   215
    private def word: Parser[String] = word_regex
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   216
    private def word3: Parser[String] = """[a-zA-Z0-9_']{3,}""".r
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   217
55813
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   218
    def is_word(s: CharSequence): Boolean = word_regex.pattern.matcher(s).matches
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   219
    def is_word_char(c: Char): Boolean = Symbol.is_ascii_letdig(c)
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   220
55813
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   221
    def extend_word(text: CharSequence, offset: Text.Offset): Text.Offset =
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   222
    {
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   223
      val n = text.length
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   224
      var i = offset
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   225
      while (i < n && is_word_char(text.charAt(i))) i += 1
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   226
      if (i < n && text.charAt(i) == '>' && read_symbol(text.subSequence(0, i + 1)).isDefined)
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   227
        i + 1
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   228
      else i
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   229
    }
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   230
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   231
    def read_symbol(in: CharSequence): Option[String] =
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   232
    {
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   233
      val reverse_in = new Library.Reverse(in)
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   234
      parse(reverse_symbol ^^ (_.reverse), reverse_in) match {
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   235
        case Success(result, _) => Some(result)
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   236
        case _ => None
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   237
      }
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   238
    }
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   239
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   240
    def read_word(explicit: Boolean, in: CharSequence): Option[String] =
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   241
    {
53322
a4cd032172e0 allow short words for explicit completion;
wenzelm
parents: 53318
diff changeset
   242
      val parse_word = if (explicit) word else word3
37072
9105c8237c7a renamed "rev" to "reverse" following usual Scala conventions;
wenzelm
parents: 36012
diff changeset
   243
      val reverse_in = new Library.Reverse(in)
53322
a4cd032172e0 allow short words for explicit completion;
wenzelm
parents: 53318
diff changeset
   244
      parse((reverse_symbol | reverse_symb | escape | parse_word) ^^ (_.reverse), reverse_in) match {
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   245
        case Success(result, _) => Some(result)
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   246
        case _ => None
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   247
      }
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   248
    }
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   249
  }
55666
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   250
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   251
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   252
  /* abbreviations */
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   253
55813
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   254
  private val caret_indicator = '\007'
55666
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   255
  private val antiquote = "@{"
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   256
  private val default_abbrs =
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   257
    Map("@{" -> "@{\007}", "`" -> "\\<open>\007\\<close>")
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   258
}
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   259
46712
8650d9a95736 prefer final ADTs -- prevent ooddities;
wenzelm
parents: 46625
diff changeset
   260
final class Completion private(
55615
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   261
  keywords: Set[String] = Set.empty,
46625
wenzelm
parents: 46624
diff changeset
   262
  words_lex: Scan.Lexicon = Scan.Lexicon.empty,
53318
ec4511548304 allow multiple entries;
wenzelm
parents: 53316
diff changeset
   263
  words_map: Multi_Map[String, String] = Multi_Map.empty,
46625
wenzelm
parents: 46624
diff changeset
   264
  abbrevs_lex: Scan.Lexicon = Scan.Lexicon.empty,
53318
ec4511548304 allow multiple entries;
wenzelm
parents: 53316
diff changeset
   265
  abbrevs_map: Multi_Map[String, (String, String)] = Multi_Map.empty)
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   266
{
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   267
  /* adding stuff */
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   268
40533
e38e80686ce5 somewhat adhoc replacement for 'thus' and 'hence';
wenzelm
parents: 37072
diff changeset
   269
  def + (keyword: String, replace: String): Completion =
46624
dc4c72092088 streamlined abstract datatype;
wenzelm
parents: 45900
diff changeset
   270
    new Completion(
55615
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   271
      keywords + keyword,
46624
dc4c72092088 streamlined abstract datatype;
wenzelm
parents: 45900
diff changeset
   272
      words_lex + keyword,
dc4c72092088 streamlined abstract datatype;
wenzelm
parents: 45900
diff changeset
   273
      words_map + (keyword -> replace),
dc4c72092088 streamlined abstract datatype;
wenzelm
parents: 45900
diff changeset
   274
      abbrevs_lex,
dc4c72092088 streamlined abstract datatype;
wenzelm
parents: 45900
diff changeset
   275
      abbrevs_map)
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   276
40533
e38e80686ce5 somewhat adhoc replacement for 'thus' and 'hence';
wenzelm
parents: 37072
diff changeset
   277
  def + (keyword: String): Completion = this + (keyword, keyword)
e38e80686ce5 somewhat adhoc replacement for 'thus' and 'hence';
wenzelm
parents: 37072
diff changeset
   278
46624
dc4c72092088 streamlined abstract datatype;
wenzelm
parents: 45900
diff changeset
   279
  private def add_symbols(): Completion =
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   280
  {
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   281
    val words =
55615
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   282
      (for ((x, _) <- Symbol.names.toList) yield (x, x)) :::
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   283
      (for ((x, y) <- Symbol.names.toList) yield ("\\" + y, x)) :::
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   284
      (for ((x, y) <- Symbol.abbrevs.toList if Completion.Word_Parsers.is_word(y)) yield (y, x))
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   285
55666
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   286
    val symbol_abbrs =
55615
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   287
      (for ((x, y) <- Symbol.abbrevs.iterator if !Completion.Word_Parsers.is_word(y))
55666
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   288
        yield (y, x)).toList
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   289
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   290
    val abbrs =
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   291
      for ((a, b) <- symbol_abbrs ::: Completion.default_abbrs.toList)
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   292
        yield (a.reverse, (a, b))
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   293
46624
dc4c72092088 streamlined abstract datatype;
wenzelm
parents: 45900
diff changeset
   294
    new Completion(
55615
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   295
      keywords,
46624
dc4c72092088 streamlined abstract datatype;
wenzelm
parents: 45900
diff changeset
   296
      words_lex ++ words.map(_._1),
dc4c72092088 streamlined abstract datatype;
wenzelm
parents: 45900
diff changeset
   297
      words_map ++ words,
dc4c72092088 streamlined abstract datatype;
wenzelm
parents: 45900
diff changeset
   298
      abbrevs_lex ++ abbrs.map(_._1),
dc4c72092088 streamlined abstract datatype;
wenzelm
parents: 45900
diff changeset
   299
      abbrevs_map ++ abbrs)
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   300
  }
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   301
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   302
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   303
  /* complete */
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   304
53337
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   305
  def complete(
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   306
    history: Completion.History,
55977
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   307
    do_decode: Boolean,
53337
b3817a0e3211 sort items according to persistent history of frequency of use;
wenzelm
parents: 53325
diff changeset
   308
    explicit: Boolean,
55813
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   309
    start: Text.Offset,
55615
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   310
    text: CharSequence,
55813
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   311
    caret: Int,
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   312
    extend_word: Boolean,
55749
75a48dc4383e tuned signature;
wenzelm
parents: 55748
diff changeset
   313
    language_context: Completion.Language_Context): Option[Completion.Result] =
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   314
  {
55977
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   315
    def decode(s: String): String = if (do_decode) Symbol.decode(s) else s
55813
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   316
    val length = text.length
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   317
55615
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   318
    val abbrevs_result =
55813
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   319
    {
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   320
      val reverse_in = new Library.Reverse(text.subSequence(0, caret))
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   321
      Scan.Parsers.parse(Scan.Parsers.literal(abbrevs_lex), reverse_in) match {
55666
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   322
        case Scan.Parsers.Success(reverse_a, _) =>
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   323
          val abbrevs = abbrevs_map.get_list(reverse_a)
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   324
          abbrevs match {
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   325
            case Nil => None
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   326
            case (a, _) :: _ =>
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   327
              val ok =
55749
75a48dc4383e tuned signature;
wenzelm
parents: 55748
diff changeset
   328
                if (a == Completion.antiquote) language_context.antiquotes
75a48dc4383e tuned signature;
wenzelm
parents: 55748
diff changeset
   329
                else language_context.symbols || Completion.default_abbrs.isDefinedAt(a)
55813
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   330
              if (ok) Some(((a, abbrevs.map(_._2)), caret))
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   331
              else None
55666
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   332
          }
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   333
        case _ => None
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   334
      }
55813
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   335
    }
55615
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   336
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   337
    val words_result =
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   338
      abbrevs_result orElse {
55813
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   339
        val end =
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   340
          if (extend_word) Completion.Word_Parsers.extend_word(text, caret)
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   341
          else caret
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   342
        (Completion.Word_Parsers.read_symbol(text.subSequence(0, end)) match {
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   343
          case Some(symbol) => Some(symbol)
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   344
          case None =>
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   345
            val word_context =
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   346
              end < length && Completion.Word_Parsers.is_word_char(text.charAt(end))
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   347
            if (word_context) None
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   348
            else Completion.Word_Parsers.read_word(explicit, text.subSequence(0, end))
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   349
        }) match {
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   350
          case Some(word) =>
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   351
            val completions =
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   352
              for {
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   353
                s <- words_lex.completions(word)
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   354
                if (if (keywords(s)) language_context.is_outer else language_context.symbols)
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   355
                r <- words_map.get_list(s)
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   356
              } yield r
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   357
            if (completions.isEmpty) None
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   358
            else Some(((word, completions), end))
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   359
          case None => None
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   360
        }
53275
b34aac6511ab tuned signature;
wenzelm
parents: 53251
diff changeset
   361
      }
55615
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   362
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   363
    words_result match {
55813
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   364
      case Some(((word, cs), end)) =>
08a1c860bc12 allow completion within a word (or symbol), like semantic completion;
wenzelm
parents: 55749
diff changeset
   365
        val range = Text.Range(- word.length, 0) + end + start
55977
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   366
        val ds = cs.map(decode(_)).filter(_ != word)
53275
b34aac6511ab tuned signature;
wenzelm
parents: 53251
diff changeset
   367
        if (ds.isEmpty) None
53296
65c60c782da5 less aggressive immediate completion, based on input and text;
wenzelm
parents: 53295
diff changeset
   368
        else {
53313
2e745fc40416 less surprising immediate completion;
wenzelm
parents: 53296
diff changeset
   369
          val immediate =
55615
bf4bbe72f740 completion of keywords and symbols based on language context;
wenzelm
parents: 55497
diff changeset
   370
            !Completion.Word_Parsers.is_word(word) &&
53313
2e745fc40416 less surprising immediate completion;
wenzelm
parents: 53296
diff changeset
   371
            Character.codePointCount(word, 0, word.length) > 1
55666
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   372
          val items =
55977
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   373
            for { (name, name1) <- cs zip ds }
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   374
            yield {
55666
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   375
              val (s1, s2) =
55977
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   376
                space_explode(Completion.caret_indicator, name1) match {
55666
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   377
                  case List(s1, s2) => (s1, s2)
55977
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   378
                  case _ => (name1, "")
55666
cc350eb1087e refined language context: antiquotes;
wenzelm
parents: 55618
diff changeset
   379
                }
55977
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   380
              val description =
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   381
                if (keywords(name)) name1 + "   (keyword)"
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   382
                else if (Symbol.names.isDefinedAt(name) && name != name1)
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   383
                  name1 + "   (symbol " + quote(name) + ")"
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   384
                else name1
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   385
              Completion.Item(
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   386
                range, word, name1, description, s1 + s2, - s2.length, explicit || immediate)
ec4830499634 more detailed description of completion items;
wenzelm
parents: 55914
diff changeset
   387
            }
55693
93ba0085e888 try explicit semantic completion before syntax completion;
wenzelm
parents: 55692
diff changeset
   388
          Some(Completion.Result(range, word, cs.length == 1, items.sorted(history.ordering)))
53296
65c60c782da5 less aggressive immediate completion, based on input and text;
wenzelm
parents: 53295
diff changeset
   389
        }
53275
b34aac6511ab tuned signature;
wenzelm
parents: 53251
diff changeset
   390
      case None => None
31765
a5fdf7a76f9d tuned input: require longer symbol prefix;
wenzelm
parents: 31763
diff changeset
   391
    }
31763
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   392
  }
c2c2d380729d Completion of symbols and keywords.
wenzelm
parents:
diff changeset
   393
}