Skip to content

Commit 92a0eed

Browse files
committed
gptel-transient: Polish gptel--read-with-prefix user experience
* gptel-transient.el (gptel--read-with-prefix-help): Drop variable. (gptel--read-with-prefix): Enable resizing minibuffer (to make cycling the ov meaningful). Drop `make-separator-line' which is buggy. Move the prompt to the last line, which looks better and avoids cursor jumping. Use `window-max-chars-per-line' instead of `window-width' (which is incorrect in terminal). Replace newlines with return symbol. Calculate the multi-line layoyt correctly to use all available space on the last line. Cycle between just two modes: one line and multiple lines (hiding one line does not add much value). Don't show the TAB help if the whole prefix fits into one line. (gptel--infix-add-directive): Use simple prompt. * gptel-rewrite.el (gptel--infix-rewrite-extra): Use simple prompt. Replace RETURN LEFT (U+2C90) with smaller RETURN SYMBOL (U+23CE), which looks more readable (with many typefaces) between two pieces of text.
1 parent a502ca5 commit 92a0eed

File tree

3 files changed

+67
-69
lines changed

3 files changed

+67
-69
lines changed

gptel-rewrite.el

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ By default, gptel uses the directive associated with the `rewrite'
547547
:display-nil "(None)"
548548
:key "d"
549549
:format " %k %d %v"
550-
:prompt (concat "Instructions " gptel--read-with-prefix-help)
550+
:prompt "Instructions: "
551551
:reader (lambda (prompt _ history)
552552
(let* ((rewrite-directive
553553
(car-safe (gptel--parse-directive gptel--rewrite-directive

gptel-transient.el

Lines changed: 64 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -108,71 +108,70 @@ Meant to be called when `gptel-menu' is active."
108108
"\n"))
109109
ov))
110110

111-
(defconst gptel--read-with-prefix-help
112-
(concat
113-
(propertize "(" 'face 'default)
114-
(propertize "TAB" 'face 'help-key-binding)
115-
(propertize ": expand, " 'face 'default)
116-
(propertize "M-n" 'face 'help-key-binding)
117-
(propertize "/" 'face 'default)
118-
(propertize "M-p" 'face 'help-key-binding)
119-
(propertize ": next/previous) " 'face 'default))
120-
"Help string ;TODO: ")
121-
122111
(defun gptel--read-with-prefix (prefix)
123112
"Show string PREFIX in the minibuffer after the minibuffer prompt.
124113
125114
PREFIX is shown in an overlay. Repeated calls to this function
126-
will toggle its visibility state."
115+
will toggle its visibility state (one line, maximum, none)."
127116
(unless (minibufferp)
128117
(user-error "This command is intended to be used in the minibuffer."))
129-
(let* ((update
130-
(lambda (ov s)
131-
(overlay-put
132-
ov 'after-string
133-
(and s (concat (propertize (concat "\n" s "\n") 'face 'shadow)
134-
(make-separator-line))))))
135-
(max-width (- (window-width) (minibuffer-prompt-end)))
136-
(max (or max-mini-window-height 0.4))
137-
(max-height (- (or (and (natnump max) max)
138-
(floor (* max (frame-height))))
139-
5)))
140-
(when (and prefix (not (string-empty-p prefix)) (> max-height 1))
141-
(unless visual-line-mode (visual-line-mode 1))
142-
(goto-char (minibuffer-prompt-end))
143-
(pcase-let ((`(,prop . ,ov)
144-
(get-char-property-and-overlay
145-
(point-min) 'gptel)))
146-
(unless ov
147-
(setq ov (make-overlay
148-
(point-min) (minibuffer-prompt-end) nil t)))
149-
(pcase prop
150-
('partial
151-
(if (> (length prefix) max-width)
152-
(progn
153-
(overlay-put ov 'gptel 'prefix)
154-
(let ((disp-size
155-
(cl-loop for char across prefix
156-
for idx upfrom 0
157-
with n = 0 with max-length = (* max-height max-width)
158-
if (eq char ?\n) do (cl-incf n)
159-
if (> n max-height) return idx
160-
if (> idx max-length)
161-
return idx
162-
finally return nil)))
163-
(funcall update ov
164-
(if disp-size
165-
(truncate-string-to-width
166-
prefix disp-size nil nil 'ellipsis)
167-
prefix))))
168-
(overlay-put ov 'gptel 'hide)
169-
(funcall update ov nil)))
170-
('prefix (overlay-put ov 'gptel 'hide)
171-
(funcall update ov nil))
172-
(_ (overlay-put ov 'gptel 'partial)
173-
(funcall update ov (truncate-string-to-width
174-
prefix max-width nil nil
175-
'ellipsis))))))))
118+
(set (make-local-variable 'resize-mini-windows) t)
119+
(cl-flet ((update (ov s)
120+
(overlay-put ov 'before-string
121+
(and s
122+
(propertize (concat
123+
s (propertize "\n"
124+
'face '(shadow default)))
125+
'rear-nonsticky t 'front-nonsticky t))))
126+
(tab-help (s)
127+
(concat
128+
(propertize "(" 'face 'default)
129+
(propertize "TAB" 'face 'help-key-binding)
130+
(propertize (concat ": " s ") ") 'face 'default))))
131+
(let* ((max (or max-mini-window-height 0.4))
132+
(max-width (window-max-chars-per-line))
133+
(max (or max-mini-window-height 0.4))
134+
(max-height (- (or (and (natnump max) max)
135+
(floor (* max (frame-height))))
136+
5))
137+
(prefix (and prefix (string-replace "\n" "" prefix))))
138+
(when (and prefix (not (string-empty-p prefix)) (> max-height 1))
139+
(pcase-let ((`(,prop . ,ov)
140+
(get-char-property-and-overlay
141+
(point-min) 'gptel)))
142+
(unless ov
143+
(setq ov (make-overlay
144+
(point-min) (minibuffer-prompt-end) nil t)))
145+
(pcase prop
146+
('partial
147+
(overlay-put ov 'gptel 'one-line)
148+
(update ov
149+
(with-temp-buffer
150+
(insert (tab-help "shrink"))
151+
(let ((b (point)))
152+
(insert prefix)
153+
(set-text-properties b (point-max) '(face (shadow default))))
154+
(goto-char (point-min))
155+
(let ((fill-column max-width))
156+
(fill-region (point) (point-max)))
157+
(goto-line (min max-height (line-number-at-pos (point-max))))
158+
(concat (buffer-substring 1 (point))
159+
(propertize (truncate-string-to-width
160+
(buffer-substring (point) (point-max))
161+
(1- max-width) nil
162+
nil
163+
t) 'face '(shadow default))))))
164+
(_ (update ov
165+
(if (>= (length prefix) max-width)
166+
(let ((he (tab-help "expand")))
167+
(overlay-put ov 'gptel 'partial)
168+
(concat he (propertize (truncate-string-to-width
169+
prefix
170+
(- max-width (length he))
171+
nil nil t)
172+
'face '(shadow default))))
173+
(overlay-put ov 'gptel 'hide)
174+
(propertize prefix 'face '(shadow default)))))))))))
176175

177176
(defun gptel--transient-read-number (prompt initial-input history)
178177
"Read a numeric value from the minibuffer.
@@ -202,7 +201,7 @@ Handle formatting for system messages when the active
202201
(propertize "]" 'face 'transient-heading))
203202
(if message
204203
(gptel--describe-directive
205-
message (max (- (window-width) 12) 14) "")
204+
message (max (- (window-width) 12) 14) "")
206205
"[No system message set]")))
207206

208207
(defun gptel--tools-init-value (obj)
@@ -353,7 +352,7 @@ which see."
353352
(len (length val)))
354353
(ptv (concat
355354
"\"" (string-replace
356-
"\n" ""
355+
"\n" ""
357356
(truncate-string-to-width
358357
val 20 nil nil t))
359358
"\"" (when (> len 20)
@@ -706,7 +705,7 @@ If EXTERNAL is non-nil, include external sources of directives."
706705
(concat "(" (gptel--describe-directive prompt (- width 30)) ")")
707706
'face 'shadow))
708707
`(lambda () (interactive)
709-
(message "%s: %s" ,msg ,(gptel--describe-directive prompt 100 ""))
708+
(message "%s: %s" ,msg ,(gptel--describe-directive prompt 100 ""))
710709
(gptel--set-with-scope ',sym ',prompt gptel--set-buffer-locally))
711710
:transient 'transient--do-return)
712711
into prompt-suffixes
@@ -1076,19 +1075,18 @@ Or in an extended conversation:
10761075
:display-nil 'none
10771076
:overlay nil
10781077
:argument ":"
1079-
:prompt (concat "Add instructions for next request only "
1080-
gptel--read-with-prefix-help)
1078+
:prompt "Instruction for next request: "
10811079
:reader (lambda (prompt initial history)
10821080
(let* ((directive
10831081
(car-safe (gptel--parse-directive gptel--system-message 'raw)))
10841082
(cycle-prefix (lambda () (interactive)
1085-
(gptel--read-with-prefix directive)))
1083+
(gptel--read-with-prefix directive)))
10861084
(minibuffer-local-map
10871085
(make-composed-keymap
10881086
(define-keymap "TAB" cycle-prefix "<tab>" cycle-prefix)
10891087
minibuffer-local-map))
10901088
(extra (minibuffer-with-setup-hook cycle-prefix
1091-
(read-string prompt (or initial " ") history))))
1089+
(read-string prompt nil history (or initial)))))
10921090
(unless (string-empty-p extra) extra)))
10931091
:format " %k %d %v"
10941092
:key "d"

gptel.el

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,7 +1760,7 @@ buffer."
17601760
(format "#<lambda %#x>" (sxhash s)))
17611761
((byte-code-function-p s)
17621762
(format "#<compiled %#x>" (sxhash s)))
1763-
((stringp s) (string-replace "\n" "" s))
1763+
((stringp s) (string-replace "\n" "" s))
17641764
(t (prin1-to-string s)))))
17651765
(inhibit-read-only t)
17661766
(info (gptel-fsm-info fsm))
@@ -2827,7 +2827,7 @@ NAME and ARG-VALUES are the name and arguments for the call."
28272827
(cond ((stringp arg)
28282828
(prin1-to-string
28292829
(replace-regexp-in-string
2830-
"\n" "" (truncate-string-to-width
2830+
"\n" "" (truncate-string-to-width
28312831
arg (floor (window-width) 4)
28322832
nil nil t))))
28332833
(t (prin1-to-string arg))))

0 commit comments

Comments
 (0)