v0.14.0: Mouse improvements - selection tracking and link clicking
This commit is contained in:
@@ -19,7 +19,8 @@
|
||||
(backend-write b (format nil "~C[2J~C[H" #\Esc #\Esc))))
|
||||
|
||||
(defgeneric draw-text (backend x y string fg bg &key
|
||||
bold italic underline reverse dim blink))
|
||||
bold italic underline reverse dim blink
|
||||
&allow-other-keys))
|
||||
|
||||
(defgeneric draw-border (backend x y width height
|
||||
&key style fg bg title title-align))
|
||||
|
||||
@@ -127,7 +127,8 @@ See =docs/plans/2026-05-11-rendering-pipeline.md= for full implementation plan.
|
||||
#:make-framebuffer #:fb-framebuffer
|
||||
#:framebuffer-width #:framebuffer-height
|
||||
#:diff-framebuffers #:flush-framebuffer
|
||||
#:with-scissor))
|
||||
#:with-scissor
|
||||
#:extract-text #:fb-cell-link-url))
|
||||
#+END_SRC
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/rendering/framebuffer.lisp
|
||||
|
||||
@@ -102,3 +102,35 @@ module adds:
|
||||
(setf cl-tty.mouse::*selection* (make-selection :text "hello"))
|
||||
(is (equal "hello" (get-selection))))
|
||||
#+END_SRC
|
||||
|
||||
** Selection tracking
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../tests/mouse-tests.lisp
|
||||
(def-test start-selection-initializes-state ()
|
||||
(start-selection 5 10)
|
||||
(is-true (selection-active-p))
|
||||
(is (equal '(5 . 10) cl-tty.mouse::*selection-start*))
|
||||
(is (equal '(5 . 10) cl-tty.mouse::*selection-end*))
|
||||
(setf cl-tty.mouse::*selection-active* nil
|
||||
cl-tty.mouse::*selection-start* nil
|
||||
cl-tty.mouse::*selection-end* nil))
|
||||
|
||||
(def-test update-selection-moves-end ()
|
||||
(start-selection 0 0)
|
||||
(update-selection 3 7)
|
||||
(is (equal '(3 . 7) cl-tty.mouse::*selection-end*))
|
||||
(setf cl-tty.mouse::*selection-active* nil
|
||||
cl-tty.mouse::*selection-start* nil
|
||||
cl-tty.mouse::*selection-end* nil))
|
||||
|
||||
(def-test finalize-selection-extracts-text ()
|
||||
(let* ((fb-be (cl-tty.rendering:make-framebuffer-backend))
|
||||
(fb (cl-tty.rendering:fb-framebuffer fb-be)))
|
||||
(cl-tty.backend:draw-text fb-be 0 0 "hello" nil nil)
|
||||
(cl-tty.backend:draw-text fb-be 0 1 "world" nil nil)
|
||||
(start-selection 0 0)
|
||||
(update-selection 4 1)
|
||||
(let ((text (finalize-selection fb)))
|
||||
(is (equal "hello
|
||||
world" text)))))
|
||||
#+END_SRC
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
#:make-framebuffer #:fb-framebuffer
|
||||
#:framebuffer-width #:framebuffer-height
|
||||
#:diff-framebuffers #:flush-framebuffer
|
||||
#:with-scissor))
|
||||
#:with-scissor
|
||||
#:extract-text #:fb-cell-link-url))
|
||||
|
||||
(in-package :cl-tty.rendering)
|
||||
|
||||
|
||||
@@ -64,3 +64,64 @@
|
||||
(draw-text fb 0 0 "X" :red nil)
|
||||
(let ((changed (flush-framebuffer (make-framebuffer 80 24) (fb-framebuffer fb) real-be)))
|
||||
(is (>= changed 1)))))
|
||||
|
||||
;; ── Frame inspection ──────────────────────────────────────────
|
||||
|
||||
(test fb-cell-link-url-returns-nil-for-blank-cell
|
||||
(let ((fb (make-framebuffer 10 10)))
|
||||
(is (null (fb-cell-link-url fb 5 5)))))
|
||||
|
||||
(test fb-cell-link-url-finds-link-url
|
||||
(let ((fb (make-framebuffer-backend)))
|
||||
(draw-text fb 0 0 "click" nil nil :link-url "https://example.com")
|
||||
(is (equal "https://example.com" (fb-cell-link-url (fb-framebuffer fb) 0 0)))
|
||||
(is (null (fb-cell-link-url (fb-framebuffer fb) 5 5)))))
|
||||
|
||||
(test fb-cell-link-url-out-of-bounds-returns-nil
|
||||
(let ((fb (make-framebuffer 5 5)))
|
||||
(is (null (fb-cell-link-url fb 10 10)))))
|
||||
|
||||
(test extract-text-single-row
|
||||
(let ((fb (make-framebuffer-backend)))
|
||||
(draw-text fb 0 0 "hello" nil nil)
|
||||
(let ((cells (fb-framebuffer fb)))
|
||||
(is (equal "hello" (extract-text cells 0 0 4 0))))))
|
||||
|
||||
(test extract-text-multi-row
|
||||
(let ((fb (make-framebuffer-backend)))
|
||||
(draw-text fb 0 0 "abc" nil nil)
|
||||
(draw-text fb 0 1 "def" nil nil)
|
||||
(let* ((cells (fb-framebuffer fb))
|
||||
(text (extract-text cells 0 0 2 1)))
|
||||
(is (equal "abc
|
||||
def" text)))))
|
||||
|
||||
;; --- Frame inspection -------------------------------------------------
|
||||
(test fb-cell-link-url-returns-nil-for-blank-cell
|
||||
(let ((fb (make-framebuffer 10 10)))
|
||||
(is (null (fb-cell-link-url fb 5 5)))))
|
||||
|
||||
(test fb-cell-link-url-finds-link-url
|
||||
(let ((fb (make-framebuffer-backend)))
|
||||
(draw-text fb 0 0 "click" nil nil :link-url "https://example.com")
|
||||
(is (equal "https://example.com" (fb-cell-link-url (fb-framebuffer fb) 0 0)))
|
||||
(is (null (fb-cell-link-url (fb-framebuffer fb) 5 5)))))
|
||||
|
||||
(test fb-cell-link-url-out-of-bounds-returns-nil
|
||||
(let ((fb (make-framebuffer 5 5)))
|
||||
(is (null (fb-cell-link-url fb 10 10)))))
|
||||
|
||||
(test extract-text-single-row
|
||||
(let ((fb (make-framebuffer-backend)))
|
||||
(draw-text fb 0 0 "hello" nil nil)
|
||||
(let ((cells (fb-framebuffer fb)))
|
||||
(is (equal "hello" (extract-text cells 0 0 4 0))))))
|
||||
|
||||
(test extract-text-multi-row
|
||||
(let ((fb (make-framebuffer-backend)))
|
||||
(draw-text fb 0 0 "abc" nil nil)
|
||||
(draw-text fb 0 1 "def" nil nil)
|
||||
(let* ((cells (fb-framebuffer fb))
|
||||
(text (extract-text cells 0 0 2 1)))
|
||||
(is (equal "abc
|
||||
def" text)))))
|
||||
|
||||
@@ -15,3 +15,32 @@
|
||||
(def-test selection-set-and-get ()
|
||||
(setf cl-tty.mouse::*selection* (make-selection :text "hello"))
|
||||
(is (equal "hello" (get-selection))))
|
||||
|
||||
;; --- Selection tracking -------------------------------------------------
|
||||
(def-test start-selection-initializes-state ()
|
||||
(start-selection 5 10)
|
||||
(is-true (selection-active-p))
|
||||
(is (equal '(5 . 10) cl-tty.mouse::*selection-start*))
|
||||
(is (equal '(5 . 10) cl-tty.mouse::*selection-end*))
|
||||
(setf cl-tty.mouse::*selection-active* nil
|
||||
cl-tty.mouse::*selection-start* nil
|
||||
cl-tty.mouse::*selection-end* nil))
|
||||
|
||||
(def-test update-selection-moves-end ()
|
||||
(start-selection 0 0)
|
||||
(update-selection 3 7)
|
||||
(is (equal '(3 . 7) cl-tty.mouse::*selection-end*))
|
||||
(setf cl-tty.mouse::*selection-active* nil
|
||||
cl-tty.mouse::*selection-start* nil
|
||||
cl-tty.mouse::*selection-end* nil))
|
||||
|
||||
(def-test finalize-selection-extracts-text ()
|
||||
(let* ((fb-be (cl-tty.rendering:make-framebuffer-backend))
|
||||
(fb (cl-tty.rendering:fb-framebuffer fb-be)))
|
||||
(cl-tty.backend:draw-text fb-be 0 0 "hello" nil nil)
|
||||
(cl-tty.backend:draw-text fb-be 0 1 "world" nil nil)
|
||||
(start-selection 0 0)
|
||||
(update-selection 4 1)
|
||||
(let ((text (finalize-selection fb)))
|
||||
(is (equal "hello
|
||||
world" text)))))
|
||||
|
||||
Reference in New Issue
Block a user