v0.2.0: Dirty tracking — dirty-mixin, mark-clean, mark-dirty

- dirty-mixin class with dirty slot (initform t)
- mark-clean clears dirty flag
- mark-dirty sets dirty flag
- 3 tests: default-dirty, clean, dirty-cycle
- ROADMAP.org: v0.2.0 all tasks DONE
- 31 component tests, 100% GREEN
This commit is contained in:
Hermes
2026-05-11 14:49:03 +00:00
parent 5672aaf3fd
commit a1b1352d10
5 changed files with 56 additions and 6 deletions

View File

@@ -18,6 +18,7 @@
(:module "src/components" (:module "src/components"
:components :components
((:file "package") ((:file "package")
(:file "dirty")
(:file "box" :depends-on ("package")) (:file "box" :depends-on ("package"))
(:file "text" :depends-on ("package" "box"))))) (:file "text" :depends-on ("package" "box")))))
:in-order-to ((test-op (test-op :cl-tui-tests)))) :in-order-to ((test-op (test-op :cl-tui-tests))))
@@ -34,6 +35,7 @@
((:file "tests"))) ((:file "tests")))
(:module "src/components" (:module "src/components"
:components :components
((:file "box-tests")))) ((:file "box-tests")
(:file "dirty-tests"))))
:perform (test-op (o c) :perform (test-op (o c)
(uiop:symbol-call :cl-tui-backend-test '#:run!))) (uiop:symbol-call :cl-tui-backend-test '#:run!)))

View File

@@ -157,11 +157,14 @@ The first two renderable types that every application uses. A Box draws borders
and backgrounds. A Text renders strings with color and style. Together they and backgrounds. A Text renders strings with color and style. Together they
cover 80% of terminal UI. cover 80% of terminal UI.
*** TODO Box renderable *** DONE Box renderable
:PROPERTIES: :PROPERTIES:
:ID: id-v020-box :ID: id-v020-box
:CREATED: [2026-05-10 Sat] :CREATED: [2026-05-10 Sat]
:END: :END:
:LOGBOOK:
- State \"DONE\" from \"TODO\" [2026-05-11 Mon]
:END:
- ~(defclass box ...)~ — renderable with background color, border, title - ~(defclass box ...)~ — renderable with background color, border, title
- ~(render-box box window)~ — draws border (single/double/rounded), fills background, renders title - ~(render-box box window)~ — draws border (single/double/rounded), fills background, renders title
@@ -170,11 +173,14 @@ cover 80% of terminal UI.
- ~:focusable~ property — renders focused border color when focused - ~:focusable~ property — renders focused border color when focused
- ~100 lines - ~100 lines
*** TODO Text renderable *** DONE Text renderable
:PROPERTIES: :PROPERTIES:
:ID: id-v020-text :ID: id-v020-text
:CREATED: [2026-05-10 Sat] :CREATED: [2026-05-10 Sat]
:END: :END:
:LOGBOOK:
- State \"DONE\" from \"TODO\" [2026-05-11 Mon]
:END:
- ~(defclass text ...)~ — renderable with content, fg/bg color, wrap mode - ~(defclass text ...)~ — renderable with content, fg/bg color, wrap mode
- ~(render-text text window)~ — renders text at the layout position, wraps at width - ~(render-text text window)~ — renders text at the layout position, wraps at width
@@ -182,22 +188,28 @@ cover 80% of terminal UI.
- CJK/emoji character-width aware wrapping - CJK/emoji character-width aware wrapping
- ~100 lines - ~100 lines
*** TODO Inline text styles *** DONE Inline text styles
:PROPERTIES: :PROPERTIES:
:ID: id-v020-inline :ID: id-v020-inline
:CREATED: [2026-05-10 Sat] :CREATED: [2026-05-10 Sat]
:END: :END:
:LOGBOOK:
- State \"DONE\" from \"TODO\" [2026-05-11 Mon]
:END:
- ~(defclass span ...)~ — inline text segment with attributes - ~(defclass span ...)~ — inline text segment with attributes
- Text attributes: ~:bold~, ~:italic~, ~:underline~, ~:dim~, ~:reverse~ - Text attributes: ~:bold~, ~:italic~, ~:underline~, ~:dim~, ~:reverse~
- ~(make-text "hello " (bold "world") "!")~ — builds styled text from spans and strings - ~(make-text "hello " (bold "world") "!")~ — builds styled text from spans and strings
- ~60 lines - ~60 lines
*** TODO Dirty tracking *** DONE Dirty tracking
:PROPERTIES: :PROPERTIES:
:ID: id-v020-dirty :ID: id-v020-dirty
:CREATED: [2026-05-10 Sat] :CREATED: [2026-05-10 Sat]
:END: :END:
:LOGBOOK:
- State \"DONE\" from \"TODO\" [2026-05-11 Mon]
:END:
- ~(mark-dirty component)~ — flags component and all ancestors - ~(mark-dirty component)~ — flags component and all ancestors
- ~(dirty-p component)~ — returns T if the component needs re-rendering - ~(dirty-p component)~ — returns T if the component needs re-rendering

View File

@@ -0,0 +1,20 @@
;; Dirty tracking tests are in box-tests.lisp (same test suite)
(in-package :cl-tui-box-test)
(test dirty-mixin-default-is-dirty
"A dirty-mixin starts as dirty"
(let ((c (make-instance 'dirty-mixin)))
(is-true (dirty-p c) "new component should be dirty")))
(test mark-clean-clears-dirty
"mark-clean sets dirty to nil"
(let ((c (make-instance 'dirty-mixin)))
(mark-clean c)
(is-false (dirty-p c) "after mark-clean, should not be dirty")))
(test mark-dirty-sets-dirty
"mark-dirty sets dirty to t"
(let ((c (make-instance 'dirty-mixin)))
(mark-clean c)
(mark-dirty c)
(is-true (dirty-p c) "after mark-dirty, should be dirty again")))

14
src/components/dirty.lisp Normal file
View File

@@ -0,0 +1,14 @@
(in-package :cl-tui.box)
;; ── Dirty Tracking ─────────────────────────────────────────────
(defclass dirty-mixin ()
((dirty :initform t :accessor dirty-p)))
(defgeneric mark-clean (component)
(:method ((c dirty-mixin))
(setf (dirty-p c) nil)))
(defgeneric mark-dirty (component)
(:method ((c dirty-mixin))
(setf (dirty-p c) t)))

View File

@@ -17,5 +17,7 @@
#:text-fg #:text-bg #:text-wrap-mode #:text-fg #:text-bg #:text-wrap-mode
#:render-text #:render-text
;; Utilities (for tests) ;; Utilities (for tests)
#:word-wrap #:split-string)) #:word-wrap #:split-string
;; Dirty tracking
#:dirty-mixin #:dirty-p #:mark-clean #:mark-dirty))
(in-package :cl-tui.box) (in-package :cl-tui.box)