Fix markdown bold/italic rendering and sidebar border gap

ober

9c534a0d7e975301d53d1336a8d69076c14c8608

diff --git a/lib/jcode/ui/tui-markdown.sls b/lib/jcode/ui/tui-markdown.sls
index 284ba3e..f74ed44 100644
--- a/lib/jcode/ui/tui-markdown.sls
+++ b/lib/jcode/ui/tui-markdown.sls
@@ -108,21 +108,33 @@
   (def (md-inline-segments text)
        "Parse inline markdown (bold, code, italic, links) → list of segments."
        (let ([len (string-length text)])
-         (let loop ([i 0] [acc '()])
+         (let loop ([i 0] [plain-from 0] [acc '()])
            (cond
-             [(>= i len) (reverse (flush-plain acc i i text))]
+             [(>= i len)
+              (reverse
+                (if (< plain-from len)
+                    (cons
+                      (seg (substring text plain-from len) 'assistant-text)
+                      acc)
+                    acc))]
              [(and (< (+ i 1) len)
                    (char=? (string-ref text i) #\*)
                    (char=? (string-ref text (+ i 1)) #\*))
               (let ([end (find-marker text (+ i 2) "**")])
                 (if end
-                    (let ([acc (flush-plain acc i (- (length acc)) text)])
+                    (let ([acc (if (< plain-from i)
+                                   (cons
+                                     (seg (substring text plain-from i)
+                                          'assistant-text)
+                                     acc)
+                                   acc)])
                       (loop
                         (+ end 2)
+                        (+ end 2)
                         (cons
                           (seg (substring text (+ i 2) end) 'bold)
                           acc)))
-                    (loop (+ i 1) acc)))]
+                    (loop (+ i 1) plain-from acc)))]
              [(and (char=? (string-ref text i) #\*)
                    (or (zero? i)
                        (not (char=? (string-ref text (- i 1)) #\*)))
@@ -130,23 +142,35 @@
                    (not (char=? (string-ref text (+ i 1)) #\*)))
               (let ([end (find-single-char text (+ i 1) #\*)])
                 (if end
-                    (let ([acc (flush-plain acc i (- (length acc)) text)])
+                    (let ([acc (if (< plain-from i)
+                                   (cons
+                                     (seg (substring text plain-from i)
+                                          'assistant-text)
+                                     acc)
+                                   acc)])
                       (loop
                         (+ end 1)
+                        (+ end 1)
                         (cons
                           (seg (substring text (+ i 1) end) 'italic)
                           acc)))
-                    (loop (+ i 1) acc)))]
+                    (loop (+ i 1) plain-from acc)))]
              [(char=? (string-ref text i) #\`)
               (let ([end (find-single-char text (+ i 1) #\`)])
                 (if end
-                    (let ([acc (flush-plain acc i (- (length acc)) text)])
+                    (let ([acc (if (< plain-from i)
+                                   (cons
+                                     (seg (substring text plain-from i)
+                                          'assistant-text)
+                                     acc)
+                                   acc)])
                       (loop
                         (+ end 1)
+                        (+ end 1)
                         (cons
                           (seg (substring text (+ i 1) end) 'code-inline)
                           acc)))
-                    (loop (+ i 1) acc)))]
+                    (loop (+ i 1) plain-from acc)))]
              [(char=? (string-ref text i) #\[)
               (let ([close (find-single-char text (+ i 1) #\])])
                 (if (and close
@@ -154,31 +178,23 @@
                          (char=? (string-ref text (+ close 1)) #\())
                     (let ([pclose (find-single-char text (+ close 2) #\))])
                       (if pclose
-                          (let ([acc (flush-plain
-                                       acc
-                                       i
-                                       (- (length acc))
-                                       text)]
+                          (let ([acc (if (< plain-from i)
+                                         (cons
+                                           (seg (substring
+                                                  text
+                                                  plain-from
+                                                  i)
+                                                'assistant-text)
+                                           acc)
+                                         acc)]
                                 [link-text (substring text (+ i 1) close)])
                             (loop
                               (+ pclose 1)
+                              (+ pclose 1)
                               (cons (seg link-text 'link) acc)))
-                          (loop (+ i 1) acc)))
-                    (loop (+ i 1) acc)))]
-             [#t (loop (+ i 1) acc)]))))
-  (def (flush-plain acc pos marker text)
-       "Flush accumulated plain text since last formatted segment."
-       (let ([start (plain-start acc pos text)])
-         (if (and (< start pos) (<= pos (string-length text)))
-             (cons (seg (substring text start pos) 'assistant-text) acc)
-             acc)))
-  (def (plain-start acc pos text)
-       "Calculate where the current plain-text run started."
-       (let loop ([i (- pos 1)])
-         (cond
-           [(< i 0) 0]
-           [(char=? (string-ref text i) #\`) i]
-           [#t (loop (- i 1))])))
+                          (loop (+ i 1) plain-from acc)))
+                    (loop (+ i 1) plain-from acc)))]
+             [#t (loop (+ i 1) plain-from acc)]))))
   (def (find-marker text start marker)
        (let ([len (string-length text)]
              [m0 (string-ref marker 0)]
diff --git a/lib/jcode/ui/tui-sidebar.sls b/lib/jcode/ui/tui-sidebar.sls
index eb232b2..9bf3bee 100644
--- a/lib/jcode/ui/tui-sidebar.sls
+++ b/lib/jcode/ui/tui-sidebar.sls
@@ -32,7 +32,7 @@
              [dfg (face-fg-attr 'sidebar-divider)])
          (let rloop ([row y])
            (when (< row (+ y height))
-             (let cloop ([col x])
+             (let cloop ([col (max 0 (- x 1))])
                (when (< col (+ x width))
                  (tb-change-cell! col row (char->integer #\space) bg bg)
                  (cloop (+ col 1))))
diff --git a/src/jcode/ui/tui-markdown.ss b/src/jcode/ui/tui-markdown.ss
index 05d7953..7275e4c 100644
--- a/src/jcode/ui/tui-markdown.ss
+++ b/src/jcode/ui/tui-markdown.ss
@@ -106,9 +106,12 @@
 (def (md-inline-segments text)
   "Parse inline markdown (bold, code, italic, links) → list of segments."
   (let ((len (string-length text)))
-    (let loop ((i 0) (acc '()))
+    (let loop ((i 0) (plain-from 0) (acc '()))
       (cond
-        ((>= i len) (reverse (flush-plain acc i i text)))
+        ((>= i len)
+         (reverse (if (< plain-from len)
+                    (cons (seg (substring text plain-from len) 'assistant-text) acc)
+                    acc)))
 
         ;; **bold**
         ((and (< (+ i 1) len)
@@ -116,10 +119,12 @@
               (char=? (string-ref text (+ i 1)) #\*))
          (let ((end (find-marker text (+ i 2) "**")))
            (if end
-             (let ((acc (flush-plain acc i (- (length acc)) text)))
-               (loop (+ end 2)
+             (let ((acc (if (< plain-from i)
+                          (cons (seg (substring text plain-from i) 'assistant-text) acc)
+                          acc)))
+               (loop (+ end 2) (+ end 2)
                      (cons (seg (substring text (+ i 2) end) 'bold) acc)))
-             (loop (+ i 1) acc))))
+             (loop (+ i 1) plain-from acc))))
 
         ;; *italic*
         ((and (char=? (string-ref text i) #\*)
@@ -128,19 +133,23 @@
               (not (char=? (string-ref text (+ i 1)) #\*)))
          (let ((end (find-single-char text (+ i 1) #\*)))
            (if end
-             (let ((acc (flush-plain acc i (- (length acc)) text)))
-               (loop (+ end 1)
+             (let ((acc (if (< plain-from i)
+                          (cons (seg (substring text plain-from i) 'assistant-text) acc)
+                          acc)))
+               (loop (+ end 1) (+ end 1)
                      (cons (seg (substring text (+ i 1) end) 'italic) acc)))
-             (loop (+ i 1) acc))))
+             (loop (+ i 1) plain-from acc))))
 
         ;; `inline code`
         ((char=? (string-ref text i) #\`)
          (let ((end (find-single-char text (+ i 1) #\`)))
            (if end
-             (let ((acc (flush-plain acc i (- (length acc)) text)))
-               (loop (+ end 1)
+             (let ((acc (if (< plain-from i)
+                          (cons (seg (substring text plain-from i) 'assistant-text) acc)
+                          acc)))
+               (loop (+ end 1) (+ end 1)
                      (cons (seg (substring text (+ i 1) end) 'code-inline) acc)))
-             (loop (+ i 1) acc))))
+             (loop (+ i 1) plain-from acc))))
 
         ;; [link](url) — show link text with link face
         ((char=? (string-ref text i) #\[)
@@ -149,33 +158,20 @@
                     (char=? (string-ref text (+ close 1)) #\())
              (let ((pclose (find-single-char text (+ close 2) #\))))
                (if pclose
-                 (let ((acc (flush-plain acc i (- (length acc)) text))
+                 (let ((acc (if (< plain-from i)
+                              (cons (seg (substring text plain-from i) 'assistant-text) acc)
+                              acc))
                        (link-text (substring text (+ i 1) close)))
-                   (loop (+ pclose 1)
+                   (loop (+ pclose 1) (+ pclose 1)
                          (cons (seg link-text 'link) acc)))
-                 (loop (+ i 1) acc)))
-             (loop (+ i 1) acc))))
+                 (loop (+ i 1) plain-from acc)))
+             (loop (+ i 1) plain-from acc))))
 
-        (#t (loop (+ i 1) acc))))))
+        (#t (loop (+ i 1) plain-from acc))))))
 
 ;; ---- Helpers ----
 
-(def (flush-plain acc pos marker text)
-  "Flush accumulated plain text since last formatted segment."
-  ;; Find where plain text started
-  (let ((start (plain-start acc pos text)))
-    (if (and (< start pos) (<= pos (string-length text)))
-      (cons (seg (substring text start pos) 'assistant-text) acc)
-      acc)))
-
-(def (plain-start acc pos text)
-  "Calculate where the current plain-text run started."
-  ;; Walk backwards through what we've consumed
-  (let loop ((i (- pos 1)))
-    (cond
-      ((< i 0) 0)
-      ((char=? (string-ref text i) #\`) i)  ;; stop heuristic
-      (#t (loop (- i 1))))))
+
 
 (def (find-marker text start marker)
   (let ((len (string-length text))
diff --git a/src/jcode/ui/tui-sidebar.ss b/src/jcode/ui/tui-sidebar.ss
index bda9115..b703139 100644
--- a/src/jcode/ui/tui-sidebar.ss
+++ b/src/jcode/ui/tui-sidebar.ss
@@ -36,10 +36,10 @@
         (tfg (face-fg-attr 'sidebar-title))
         (tbg (face-bg-attr 'sidebar-title))
         (dfg (face-fg-attr 'sidebar-divider)))
-    ;; Clear sidebar area
+    ;; Clear sidebar area (include 1 col left of divider to fill gap)
     (let rloop ((row y))
       (when (< row (+ y height))
-        (let cloop ((col x))
+        (let cloop ((col (max 0 (- x 1))))
           (when (< col (+ x width))
             (tb-change-cell! col row (char->integer #\space) bg bg)
             (cloop (+ col 1))))