/
ShellConfig.scala
154 lines (129 loc) · 5.71 KB
/
ShellConfig.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/
package scala.tools.nsc.interpreter.shell
import java.io.File
import java.util.{Formattable, FormattableFlags, Formatter}
import scala.annotation.nowarn
import scala.sys.{BooleanProp, Prop}
import scala.sys.Prop._
import scala.tools.nsc.{GenericRunnerSettings, Settings}
import scala.tools.nsc.Properties.{
coloredOutputEnabled, consoleIsTerminal, envOrNone, javaVersion, javaVmName,
shellBannerString, shellInterruptedString, shellPromptString, shellWelcomeString,
userHome, versionString, versionNumberString,
}
object ShellConfig {
val EDITOR = envOrNone("EDITOR")
// how to say we :quit
val InterruptedString = shellInterruptedString
def apply(settings: Settings) = settings match {
case settings: GenericRunnerSettings => new ShellConfig {
val filesToPaste: List[String] = settings.pastefiles.value
val filesToLoad: List[String] = settings.loadfiles.value
val batchText: String = if (settings.execute.isSetByUser) settings.execute.value else ""
val batchMode: Boolean = batchText.nonEmpty
val doCompletion: Boolean = !(settings.noCompletion.value || batchMode)
override val haveInteractiveConsole: Boolean = super.haveInteractiveConsole && !settings.Xnojline.value
def xsource: String = if (settings.isScala3: @nowarn) settings.source.value.versionString else ""
}
case _ => new ShellConfig {
val filesToPaste: List[String] = Nil
val filesToLoad: List[String] = Nil
val batchText: String = ""
val batchMode: Boolean = false
val doCompletion: Boolean = !settings.noCompletion.value
override val haveInteractiveConsole: Boolean = super.haveInteractiveConsole && !settings.Xnojline.value
def xsource: String = if (settings.isScala3: @nowarn) settings.source.value.versionString else ""
}
}
}
trait ShellConfig {
def filesToPaste: List[String]
def filesToLoad: List[String]
def batchText: String
def batchMode: Boolean
def doCompletion: Boolean
def haveInteractiveConsole: Boolean = consoleIsTerminal
// source compatibility, i.e., -Xsource
def xsource: String
private def bool(name: String) = BooleanProp.keyExists(name)
private def int(name: String) = Prop[Int](name)
// This property is used in TypeDebugging. Let's recycle it.
val colorOk = coloredOutputEnabled
val historyFile = s"$userHome/.scala_history_jline3"
private val info = bool("scala.repl.info")
private val debug = bool("scala.repl.debug")
private val trace = bool("scala.repl.trace")
val power = bool("scala.repl.power")
def enversion(s: String) = {
import FormattableFlags._
val v = new Formattable {
override def formatTo(formatter: Formatter, flags: Int, width: Int, precision: Int) = {
val version = if ((flags & ALTERNATE) != 0) versionNumberString else versionString
val left = if ((flags & LEFT_JUSTIFY) != 0) "-" else ""
val w = if (width >= 0) s"$width" else ""
val p = if (precision >= 0) s".$precision" else ""
val fmt = s"%${left}${w}${p}s"
val xversion = if (xsource.isEmpty) version else s"$version -Xsource:$xsource"
formatter.format(fmt, xversion)
}
}
s.format(v, javaVersion, javaVmName)
}
def encolor(s: String) = {
import scala.io.AnsiColor.{MAGENTA, RESET}
if (colorOk) s"$MAGENTA$s$RESET" else s
}
// Handy system prop for shell prompt, or else pick it up from compiler.properties
val promptString = Prop[String]("scala.repl.prompt").option getOrElse (if (info) "%nscala %#s> " else shellPromptString)
val promptText = enversion(promptString)
// Prompt for continued input, will be right-adjusted to width of the primary prompt
val continueString = Prop[String]("scala.repl.continue").option getOrElse "| "
val continueText = {
val text = enversion(continueString)
val margin = promptText.linesIterator.toList.last.length - text.length
if (margin > 0) " " * margin + text else text
}
// What to display at REPL startup.
val welcomeString = Prop[String]("scala.repl.welcome").option match {
case Some("banner") => shellBannerString
case Some(text) => text
case _ => shellWelcomeString
}
val pasteDelimiter = Prop[String]("scala.repl.here")
/** CSV of paged,across to enable pagination or `-x` style
* columns, "across" instead of down the column. Since
* pagination turns off columnar output, these flags are
* currently mutually exclusive.
*/
val format = Prop[String]("scala.repl.format")
val isPaged: Boolean = format.isSet && csv(format.get, "paged")
val isAcross: Boolean = format.isSet && csv(format.get, "across")
private def csv(p: String, v: String) = p.split(",").contains(v)
val replAutorunCode = Prop[File]("scala.repl.autoruncode")
val powerInitCode = Prop[File]("scala.repl.power.initcode")
val powerBanner = Prop[File]("scala.repl.power.banner")
val maxPrintString = int("scala.repl.maxprintstring")
def isReplInfo: Boolean = info || isReplDebug
def replinfo(msg: => String) = if (isReplInfo) echo(msg)
def isReplDebug: Boolean = debug || isReplTrace
def repldbg(msg: => String) = if (isReplDebug) echo(msg)
def isReplTrace: Boolean = trace
def repltrace(msg: => String) = if (isReplTrace) echo(msg)
def isReplPower: Boolean = power
private def echo(msg: => String) =
try Console.println(msg)
catch {
case e: AssertionError =>
Console.println(s"Assertion error printing debugging output: $e")
}
}