Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9dfa3e124f | |||
| 4c115f41fb | |||
| 7ca74d51d1 | |||
| 02fc840c4d | |||
| 145d9fcf3c | |||
| 401c0a354a | |||
| 133ef02945 | |||
| 57520ef947 | |||
| ff4b2600a1 | |||
| dd73965e39 | |||
| 1eefc31cfe | |||
| 4cc69a8dbd | |||
| bbeb703f9d | |||
|
|
037b9a8e96 |
18
.idea/artifacts/ide_jar.xml
generated
Normal file
18
.idea/artifacts/ide_jar.xml
generated
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<component name="ArtifactManager">
|
||||||
|
<artifact type="jar" build-on-make="true" name="ide:jar">
|
||||||
|
<output-path>$PROJECT_DIR$/out/artifacts/ide_jar</output-path>
|
||||||
|
<root id="archive" name="ide.jar">
|
||||||
|
<element id="module-output" name="ide" />
|
||||||
|
<element id="module-output" name="befunge" />
|
||||||
|
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.2.60/kotlin-stdlib-jdk8-1.2.60.jar" path-in-jar="/" />
|
||||||
|
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.3.0/kotlin-stdlib-1.3.0.jar" path-in-jar="/" />
|
||||||
|
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/javax/json/javax.json-api/1.1.2/javax.json-api-1.1.2.jar" path-in-jar="/" />
|
||||||
|
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" path-in-jar="/" />
|
||||||
|
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/no/tornado/tornadofx/1.7.17/tornadofx-1.7.17.jar" path-in-jar="/" />
|
||||||
|
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/glassfish/javax.json/1.1.2/javax.json-1.1.2.jar" path-in-jar="/" />
|
||||||
|
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-common/1.3.0/kotlin-stdlib-common-1.3.0.jar" path-in-jar="/" />
|
||||||
|
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.2.60/kotlin-stdlib-jdk7-1.2.60.jar" path-in-jar="/" />
|
||||||
|
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.2.60/kotlin-reflect-1.2.60.jar" path-in-jar="/" />
|
||||||
|
</root>
|
||||||
|
</artifact>
|
||||||
|
</component>
|
||||||
@@ -14,6 +14,14 @@ class B93Funge : Funge {
|
|||||||
|
|
||||||
private var cars = Array(height) { Array(width) { Value(' ') } }
|
private var cars = Array(height) { Array(width) { Value(' ') } }
|
||||||
|
|
||||||
|
override var values
|
||||||
|
get() = cars.map { it.toList() }
|
||||||
|
set(data) {
|
||||||
|
for (y in 0 until cars.size)
|
||||||
|
for (x in 0 until cars[y].size)
|
||||||
|
cars[y][x] = data[y][x]
|
||||||
|
}
|
||||||
|
|
||||||
override fun get(vec: Vec): Value {
|
override fun get(vec: Vec): Value {
|
||||||
return cars[vec.y][vec.x]
|
return cars[vec.y][vec.x]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class B93Interpreter : Interpreter {
|
|||||||
override val stdInput = LinkedList<Char>()
|
override val stdInput = LinkedList<Char>()
|
||||||
override val stdOutput = LinkedList<String>()
|
override val stdOutput = LinkedList<String>()
|
||||||
private var outBuf: StringBuffer = StringBuffer()
|
private var outBuf: StringBuffer = StringBuffer()
|
||||||
private var bufLimit = 10
|
private var bufLimit = 0
|
||||||
|
|
||||||
private val fungeMods = HashMap<Vec,Value>()
|
private val fungeMods = HashMap<Vec,Value>()
|
||||||
|
|
||||||
@@ -266,7 +266,7 @@ class B93Interpreter : Interpreter {
|
|||||||
outBuf.delete(0, outBuf.length)
|
outBuf.delete(0, outBuf.length)
|
||||||
outputChanged.invoke(OutputEvent())
|
outputChanged.invoke(OutputEvent())
|
||||||
ip.mode = IpMode.Inactive
|
ip.mode = IpMode.Inactive
|
||||||
return true
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun pushDig(dig: Char): Boolean {
|
private fun pushDig(dig: Char): Boolean {
|
||||||
@@ -295,7 +295,8 @@ class B93Interpreter : Interpreter {
|
|||||||
'&', '~' -> input(car)
|
'&', '~' -> input(car)
|
||||||
'@' -> terminate()
|
'@' -> terminate()
|
||||||
in '0'..'9' -> pushDig(car)
|
in '0'..'9' -> pushDig(car)
|
||||||
else -> noOp()
|
' ' -> true
|
||||||
|
else -> true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,9 +320,14 @@ class B93Interpreter : Interpreter {
|
|||||||
if (processed) {
|
if (processed) {
|
||||||
stepIP()
|
stepIP()
|
||||||
if (ip.mode != IpMode.String) {
|
if (ip.mode != IpMode.String) {
|
||||||
while (funge[ip.pos].asChar == ' ') {
|
var numsteps = 0
|
||||||
|
val maxsteps = if (funge.height > funge.width) funge.height else funge.width
|
||||||
|
while (funge[ip.pos].asChar == ' ' && numsteps++ < maxsteps) {
|
||||||
stepIP()
|
stepIP()
|
||||||
}
|
}
|
||||||
|
if (numsteps == maxsteps) {
|
||||||
|
ip.mode = IpMode.Inactive
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val newIP = ip.copy()
|
val newIP = ip.copy()
|
||||||
ipChanged(IpEvent(currIP, newIP))
|
ipChanged(IpEvent(currIP, newIP))
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ interface Funge {
|
|||||||
operator fun get(vec: Vec): Value
|
operator fun get(vec: Vec): Value
|
||||||
operator fun set(vec: Vec, value: Value)
|
operator fun set(vec: Vec, value: Value)
|
||||||
|
|
||||||
|
var values: List<List<Value>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the next position to be executed starting at [vec] and stepping by [delta]
|
* Get the next position to be executed starting at [vec] and stepping by [delta]
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,17 +1,26 @@
|
|||||||
package befide.ide
|
package befide.ide
|
||||||
|
|
||||||
import befide.befunge.core.Interpreter
|
import befide.befunge.core.Interpreter
|
||||||
|
import befide.befunge.state.IpMode
|
||||||
import javafx.animation.Animation
|
import javafx.animation.Animation
|
||||||
import javafx.animation.Timeline
|
import javafx.animation.Timeline
|
||||||
|
import javafx.beans.property.SimpleBooleanProperty
|
||||||
|
import javafx.beans.property.SimpleObjectProperty
|
||||||
|
import javafx.stage.FileChooser
|
||||||
import javafx.util.Duration
|
import javafx.util.Duration
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
import tornadofx.getValue
|
||||||
|
import tornadofx.setValue
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class ActionView(val interp: Interpreter, val codeView: CodeView, val ioView: IOView, val editorView: EditorView) : View() {
|
||||||
|
val stepProperty = SimpleBooleanProperty(false)
|
||||||
|
var step by stepProperty
|
||||||
|
|
||||||
class ActionView(val interp: Interpreter, val codeView: CodeView, val ioView: IOView) : View() {
|
|
||||||
var runTimeline: Timeline = timeline(false) {
|
var runTimeline: Timeline = timeline(false) {
|
||||||
keyframe(Duration.seconds(0.0)) {
|
keyframe(Duration.seconds(0.0)) {
|
||||||
setOnFinished {
|
setOnFinished {
|
||||||
if (!interp.step())
|
step = interp.step()
|
||||||
this@timeline.stop()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keyframe(Duration.seconds(1.0)) {}
|
keyframe(Duration.seconds(1.0)) {}
|
||||||
@@ -19,50 +28,158 @@ class ActionView(val interp: Interpreter, val codeView: CodeView, val ioView: IO
|
|||||||
cycleCount = Animation.INDEFINITE
|
cycleCount = Animation.INDEFINITE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val isRunningProperty = SimpleBooleanProperty(false)
|
||||||
|
var isRunning by isRunningProperty
|
||||||
|
|
||||||
|
val canResetProperty = SimpleBooleanProperty(false)
|
||||||
|
var canReset by canResetProperty
|
||||||
|
|
||||||
|
val saveFileProperty = SimpleObjectProperty<File>()
|
||||||
|
var saveFile by saveFileProperty
|
||||||
|
|
||||||
|
fun start(rate: Double) {
|
||||||
|
stop()
|
||||||
|
|
||||||
|
if (interp.ip.mode == IpMode.Inactive) reset()
|
||||||
|
|
||||||
|
isRunning = true
|
||||||
|
canReset = true
|
||||||
|
|
||||||
|
interp.funge.values = codeView.values
|
||||||
|
|
||||||
|
runTimeline.rate = rate
|
||||||
|
runTimeline.playFromStart()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun step() {
|
||||||
|
canReset = true
|
||||||
|
|
||||||
|
interp.funge.values = codeView.values
|
||||||
|
|
||||||
|
step = interp.step()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stop() {
|
||||||
|
isRunning = false
|
||||||
|
|
||||||
|
runTimeline.stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reset() {
|
||||||
|
stop()
|
||||||
|
interp.reset()
|
||||||
|
ioView.reset()
|
||||||
|
canReset = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearCode() {
|
||||||
|
reset()
|
||||||
|
codeView.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun save() {
|
||||||
|
if (saveFile == null) {
|
||||||
|
saveAs()
|
||||||
|
} else {
|
||||||
|
saveFile.writeText(codeView.src)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val chooser: FileChooser = FileChooser().apply {
|
||||||
|
title = "Befunge File"
|
||||||
|
extensionFilters.setAll(
|
||||||
|
FileChooser.ExtensionFilter("Befunge 93", "*.bf", "*.b93"),
|
||||||
|
FileChooser.ExtensionFilter("Befunge 98", "*.bf", "*.b98"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveAs() {
|
||||||
|
val file: File? = chooser.showSaveDialog(primaryStage)
|
||||||
|
if (file != null) {
|
||||||
|
saveFile = file
|
||||||
|
save()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun open() {
|
||||||
|
val file: File? = chooser.showOpenDialog(primaryStage)
|
||||||
|
if (file != null) {
|
||||||
|
saveFile = file
|
||||||
|
|
||||||
|
editorView.title = "${saveFile.nameWithoutExtension} [${saveFile.absolutePath}] - Befide"
|
||||||
|
|
||||||
|
reset()
|
||||||
|
codeView.src = saveFile.readText()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun new() {
|
||||||
|
clearCode()
|
||||||
|
saveFile = null
|
||||||
|
editorView.title = "Befide"
|
||||||
|
}
|
||||||
|
|
||||||
override val root = hbox {
|
override val root = hbox {
|
||||||
button("step") {
|
button("step") {
|
||||||
setOnAction {
|
setOnAction { step() }
|
||||||
interp.funge.setString(codeView.src)
|
disableWhen(isRunningProperty)
|
||||||
interp.step()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button("reset") {
|
separator {}
|
||||||
setOnAction {
|
|
||||||
interp.reset()
|
|
||||||
ioView.reset()
|
|
||||||
codeView.src = interp.funge.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
button("run") {
|
button("run") {
|
||||||
setOnAction {
|
setOnAction { start(10000.0) }
|
||||||
interp.funge.setString(codeView.src)
|
|
||||||
runTimeline.rate = 10000.0
|
|
||||||
runTimeline.playFromStart()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button("walk") {
|
button("walk") {
|
||||||
setOnAction {
|
setOnAction { start(50.0) }
|
||||||
interp.funge.setString(codeView.src)
|
|
||||||
runTimeline.rate = 50.0
|
|
||||||
runTimeline.playFromStart()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button("crawl") {
|
button("crawl") {
|
||||||
setOnAction {
|
setOnAction { start(4.0) }
|
||||||
interp.funge.setString(codeView.src)
|
|
||||||
runTimeline.rate = 4.0
|
|
||||||
runTimeline.playFromStart()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
separator {}
|
||||||
|
|
||||||
button("stop") {
|
button("stop") {
|
||||||
setOnAction {
|
setOnAction { stop() }
|
||||||
runTimeline.stop()
|
enableWhen(isRunningProperty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spacer {}
|
||||||
|
|
||||||
|
button("reset") {
|
||||||
|
setOnAction { reset() }
|
||||||
|
enableWhen(canResetProperty)
|
||||||
|
}
|
||||||
|
|
||||||
|
separator {}
|
||||||
|
|
||||||
|
button("open") {
|
||||||
|
setOnAction { open() }
|
||||||
|
disableWhen(isRunningProperty)
|
||||||
|
}
|
||||||
|
|
||||||
|
button("save as") {
|
||||||
|
setOnAction { saveAs() }
|
||||||
|
}
|
||||||
|
|
||||||
|
button("save") {
|
||||||
|
setOnAction { save() }
|
||||||
|
|
||||||
|
enableWhen(saveFileProperty.isNotNull.and(isRunningProperty.not()))
|
||||||
|
}
|
||||||
|
|
||||||
|
button("new") {
|
||||||
|
setOnAction { new() }
|
||||||
|
disableWhen(isRunningProperty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
stepProperty.onChange {
|
||||||
|
if (!it) stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
new()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package befide.ide
|
package befide.ide
|
||||||
|
|
||||||
import befide.befunge.core.Interpreter
|
import befide.befunge.core.Interpreter
|
||||||
|
import befide.befunge.state.Value
|
||||||
import befide.befunge.state.Vec
|
import befide.befunge.state.Vec
|
||||||
import javafx.beans.property.ObjectProperty
|
import javafx.beans.property.ObjectProperty
|
||||||
import javafx.beans.property.SimpleObjectProperty
|
import javafx.beans.property.SimpleObjectProperty
|
||||||
@@ -8,15 +9,20 @@ import javafx.scene.control.Label
|
|||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
class CodeLabel(val pos: Vec, val cursorPos: ObjectProperty<Vec>, val interp: Interpreter) : Label() {
|
class CodeLabel(val pos: Vec, val cursorPos: ObjectProperty<Vec>, val interp: Interpreter) : Label() {
|
||||||
val charProperty = SimpleObjectProperty<Char>('\u0000')
|
var valueProperty = SimpleObjectProperty<Value>(Value(' '))
|
||||||
var char: Char by charProperty
|
var value: Value by valueProperty
|
||||||
|
|
||||||
fun restyle() {
|
fun restyle() {
|
||||||
styleClass.setAll("code")
|
styleClass.setAll("code")
|
||||||
|
|
||||||
|
val char = value.asChar ?: '\u2022'
|
||||||
|
|
||||||
if (char in "0123456789") styleClass.add("code-num")
|
if (char in "0123456789") styleClass.add("code-num")
|
||||||
if (char in "gp") styleClass.add("code-funge")
|
if (char in "gp") styleClass.add("code-funge")
|
||||||
if (char in "<>^v?#") styleClass.add("code-dir")
|
if (char in "<>^v?#") styleClass.add("code-dir")
|
||||||
|
if (char in "@") styleClass.add("code-stop")
|
||||||
|
if (char in "_|") styleClass.add("code-condition")
|
||||||
|
if (char in "\"") styleClass.add("code-quote")
|
||||||
|
|
||||||
if (pos == cursorPos.value) styleClass.add("code-cursor")
|
if (pos == cursorPos.value) styleClass.add("code-cursor")
|
||||||
if (pos == interp.ip.pos) styleClass.add("code-cursor-ip")
|
if (pos == interp.ip.pos) styleClass.add("code-cursor-ip")
|
||||||
@@ -24,14 +30,14 @@ class CodeLabel(val pos: Vec, val cursorPos: ObjectProperty<Vec>, val interp: In
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
textProperty().bind(charProperty.stringBinding { it?.toString() ?: " " })
|
textProperty().bind(valueProperty.stringBinding { it?.asChar?.toString() ?: "\u2022" })
|
||||||
|
|
||||||
setOnMouseClicked {
|
setOnMouseClicked {
|
||||||
cursorPos.value = pos
|
cursorPos.value = pos
|
||||||
}
|
}
|
||||||
|
|
||||||
charProperty.addListener { _, _, _ -> restyle() }
|
valueProperty.addListener { _, _, _ -> restyle() }
|
||||||
|
|
||||||
char = ' '
|
restyle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
package befide.ide
|
package befide.ide
|
||||||
|
|
||||||
import befide.befunge.core.Interpreter
|
import befide.befunge.core.Interpreter
|
||||||
|
import befide.befunge.state.Value
|
||||||
import befide.befunge.state.Vec
|
import befide.befunge.state.Vec
|
||||||
import javafx.beans.property.ObjectProperty
|
import javafx.beans.property.ObjectProperty
|
||||||
import javafx.beans.property.SimpleBooleanProperty
|
|
||||||
import javafx.beans.property.SimpleObjectProperty
|
import javafx.beans.property.SimpleObjectProperty
|
||||||
import javafx.scene.input.KeyCode
|
import javafx.scene.input.KeyCode
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
import tornadofx.getValue
|
|
||||||
import tornadofx.setValue
|
|
||||||
|
|
||||||
operator fun <T> List<List<T>>.get(v: Vec): T = this[v.y][v.x]
|
operator fun <T> List<List<T>>.get(v: Vec): T = this[v.y][v.x]
|
||||||
|
|
||||||
@@ -21,6 +19,14 @@ class CodeView(val interp: Interpreter) : View() {
|
|||||||
|
|
||||||
var labels: List<List<CodeLabel>> = List(25) { y -> List(80) { x -> CodeLabel(Vec(x, y), cursorPosProperty, interp) } }
|
var labels: List<List<CodeLabel>> = List(25) { y -> List(80) { x -> CodeLabel(Vec(x, y), cursorPosProperty, interp) } }
|
||||||
|
|
||||||
|
var values: List<List<Value>>
|
||||||
|
get() = labels.map { it.map { it.value } }
|
||||||
|
set(data) {
|
||||||
|
for (y in 0 until labels.size)
|
||||||
|
for (x in 0 until labels[y].size)
|
||||||
|
labels[y][x].value = data[y][x]
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
cursorPosProperty.addListener { _, old, new ->
|
cursorPosProperty.addListener { _, old, new ->
|
||||||
labels[old].restyle()
|
labels[old].restyle()
|
||||||
@@ -34,7 +40,7 @@ class CodeView(val interp: Interpreter) : View() {
|
|||||||
|
|
||||||
interp.fungeChanged += {
|
interp.fungeChanged += {
|
||||||
for (change in it.changes) {
|
for (change in it.changes) {
|
||||||
labels[change.vec].char = change.to.asChar ?: '\u2022'
|
labels[change.vec].value = change.to
|
||||||
labels[change.vec].restyle()
|
labels[change.vec].restyle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,12 +50,20 @@ class CodeView(val interp: Interpreter) : View() {
|
|||||||
cursorPos = interp.funge.nextVec(cursorPos, delta ?: cursorDelta)
|
cursorPos = interp.funge.nextVec(cursorPos, delta ?: cursorDelta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun clear() {
|
||||||
|
for (row in labels) {
|
||||||
|
for (lbl in row) {
|
||||||
|
lbl.value = Value(' ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var src: String
|
var src: String
|
||||||
get() = labels.joinToString("\n") { row ->
|
get() = labels.joinToString("\n") { row ->
|
||||||
row.dropLastWhile { lbl ->
|
row.dropLastWhile { lbl ->
|
||||||
lbl.char.isWhitespace()
|
lbl.value.asChar?.isWhitespace() ?: false
|
||||||
}.joinToString("") { lbl ->
|
}.joinToString("") { lbl ->
|
||||||
lbl.char.toString()
|
lbl.value.asChar?.toString() ?: "\u2022"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set(value) {
|
set(value) {
|
||||||
@@ -57,7 +71,8 @@ class CodeView(val interp: Interpreter) : View() {
|
|||||||
|
|
||||||
for (row in labels) {
|
for (row in labels) {
|
||||||
for (lbl in row) {
|
for (lbl in row) {
|
||||||
lbl.char = lines.getOrNull(lbl.pos.y)?.getOrNull(lbl.pos.x) ?: ' '
|
val char = lines.getOrNull(lbl.pos.y)?.getOrNull(lbl.pos.x) ?: ' '
|
||||||
|
lbl.value = Value(char)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,7 +120,7 @@ class CodeView(val interp: Interpreter) : View() {
|
|||||||
else -> cursorDelta
|
else -> cursorDelta
|
||||||
}
|
}
|
||||||
|
|
||||||
labels[cursorPos].char = ch
|
labels[cursorPos].value = Value(ch)
|
||||||
|
|
||||||
move()
|
move()
|
||||||
}
|
}
|
||||||
@@ -113,7 +128,26 @@ class CodeView(val interp: Interpreter) : View() {
|
|||||||
ch == '\u0008' -> { // backspace
|
ch == '\u0008' -> { // backspace
|
||||||
move(-cursorDelta)
|
move(-cursorDelta)
|
||||||
|
|
||||||
labels[cursorPos].char = ' '
|
labels[cursorPos].value = Value(' ')
|
||||||
|
}
|
||||||
|
|
||||||
|
ch == '\u000d' -> when (cursorDelta) { // return
|
||||||
|
Vec(1, 0) -> {
|
||||||
|
move(Vec(0, 1))
|
||||||
|
cursorPos = Vec(0, cursorPos.y)
|
||||||
|
}
|
||||||
|
Vec(-1, 0) -> {
|
||||||
|
move(Vec(0, -1))
|
||||||
|
cursorPos = Vec(interp.funge.width - 1, cursorPos.y)
|
||||||
|
}
|
||||||
|
Vec(0, 1) -> {
|
||||||
|
move(Vec(-1, 0))
|
||||||
|
cursorPos = Vec(cursorPos.x, 0)
|
||||||
|
}
|
||||||
|
Vec(0, -1) -> {
|
||||||
|
move(Vec(1, 0))
|
||||||
|
cursorPos = Vec(cursorPos.x, interp.funge.height - 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class EditorView : View("Befide") {
|
|||||||
private val codeView = CodeView(interp)
|
private val codeView = CodeView(interp)
|
||||||
private val stackView = StackView(interp)
|
private val stackView = StackView(interp)
|
||||||
private val ioView = IOView(interp)
|
private val ioView = IOView(interp)
|
||||||
private val actionView = ActionView(interp, codeView, ioView)
|
private val actionView = ActionView(interp, codeView, ioView, this)
|
||||||
|
|
||||||
override val root = borderpane {
|
override val root = borderpane {
|
||||||
top { add(actionView) }
|
top { add(actionView) }
|
||||||
@@ -23,12 +23,7 @@ class EditorView : View("Befide") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
codeView.src = """ 2>:3g" "-!v\ g30 <
|
primaryStage.isResizable = false
|
||||||
|!`"O":+1_:.:03p>03g+:"O"`|
|
|
||||||
@ ^ p3\" ":<
|
|
||||||
2 234567890123456789012345678901234567890123456789012345678901234567890123456789"""
|
|
||||||
|
|
||||||
// codeView.src = """"hello world",,,,,,,,,,,@"""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDock() {
|
override fun onDock() {
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ class IOView(val interp: Interpreter) : View() {
|
|||||||
textarea(oldinputProperty) {
|
textarea(oldinputProperty) {
|
||||||
isEditable = false
|
isEditable = false
|
||||||
prefHeight = 0.0
|
prefHeight = 0.0
|
||||||
|
|
||||||
|
oldinputProperty.onChange { scrollTop = Double.MAX_VALUE }
|
||||||
}
|
}
|
||||||
textfield {
|
textfield {
|
||||||
onAction = EventHandler {
|
onAction = EventHandler {
|
||||||
|
|||||||
@@ -7,3 +7,7 @@ class MainApp : App(EditorView::class) {
|
|||||||
importStylesheet(resources["style.css"])
|
importStylesheet(resources["style.css"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
launch<MainApp>(args)
|
||||||
|
}
|
||||||
@@ -3,7 +3,12 @@ package befide.ide
|
|||||||
import befide.befunge.b93.padEnd
|
import befide.befunge.b93.padEnd
|
||||||
import befide.befunge.core.Interpreter
|
import befide.befunge.core.Interpreter
|
||||||
import befide.befunge.state.Value
|
import befide.befunge.state.Value
|
||||||
|
import javafx.beans.property.SimpleListProperty
|
||||||
|
import javafx.beans.property.SimpleObjectProperty
|
||||||
import javafx.beans.property.SimpleStringProperty
|
import javafx.beans.property.SimpleStringProperty
|
||||||
|
import javafx.collections.FXCollections
|
||||||
|
import javafx.scene.layout.Priority
|
||||||
|
import javafx.scene.text.Font
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
import tornadofx.getValue
|
import tornadofx.getValue
|
||||||
import tornadofx.setValue
|
import tornadofx.setValue
|
||||||
@@ -11,37 +16,27 @@ import tornadofx.setValue
|
|||||||
class StackView(val interp: Interpreter) : View() {
|
class StackView(val interp: Interpreter) : View() {
|
||||||
val charOutProperty = SimpleStringProperty()
|
val charOutProperty = SimpleStringProperty()
|
||||||
var charOut by charOutProperty
|
var charOut by charOutProperty
|
||||||
val longOutProperty = SimpleStringProperty()
|
|
||||||
var longOut by longOutProperty
|
|
||||||
|
|
||||||
|
override val root = textarea(charOutProperty) {
|
||||||
override val root = hbox {
|
addClass("stack-pane")
|
||||||
textarea(charOutProperty) {
|
prefWidth = 150.0
|
||||||
maxWidth = 1.0
|
isEditable = false
|
||||||
paddingHorizontal = 1
|
|
||||||
isEditable = false
|
|
||||||
}
|
|
||||||
textarea(longOutProperty) {
|
|
||||||
prefWidth = 90.0
|
|
||||||
isEditable = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> getStackStr(mapping: (Value) -> T): String {
|
private fun <T> getStackStr(mapping: (Value) -> T): String {
|
||||||
return interp.stack.takeLast(interp.funge.height)
|
val num = interp.funge.height - 3
|
||||||
.map (mapping)
|
return interp.stack.takeLast(num)
|
||||||
.padEnd(interp.funge.height, "")
|
.map(mapping)
|
||||||
.reversed()
|
.padEnd(num, "")
|
||||||
|
// .reversed()
|
||||||
.joinToString("\n")
|
.joinToString("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
charOut = getStackStr { it.asChar ?: '*'}
|
charOut = getStackStr { "${it.asChar ?: '\u2022'} (${it.value})" }
|
||||||
longOut = getStackStr { it.value }
|
|
||||||
|
|
||||||
interp.stackChanged += {
|
interp.stackChanged += {
|
||||||
charOut = getStackStr { it.asChar ?: '*'}
|
charOut = getStackStr { "${it.asChar ?: '\u2022'} (${it.value})" }
|
||||||
longOut = getStackStr { it.value }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3
ide/src/main/resources/META-INF/MANIFEST.MF
Normal file
3
ide/src/main/resources/META-INF/MANIFEST.MF
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Main-Class: befide.ide.MainApp
|
||||||
|
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
* {
|
* {
|
||||||
-fx-font-size: 14;
|
-fx-font-size: 18;
|
||||||
-fx-font-fill: black;
|
-fx-font-fill: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.code, .text-area {
|
.code, .text-area, .stack-pane {
|
||||||
-fx-font-family: Consolas, monospace;
|
-fx-font-family: Consolas, monospace;
|
||||||
-fx-text-fill: black;
|
-fx-text-fill: black;
|
||||||
|
-fx-font-size: 18;
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-view, .text-area {
|
.code-view, .text-area {
|
||||||
@@ -13,7 +14,6 @@
|
|||||||
-fx-border-radius: 2px;
|
-fx-border-radius: 2px;
|
||||||
-fx-border-width: 1px;
|
-fx-border-width: 1px;
|
||||||
-fx-background-color: #fff;
|
-fx-background-color: #fff;
|
||||||
-fx-graphic: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-num {
|
.code-num {
|
||||||
@@ -21,17 +21,27 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.code-funge {
|
.code-funge {
|
||||||
-fx-text-fill: #258135;
|
-fx-text-fill: #418148;
|
||||||
-fx-font-style: italic;
|
-fx-font-style: italic;
|
||||||
-fx-font-weight: bold;
|
-fx-font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-dir {
|
.code-dir {
|
||||||
-fx-text-fill: #b82893;
|
-fx-text-fill: #b82893;
|
||||||
|
-fx-font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-str {
|
.code-condition {
|
||||||
-fx-text-fill: #0a5158;
|
-fx-text-fill: #ffa235;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-stop {
|
||||||
|
-fx-font-weight: bold;
|
||||||
|
-fx-text-fill: #990208;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-quote {
|
||||||
|
-fx-text-fill: #258135;
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-cursor-ip {
|
.code-cursor-ip {
|
||||||
|
|||||||
Reference in New Issue
Block a user