# A trace records the evolution of a computation.
# An integral part of the Mu Shell is facilities for browsing traces.
type trace {
curr-depth: int # depth that will be assigned to next line appended
data: (handle array trace-line)
first-free: int
first-full: int # used only by check-trace-scan
# steady-state life cycle of a trace:
# reload loop:
# there are already some visible lines
# append a bunch of new trace lines to the trace
# render loop:
# rendering displays trace lines that match visible lines
# rendering computes cursor-line based on the cursor-y coordinate
# edit-trace updates cursor-y coordinate
# edit-trace might add/remove lines to visible
visible: (handle array trace-line)
recompute-visible?: boolean
top-line-index: int # index into data
cursor-y: int # row index on screen
cursor-line-index: int # index into data
}
type trace-line {
depth: int
label: (handle array byte)
data: (handle array byte)
visible?: boolean
}
## generating traces
fn initialize-trace _self: (addr trace), capacity: int, visible-capacity: int {
var self/esi: (addr trace) <- copy _self
compare self, 0
break-if-=
var trace-ah/eax: (addr handle array trace-line) <- get self, data
populate trace-ah, capacity
var visible-ah/eax: (addr handle array trace-line) <- get self, visible
populate visible-ah, visible-capacity
}
fn clear-trace _self: (addr trace) {
var self/eax: (addr trace) <- copy _self
compare self, 0
break-if-=
var len/edx: (addr int) <- get self, first-free
copy-to *len, 0
# might leak memory; existing elements won't be used anymore
}
fn has-errors? _self: (addr trace) -> _/eax: boolean {
var self/eax: (addr trace) <- copy _self
{
compare self, 0
break-if-!=
return 0/false
}
var max/edx: (addr int) <- get self, first-free
var trace-ah/eax: (addr handle array trace-line) <- get self, data
var _trace/eax: (addr array trace-line) <- lookup *trace-ah
var trace/esi: (addr array trace-line) <- copy _trace
var i/ecx: int <- copy 0
{
compare i, *max
break-if->=
var offset/eax: (offset trace-line) <- compute-offset trace, i
var curr/eax: (addr trace-line) <- index trace, offset
var curr-label-ah/eax: (addr handle array byte) <- get curr, label
var curr-label/eax: (addr array byte) <- lookup *curr-label-ah
var error?/eax: boolean <- string-equal? curr-label, "error"
compare error?, 0/false
{
break-if-=
return 1/true
}
i <- increment
loop
}
return 0/false
}
fn trace _self: (addr trace), label: (addr array byte), message: (addr stream byte) {
var self/esi: (addr trace) <- copy _self
compare self, 0
break-if-=
var data-ah/eax: (addr handle array trace-line) <- get self, data
var data/eax: (addr array trace-line) <- lookup *data-ah
var index-addr/edi: (addr int) <- get self, first-free
var index/ecx: int <- copy *index-addr
var offset/ecx: (offset trace-line) <- compute-offset data, index
var dest/eax: (addr trace-line) <- index data, offset
var depth/ecx: (addr int) <- get self, curr-depth
rewind-stream message
initialize-trace-line *depth, label, message, dest
increment *index-addr
}
fn trace-text self: (addr trace), label: (addr array byte), s: (addr array byte) {
compare self, 0
break-if-=
var data-storage: (stream byte 0x100)
var data/eax: (addr stream byte) <- address data-storage
write data, s
trace self, label, data
}
fn error self: (addr trace), message: (addr array byte) {
trace-text self, "error", message
}
fn initialize-trace-line depth: int, label: (addr array byte), data: (addr stream byte), _out: (addr trace-line) {
var out/edi: (addr trace-line) <- copy _out
# depth
var src/eax: int <- copy depth
var dest/ecx: (addr int) <- get out, depth
copy-to *dest, src
# label
var dest/eax: (addr handle array byte) <- get out, label
copy-array-object label, dest
# data
var dest/eax: (addr handle array byte) <- get out, data
stream-to-array data, dest
}
fn trace-lower _self: (addr trace) {
var self/esi: (addr trace) <- copy _self
compare self, 0
break-if-=
var depth/eax: (addr int) <- get self, curr-depth
increment *depth
}
fn trace-higher _self: (addr trace) {
var self/esi: (addr trace) <- copy _self
compare self, 0
break-if-=
var depth/eax: (addr int) <- get self, curr-depth
decrement *depth
}
## checking traces
fn check-trace-scans-to self: (addr trace), label: (addr array byte), data: (addr array byte), message: (addr array byte) {
var tmp/eax: boolean <- trace-scans-to? self, label, data
check tmp, message
}
fn trace-scans-to? _self: (addr trace), label: (addr array byte), data: (addr array byte) -> _/eax: boolean {
var self/esi: (addr trace) <- copy _self
var start/eax: (addr int) <- get self, first-full
var result/eax: boolean <- trace-contains? self, label, data, *start
return result
}
fn test-trace-scans-to {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0/visible # we don't use trace UI
#
trace-text t, "label", "line 1"
trace-text t, "label", "line 2"
check-trace-scans-to t, "label", "line 1", "F - test-trace-scans-to/0"
check-trace-scans-to t, "label", "line 2", "F - test-trace-scans-to/1"
var tmp/eax: boolean <- trace-scans-to? t, "label", "line 1"
check-not tmp, "F - test-trace-scans-to: fail on previously encountered lines"
var tmp/eax: boolean <- trace-scans-to? t, "label", "line 3"
check-not tmp, "F - test-trace-scans-to: fail on missing"
}
# scan trace from start
# resets previous scans
fn check-trace-contains self: (addr trace), label: (addr array byte), data: (addr array byte), message: (addr array byte) {
var tmp/eax: boolean <- trace-contains? self, label, data, 0
check tmp, message
}
fn test-trace-contains {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0/visible # we don't use trace UI
#
trace-text t, "label", "line 1"
trace-text t, "label", "line 2"
check-trace-contains t, "label", "line 1", "F - test-trace-contains/0"
check-trace-contains t, "label", "line 2", "F - test-trace-contains/1"
check-trace-contains t, "label", "line 1", "F - test-trace-contains: find previously encountered lines"
var tmp/eax: boolean <- trace-contains? t, "label", "line 3", 0/start
check-not tmp, "F - test-trace-contains: fail on missing"
}
# this is super-inefficient, string comparing every trace line
# against every visible line on every render
fn trace-contains? _self: (addr trace), label: (addr array byte), data: (addr array byte), start: int -> _/eax: boolean {
var self/esi: (addr trace) <- copy _self
var candidates-ah/eax: (addr handle array trace-line) <- get self, data
var candidates/eax: (addr array trace-line) <- lookup *candidates-ah
var i/ecx: int <- copy start
var max/edx: (addr int) <- get self, first-free
{
compare i, *max
break-if->=
{
var read-until-index/eax: (addr int) <- get self, first-full
copy-to *read-until-index, i
}
{
var curr-offset/ecx: (offset trace-line) <- compute-offset candidates, i
var curr/ecx: (addr trace-line) <- index candidates, curr-offset
# if curr->label does not match, return false
var curr-label-ah/eax: (addr handle array byte) <- get curr, label
var curr-label/eax: (addr array byte) <- lookup *curr-label-ah
var match?/eax: boolean <- string-equal? curr-label, label
compare match?, 0/false
break-if-=
# if curr->data does not match, return false
var curr-data-ah/eax: (addr handle array byte) <- get curr, data
var curr-data/eax: (addr array byte) <- lookup *curr-data-ah
var match?/eax: boolean <- string-equal? curr-data, data
compare match?, 0/false
break-if-=
return 1/true
}
i <- increment
loop
}
return 0/false
}
fn trace-lines-equal? _a: (addr trace-line), _b: (addr trace-line) -> _/eax: boolean {
var a/esi: (addr trace-line) <- copy _a
var b/edi: (addr trace-line) <- copy _b
var a-depth/ecx: (addr int) <- get a, depth
var b-depth/edx: (addr int) <- get b, depth
var benchmark/eax: int <- copy *b-depth
compare *a-depth, benchmark
{
break-if-=
return 0/false
}
var a-label-ah/eax: (addr handle array byte) <- get a, label
var _a-label/eax: (addr array byte) <- lookup *a-label-ah
var a-label/ecx: (addr array byte) <- copy _a-label
var b-label-ah/ebx: (addr handle array byte) <- get b, label
var b-label/eax: (addr array byte) <- lookup *b-label-ah
var label-match?/eax: boolean <- string-equal? a-label, b-label
{
compare label-match?, 0/false
break-if-!=
return 0/false
}
var a-data-ah/eax: (addr handle array byte) <- get a, data
var _a-data/eax: (addr array byte) <- lookup *a-data-ah
var a-data/ecx: (addr array byte) <- copy _a-data
var b-data-ah/ebx: (addr handle array byte) <- get b, data
var b-data/eax: (addr array byte) <- lookup *b-data-ah
var data-match?/eax: boolean <- string-equal? a-data, b-data
return data-match?
}
fn dump-trace _self: (addr trace) {
var already-hiding-lines?: boolean
var y/ecx: int <- copy 0
var self/esi: (addr trace) <- copy _self
compare self, 0
{
break-if-!=
return
}
var trace-ah/eax: (addr handle array trace-line) <- get self, data
var _trace/eax: (addr array trace-line) <- lookup *trace-ah
var trace/edi: (addr array trace-line) <- copy _trace
var i/edx: int <- copy 0
var max-addr/ebx: (addr int) <- get self, first-free
var max/ebx: int <- copy *max-addr
$dump-trace:loop: {
compare i, max
break-if->=
$dump-trace:iter: {
var offset/ebx: (offset trace-line) <- compute-offset trace, i
var curr/ebx: (addr trace-line) <- index trace, offset
var curr-label-ah/eax: (addr handle array byte) <- get curr, label
var curr-label/eax: (addr array byte) <- lookup *curr-label-ah
y <- render-trace-line 0/screen, curr, 0, y, 0x80/width, 0x30/height, 7/fg, 0/bg
}
i <- increment
loop
}
}
## UI stuff
fn mark-lines-dirty _self: (addr trace) {
var self/eax: (addr trace) <- copy _self
var dest/edx: (addr boolean) <- get self, recompute-visible?
copy-to *dest, 1/true
}
fn mark-lines-clean _self: (addr trace) {
var self/eax: (addr trace) <- copy _self
var dest/edx: (addr boolean) <- get self, recompute-visible?
copy-to *dest, 0/false
}
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?: boolean
var y/ecx: int <- copy ymin
var self/esi: (addr trace) <- copy _self
compare self, 0
{
break-if-!=
return ymin
}
clamp-cursor-to-top self, y
var trace-ah/eax: (addr handle array trace-line) <- get self, data
var _trace/eax: (addr array trace-line) <- lookup *trace-ah
var trace/edi: (addr array trace-line) <- copy _trace
var i/edx: int <- copy 0
var max-addr/ebx: (addr int) <- get self, first-free
var max/ebx: int <- copy *max-addr
$render-trace:loop: {
compare i, max
break-if->=
$render-trace:iter: {
var offset/ebx: (offset trace-line) <- compute-offset trace, i
var curr/ebx: (addr trace-line) <- index trace, offset
var curr-label-ah/eax: (addr handle array byte) <- get curr, label
var curr-label/eax: (addr array byte) <- lookup *curr-label-ah
var bg/edi: int <- copy 0/black
compare show-cursor?, 0/false
{
break-if-=
var cursor-y/eax: (addr int) <- get self, cursor-y
compare *cursor-y, y
break-if-!=
bg <- copy 7/cursor-line-bg
var cursor-line-index/eax: (addr int) <- get self, cursor-line-index
copy-to *cursor-line-index, i
}
# always display errors
var error?/eax: boolean <- string-equal? curr-label, "error"
{
compare error?, 0/false
break-if-=
y <- render-trace-line screen, curr, xmin, y, xmax, ymax, 0xc/fg=trace-error, bg
copy-to already-hiding-lines?, 0/false
break $render-trace:iter
}
# display expanded lines
var display?/eax: boolean <- should-render? self, curr
{
compare display?, 0/false
break-if-=
y <- render-trace-line screen, curr, xmin, y, xmax, ymax, 9/fg=blue, bg
copy-to already-hiding-lines?, 0/false
break $render-trace:iter
}
# ignore the rest
compare already-hiding-lines?, 0/false
{
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, bg
y <- increment
copy-to already-hiding-lines?, 1/true
}
}
i <- increment
loop
}
# prevent cursor from going too far down
clamp-cursor-to-bottom self, y, screen, xmin, ymin, xmax, ymax
mark-lines-clean self
return y
}
fn render-trace-line screen: (addr screen), _self: (addr trace-line), xmin: int, ymin: int, xmax: int, ymax: int, fg: int, bg: int -> _/ecx: int {
var self/esi: (addr trace-line) <- copy _self
var xsave/edx: int <- copy xmin
var y/ecx: int <- copy ymin
var label-ah/eax: (addr handle array byte) <- get self, label
var _label/eax: (addr array byte) <- lookup *label-ah
var label/ebx: (addr array byte) <- copy _label
var error?/eax: boolean <- string-equal? label, "error"
compare error?, 0/false
{
break-if-!=
var x/eax: int <- copy xsave
{
var depth/edx: (addr int) <- get self, depth
x, y <- draw-int32-decimal-wrapping-right-then-down screen, *depth, xmin, ymin, xmax, ymax, x, y, fg, bg
x, y <- draw-text-wrapping-right-then-down screen, " ", xmin, ymin, xmax, ymax, x, y, fg, bg
# don't show label in UI; it's just for tests
}
xsave <- copy x
}
var data-ah/eax: (addr handle array byte) <- get self, data
var _data/eax: (addr array byte) <- lookup *data-ah
var data/ebx: (addr array byte) <- copy _data
var x/eax: int <- copy xsave
x, y <- draw-text-wrapping-right-then-down screen, data, xmin, ymin, xmax, ymax, x, y, fg, bg
y <- increment
return y
}
# this is super-inefficient, string comparing every trace line
# against every visible line on every render
fn should-render? _self: (addr trace), _line: (addr trace-line) -> _/eax: boolean {
var self/esi: (addr trace) <- copy _self
# if visible? is already cached, just return it
var dest/edx: (addr boolean) <- get self, recompute-visible?
compare *dest, 0/false
{
break-if-!=
var line/eax: (addr trace-line) <- copy _line
var result/eax: (addr boolean) <- get line, visible?
return *result
}
# recompute
var candidates-ah/eax: (addr handle array trace-line) <- get self, visible
var candidates/eax: (addr array trace-line) <- lookup *candidates-ah
var i/ecx: int <- copy 0
var len/edx: int <- length candidates
{
compare i, len
break-if->=
{
var curr-offset/ecx: (offset trace-line) <- compute-offset candidates, i
var curr/ecx: (addr trace-line) <- index candidates, curr-offset
var match?/eax: boolean <- trace-lines-equal? curr, _line
compare match?, 0/false
break-if-=
var line/eax: (addr trace-line) <- copy _line
var dest/eax: (addr boolean) <- get line, visible?
copy-to *dest, 1/true
return 1/true
}
i <- increment
loop
}
var line/eax: (addr trace-line) <- copy _line
var dest/eax: (addr boolean) <- get line, visible?
copy-to *dest, 0/false
return 0/false
}
fn clamp-cursor-to-top _self: (addr trace), _y: int {
var y/ecx: int <- copy _y
var self/esi: (addr trace) <- copy _self
var cursor-y/eax: (addr int) <- get self, cursor-y
compare *cursor-y, y
break-if->=
copy-to *cursor-y, y
}
# extremely hacky; consider deleting test-render-trace-empty-3 when you clean this up
fn clamp-cursor-to-bottom _self: (addr trace), _y: int, screen: (addr screen), xmin: int, ymin: int, xmax: int, ymax: int {
var y/ebx: int <- copy _y
compare y, ymin
{
break-if->
return
}
y <- decrement
var self/esi: (addr trace) <- copy _self
var cursor-y/eax: (addr int) <- get self, cursor-y
compare *cursor-y, y
break-if-<=
copy-to *cursor-y, y
# redraw cursor-line
# TODO: ugly duplication
var trace-ah/eax: (addr handle array trace-line) <- get self, data
var trace/eax: (addr array trace-line) <- lookup *trace-ah
var cursor-line-index-addr/ecx: (addr int) <- get self, cursor-line-index
var cursor-line-index/ecx: int <- copy *cursor-line-index-addr
var first-free/edx: (addr int) <- get self, first-free
compare cursor-line-index, *first-free
{
break-if-<
return
}
var cursor-offset/ecx: (offset trace-line) <- compute-offset trace, cursor-line-index
var cursor-line/ecx: (addr trace-line) <- index trace, cursor-offset
var display?/eax: boolean <- should-render? self, cursor-line
{
compare display?, 0/false
break-if-=
var dummy/ecx: int <- render-trace-line screen, cursor-line, xmin, y, xmax, ymax, 9/fg=blue, 7/cursor-line-bg
return
}
var dummy1/eax: int <- copy 0
var dummy2/ecx: int <- copy 0
dummy1, dummy2 <- draw-text-wrapping-right-then-down screen, "...", xmin, ymin, xmax, ymax, xmin, y, 9/fg=trace, 7/cursor-line-bg
}
fn test-render-trace-empty {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 5/width, 4/height
#
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"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-render-trace-empty/bg"
}
fn test-render-trace-empty-2 {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 5/width, 4/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 2/ymin, 5/xmax, 4/ymax, 0/no-cursor # cursor below top row
#
check-ints-equal y, 2, "F - test-render-trace-empty-2/cursor"
check-screen-row screen, 2/y, " ", "F - test-render-trace-empty-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-render-trace-empty-2/bg"
}
fn test-render-trace-empty-3 {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 5/width, 4/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 2/ymin, 5/xmax, 4/ymax, 1/show-cursor # try show cursor
# still no cursor to show
check-ints-equal y, 2, "F - test-render-trace-empty-3/cursor"
check-screen-row screen, 1/y, " ", "F - test-render-trace-empty-3/line-above-cursor"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-render-trace-empty-3/bg-for-line-above-cursor"
check-screen-row screen, 2/y, " ", "F - test-render-trace-empty-3"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-render-trace-empty-3/bg"
}
fn test-render-trace-collapsed-by-default {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
trace-text t, "l", "data"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 5/width, 4/height
#
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"
}
fn test-render-trace-error {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
error t, "error"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0xa/width, 4/height
#
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"
}
fn test-render-trace-error-at-start {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
error t, "error"
trace-text t, "l", "data"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0xa/width, 4/height
#
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"
check-screen-row screen, 1/y, "... ", "F - test-render-trace-error-at-start/1"
}
fn test-render-trace-error-at-end {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "data"
error t, "error"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0xa/width, 4/height
#
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"
check-screen-row screen, 1/y, "error", "F - test-render-trace-error-at-end/1"
}
fn test-render-trace-error-in-the-middle {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1"
error t, "error"
trace-text t, "l", "line 3"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0xa/width, 4/height
#
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 test-render-trace-cursor-in-single-line {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1"
error t, "error"
trace-text t, "l", "line 3"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0xa/width, 4/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-render-trace-cursor-in-single-line/0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-render-trace-cursor-in-single-line/0/cursor"
check-screen-row screen, 1/y, "error ", "F - test-render-trace-cursor-in-single-line/1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-render-trace-cursor-in-single-line/1/cursor"
check-screen-row screen, 2/y, "... ", "F - test-render-trace-cursor-in-single-line/2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-render-trace-cursor-in-single-line/2/cursor"
}
fn render-trace-menu screen: (addr screen) {
var width/eax: int <- copy 0
var height/ecx: int <- copy 0
width, height <- screen-size screen
var y/ecx: int <- copy height
y <- decrement
set-cursor-position screen, 0/x, y
draw-text-rightward-from-cursor screen, " ctrl-s ", width, 0/fg, 7/bg=grey
draw-text-rightward-from-cursor screen, " run sandbox ", width, 7/fg, 0/bg
draw-text-rightward-from-cursor screen, " tab ", width, 0/fg, 0x18/bg=keyboard
draw-text-rightward-from-cursor screen, " move to keyboard ", width, 7/fg, 0/bg
draw-text-rightward-from-cursor screen, " j ", width, 0/fg, 7/bg=grey
draw-text-rightward-from-cursor screen, " down ", width, 7/fg, 0/bg
draw-text-rightward-from-cursor screen, " k ", width, 0/fg, 7/bg=grey
draw-text-rightward-from-cursor screen, " up ", width, 7/fg, 0/bg
draw-text-rightward-from-cursor screen, " enter ", width, 0/fg, 7/bg=grey
draw-text-rightward-from-cursor screen, " expand ", width, 7/fg, 0/bg
draw-text-rightward-from-cursor screen, " backspace ", width, 0/fg, 7/bg=grey
draw-text-rightward-from-cursor screen, " collapse ", width, 7/fg, 0/bg
}
fn edit-trace _self: (addr trace), key: grapheme {
var self/esi: (addr trace) <- copy _self
# cursor down
{
compare key, 0x6a/j
break-if-!=
var cursor-y/eax: (addr int) <- get self, cursor-y
increment *cursor-y
return
}
{
compare key, 0x81/down-arrow
break-if-!=
var cursor-y/eax: (addr int) <- get self, cursor-y
increment *cursor-y
return
}
# cursor up
{
compare key, 0x6b/k
break-if-!=
var cursor-y/eax: (addr int) <- get self, cursor-y
decrement *cursor-y
return
}
{
compare key, 0x82/up-arrow
break-if-!=
var cursor-y/eax: (addr int) <- get self, cursor-y
decrement *cursor-y
return
}
# enter = expand
{
compare key, 0xa/newline
break-if-!=
expand self
return
}
# backspace = collapse
{
compare key, 8/backspace
break-if-!=
collapse self
return
}
}
fn expand _self: (addr trace) {
var self/esi: (addr trace) <- copy _self
var trace-ah/eax: (addr handle array trace-line) <- get self, data
var _trace/eax: (addr array trace-line) <- lookup *trace-ah
var trace/edi: (addr array trace-line) <- copy _trace
var cursor-line-index-addr/ecx: (addr int) <- get self, cursor-line-index
var cursor-line-index/ecx: int <- copy *cursor-line-index-addr
var cursor-line-offset/eax: (offset trace-line) <- compute-offset trace, cursor-line-index
var cursor-line/edx: (addr trace-line) <- index trace, cursor-line-offset
var cursor-line-visible?/eax: (addr boolean) <- get cursor-line, visible?
var cursor-line-depth/ebx: (addr int) <- get cursor-line, depth
var target-depth/ebx: int <- copy *cursor-line-depth
# if cursor-line is already visible, increment target-depth
compare *cursor-line-visible?, 0/false
{
break-if-=
target-depth <- increment
}
# reveal the run of lines starting at cursor-line-index with depth target-depth
var i/ecx: int <- copy cursor-line-index
var max/edx: (addr int) <- get self, first-free
{
compare i, *max
break-if->=
var curr-line-offset/eax: (offset trace-line) <- compute-offset trace, i
var curr-line/edx: (addr trace-line) <- index trace, curr-line-offset
var curr-line-depth/eax: (addr int) <- get curr-line, depth
compare *curr-line-depth, target-depth
break-if-<
{
break-if-!=
var curr-line-visible?/eax: (addr boolean) <- get curr-line, visible?
copy-to *curr-line-visible?, 1/true
reveal-trace-line self, curr-line
}
i <- increment
loop
}
}
fn collapse _self: (addr trace) {
var self/esi: (addr trace) <- copy _self
var trace-ah/eax: (addr handle array trace-line) <- get self, data
var _trace/eax: (addr array trace-line) <- lookup *trace-ah
var trace/edi: (addr array trace-line) <- copy _trace
var cursor-line-index-addr/ecx: (addr int) <- get self, cursor-line-index
var cursor-line-index/ecx: int <- copy *cursor-line-index-addr
var cursor-line-offset/eax: (offset trace-line) <- compute-offset trace, cursor-line-index
var cursor-line/edx: (addr trace-line) <- index trace, cursor-line-offset
var cursor-line-visible?/eax: (addr boolean) <- get cursor-line, visible?
# if cursor-line is not visible, do nothing
compare *cursor-line-visible?, 0/false
{
break-if-!=
return
}
# hide all lines between previous and next line with a lower depth
var cursor-line-depth/ebx: (addr int) <- get cursor-line, depth
var cursor-y/edx: (addr int) <- get self, cursor-y
var target-depth/ebx: int <- copy *cursor-line-depth
var i/ecx: int <- copy cursor-line-index
$collapse:loop1: {
compare i, 0
break-if-<
var curr-line-offset/eax: (offset trace-line) <- compute-offset trace, i
var curr-line/eax: (addr trace-line) <- index trace, curr-line-offset
{
var curr-line-depth/eax: (addr int) <- get curr-line, depth
compare *curr-line-depth, target-depth
break-if-< $collapse:loop1
}
# if cursor-line is visible, decrement cursor-y
{
var curr-line-visible?/eax: (addr boolean) <- get curr-line, visible?
compare *curr-line-visible?, 0/false
break-if-=
decrement *cursor-y
}
i <- decrement
loop
}
i <- increment
var max/edx: (addr int) <- get self, first-free
$collapse:loop2: {
compare i, *max
break-if->=
var curr-line-offset/eax: (offset trace-line) <- compute-offset trace, i
var curr-line/edx: (addr trace-line) <- index trace, curr-line-offset
var curr-line-depth/eax: (addr int) <- get curr-line, depth
compare *curr-line-depth, target-depth
break-if-<
{
hide-trace-line self, curr-line
var curr-line-visible?/eax: (addr boolean) <- get curr-line, visible?
copy-to *curr-line-visible?, 0/false
}
i <- increment
loop
}
}
# the 'visible' array is not required to be in order
# elements can also be deleted out of order
# so it can have holes
# however, lines in it always have visible? set
# we'll use visible? being unset as a sign of emptiness
fn reveal-trace-line _self: (addr trace), line: (addr trace-line) {
var self/esi: (addr trace) <- copy _self
var visible-ah/eax: (addr handle array trace-line) <- get self, visible
var visible/eax: (addr array trace-line) <- lookup *visible-ah
var i/ecx: int <- copy 0
var len/edx: int <- length visible
{
compare i, len
break-if->=
var curr-offset/edx: (offset trace-line) <- compute-offset visible, i
var curr/edx: (addr trace-line) <- index visible, curr-offset
var curr-visible?/eax: (addr boolean) <- get curr, visible?
compare *curr-visible?, 0/false
{
break-if-!=
# empty slot found
copy-object line, curr
return
}
i <- increment
loop
}
abort "too many visible lines; increase size of array trace.visible"
}
fn hide-trace-line _self: (addr trace), line: (addr trace-line) {
var self/esi: (addr trace) <- copy _self
var visible-ah/eax: (addr handle array trace-line) <- get self, visible
var visible/eax: (addr array trace-line) <- lookup *visible-ah
var i/ecx: int <- copy 0
var len/edx: int <- length visible
{
compare i, len
break-if->=
var curr-offset/edx: (offset trace-line) <- compute-offset visible, i
var curr/edx: (addr trace-line) <- index visible, curr-offset
var found?/eax: boolean <- trace-lines-equal? curr, line
compare found?, 0/false
{
break-if-=
clear-object curr
}
i <- increment
loop
}
}
fn test-cursor-down-and-up-within-trace {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1"
error t, "error"
trace-text t, "l", "line 3"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0xa/width, 4/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-cursor-down-and-up-within-trace/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-cursor-down-and-up-within-trace/pre-0/cursor"
check-screen-row screen, 1/y, "error ", "F - test-cursor-down-and-up-within-trace/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-cursor-down-and-up-within-trace/pre-1/cursor"
check-screen-row screen, 2/y, "... ", "F - test-cursor-down-and-up-within-trace/pre-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-cursor-down-and-up-within-trace/pre-2/cursor"
# cursor down
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-cursor-down-and-up-within-trace/down-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-cursor-down-and-up-within-trace/down-0/cursor"
check-screen-row screen, 1/y, "error ", "F - test-cursor-down-and-up-within-trace/down-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "||||| ", "F - test-cursor-down-and-up-within-trace/down-1/cursor"
check-screen-row screen, 2/y, "... ", "F - test-cursor-down-and-up-within-trace/down-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-cursor-down-and-up-within-trace/down-2/cursor"
# cursor up
edit-trace t, 0x6b/k
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-cursor-down-and-up-within-trace/up-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-cursor-down-and-up-within-trace/up-0/cursor"
check-screen-row screen, 1/y, "error ", "F - test-cursor-down-and-up-within-trace/up-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-cursor-down-and-up-within-trace/up-1/cursor"
check-screen-row screen, 2/y, "... ", "F - test-cursor-down-and-up-within-trace/up-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-cursor-down-and-up-within-trace/up-2/cursor"
}
fn test-cursor-down-past-bottom-of-trace {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1"
error t, "error"
trace-text t, "l", "line 3"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0xa/width, 4/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-cursor-down-past-bottom-of-trace/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-cursor-down-past-bottom-of-trace/pre-0/cursor"
check-screen-row screen, 1/y, "error ", "F - test-cursor-down-past-bottom-of-trace/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-cursor-down-past-bottom-of-trace/pre-1/cursor"
check-screen-row screen, 2/y, "... ", "F - test-cursor-down-past-bottom-of-trace/pre-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-cursor-down-past-bottom-of-trace/pre-2/cursor"
# cursor down several times
edit-trace t, 0x6a/j
edit-trace t, 0x6a/j
edit-trace t, 0x6a/j
edit-trace t, 0x6a/j
edit-trace t, 0x6a/j
# hack: we do need to render to make this test pass; we're mixing state management with rendering
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
# cursor clamps at bottom
check-screen-row screen, 0/y, "... ", "F - test-cursor-down-past-bottom-of-trace/down-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-cursor-down-past-bottom-of-trace/down-0/cursor"
check-screen-row screen, 1/y, "error ", "F - test-cursor-down-past-bottom-of-trace/down-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-cursor-down-past-bottom-of-trace/down-1/cursor"
check-screen-row screen, 2/y, "... ", "F - test-cursor-down-past-bottom-of-trace/down-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "||| ", "F - test-cursor-down-past-bottom-of-trace/down-2/cursor"
}
fn test-expand-within-trace {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-text t, "l", "line 2"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-expand-within-trace/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-expand-within-trace/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-expand-within-trace/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-expand-within-trace/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "0 line 1 ", "F - test-expand-within-trace/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-expand-within-trace/expand-0/cursor"
check-screen-row screen, 1/y, "0 line 2 ", "F - test-expand-within-trace/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-expand-within-trace/expand-1/cursor"
check-screen-row screen, 2/y, " ", "F - test-expand-within-trace/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-expand-within-trace/expand-2/cursor"
}
fn test-trace-expand-skips-lower-depth {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-lower t
trace-text t, "l", "line 2"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-expand-skips-lower-depth/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-expand-skips-lower-depth/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-expand-skips-lower-depth/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-skips-lower-depth/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-expand-skips-lower-depth/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-expand-skips-lower-depth/expand-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-expand-skips-lower-depth/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-skips-lower-depth/expand-1/cursor"
check-screen-row screen, 2/y, " ", "F - test-trace-expand-skips-lower-depth/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-skips-lower-depth/expand-2/cursor"
}
fn test-trace-expand-continues-past-lower-depth {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-lower t
trace-text t, "l", "line 1.1"
trace-higher t
trace-text t, "l", "line 2"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-expand-continues-past-lower-depth/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-expand-continues-past-lower-depth/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-expand-continues-past-lower-depth/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-continues-past-lower-depth/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-expand-continues-past-lower-depth/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-expand-continues-past-lower-depth/expand-0/cursor"
# TODO: might be too wasteful to show every place where lines are hidden
check-screen-row screen, 1/y, "... ", "F - test-trace-expand-continues-past-lower-depth/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-continues-past-lower-depth/expand-1/cursor"
check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-expand-continues-past-lower-depth/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-continues-past-lower-depth/expand-2/cursor"
}
fn test-trace-expand-stops-at-higher-depth {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1.1"
trace-lower t
trace-text t, "l", "line 1.1.1"
trace-higher t
trace-text t, "l", "line 1.2"
trace-higher t
trace-text t, "l", "line 2"
trace-lower t
trace-text t, "l", "line 2.1"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 8/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-expand-stops-at-higher-depth/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-expand-stops-at-higher-depth/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-expand-stops-at-higher-depth/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-stops-at-higher-depth/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "0 line 1.1 ", "F - test-trace-expand-stops-at-higher-depth/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||||| ", "F - test-trace-expand-stops-at-higher-depth/expand-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-expand-stops-at-higher-depth/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-1/cursor"
check-screen-row screen, 2/y, "0 line 1.2 ", "F - test-trace-expand-stops-at-higher-depth/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-2/cursor"
check-screen-row screen, 3/y, "... ", "F - test-trace-expand-stops-at-higher-depth/expand-3"
check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-3/cursor"
check-screen-row screen, 4/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-4"
check-background-color-in-screen-row screen, 7/bg=cursor, 4/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-4/cursor"
}
fn test-trace-expand-twice {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-lower t
trace-text t, "l", "line 1.1"
trace-higher t
trace-text t, "l", "line 2"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-expand-twice/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-expand-twice/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-expand-twice/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-twice/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-expand-twice/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-expand-twice/expand-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-expand-twice/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-twice/expand-1/cursor"
check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-expand-twice/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-twice/expand-2/cursor"
# cursor down
edit-trace t, 0x6a/j
# hack: we need to render here to make this test pass; we're mixing state management with rendering
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-expand-twice/down-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-expand-twice/down-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-expand-twice/down-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "||| ", "F - test-trace-expand-twice/down-1/cursor"
check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-expand-twice/down-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-twice/down-2/cursor"
# expand again
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-expand-twice/expand2-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-expand-twice/expand2-0/cursor"
check-screen-row screen, 1/y, "1 line 1.1 ", "F - test-trace-expand-twice/expand2-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "|||||||||| ", "F - test-trace-expand-twice/expand2-1/cursor"
check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-expand-twice/expand2-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-twice/expand2-2/cursor"
}
fn test-trace-refresh-cursor {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-text t, "l", "line 2"
trace-text t, "l", "line 3"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-refresh-cursor/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-refresh-cursor/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-refresh-cursor/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-refresh-cursor/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-refresh-cursor/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-refresh-cursor/expand-0/cursor"
check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-refresh-cursor/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-refresh-cursor/expand-1/cursor"
check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-refresh-cursor/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-refresh-cursor/expand-2/cursor"
# cursor down
edit-trace t, 0x6a/j
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-refresh-cursor/down-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-refresh-cursor/down-0/cursor"
check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-refresh-cursor/down-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-refresh-cursor/down-1/cursor"
check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-refresh-cursor/down-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-refresh-cursor/down-2/cursor"
# recreate trace
clear-trace t
trace-text t, "l", "line 1"
trace-text t, "l", "line 2"
trace-text t, "l", "line 3"
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# cursor remains unchanged
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-refresh-cursor/refresh-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-refresh-cursor/refresh-0/cursor"
check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-refresh-cursor/refresh-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-refresh-cursor/refresh-1/cursor"
check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-refresh-cursor/refresh-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-refresh-cursor/refresh-2/cursor"
}
fn test-trace-preserve-cursor-on-refresh {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-text t, "l", "line 2"
trace-text t, "l", "line 3"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-preserve-cursor-on-refresh/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-preserve-cursor-on-refresh/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-preserve-cursor-on-refresh/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-preserve-cursor-on-refresh/expand-0/cursor"
check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-preserve-cursor-on-refresh/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/expand-1/cursor"
check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-preserve-cursor-on-refresh/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-preserve-cursor-on-refresh/expand-2/cursor"
# cursor down
edit-trace t, 0x6a/j
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-preserve-cursor-on-refresh/down-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-preserve-cursor-on-refresh/down-0/cursor"
check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-preserve-cursor-on-refresh/down-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/down-1/cursor"
check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-preserve-cursor-on-refresh/down-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-preserve-cursor-on-refresh/down-2/cursor"
# recreate trace with slightly different lines
clear-trace t
trace-text t, "l", "line 4"
trace-text t, "l", "line 5"
trace-text t, "l", "line 3" # cursor line is unchanged
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# cursor remains unchanged
check-screen-row screen, 0/y, "0 line 4 ", "F - test-trace-preserve-cursor-on-refresh/refresh-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-preserve-cursor-on-refresh/refresh-0/cursor"
check-screen-row screen, 1/y, "0 line 5 ", "F - test-trace-preserve-cursor-on-refresh/refresh-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/refresh-1/cursor"
check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-preserve-cursor-on-refresh/refresh-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-preserve-cursor-on-refresh/refresh-2/cursor"
}
fn test-trace-keep-cursor-visible-on-refresh {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-text t, "l", "line 2"
trace-text t, "l", "line 3"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-keep-cursor-visible-on-refresh/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-keep-cursor-visible-on-refresh/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-keep-cursor-visible-on-refresh/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-keep-cursor-visible-on-refresh/expand-0/cursor"
check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-keep-cursor-visible-on-refresh/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/expand-1/cursor"
check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-keep-cursor-visible-on-refresh/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/expand-2/cursor"
# cursor down
edit-trace t, 0x6a/j
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-keep-cursor-visible-on-refresh/down-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/down-0/cursor"
check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-keep-cursor-visible-on-refresh/down-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/down-1/cursor"
check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-keep-cursor-visible-on-refresh/down-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-keep-cursor-visible-on-refresh/down-2/cursor"
# recreate trace with entirely different lines
clear-trace t
trace-text t, "l", "line 4"
trace-text t, "l", "line 5"
trace-text t, "l", "line 6"
mark-lines-dirty t
clear-screen screen
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# trace collapses, and cursor bumps up
check-screen-row screen, 0/y, "... ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-1/cursor"
check-screen-row screen, 2/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-2/cursor"
}
fn test-trace-collapse-at-top {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-lower t
trace-text t, "l", "line 1.1"
trace-higher t
trace-text t, "l", "line 2"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-at-top/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-at-top/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse-at-top/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-at-top/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-at-top/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse-at-top/expand-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-at-top/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-at-top/expand-1/cursor"
check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-at-top/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-at-top/expand-2/cursor"
# collapse
edit-trace t, 8/backspace
# hack: we need to render here to make this test pass; we're mixing state management with rendering
clear-screen screen
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-ints-equal y, 1, "F - test-trace-collapse-at-top/post-0/y"
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-at-top/post-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-at-top/post-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse-at-top/post-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-at-top/post-1/cursor"
}
fn test-trace-collapse {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-text t, "l", "line 2"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse/expand-0/cursor"
check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-collapse/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse/expand-1/cursor"
# cursor down
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# collapse
edit-trace t, 8/backspace
clear-screen screen
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-ints-equal y, 1, "F - test-trace-collapse/post-0/y"
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse/post-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse/post-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse/post-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse/post-1/cursor"
}
fn test-trace-collapse-skips-invisible-lines {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-lower t
trace-text t, "l", "line 1.1"
trace-higher t
trace-text t, "l", "line 2"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-skips-invisible-lines/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-skips-invisible-lines/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# two visible lines with an invisible line in between
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-skips-invisible-lines/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse-skips-invisible-lines/expand-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-skips-invisible-lines/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/expand-1/cursor"
check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-skips-invisible-lines/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-skips-invisible-lines/expand-2/cursor"
# cursor down to second visible line
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# collapse
edit-trace t, 8/backspace
clear-screen screen
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-ints-equal y, 1, "F - test-trace-collapse-skips-invisible-lines/post-0/y"
var cursor-y/eax: (addr int) <- get t, cursor-y
check-ints-equal *cursor-y, 0, "F - test-trace-collapse-skips-invisible-lines/post-0/cursor-y"
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-skips-invisible-lines/post-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-skips-invisible-lines/post-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/post-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/post-1/cursor"
}
fn test-trace-collapse-two-levels {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-lower t
trace-text t, "l", "line 1.1"
trace-higher t
trace-text t, "l", "line 2"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-two-levels/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-two-levels/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse-two-levels/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-two-levels/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# two visible lines with an invisible line in between
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-two-levels/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse-two-levels/expand-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-two-levels/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-two-levels/expand-1/cursor"
check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-two-levels/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-two-levels/expand-2/cursor"
# cursor down to ellipses
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# two visible lines with an invisible line in between
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-two-levels/expand2-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-collapse-two-levels/expand2-0/cursor"
check-screen-row screen, 1/y, "1 line 1.1 ", "F - test-trace-collapse-two-levels/expand2-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "|||||||||| ", "F - test-trace-collapse-two-levels/expand2-1/cursor"
check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-two-levels/expand2-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-two-levels/expand2-2/cursor"
# cursor down to second visible line
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# collapse
edit-trace t, 8/backspace
clear-screen screen
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-ints-equal y, 1, "F - test-trace-collapse-two-levels/post-0/y"
var cursor-y/eax: (addr int) <- get t, cursor-y
check-ints-equal *cursor-y, 0, "F - test-trace-collapse-two-levels/post-0/cursor-y"
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-two-levels/post-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-two-levels/post-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse-two-levels/post-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-two-levels/post-1/cursor"
}
fn test-trace-collapse-nested-level {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-lower t
trace-text t, "l", "line 1.1"
trace-higher t
trace-text t, "l", "line 2"
trace-lower t
trace-text t, "l", "line 2.1"
trace-text t, "l", "line 2.2"
trace-higher t
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 8/height
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-nested-level/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-nested-level/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse-nested-level/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-nested-level/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
# two visible lines with an invisible line in between
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-nested-level/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse-nested-level/expand-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-nested-level/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-nested-level/expand-1/cursor"
check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-nested-level/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-nested-level/expand-2/cursor"
check-screen-row screen, 3/y, "... ", "F - test-trace-collapse-nested-level/expand-3"
check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-trace-collapse-nested-level/expand-3/cursor"
# cursor down to bottom
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
# two visible lines with an invisible line in between
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-nested-level/expand2-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-collapse-nested-level/expand2-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-nested-level/expand2-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-nested-level/expand2-1/cursor"
check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-nested-level/expand2-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-nested-level/expand2-2/cursor"
check-screen-row screen, 3/y, "1 line 2.1 ", "F - test-trace-collapse-nested-level/expand2-3"
check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "|||||||||| ", "F - test-trace-collapse-nested-level/expand2-3/cursor"
check-screen-row screen, 4/y, "1 line 2.2 ", "F - test-trace-collapse-nested-level/expand2-4"
check-background-color-in-screen-row screen, 7/bg=cursor, 4/y, " ", "F - test-trace-collapse-nested-level/expand2-4/cursor"
# collapse
edit-trace t, 8/backspace
clear-screen screen
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
#
check-ints-equal y, 4, "F - test-trace-collapse-nested-level/post-0/y"
var cursor-y/eax: (addr int) <- get t, cursor-y
check-ints-equal *cursor-y, 2, "F - test-trace-collapse-nested-level/post-0/cursor-y"
check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-nested-level/post-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-collapse-nested-level/post-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-nested-level/post-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-nested-level/post-1/cursor"
check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-nested-level/post-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-collapse-nested-level/post-2/cursor"
check-screen-row screen, 3/y, "... ", "F - test-trace-collapse-nested-level/post-3"
check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-trace-collapse-nested-level/post-3/cursor"
}