@@ -7,8 +7,6 @@ import dotty.tools.dotc.printing.SyntaxHighlighting
7
7
import dotty .tools .dotc .reporting .Reporter
8
8
import dotty .tools .dotc .util .SourceFile
9
9
import org .jline .reader
10
- import org .jline .reader .LineReader .Option ._
11
- import org .jline .reader .LineReader ._
12
10
import org .jline .reader .Parser .ParseContext
13
11
import org .jline .reader ._
14
12
import org .jline .reader .impl .history .DefaultHistory
@@ -44,6 +42,8 @@ final class JLineTerminal extends java.io.Closeable {
44
42
def readLine (
45
43
completer : Completer // provide auto-completions
46
44
)(implicit ctx : Context ): String = {
45
+ import LineReader .Option ._
46
+ import LineReader ._
47
47
val lineReader = LineReaderBuilder .builder()
48
48
.terminal(terminal)
49
49
.history(history)
@@ -89,6 +89,8 @@ final class JLineTerminal extends java.io.Closeable {
89
89
def parse (line : String , cursor : Int , context : ParseContext ): reader.ParsedLine = {
90
90
def parsedLine (word : String , wordCursor : Int ) =
91
91
new ParsedLine (cursor, line, word, wordCursor)
92
+ // Used when no word is being completed
93
+ def defaultParsedLine = parsedLine(" " , 0 )
92
94
93
95
def incomplete (): Nothing = throw new EOFError (
94
96
// Using dummy values, not sure what they are used for
@@ -97,39 +99,44 @@ final class JLineTerminal extends java.io.Closeable {
97
99
/* message = */ " " ,
98
100
/* missing = */ newLinePrompt)
99
101
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
+
100
119
context match {
101
120
case ParseContext .ACCEPT_LINE =>
102
121
// ENTER means SUBMIT when
103
122
// - cursor is at end (discarding whitespaces)
104
123
// - and, input line is complete
105
124
val cursorIsAtEnd = line.indexWhere(! _.isWhitespace, from = cursor) >= 0
106
125
if (cursorIsAtEnd || ParseResult .isIncomplete(line)) incomplete()
107
- else parsedLine( " " , 0 )
126
+ else defaultParsedLine
108
127
// using dummy values, resulting parsed line is probably unused
109
128
110
129
case ParseContext .COMPLETE =>
111
130
// 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) =>
127
134
val word = line.substring(start, end)
128
135
val wordCursor = cursor - start
129
- return parsedLine(word, wordCursor)
130
- }
136
+ parsedLine(word, wordCursor)
137
+ case _ =>
138
+ defaultParsedLine
131
139
}
132
- parsedLine(" " , 0 ) // no word being completed
133
140
134
141
case _ =>
135
142
incomplete()
0 commit comments