@@ -7,8 +7,6 @@ import dotty.tools.dotc.printing.SyntaxHighlighting
77import dotty .tools .dotc .reporting .Reporter
88import dotty .tools .dotc .util .SourceFile
99import org .jline .reader
10- import org .jline .reader .LineReader .Option ._
11- import org .jline .reader .LineReader ._
1210import org .jline .reader .Parser .ParseContext
1311import org .jline .reader ._
1412import org .jline .reader .impl .history .DefaultHistory
@@ -44,6 +42,8 @@ final class JLineTerminal extends java.io.Closeable {
4442 def readLine (
4543 completer : Completer // provide auto-completions
4644 )(implicit ctx : Context ): String = {
45+ import LineReader .Option ._
46+ import LineReader ._
4747 val lineReader = LineReaderBuilder .builder()
4848 .terminal(terminal)
4949 .history(history)
@@ -89,6 +89,8 @@ final class JLineTerminal extends java.io.Closeable {
8989 def parse (line : String , cursor : Int , context : ParseContext ): reader.ParsedLine = {
9090 def parsedLine (word : String , wordCursor : Int ) =
9191 new ParsedLine (cursor, line, word, wordCursor)
92+ // Used when no word is being completed
93+ def defaultParsedLine = parsedLine(" " , 0 )
9294
9395 def incomplete (): Nothing = throw new EOFError (
9496 // Using dummy values, not sure what they are used for
@@ -97,39 +99,44 @@ final class JLineTerminal extends java.io.Closeable {
9799 /* message = */ " " ,
98100 /* missing = */ newLinePrompt)
99101
102+ case class TokenData (token : Token , start : Int , end : Int )
103+ def currentToken : TokenData /* | Null */ = {
104+ val source = new SourceFile (" <completions>" , line)
105+ val scanner = new Scanner (source)(ctx.fresh.setReporter(Reporter .NoReporter ))
106+ while (scanner.token != EOF ) {
107+ val start = scanner.offset
108+ val token = scanner.token
109+ scanner.nextToken()
110+ val end = scanner.lastOffset
111+
112+ val isCurrentToken = cursor >= start && cursor <= end
113+ if (isCurrentToken)
114+ return TokenData (token, start, end)
115+ }
116+ null
117+ }
118+
100119 context match {
101120 case ParseContext .ACCEPT_LINE =>
102121 // ENTER means SUBMIT when
103122 // - cursor is at end (discarding whitespaces)
104123 // - and, input line is complete
105124 val cursorIsAtEnd = line.indexWhere(! _.isWhitespace, from = cursor) >= 0
106125 if (cursorIsAtEnd || ParseResult .isIncomplete(line)) incomplete()
107- else parsedLine( " " , 0 )
126+ else defaultParsedLine
108127 // using dummy values, resulting parsed line is probably unused
109128
110129 case ParseContext .COMPLETE =>
111130 // Parse to find completions (typically after a Tab).
112- val source = new SourceFile (" <completions>" , line)
113- val scanner = new Scanner (source)(ctx.fresh.setReporter(Reporter .NoReporter ))
114-
115- // Looking for the current word being completed
116- // and the cursor position within this word
117- while (scanner.token != EOF ) {
118- val start = scanner.offset
119- val token = scanner.token
120- scanner.nextToken()
121- val end = scanner.lastOffset
122-
123- val isCompletable =
124- isIdentifier(token) || isKeyword(token) // keywords can start identifiers
125- def isCurrentWord = cursor >= start && cursor <= end
126- if (isCompletable && isCurrentWord) {
131+ def isCompletable (token : Token ) = isIdentifier(token) || isKeyword(token)
132+ currentToken match {
133+ case TokenData (token, start, end) if isCompletable(token) =>
127134 val word = line.substring(start, end)
128135 val wordCursor = cursor - start
129- return parsedLine(word, wordCursor)
130- }
136+ parsedLine(word, wordCursor)
137+ case _ =>
138+ defaultParsedLine
131139 }
132- parsedLine(" " , 0 ) // no word being completed
133140
134141 case _ =>
135142 incomplete()
0 commit comments