Skip to content

Commit 2151240

Browse files
committed
gptel-transient: Polish gptel--read-with-prefix user experience
* gptel-transient.el (gptel--read-with-prefix-help): Turn into a function to show one function. (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 2151240

File tree

3 files changed

+49
-52
lines changed

3 files changed

+49
-52
lines changed

gptel-rewrite.el

+1-1
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

+46-49
Original file line numberDiff line numberDiff line change
@@ -108,38 +108,34 @@ Meant to be called when `gptel-menu' is active."
108108
"\n"))
109109
ov))
110110

111-
(defconst gptel--read-with-prefix-help
111+
(defun gptel--read-with-prefix-help (s)
112+
"Show help for TAB key in `read-with-prefix-help'."
112113
(concat
113114
(propertize "(" 'face 'default)
114115
(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: ")
116+
(propertize (concat ": " s ") ") 'face 'default)))
121117

122118
(defun gptel--read-with-prefix (prefix)
123119
"Show string PREFIX in the minibuffer after the minibuffer prompt.
124120
125121
PREFIX is shown in an overlay. Repeated calls to this function
126-
will toggle its visibility state."
122+
will toggle its visibility state (one line, maximum, none)."
127123
(unless (minibufferp)
128124
(user-error "This command is intended to be used in the minibuffer."))
125+
(set (make-local-variable 'resize-mini-windows) t)
129126
(let* ((update
130127
(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)))
128+
(overlay-put ov 'before-string
129+
(and s (propertize (concat s (propertize "\n"'face '(shadow default)))
130+
'rear-nonsticky t 'front-nonsticky t)))))
131+
(max (or max-mini-window-height 0.4))
132+
(max-width (window-max-chars-per-line))
136133
(max (or max-mini-window-height 0.4))
137134
(max-height (- (or (and (natnump max) max)
138135
(floor (* max (frame-height))))
139-
5)))
136+
5))
137+
(prefix (string-replace "\n" "" prefix)))
140138
(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))
143139
(pcase-let ((`(,prop . ,ov)
144140
(get-char-property-and-overlay
145141
(point-min) 'gptel)))
@@ -148,32 +144,34 @@ will toggle its visibility state."
148144
(point-min) (minibuffer-prompt-end) nil t)))
149145
(pcase prop
150146
('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))))))))
176-
147+
(overlay-put ov 'gptel 'one-line)
148+
(funcall update ov
149+
(with-temp-buffer
150+
(insert (gptel--read-with-prefix-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+
(_ (funcall update ov
165+
(if (>= (length prefix) max-width)
166+
(let ((he (gptel--read-with-prefix-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))))))))))
177175
(defun gptel--transient-read-number (prompt initial-input history)
178176
"Read a numeric value from the minibuffer.
179177
@@ -202,7 +200,7 @@ Handle formatting for system messages when the active
202200
(propertize "]" 'face 'transient-heading))
203201
(if message
204202
(gptel--describe-directive
205-
message (max (- (window-width) 12) 14) "")
203+
message (max (- (window-width) 12) 14) "")
206204
"[No system message set]")))
207205

208206
(defun gptel--tools-init-value (obj)
@@ -353,7 +351,7 @@ which see."
353351
(len (length val)))
354352
(ptv (concat
355353
"\"" (string-replace
356-
"\n" ""
354+
"\n" ""
357355
(truncate-string-to-width
358356
val 20 nil nil t))
359357
"\"" (when (> len 20)
@@ -706,7 +704,7 @@ If EXTERNAL is non-nil, include external sources of directives."
706704
(concat "(" (gptel--describe-directive prompt (- width 30)) ")")
707705
'face 'shadow))
708706
`(lambda () (interactive)
709-
(message "%s: %s" ,msg ,(gptel--describe-directive prompt 100 ""))
707+
(message "%s: %s" ,msg ,(gptel--describe-directive prompt 100 ""))
710708
(gptel--set-with-scope ',sym ',prompt gptel--set-buffer-locally))
711709
:transient 'transient--do-return)
712710
into prompt-suffixes
@@ -1076,19 +1074,18 @@ Or in an extended conversation:
10761074
:display-nil 'none
10771075
:overlay nil
10781076
:argument ":"
1079-
:prompt (concat "Add instructions for next request only "
1080-
gptel--read-with-prefix-help)
1077+
:prompt "Instruction for next request: "
10811078
:reader (lambda (prompt initial history)
10821079
(let* ((directive
10831080
(car-safe (gptel--parse-directive gptel--system-message 'raw)))
10841081
(cycle-prefix (lambda () (interactive)
1085-
(gptel--read-with-prefix directive)))
1082+
(gptel--read-with-prefix directive)))
10861083
(minibuffer-local-map
10871084
(make-composed-keymap
10881085
(define-keymap "TAB" cycle-prefix "<tab>" cycle-prefix)
10891086
minibuffer-local-map))
10901087
(extra (minibuffer-with-setup-hook cycle-prefix
1091-
(read-string prompt (or initial " ") history))))
1088+
(read-string prompt nil history (or initial)))))
10921089
(unless (string-empty-p extra) extra)))
10931090
:format " %k %d %v"
10941091
:key "d"

gptel.el

+2-2
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)