Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JLine 3: handle .inputrc? #12269

Closed
SethTisue opened this issue Mar 5, 2020 · 4 comments · Fixed by scala/scala#9518
Closed

JLine 3: handle .inputrc? #12269

SethTisue opened this issue Mar 5, 2020 · 4 comments · Fixed by scala/scala#9518
Assignees
Milestone

Comments

@SethTisue
Copy link
Member

at scala/scala#8036 (comment) , @retronym wrote:

In our usage of JLine2, we picked up configuration from ~/.inputrc etc.

JLine3 does have support for parsing this file since jline/jline3@9ccfe0b, but it looks like we need to call InputRC.configure after determining which config file to use ourselves.

Furthermore, in the current configuration file, sections guarded with $if JLine .... $endif are interpreted by the Scala REPL. Under this change, config would need to be moved to $if scala (the appname used here. That's probably fine if release noted.

Here's my .inputrc for reference.

$if Bash
	"\e[A": history-search-backward
	"\e[B": history-search-forward
    Space: magic-space
$endif

#set blink-matching-paren on
"\C-xq": "\eb\"\ef\""

"\C-x)": "\ea\(\ee\)"

$if JLine
	"\C-xu": "import scala.tools.reflect.ToolBox; val m = scala.reflect.runtime.currentMirror; val u = m.universe; import u._; val tb = m.mkToolBox()"
	"\C-x)": "\C-a(\C-e)"
	"\C-x}": "\C-a{\C-e}"
	"\C-x{": "{}\C-b"
	"\C-x(": "()\C-b"

$endif
@SethTisue
Copy link
Member Author

perhaps we can imitate @xuwei-k's sbt/sbt#5973

@SethTisue SethTisue transferred this issue from scala/scala-dev Dec 8, 2020
@SethTisue SethTisue added this to the Backlog milestone Dec 8, 2020
@jxnu-liguobin
Copy link
Member

jxnu-liguobin commented Feb 20, 2021

@SethTisue
I think we just need to load the file, as follows(but this test doesn't seem easy. reference resources https://github.com/sbt/sbt/pull/5973/files)

def inputrcFileUrl(): Option[URL] = {
      sys.props
         .get("jline.inputrc")
         .flatMap { path =>
           try Some(new URL(path))
           catch {
             case _: MalformedURLException =>
               Some(new File(path).toURI.toURL)
           }
         }.orElse {
        sys.props.get("user.home").map { home =>
          val f = new File(home).toPath.resolve(".inputrc").toFile
          (if (f.isFile) f else new File("/etc/inputrc")).toURI.toURL
        }
      }
    }

    def getByteArray(url: URL): Array[Byte] = {
      Using.resource(Source.fromURL(url).bufferedReader()) {
        bufferedReader =>
          LazyList.continually(bufferedReader.read).takeWhile(_ != -1).map(_.toByte).toArray
      }
    }

    lazy val inputrcFileContents: Option[Array[Byte]] = inputrcFileUrl().map(in => getByteArray(in))

    val jlineTerminal = TerminalBuilder.builder().jna(true).build()
    val completer = new Completion(completion)
    val parser    = new ReplParser(repl)
    val history   = new DefaultHistory

    val builder =
      LineReaderBuilder.builder()
      .appName("scala")
      .completer(completer)
      .history(history)
      .parser(parser)
      .terminal(jlineTerminal)

    locally {
      import LineReader._, Option._
      builder
        .option(AUTO_GROUP, false)
        .option(LIST_PACKED, true)  // TODO
        .option(INSERT_TAB, true)   // At the beginning of the line, insert tab instead of completing
        .variable(HISTORY_FILE, config.historyFile) // Save history to file
        .variable(SECONDARY_PROMPT_PATTERN, config.encolor(config.continueText)) // Continue prompt
        .variable(WORDCHARS, LineReaderImpl.DEFAULT_WORDCHARS.filterNot("*?.[]~=/&;!#%^(){}<>".toSet))
        .option(Option.DISABLE_EVENT_EXPANSION, true) // Otherwise `scala> println(raw"\n".toList)` gives `List(n)` !!
    }

    val reader = builder.build()
    try inputrcFileContents.foreach(f => InputRC.configure(reader, new ByteArrayInputStream(f))) catch {
      case NonFatal(_) =>
    } //ignore

@SethTisue
Copy link
Member Author

I think manual testing on this one is fine. (And if you have access to a Windows machine to test it on, that would be cool; otherwise, we can ask for a volunteer Windows tester at PR review time.)

@jxnu-liguobin
Copy link
Member

👌

jxnu-liguobin added a commit to jxnu-liguobin/scala that referenced this issue Feb 22, 2021
jxnu-liguobin added a commit to jxnu-liguobin/scala that referenced this issue Mar 19, 2021
jxnu-liguobin added a commit to jxnu-liguobin/scala that referenced this issue Mar 19, 2021
jxnu-liguobin added a commit to jxnu-liguobin/scala that referenced this issue Mar 29, 2021
@SethTisue SethTisue modified the milestones: Backlog, 2.13.6 Apr 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants