Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions pi-coding-agent-input.el
Original file line number Diff line number Diff line change
Expand Up @@ -310,12 +310,16 @@ The /compact command is handled locally; other slash commands sent to pi."
(interactive)
(let* ((text (string-trim (buffer-string)))
(chat-buf (pi-coding-agent--get-chat-buffer))
(transitioning (and chat-buf
(chat-live-p (buffer-live-p chat-buf))
(transitioning (and chat-live-p
(pi-coding-agent--session-transition-active-p
chat-buf)))
(busy (and chat-buf (pi-coding-agent--session-busy-p chat-buf))))
(busy (and chat-live-p
(pi-coding-agent--session-busy-p chat-buf))))
(cond
((string-empty-p text) nil)
((not chat-live-p)
(message "Pi: No chat session available"))
(transitioning
(message "Pi: Cannot send while session is switching"))
((and busy (pi-coding-agent--builtin-command-text-p text))
Expand All @@ -331,11 +335,11 @@ The /compact command is handled locally; other slash commands sent to pi."

(defun pi-coding-agent-abort ()
"Abort the current pi operation.
Works while streaming or compacting."
Works while sending, streaming, or compacting."
(interactive)
(when-let* ((chat-buf (pi-coding-agent--get-chat-buffer)))
(let ((status (buffer-local-value 'pi-coding-agent--status chat-buf)))
(when (memq status '(streaming compacting))
(when (memq status '(sending streaming compacting))
(when (eq status 'streaming)
(with-current-buffer chat-buf
(pi-coding-agent--set-aborted t)))
Expand Down Expand Up @@ -388,12 +392,16 @@ Includes both built-in commands and commands from pi's `get_commands' RPC."
(when (and (eq (char-after (point-min)) ?/)
(> (point) (point-min)))
(let* ((start (1+ (point-min)))
(end (point))
(end (save-excursion
(goto-char start)
(skip-chars-forward "^ \t\n")
(point)))
(builtin-names (mapcar #'car pi-coding-agent--builtin-commands))
(rpc-names (mapcar (lambda (cmd) (plist-get cmd :name))
pi-coding-agent--commands))
(commands (delete-dups (append builtin-names rpc-names))))
(list start end commands :exclusive 'no))))
(when (<= start (point) end)
(list start end commands :exclusive 'no)))))

;;;; Editor Features: File Reference (@)

Expand Down Expand Up @@ -479,15 +487,9 @@ Triggers when @ is typed, provides completion of project files."
(point)))))
(let* ((start (1+ at-pos))
(end (point))
(prefix (buffer-substring-no-properties start end))
(files (pi-coding-agent--get-project-files))
(candidates (if (string-empty-p prefix)
files
(cl-remove-if-not
(lambda (f) (string-match-p (regexp-quote prefix) f))
files))))
(when candidates
(list start end candidates
(files (pi-coding-agent--get-project-files)))
(when files
(list start end files
:exclusive 'no
:annotation-function (lambda (_) " (file)")
:company-kind (lambda (_) 'file))))))
Expand Down
17 changes: 15 additions & 2 deletions pi-coding-agent-menu.el
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,14 @@ handled, even when the response failed."
(pi-coding-agent--finish-session-transition
generation)))))))))))

(defun pi-coding-agent--discard-reload-process (proc)
"Detach and terminate temporary reload process PROC."
(when (processp proc)
(pi-coding-agent--unregister-display-handler proc)
(when (process-live-p proc)
(delete-process proc))
(pi-coding-agent--cleanup-process-stderr-buffer proc)))

;;;###autoload
(defun pi-coding-agent-reload ()
"Reload the current session by restarting the pi process.
Expand All @@ -675,6 +683,7 @@ buffer from session history."
(message "Pi: No session to reload"))
((not session-file)
(message "Pi: No session file available - cannot reload"))
((not (pi-coding-agent--session-transition-ready-p chat-buf "reload")))
(t
(message "Pi: Reloading...")
(with-current-buffer chat-buf
Expand All @@ -699,8 +708,12 @@ buffer from session history."
new-proc
(list :type "switch_session" :sessionPath session-path)
(lambda (response)
(when (pi-coding-agent--session-transition-current-p
chat-buf new-proc generation)
(when (or (pi-coding-agent--session-transition-current-p
chat-buf new-proc generation)
(progn
(pi-coding-agent--discard-reload-process
new-proc)
nil))
(let* ((data (plist-get response :data))
(cancelled (plist-get data :cancelled)))
(if (and (eq (plist-get response :success) t)
Expand Down
3 changes: 3 additions & 0 deletions pi-coding-agent-render.el
Original file line number Diff line number Diff line change
Expand Up @@ -1223,6 +1223,9 @@ Updates buffer-local state and renders display updates."
(plist-get message :content))))
(_
;; Assistant message - show header if needed, reset markers
(setq pi-coding-agent--line-parse-state 'line-start
pi-coding-agent--in-code-block nil
pi-coding-agent--streaming-table-candidate nil)
(unless pi-coding-agent--assistant-header-shown
(pi-coding-agent--append-to-chat
(concat "\n" (pi-coding-agent--make-separator "Assistant") "\n"))
Expand Down
126 changes: 95 additions & 31 deletions pi-coding-agent-table.el
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ visible after streaming while hidden."
(setq pi-coding-agent--table-decoration-pending nil)
(setq pi-coding-agent--last-table-display-width width)
(let ((gc-cons-threshold (max gc-cons-threshold (* 8 1024 1024))))
;; Known macOS NS limitation: shrinking a scrolled chat frame can move
;; the top visible line after overlay rewrapping. Reproduce with
;; `pi-coding-agent-gui-test-table-resize-refreshes-hot-tail-only'.
(pi-coding-agent--with-scroll-preservation
(save-excursion
(pi-coding-agent--refresh-hot-tail-tables width)))))))
Expand Down Expand Up @@ -300,6 +303,8 @@ When `pi-coding-agent-prettify-tables' is non-nil, emits Unicode
box-drawing verticals instead of markdown pipes."
(let* ((num-cols (length col-widths))
(padded (append cells (make-list (max 0 (- num-cols (length cells))) "")))
(aligns (append aligns
(make-list (max 0 (- num-cols (length aligns))) nil)))
(wrapped-cells
(cl-mapcar (lambda (cell column-width)
(markdown-table-wrap-cell (or cell "") column-width))
Expand Down Expand Up @@ -345,30 +350,56 @@ box-drawing verticals instead of markdown pipes."
"Render the separator line for COL-WIDTHS and ALIGNS.
When `pi-coding-agent-prettify-tables' is non-nil, emits a box-drawing
rule (├─┼─┤) directly; otherwise emits standard markdown syntax."
(if pi-coding-agent-prettify-tables
(concat "├─" (mapconcat (lambda (w) (make-string (max 1 w) ?─))
col-widths "─┼─")
"─┤")
(let ((parts
(cl-mapcar
(lambda (column-width align)
(let ((dashes (make-string (max 1 column-width) ?-)))
(pcase align
('left
(if (>= column-width 2)
(concat ":" (substring dashes 1))
":"))
('right
(if (>= column-width 2)
(concat (substring dashes 1) ":")
":"))
('center
(if (>= column-width 3)
(concat ":" (substring dashes 2) ":")
(if (>= column-width 2) "::" ":")))
(_ dashes))))
col-widths aligns)))
(concat "| " (mapconcat #'identity parts " | ") " |"))))
(let* ((num-cols (length col-widths))
(aligns (append aligns
(make-list (max 0 (- num-cols (length aligns))) nil))))
(if pi-coding-agent-prettify-tables
(concat "├─" (mapconcat (lambda (w) (make-string w ?─))
col-widths "─┼─")
"─┤")
(let ((parts
(cl-mapcar
(lambda (column-width align)
(if (zerop column-width)
""
(let ((dashes (make-string column-width ?-)))
(pcase align
('left
(if (>= column-width 2)
(concat ":" (substring dashes 1))
":"))
('right
(if (>= column-width 2)
(concat (substring dashes 1) ":")
":"))
('center
(if (>= column-width 3)
(concat ":" (substring dashes 2) ":")
(if (>= column-width 2) "::" ":")))
(_ dashes)))))
col-widths aligns)))
(concat "| " (mapconcat #'identity parts " | ") " |")))))

(defun pi-coding-agent--table-full-grid-p ()
"Return non-nil when tables should render a full web-style cell grid.
Requires both `pi-coding-agent-prettify-tables' and
`pi-coding-agent-table-full-grid' to be enabled."
(and pi-coding-agent-prettify-tables
pi-coding-agent-table-full-grid))

(defun pi-coding-agent--render-table-grid-rule (col-widths position)
"Render a horizontal box-drawing rule for COL-WIDTHS.
POSITION is one of `top', `middle', or `bottom', selecting the corner
and junction characters (┌┬┐ / ├┼┤ / └┴┘). Each column contributes
`column-width' + 2 horizontal bars to match the one-space cell padding
used by `pi-coding-agent--render-table-row-lines'."
(let ((left (pcase position ('top "┌") ('bottom "└") (_ "├")))
(mid (pcase position ('top "┬") ('bottom "┴") (_ "┼")))
(right (pcase position ('top "┐") ('bottom "┘") (_ "┤"))))
(concat left
(mapconcat (lambda (w) (make-string (+ w 2) ?─))
col-widths mid)
right)))

(defun pi-coding-agent--table-alignments (separator-line)
"Return column alignment symbols parsed from SEPARATOR-LINE."
Expand Down Expand Up @@ -443,20 +474,53 @@ Plain tables (no prefix) take a fast path that skips prefix splitting."
(mapcar (lambda (row)
(pi-coding-agent--render-table-row-lines
row col-widths aligns))
display-rows)))
display-rows))
;; Full web-style grid: weave border rules into the existing
;; per-raw-line groups so the group↔raw-line 1:1 invariant that
;; `pi-coding-agent--decorate-table' relies on is preserved.
;; The top border joins the header group, an inter-row rule
;; prefixes every data group after the first, and the bottom
;; border joins the last group (or the separator group when the
;; table has no data rows).
(full-grid (pi-coding-agent--table-full-grid-p))
(has-data (consp row-groups))
(header-group
(if full-grid
(cons (pi-coding-agent--render-table-grid-rule col-widths 'top)
header-lines)
header-lines))
(sep-group
(if (and full-grid (not has-data))
(list separator-line
(pi-coding-agent--render-table-grid-rule col-widths 'bottom))
(list separator-line)))
(data-groups
(if (and full-grid has-data)
(let ((mid-rule (pi-coding-agent--render-table-grid-rule
col-widths 'middle))
(bottom (pi-coding-agent--render-table-grid-rule
col-widths 'bottom))
(last-index (1- (length row-groups))))
(cl-loop for group in row-groups
for i from 0
collect (append (when (> i 0) (list mid-rule))
group
(when (= i last-index) (list bottom)))))
row-groups)))
(if no-prefix
(append (list header-lines)
(list (list separator-line))
row-groups)
(append (list header-group)
(list sep-group)
data-groups)
(append
(list (mapcar (lambda (line) (concat (car prefixes) line))
header-lines))
(list (list (concat (nth 1 prefixes) separator-line)))
header-group))
(list (mapcar (lambda (line) (concat (nth 1 prefixes) line))
sep-group))
(cl-mapcar (lambda (prefix row-lines)
(mapcar (lambda (line) (concat prefix line))
row-lines))
(nthcdr 2 prefixes)
row-groups)))))))
data-groups)))))))

;;;; Line Mapping

Expand Down
11 changes: 11 additions & 0 deletions pi-coding-agent-ui.el
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,17 @@ still operate on the raw table source."
:type 'boolean
:group 'pi-coding-agent)

(defcustom pi-coding-agent-table-full-grid t
"Whether prettified tables draw a full cell grid (web-style borders).
When non-nil, and `pi-coding-agent-prettify-tables' is also enabled,
tables render a top border, a horizontal rule between every row, and a
bottom border using Unicode box-drawing characters, so each cell is fully
enclosed like an HTML table. When nil, tables keep only the column
verticals and a single header rule. Has no effect when
`pi-coding-agent-prettify-tables' is nil (raw markdown pipes are used)."
:type 'boolean
:group 'pi-coding-agent)

;;;; Faces

(defface pi-coding-agent-timestamp
Expand Down
Loading
Loading