[2.x] feat: case-insensitive tab completion (#8827)

Replace the custom JLineCompletion fallback with JLine 3's built-in
CASE_INSENSITIVE option on the LineReader, which handles case-insensitive
matching natively. Revert JLineCompletion.scala to its original state.

Fixes #2251
This commit is contained in:
bitloi 2026-02-28 17:19:02 -05:00 committed by GitHub
parent f64b5288ca
commit c1475da07c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 1 deletions

View File

@ -107,7 +107,12 @@ object LineReader {
new LineReader {
override def readLine(prompt: String, mask: Option[Char]): Option[String] = {
val term = JLine3(terminal)
val reader = LineReaderBuilder.builder().terminal(term).completer(completer(parser)).build()
val reader = LineReaderBuilder
.builder()
.terminal(term)
.completer(completer(parser))
.option(JLineReader.Option.CASE_INSENSITIVE, true)
.build()
try {
inputrcFileContents.foreach { bytes =>
InputRC.configure(

View File

@ -0,0 +1,25 @@
/*
* sbt
* Copyright 2023, Scala center
* Copyright 2011 - 2022, Lightbend, Inc.
* Copyright 2008 - 2010, Mark Harrah
* Licensed under Apache License 2.0 (see LICENSE)
*/
package sbt.internal.util
package complete
import org.scalacheck.*
import org.scalacheck.Prop.*
object JLineCompletionSpec extends Properties("JLineCompletion"):
property("case-insensitive completions are available at token start") =
val commands = Set("testOnly", "testQuick", "compile", "clean")
val parser = Parser.token(DefaultParsers.ID.examples(commands))
val completions = Parser.completions(parser, "", 1).get
val names = completions.map(_.append)
(names.contains("testOnly")) :| "testOnly is in initial completions" &&
(names.contains("compile")) :| "compile is in initial completions"
end JLineCompletionSpec