As the documentation says that RET will comint-send-input
anywhere in a shell mode. The issue is that if you by mistake hit enter on any line and you are not at a prompt it will execute the whole random text until the next prompt. How can I prevent this from happening? It would be nice if hitting Enter
anywhere out of the prompt will send you to a new prompt at the bottom.
Asked
Active
Viewed 389 times
2
-
Can you make use of C-h v comint-input-filter-functions ? – aartist Sep 07 '18 at 19:21
-
@aartis Idk, do you have ideas? – Yuki Sep 08 '18 at 08:44
-
Nope, I happen to see that it could be useful in this context. – aartist Sep 11 '18 at 14:28
2 Answers
5
Something like this?
(defun my-comint-send-input-maybe ()
"Only `comint-send-input' when point is after the latest prompt.
Otherwise move to the end of the buffer."
(interactive)
(let ((proc (get-buffer-process (current-buffer))))
(if (and proc (>= (point) (marker-position (process-mark proc))))
(comint-send-input)
(goto-char (point-max)))))
(with-eval-after-load "comint"
(define-key shell-mode-map [remap comint-send-input] 'my-comint-send-input-maybe))
You could replace (goto-char (point-max))
with (comint-copy-old-input)
to insert but not send the old input at the new prompt; but that's still liable to cause problems when the inserted input looks like output.
However, also note the comments and link in C-hf comint-send-input
regarding comint-get-old-input
-- this can be used to implement custom logic for establishing what the "old input" should be when comint-send-input
is invoked with point before the process mark.

phils
- 71,335
- 11
- 153
- 198
-
This works like a charm. Thank you. I did make a replacement to `comint-get-old-input`, it is much more convenient. If by mistake I hit `RET` I can easily delete it, if I want execute some previous input I am able to do that. – Yuki Sep 07 '18 at 09:37
-
I was just thinking, how can I test if current line is output of some command or an old prompt. Because even better could be this logic `(if (command output) (goto-char (point-max)) (comint-send-input))`. – Yuki Sep 07 '18 at 09:51
-
I guess the key thing is that you'd need to differentiate the point between the end of a command and the beginning of the resulting output (if any). I don't know offhand whether that's currently supported. If not, you'd need to track those positions yourself. – phils Sep 07 '18 at 10:43
-
`M-x apropos RET comint-last RET` would be of interest, but you'd need to read the code to confirm how those variables are used and when they're reliably available. – phils Sep 07 '18 at 10:51
-
1
Bulletproof:
(defun comint-send-input-or-insert-previous-input ()
"Call `comint-send-input' if point is after the process output marker.
Otherwise, move point to the process mark and try to insert a previous input
from `comint-input-ring' (if any) returned by `comint-previous-input-string'
and affected by the current value of `comint-input-ring-index'.
Implementation is synthesized from and inspired by the `comint-after-pmark-p',
`comint-goto-process-mark', and `comint-copy-old-input' functions."
(interactive)
(let ((process (get-buffer-process (current-buffer))))
(if (not process)
(user-error "Current buffer has no process")
(let ((pmark (process-mark process)))
(if (<= (marker-position pmark) (point))
(comint-send-input)
(goto-char pmark)
(when (and (eolp) comint-input-ring)
(let ((input (comint-previous-input-string 0)))
(when (char-or-string-p input)
(insert input)))))))))

Alexander Shukaev
- 16,674
- 8
- 70
- 85