Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.

## [0.2]
### Added
- Customized prompt.
- Syntax highlight.
- JShell-like Kotlin snippets.
- Completely new REPL architecture with object based class layout `kshell-repl-api`.
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@ mvn clean install
One can run `KShell` out of box by following command from sparklin home directory in the terminal:
```bash
bin/kshell.sh
```
# Install Zeppelin interpreter
In order to install Kotlin to Zeppelin, change directory to `zeppelin-interpreter` and run
```bash
mvn clean install
```
Maven will produce 2 jars: the first one is interpreter itself, the second one is for dependencies due to [KT-24453](http://youtrack.jetbrains.com/issue/KT-24453).

# Spark 1.x
By default `KShell` don't need a configuration file, but if you want to try Spark you need to enable plugin.
It can be done by passing system property `config.path` to JVM. Example of Spark 1.x plugin configuration you may
Expand Down
Binary file not shown.
12 changes: 7 additions & 5 deletions kshell/src/main/kotlin/sparklin/kshell/KShell.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@ import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.utils.PathUtil
import sparklin.kshell.org.jline.reader.LineReaderBuilder
import sparklin.kshell.org.jline.terminal.TerminalBuilder
import sparklin.kshell.configuration.Configuration
import sparklin.kshell.configuration.IntConverter
import sparklin.kshell.org.jline.reader.LineReader
import sparklin.kshell.org.jline.reader.impl.history.DefaultHistory
import sparklin.kshell.org.jline.reader.LineReaderBuilder
import sparklin.kshell.org.jline.terminal.TerminalBuilder
import sparklin.kshell.repl.*
import sparklin.kshell.wrappers.ResultWrapper
import java.io.Closeable
import java.io.File
import java.net.URLClassLoader
import java.util.concurrent.locks.ReentrantReadWriteLock
Expand Down Expand Up @@ -50,6 +49,8 @@ open class KShell(val disposable: Disposable,
val term = TerminalBuilder.builder().build()
lateinit var readerBuilder: LineReaderBuilder
lateinit var reader: LineReader
private var maxResultLength: Int = 500

val highlighter = ContextHighlighter({ s -> !isCommandMode(s)}, { s -> commands.firstOrNull { it.weakMatch(s) } })

val commands = mutableListOf<sparklin.kshell.Command>(FakeQuit())
Expand Down Expand Up @@ -84,6 +85,7 @@ open class KShell(val disposable: Disposable,
configuration.load()
configuration.plugins().forEach { it.init(this, configuration) }

maxResultLength = configuration.get("maxResultLength", IntConverter, 500)
reader.setVariable(LineReader.HISTORY_FILE, configuration.get(LineReader.HISTORY_FILE,
System.getProperty("user.home") + File.separator + ".kshell_history"))
reader.setVariable(LineReader.SECONDARY_PROMPT_PATTERN, "")
Expand Down Expand Up @@ -181,7 +183,7 @@ open class KShell(val disposable: Disposable,

fun handleSuccess(result: EvalResult) {
if (result is EvalResult.ValueResult)
println(result.toString())
println(result.toString().bound(maxResultLength))
}

private fun commandError(e: Exception) {
Expand Down
4 changes: 4 additions & 0 deletions kshell/src/main/kotlin/sparklin/kshell/Util.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ fun calcHumanReadableSize(bytes: Long, si: Boolean = false): String {
val exp = (Math.log(bytes.toDouble()) / Math.log(unit.toDouble())).toInt()
val pre = (if (si) "kMGTPE" else "KMGTPE")[exp - 1] + if (si) "" else "i"
return String.format("%.1f %sB", bytes / Math.pow(unit.toDouble(), exp.toDouble()), pre)
}

fun String.bound(maxLength: Int): String {
return if (length > maxLength) substring(0, maxLength - 1) + " ..." else this
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ object TrimConverter: Converter<String> {

object BooleanConverter: Converter<Boolean> {
override fun convert(s: String): Boolean = s.toBoolean()
}

object IntConverter: Converter<Int> {
override fun convert(s: String): Int = s.toInt()
}
37 changes: 25 additions & 12 deletions kshell/src/main/kotlin/sparklin/kshell/plugins/PromptPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,22 @@ class PromptPlugin: Plugin {
if (p > 0) {
this@PromptPlugin.pattern = line.substring(p + 1).trim()
} else {
help()
println(this@PromptPlugin.pattern)
}
}

override fun help(): String {
return "no available"
val help = types.toSortedMap().map {
val type = it.value
"%${type.type}\t${type.help}"
}.joinToString(separator = "\n|")
return """
|:prompt [format]
|
|The command customizes prompt.
|Format can contain following specials:
|$help
""".trimMargin()
}

}
Expand All @@ -44,14 +54,17 @@ class PromptPlugin: Plugin {
lateinit var pattern: String
lateinit var incomplete: String

data class PromptType(val type: String, val display: () -> String, val help: String)

private val types = mutableMapOf(
"l" to { "${repl.state.lineIndex.get()}" },
"u" to { System.getProperty("user.name") },
"h" to { InetAddress.getLocalHost().hostName },
"d" to ::formattedTime,
"t" to ::totalMemory,
"m" to ::maxMemory,
"e" to ::evalTime)
"l" to PromptType("l", { "${repl.state.lineIndex.get()}" }, "line number"),
"u" to PromptType("u", { System.getProperty("user.name") }, "user name"),
"h" to PromptType("h", { InetAddress.getLocalHost().hostName }, "host name"),
"d" to PromptType("d", ::formattedTime, "current time"),
"t" to PromptType("t", ::totalMemory, "total memory"),
"m" to PromptType("m", ::maxMemory, "maximum memory"),
"e" to PromptType("e", ::evalTime, "evaluation time")
)

override fun init(repl: KShell, config: Configuration) {
this.repl = repl
Expand All @@ -69,11 +82,11 @@ class PromptPlugin: Plugin {

private fun evalTime() = String.format("%.2fs", repl.evaluationTimeMillis / 1000.0)

private fun promptFunc(): String = if (repl.incompleteLines.isNotEmpty()) incomplete else format("$pattern ", types)
private fun promptFunc(): String = if (repl.incompleteLines.isNotEmpty()) incomplete else format("$pattern ", types.mapValues { it.value.display })

fun registerCustomType(type: String, display: () -> String) {
fun registerCustomType(promptType: PromptType) {
// TODO: check conflicts
types[type] = display
types[promptType.type] = promptType
}

override fun cleanUp() { }
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

<modules>
<module>kshell-repl-api</module>
<module>jline3-shaded</module>
<!--<module>jline3-shaded</module>-->
<module>kshell</module>
<module>sparklin-spark-1.x</module>
<module>sparklin-spark-2.x</module>
Expand Down
3 changes: 2 additions & 1 deletion zeppelin-interpreter/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,10 @@
<classesDirectory>${project.build.directory}/unpack/temp</classesDirectory>
<excludes>
<exclude>**/org/apache/log4j/**</exclude>
<exclude>**/org/apache/zeppelin/**</exclude>
</excludes>
<outputDirectory>${project.build.directory}</outputDirectory>
<finalName>zeppelin-interpreter-0.1.3-dependencies-repackaged</finalName> <!-- give a proper name here -->
<finalName>zeppelin-interpreter-${sparklin.version}-dependencies-repackaged</finalName> <!-- give a proper name here -->
</configuration>
</execution>
</executions>
Expand Down