mirror of https://github.com/sbt/sbt.git
work around unclosed jline history-related streams
This commit is contained in:
parent
e23abdfce3
commit
c3c7c92053
|
|
@ -3,23 +3,40 @@
|
||||||
*/
|
*/
|
||||||
package sbt
|
package sbt
|
||||||
|
|
||||||
import jline.{Completor, ConsoleReader}
|
import jline.{Completor, ConsoleReader, History}
|
||||||
import java.io.File
|
import java.io.{File,PrintWriter}
|
||||||
import complete.Parser
|
import complete.Parser
|
||||||
|
|
||||||
abstract class JLine extends LineReader
|
abstract class JLine extends LineReader
|
||||||
{
|
{
|
||||||
protected[this] val reader: ConsoleReader
|
protected[this] val reader: ConsoleReader
|
||||||
|
protected[this] val historyPath: Option[File]
|
||||||
|
|
||||||
def readLine(prompt: String, mask: Option[Char] = None) = JLine.withJLine { unsynchronizedReadLine(prompt, mask) }
|
def readLine(prompt: String, mask: Option[Char] = None) = JLine.withJLine { unsynchronizedReadLine(prompt, mask) }
|
||||||
|
|
||||||
private[this] def unsynchronizedReadLine(prompt: String, mask: Option[Char]) =
|
private[this] def unsynchronizedReadLine(prompt: String, mask: Option[Char]) =
|
||||||
(mask match {
|
readLineWithHistory(prompt, mask) match
|
||||||
case Some(m) => reader.readLine(prompt, m)
|
|
||||||
case None => reader.readLine(prompt)
|
|
||||||
}) match
|
|
||||||
{
|
{
|
||||||
case null => None
|
case null => None
|
||||||
case x => Some(x.trim)
|
case x => Some(x.trim)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private[this] def readLineWithHistory(prompt: String, mask: Option[Char]): String =
|
||||||
|
historyPath match
|
||||||
|
{
|
||||||
|
case None => readLineDirect(prompt, mask)
|
||||||
|
case Some(file) =>
|
||||||
|
val h = reader.getHistory
|
||||||
|
JLine.loadHistory(h, file)
|
||||||
|
try { readLineDirect(prompt, mask) }
|
||||||
|
finally { JLine.saveHistory(h, file) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private[this] def readLineDirect(prompt: String, mask: Option[Char]): String =
|
||||||
|
mask match {
|
||||||
|
case Some(m) => reader.readLine(prompt, m)
|
||||||
|
case None => reader.readLine(prompt)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private object JLine
|
private object JLine
|
||||||
{
|
{
|
||||||
|
|
@ -44,18 +61,20 @@ private object JLine
|
||||||
try { action }
|
try { action }
|
||||||
finally { t.enableEcho() }
|
finally { t.enableEcho() }
|
||||||
}
|
}
|
||||||
private[sbt] def initializeHistory(cr: ConsoleReader, historyPath: Option[File]): Unit =
|
private[sbt] def loadHistory(h: History, file: File)
|
||||||
for(historyLocation <- historyPath)
|
|
||||||
{
|
{
|
||||||
val historyFile = historyLocation.getAbsoluteFile
|
h.setMaxSize(MaxHistorySize)
|
||||||
ErrorHandling.wideConvert
|
if(file.isFile) IO.reader(file)( h.load )
|
||||||
{
|
|
||||||
historyFile.getParentFile.mkdirs()
|
|
||||||
val history = cr.getHistory
|
|
||||||
history.setMaxSize(MaxHistorySize)
|
|
||||||
history.setHistoryFile(historyFile)
|
|
||||||
}
|
}
|
||||||
|
private[sbt] def saveHistory(h: History, file: File): Unit =
|
||||||
|
Using.fileWriter()(file) { writer =>
|
||||||
|
val out = new PrintWriter(writer, false)
|
||||||
|
h.setOutput(out)
|
||||||
|
h.flushBuffer()
|
||||||
|
out.close()
|
||||||
|
h.setOutput(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
def simple(historyPath: Option[File]): SimpleReader = new SimpleReader(historyPath)
|
def simple(historyPath: Option[File]): SimpleReader = new SimpleReader(historyPath)
|
||||||
val MaxHistorySize = 500
|
val MaxHistorySize = 500
|
||||||
}
|
}
|
||||||
|
|
@ -64,24 +83,20 @@ trait LineReader
|
||||||
{
|
{
|
||||||
def readLine(prompt: String, mask: Option[Char] = None): Option[String]
|
def readLine(prompt: String, mask: Option[Char] = None): Option[String]
|
||||||
}
|
}
|
||||||
final class FullReader(historyPath: Option[File], complete: Parser[_]) extends JLine
|
final class FullReader(val historyPath: Option[File], complete: Parser[_]) extends JLine
|
||||||
{
|
{
|
||||||
protected[this] val reader =
|
protected[this] val reader =
|
||||||
{
|
{
|
||||||
val cr = new ConsoleReader
|
val cr = new ConsoleReader
|
||||||
cr.setBellEnabled(false)
|
cr.setBellEnabled(false)
|
||||||
JLine.initializeHistory(cr, historyPath)
|
|
||||||
sbt.complete.JLineCompletion.installCustomCompletor(cr, complete)
|
sbt.complete.JLineCompletion.installCustomCompletor(cr, complete)
|
||||||
cr
|
cr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SimpleReader private[sbt] (historyPath: Option[File]) extends JLine
|
class SimpleReader private[sbt] (val historyPath: Option[File]) extends JLine
|
||||||
{
|
|
||||||
protected[this] val reader = JLine.createReader()
|
|
||||||
JLine.initializeHistory(reader, historyPath)
|
|
||||||
}
|
|
||||||
object SimpleReader extends JLine
|
|
||||||
{
|
{
|
||||||
protected[this] val reader = JLine.createReader()
|
protected[this] val reader = JLine.createReader()
|
||||||
}
|
}
|
||||||
|
object SimpleReader extends SimpleReader(None)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue