diff --git a/baremetal/mu-init.subx b/baremetal/mu-init.subx index 26b83451..b9479101 100644 --- a/baremetal/mu-init.subx +++ b/baremetal/mu-init.subx @@ -8,6 +8,7 @@ # initialize stack bd/copy-to-ebp 0/imm32 +#? (test-run-move-cursor-into-trace) # always first run tests (run-tests) (num-test-failures) # => eax diff --git a/baremetal/shell/gap-buffer.mu b/baremetal/shell/gap-buffer.mu index 6e5d7f6d..5b6591db 100644 --- a/baremetal/shell/gap-buffer.mu +++ b/baremetal/shell/gap-buffer.mu @@ -750,3 +750,10 @@ fn skip-whitespace-from-gap-buffer self: (addr gap-buffer) { g <- read-from-gap-buffer self loop } + +fn edit-gap-buffer self: (addr gap-buffer), key: grapheme { +} + +fn cursor-on-final-line? self: (addr gap-buffer) -> _/eax: boolean { + return 1/true +} diff --git a/baremetal/shell/sandbox.mu b/baremetal/shell/sandbox.mu index 08b76c3a..d7fed376 100644 --- a/baremetal/shell/sandbox.mu +++ b/baremetal/shell/sandbox.mu @@ -2,6 +2,7 @@ type sandbox { data: (handle gap-buffer) value: (handle stream byte) trace: (handle trace) + cursor-in-trace?: boolean } fn initialize-sandbox _self: (addr sandbox) { @@ -58,13 +59,21 @@ fn render-sandbox screen: (addr screen), _self: (addr sandbox), _x: int, _y: int var data/edx: (addr gap-buffer) <- copy _data var x/eax: int <- copy _x var y/ecx: int <- copy _y - x, y <- render-gap-buffer-wrapping-right-then-down screen, data, x, y, 0x20/xmax, 0x20/ymax, x, y, 1/show-cursor + var cursor-in-sandbox?/ebx: boolean <- copy 0/false + { + var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace? + compare *cursor-in-trace?, 0/false + break-if-!= + cursor-in-sandbox? <- copy 1/true + } + x, y <- render-gap-buffer-wrapping-right-then-down screen, data, x, y, 0x20/xmax, 0x20/ymax, x, y, cursor-in-sandbox? y <- increment # trace var trace-ah/eax: (addr handle trace) <- get self, trace var _trace/eax: (addr trace) <- lookup *trace-ah var trace/edx: (addr trace) <- copy _trace - y <- render-trace screen, trace, _x, y, 0x20/xmax, 0x20/ymax + var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace? + y <- render-trace screen, trace, _x, y, 0x20/xmax, 0x20/ymax, *cursor-in-trace? # value var value-ah/eax: (addr handle stream byte) <- get self, value var _value/eax: (addr stream byte) <- lookup *value-ah @@ -90,6 +99,7 @@ fn edit-sandbox _self: (addr sandbox), key: byte { delete-grapheme-before-cursor self return } + # running code { compare g, 0x12/ctrl-r break-if-!= @@ -114,6 +124,41 @@ fn edit-sandbox _self: (addr sandbox), key: byte { run data, value, trace return } + # arrow keys + { + compare g, 0x4/ctrl-d + break-if-!= + # ctrl-d: cursor down (into trace if it makes sense) + var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace? + # if cursor in input, check if we need to switch to trace + { + compare *cursor-in-trace?, 0/false + break-if-!= + var data-ah/eax: (addr handle gap-buffer) <- get self, data + var data/eax: (addr gap-buffer) <- lookup *data-ah + var at-bottom?/eax: boolean <- cursor-on-final-line? data + compare at-bottom?, 0/false + break-if-= + var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace? + copy-to *cursor-in-trace?, 1/true + return + } + # if cursor in trace, send cursor to trace + { + compare cursor-in-trace?, 0/false + break-if-= + var trace-ah/eax: (addr handle trace) <- get self, trace + var trace/eax: (addr trace) <- lookup *trace-ah + edit-trace trace, g + return + } + # otherwise send cursor to input + var data-ah/eax: (addr handle gap-buffer) <- get self, data + var data/eax: (addr gap-buffer) <- lookup *data-ah + edit-gap-buffer data, g + return + } + # default: insert character add-grapheme-to-sandbox self, g } @@ -130,3 +175,69 @@ fn run in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { # TODO: eval print-cell read-result, out } + +fn test-run-integer { + var sandbox-storage: sandbox + var sandbox/esi: (addr sandbox) <- address sandbox-storage + initialize-sandbox sandbox + # type "1" + edit-sandbox sandbox, 0x31/1 + # eval + edit-sandbox sandbox, 0x13/ctrl-s + # setup: screen + var screen-on-stack: screen + var screen/edi: (addr screen) <- address screen-on-stack + initialize-screen screen, 0xa, 4 + # + render-sandbox screen, sandbox, 0/x, 0/y + check-screen-row screen, 0/y, "1 ", "F - test-run-integer/0" + check-screen-row screen, 1/y, "=> 1 ", "F - test-run-integer/1" +} + +fn test-run-error-invalid-integer { + var sandbox-storage: sandbox + var sandbox/esi: (addr sandbox) <- address sandbox-storage + initialize-sandbox sandbox + # type "1a" + edit-sandbox sandbox, 0x31/1 + edit-sandbox sandbox, 0x61/a + # eval + edit-sandbox sandbox, 0x13/ctrl-s + # setup: screen + var screen-on-stack: screen + var screen/edi: (addr screen) <- address screen-on-stack + initialize-screen screen, 0x10, 4 + # + render-sandbox screen, sandbox, 0/x, 0/y + check-screen-row screen, 0/y, "1a ", "F - test-run-error-invalid-integer/0" + check-screen-row screen, 1/y, "invalid number ", "F - test-run-error-invalid-integer/1" +} + +fn test-run-move-cursor-into-trace { + var sandbox-storage: sandbox + var sandbox/esi: (addr sandbox) <- address sandbox-storage + initialize-sandbox sandbox + # type "1a" + edit-sandbox sandbox, 0x31/1 + edit-sandbox sandbox, 0x61/a + # eval + edit-sandbox sandbox, 0x13/ctrl-s + # setup: screen + var screen-on-stack: screen + var screen/edi: (addr screen) <- address screen-on-stack + initialize-screen screen, 0x10, 4 + # + render-sandbox screen, sandbox, 0/x, 0/y + check-screen-row screen, 0/y, "1a ", "F - test-run-move-cursor-into-trace/pre-0" + check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-run-move-cursor-into-trace/pre-0/cursor" + check-screen-row screen, 1/y, "invalid number ", "F - test-run-move-cursor-into-trace/pre-1" + check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-run-move-cursor-into-trace/pre-1/cursor" + # move cursor down + edit-sandbox sandbox, 4/ctrl-d + # + render-sandbox screen, sandbox, 0/x, 0/y + check-screen-row screen, 0/y, "1a ", "F - test-run-move-cursor-into-trace/0" + check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-run-move-cursor-into-trace/0/cursor" + check-screen-row screen, 1/y, "invalid number ", "F - test-run-move-cursor-into-trace/1" + check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "|||||||||||||| ", "F - test-run-move-cursor-into-trace/1/cursor" +} diff --git a/baremetal/shell/trace.mu b/baremetal/shell/trace.mu index 4c699a08..d3549f2a 100644 --- a/baremetal/shell/trace.mu +++ b/baremetal/shell/trace.mu @@ -2,8 +2,9 @@ # An integral part of the Mu Shell is facilities for browsing traces. type trace { - curr-depth: int + curr-depth: int # depth that will be assigned to next line appended data: (handle stream trace-line) + cursor-y: int # row index on screen } type trace-line { @@ -92,8 +93,14 @@ fn trace-higher _self: (addr trace) { decrement *depth } -fn render-trace screen: (addr screen), _self: (addr trace), xmin: int, ymin: int, xmax: int, ymax: int -> _/ecx: int { +fn render-trace screen: (addr screen), _self: (addr trace), xmin: int, ymin: int, xmax: int, ymax: int, show-cursor?: boolean -> _/ecx: int { var already-hiding-lines?/ebx: boolean <- copy 0/false + var bg/edi: int <- copy 0/black + compare show-cursor?, 0/false + { + break-if-= + bg <- copy 7/grey + } var y/ecx: int <- copy ymin var self/eax: (addr trace) <- copy _self var trace-ah/eax: (addr handle stream trace-line) <- get self, data @@ -118,7 +125,7 @@ fn render-trace screen: (addr screen), _self: (addr trace), xmin: int, ymin: int var _curr-data/eax: (addr array byte) <- lookup *curr-data-ah var curr-data/edx: (addr array byte) <- copy _curr-data var x/eax: int <- copy xmin - x, y <- draw-text-wrapping-right-then-down screen, curr-data, xmin, ymin, xmax, ymax, x, y, 0xc/fg=trace-error, 0/bg + x, y <- draw-text-wrapping-right-then-down screen, curr-data, xmin, ymin, xmax, ymax, x, y, 0xc/fg=trace-error, bg y <- increment already-hiding-lines? <- copy 0/false loop $render-trace:loop @@ -128,7 +135,7 @@ fn render-trace screen: (addr screen), _self: (addr trace), xmin: int, ymin: int { break-if-!= var x/eax: int <- copy xmin - x, y <- draw-text-wrapping-right-then-down screen, "...", xmin, ymin, xmax, ymax, x, y, 9/fg=trace, 0/bg + x, y <- draw-text-wrapping-right-then-down screen, "...", xmin, ymin, xmax, ymax, x, y, 9/fg=trace, bg y <- increment } loop @@ -145,7 +152,7 @@ fn test-render-trace-empty { var screen/edi: (addr screen) <- address screen-on-stack initialize-screen screen, 5, 4 # - var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 5/xmax, 4/ymax + var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 5/xmax, 4/ymax, 0/no-cursor # check-ints-equal y, 0, "F - test-render-trace-empty/cursor" check-screen-row screen, 0/y, " ", "F - test-render-trace-empty" @@ -164,7 +171,7 @@ fn test-render-trace-collapsed-by-default { var screen/edi: (addr screen) <- address screen-on-stack initialize-screen screen, 5, 4 # - var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 5/xmax, 4/ymax + var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 5/xmax, 4/ymax, 0/no-cursor # check-ints-equal y, 1, "F - test-render-trace-collapsed-by-default/cursor" check-screen-row screen, 0/y, "... ", "F - test-render-trace-collapsed-by-default" @@ -180,7 +187,7 @@ fn test-render-trace-error { var screen/edi: (addr screen) <- address screen-on-stack initialize-screen screen, 0xa, 4 # - var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax + var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor # check-ints-equal y, 1, "F - test-render-trace-error/cursor" check-screen-row screen, 0/y, "error", "F - test-render-trace-error" @@ -202,7 +209,7 @@ fn test-render-trace-error-at-start { var screen/edi: (addr screen) <- address screen-on-stack initialize-screen screen, 0xa, 4 # - var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax + var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor # check-ints-equal y, 2, "F - test-render-trace-error-at-start/cursor" check-screen-row screen, 0/y, "error", "F - test-render-trace-error-at-start/0" @@ -225,7 +232,7 @@ fn test-render-trace-error-at-end { var screen/edi: (addr screen) <- address screen-on-stack initialize-screen screen, 0xa, 4 # - var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax + var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor # check-ints-equal y, 2, "F - test-render-trace-error-at-end/cursor" check-screen-row screen, 0/y, "... ", "F - test-render-trace-error-at-end/0" @@ -250,10 +257,13 @@ fn test-render-trace-error-in-the-middle { var screen/edi: (addr screen) <- address screen-on-stack initialize-screen screen, 0xa, 4 # - var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax + var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor # check-ints-equal y, 3, "F - test-render-trace-error-in-the-middle/cursor" check-screen-row screen, 0/y, "... ", "F - test-render-trace-error-in-the-middle/0" check-screen-row screen, 1/y, "error", "F - test-render-trace-error-in-the-middle/1" check-screen-row screen, 2/y, "... ", "F - test-render-trace-error-in-the-middle/2" } + +fn edit-trace self: (addr trace), key: grapheme { +}