9

This is admittedly a superficial question.

Although ansi-term starts out behaving correctly when I first open it, it seems to degrade into an 'editable' mode after a few commands, e.g., when I do C-a (start of line) followed by C-k (kill line), it wipes out the whole prompt.

For my aesthetic sanity, is there any way to make the prompts and previous output uneditable (for shell)? (Updated to exclude ansi-term given the meaningful differences.)

I'm using zsh in Emacs 24.4; OS is LXDE (Ubuntu 14.04) via Virtual Box.

(Ideally I'd still be able to move my cursor around...)

iceman
  • 1,078
  • 1
  • 9
  • 19
  • 1
    Are you on an "odd" OS by any chance? Usually in shell-mode C-a jumps to the start of the commandline, *after* the prompt, and a second C-a is required to jump to the very start. On Windows and Solaris (in a former life) I usually found that C-a jumped to the very start, wheras on MacOS, Linux etc. it works as expected for me. – Mark Oct 31 '14 at 02:05
  • @Mark A: I've updated the original post to include a few more details, including my current set-up. – iceman Oct 31 '14 at 02:25
  • The described behaviour of ansi-term sounds like you've switched to line mode by either a weird default or `C-c C-j`. Try finding out that default or switch to char mode with `C-c C-k`. – wasamasa Oct 31 '14 at 09:39
  • 1
    Since `shell-mode` / `term-mode` respectively do / do not derive from `comint-mode`, you're asking two very different questions at the same time here. Mind splitting this into two separate questions? – purple_arrows Oct 31 '14 at 12:50

3 Answers3

16

comint-derived modes (like shell, ielm, ...) support filter functions, the following snippet makes the output and prompt read-only:

(setq comint-prompt-read-only t)

(defun my-comint-preoutput-turn-buffer-read-only (text)
  (propertize text 'read-only t))

(add-hook 'comint-preoutput-filter-functions 'my-comint-preoutput-turn-buffer-read-only)

As for ansi-term (which is not derived from comint), it features two modes of operation, char mode which stays as truthful to the bindings of the shell and the software running in it as possible and line mode which allows you to edit the buffer as you please. You should generally stay in char mode (bound to C-c C-k) and occasionally switch to line mode (bound to C-c C-j) for editing command output.

wasamasa
  • 21,803
  • 1
  • 65
  • 97
  • This was really pretty, but stopped working… :( I have a working solution that takes considerably more code → https://github.com/michalrus/dotfiles/commit/bd2e0ee668b99d88cd9296381176f41d8027c127 – Michal Rus Apr 28 '17 at 23:05
  • Dunno, still works for me on 25.2. – wasamasa Apr 29 '17 at 08:55
  • It does in a sense, that you cannot delete this text, but you can insert new, interleaving with that immutable one. – Michal Rus Apr 29 '17 at 20:19
  • 1
    I see, didn't test that specifically. – wasamasa Apr 30 '17 at 09:06
  • Oops, one more change for anyone looking. I missed some loopholes before. This one works perfectly for me. https://github.com/michalrus/dotfiles/blob/c4421e361400c4184ea90a021254766372a1f301/.emacs.d/init.d/040-terminal.el.symlink#L26-L48 – Michal Rus May 01 '17 at 00:02
2

When mixing term with shell-mode, the variable comint-use-prompt-regexp seems to get set occasionally. This causes behavior a bit like you've described: in shell-mode C-a will go to the beginning of the line, C-k will kill the whole line, including prompt.

A simple fix is to reset comint-use-prompt-regexp with C-: (setq comint-use-prompt-regexp nil), forcing shell mode to use text properties which cursor movement keys are aware of.

There's a description of how this works in the GNU Emacs manual here: https://www.gnu.org/software/emacs/manual/html_node/emacs/Shell-Prompts.html

ataylor
  • 121
  • 2
1

Try customizing the variable comint-prompt-read-only to t.

This will affect shell-mode and others derived from comint-mode, but not term-mode.

purple_arrows
  • 2,373
  • 10
  • 19