-
Notifications
You must be signed in to change notification settings - Fork 1.1k
REPL: make truncation behaviour configurable #16011
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
Changes from 6 commits
60f9f45
35a61a5
e48c71e
3e08a78
0eb5f26
a5fce18
f57fb8e
9f5cc90
fc58628
3e21b0b
1904a78
2da662a
2db4447
253143b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,15 +28,12 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None): | |
|
||
import Rendering._ | ||
|
||
private val MaxStringElements: Int = 1000 // no need to mkString billions of elements | ||
|
||
private var myClassLoader: AbstractFileClassLoader = _ | ||
|
||
private var myReplStringOf: Object => String = _ | ||
|
||
|
||
/** Class loader used to load compiled code */ | ||
private[repl] def classLoader()(using Context) = | ||
private[repl] def classLoader()(using ctx: Context) = | ||
mpollmeier marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (myClassLoader != null && myClassLoader.root == ctx.settings.outputDir.value) myClassLoader | ||
else { | ||
val parent = Option(myClassLoader).orElse(parentClassLoader).getOrElse { | ||
|
@@ -52,6 +49,7 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None): | |
} | ||
|
||
myClassLoader = new AbstractFileClassLoader(ctx.settings.outputDir.value, parent) | ||
val maxPrintElements = ctx.settings.VreplMaxPrintElements.valueIn(ctx.settingsState) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we plan to have 2 separate flags for the limits of elements and characters then this setting would actually correspond to the limit of characters, not the limit of elements, so we should give the setting the proper name from the start instead of renaming it later There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned above my intention was to keep this PR small, but yes you raise a valid point, so I'll add the split into two properties (with different name and semantics) into this PR. Some time later today - I'll let you know. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't mean making the PR any bigger actually - just renaming There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok sure - done via 9f5cc90 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I meant doing the rename of every occurance of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe I misunderstood the concept of having 2 separate settings for controlling the truncation behaviour suggested by @som-snytt then.
?
In case 2) that seems not to be fully specified yet but I suppose that would be something like
or
depending on what we understand as an element - probably a node in some high level syntax tree (?). Or did I get the entire idea wrong? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No certainly not, your explanation above looks completely correct, up until (but excluding) this sentence:
An element of a string certainly is a character. But the scala> scala.runtime.ScalaRunTime.stringOf(List(10,20,30,40), maxElements = 10)
val res0: String = List(10, 20, 30, 40)
scala> scala.runtime.ScalaRunTime.stringOf(List(10,20,30,40), maxElements = 4)
val res1: String = List(10, 20, 30, 40)
scala> scala.runtime.ScalaRunTime.stringOf(List(10,20,30,40), maxElements = 3)
val res2: String = List(10, 20, 30)
scala> scala.runtime.ScalaRunTime.stringOf(List(10,20,30,40), maxElements = 2)
val res3: String = List(10, 20) Does that make sense? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I think the point is that somehow I missed this comment, sorry for that
I would say that in this situations the reasonable options would be to either
or
I still think we should not introduce a single setting changing these two values (maxElements and maxCharacters) just to later change the semantics of this setting to set just one value instead of two There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the interest in keeping this PR small, let's go with Option 2. If you specify the setting when starting the repl it does work just fine ( I tried a few things - e.g. using reflection: given that the invocation of val settingClazz = Class.forName("dotty.tools.dotc.config.Settings$Setting", true, myClassLoader)
val valueInMethod = settingClazz.getMethod("valueIn", classOf[SettingsState])
valueInMethod.invoke(ctx.settings.VreplMaxPrintElements, ctx.settingsState)
// java.lang.NoSuchMethodException:
// dotty.tools.dotc.config.Settings$Setting.valueIn(dotty.tools.dotc.config.Settings$SettingsState) Any idea what's going on, or alternative ways to fix it? I'm running out of ideas tbh. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like the problem is that when |
||
myReplStringOf = { | ||
// We need to use the ScalaRunTime class coming from the scala-library | ||
// on the user classpath, and not the one available in the current | ||
|
@@ -64,12 +62,12 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None): | |
val meth = scalaRuntime.getMethod(renderer, classOf[Object], classOf[Int], classOf[Boolean]) | ||
val truly = java.lang.Boolean.TRUE | ||
|
||
(value: Object) => meth.invoke(null, value, Integer.valueOf(MaxStringElements), truly).asInstanceOf[String] | ||
(value: Object) => meth.invoke(null, value, Integer.valueOf(maxPrintElements), truly).asInstanceOf[String] | ||
mpollmeier marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} catch { | ||
case _: NoSuchMethodException => | ||
val meth = scalaRuntime.getMethod(renderer, classOf[Object], classOf[Int]) | ||
|
||
(value: Object) => meth.invoke(null, value, Integer.valueOf(MaxStringElements)).asInstanceOf[String] | ||
(value: Object) => meth.invoke(null, value, Integer.valueOf(maxPrintElements)).asInstanceOf[String] | ||
mpollmeier marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
myClassLoader | ||
|
@@ -81,11 +79,12 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None): | |
* then this bug will surface, so perhaps better not? | ||
* https://github.com/scala/bug/issues/12337 | ||
*/ | ||
private[repl] def truncate(str: String): String = | ||
private[repl] def truncate(str: String)(using ctx: Context): String = | ||
val maxPrintElements = ctx.settings.VreplMaxPrintElements.valueIn(ctx.settingsState) | ||
val showTruncated = " ... large output truncated, print value to show all" | ||
val ncp = str.codePointCount(0, str.length) // to not cut inside code point | ||
if ncp <= MaxStringElements then str | ||
else str.substring(0, str.offsetByCodePoints(0, MaxStringElements - 1)) + showTruncated | ||
if ncp <= maxPrintElements then str | ||
else str.substring(0, str.offsetByCodePoints(0, maxPrintElements - 1)) + showTruncated | ||
|
||
/** Return a String representation of a value we got from `classLoader()`. */ | ||
private[repl] def replStringOf(value: Object)(using Context): String = | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
scala> 1 | ||
val res0: Int = 1 | ||
|
||
scala>:settings -Xrepl-disable-display | ||
|
||
scala> 2 | ||
|
||
scala>:reset | ||
Resetting REPL state. | ||
|
||
scala> 3 | ||
val res0: Int = 3 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
scala> 1.to(300).toList | ||
val res0: List[Int] = List(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, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 22 ... large output truncated, print value to show all | ||
|
||
scala>:settings -Vrepl-max-print-elements:2000 | ||
|
||
scala> 1.to(300).toList | ||
val res1: List[Int] = List(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, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300) |
Uh oh!
There was an error while loading. Please reload this page.