diff --git a/org/channel-tui-view.org b/org/channel-tui-view.org index 3a521a7..6a37bf4 100644 --- a/org/channel-tui-view.org +++ b/org/channel-tui-view.org @@ -17,7 +17,7 @@ right-aligned lowercase hint at h-2. 4. (redraw fb w h): wraps view-status/chat/input in begin-sync/end-sync, dispatches per dirty flags, fills global :bg first. -5. (char-width ch): returns terminal column width of character CH. +5. ~cl-tty.box:char-width~ for terminal column width. ASCII < 128 = 1. CJK, fullwidth, emoji = 2. Combining marks = 0. Tab = 8. Used by word-wrap for accurate line counting (v0.7.0). 6. (sidebar-visible-p w): returns T if sidebar should show given width W @@ -82,22 +82,9 @@ Returns a list of strings, one per line." (- h 4 panel-rows -1))) -;; v0.7.2: search-highlight — wrap matching text in **bold** for markdown -(defun search-highlight (content query) - "Wrap occurrences of QUERY in CONTENT with **bold** markers." - (let ((lower-content (string-downcase content)) - (lower-query (string-downcase query)) - (result "") (pos 0)) - (when (and query (> (length query) 0)) - (loop - (let ((found (search lower-query lower-content :start2 pos))) - (unless found (return)) - (setf result (concatenate 'string result - (subseq content pos found) - "**" (subseq content found (+ found (length query))) "**")) - (setf pos (+ found (length query))))) - (setf result (concatenate 'string result (subseq content pos))) - (if (string= result "") content result)))) +;; Build simple tab-like blocks +#+BEGIN_SRC lisp :tangle /home/user/.local/share/passepartout/lisp/channel-tui-view.lisp +(in-package :passepartout.channel-tui) (defun view-chat (fb w h) (let* ((w (or (and (numberp w) (> w 0) w) 80)) @@ -122,7 +109,7 @@ Returns a list of strings, one per line." (dotimes (i total) (let* ((msg (aref msgs i)) (role (getf msg :role)) (content (getf msg :content)) - (cs (if is-search (search-highlight content (st :search-query)) content)) + (cs (if is-search (cl-tty.markdown:search-highlight content (st :search-query)) content)) (pairs nil) (think-bg (theme-color :thinking-bg)) (sym-bdr (theme-color :symbolic-border)) @@ -380,33 +367,7 @@ Returns a list of strings, one per line." #+END_SRC * Implementation — v0.7.0 additions -#+BEGIN_SRC lisp :tangle /home/user/.local/share/passepartout/lisp/channel-tui-view.lisp -(in-package :passepartout) - -(defun char-width (ch) - "Returns the terminal column width of character CH. -ASCII < 128 = 1. CJK, fullwidth, emoji = 2. Combining marks = 0. Tab = 8." - (let ((code (char-code ch))) - (cond - ((= code 9) 8) - ((< code 32) 0) - ((<= code 127) 1) - ((<= #x4E00 code #x9FFF) 2) - ((<= #x3400 code #x4DBF) 2) - ((<= #x3040 code #x309F) 2) - ((<= #x30A0 code #x30FF) 2) - ((<= #xAC00 code #xD7AF) 2) - ((<= #xFF01 code #xFF60) 2) - ((<= #xFFE0 code #xFFE6) 2) - ((<= #x1F300 code #x1F9FF) 2) - ((<= #x2600 code #x27BF) 2) - ((<= #x0300 code #x036F) 0) - ((<= #x20D0 code #x20FF) 0) - ((<= #xFE00 code #xFE0F) 0) - (t 1)))) -#+END_SRC - -* v0.7.1 — Markdown Rendering + * v0.7.1 — Markdown Rendering ~render-styled~ accepts a ~(text . plist)~ segment list from the span parser and emits ~draw-text~ calls. The ~w~ parameter is ignored (layout @@ -585,24 +546,6 @@ dead code. (def-suite tui-view-suite :description "TUI view rendering helpers") (in-suite tui-view-suite) -(test test-char-width-ascii - "Contract 5: ASCII characters (< 128) have width 1." - (is (= 1 (passepartout::char-width #\a))) - (is (= 1 (passepartout::char-width #\Space))) - (is (= 1 (passepartout::char-width #\@)))) - -(test test-char-width-tab - "Contract 5: tab character has width 8." - (is (= 8 (passepartout::char-width #\Tab)))) - -(test test-char-width-cjk - "Contract 5: CJK characters have width 2." - (is (= 2 (passepartout::char-width #\日)))) - -(test test-char-width-null - "Contract 5: null has width 0." - (is (= 0 (passepartout::char-width #\Nul)))) - (test test-markdown-bold "Contract 7: parse-markdown-spans detects **bold**." (let ((segments (passepartout::parse-markdown-spans "hello **world**!")))