> [Question] Why not simply shifting between character mode and line mode? Is there a bigger reason to really shift to a real Shell buffer?
‘M-x shell’ to invoke a shell. The shell is an external program, and shell mode inherits the ability to interact with the program and its basic behaviors from ComintMode. If you want to use a shell written entirely in elisp use
‘M-x eshell’, see [[Eshell?]]. To invoke another shell, use
‘C-u M-x shell’.
(add-hook 'comint-output-filter-functions 'comint-strip-ctrl-m)
However, cygwin-builds of bash since 2001-06-06 seem to confuse Emacs. There is an elegant solution, however: Tell Emacs that the bash process is returning DOS end-of-line bytes:
(add-to-list 'process-coding-system-alist '("bash" . (undecided-dos . undecided-unix)))
This way, bash doesn’t get ^M from Emacs, but Emacs removes ^M it gets from bash. You no longer need to add
‘comint-strip-ctrl-m’ to the filter functions.
For some instructions on how to setup the cygwin shell with emacs, see http://www.khngai.com/emacs/cygwin.php
You need cygwin-mount.el
Here is a a way to define new shell buffers using the usual
‘shell’ command. The point is that I don’t want to bother of the buffer’s name. So one press f7 to go to a shell buffer (if needed the command will start a new process), further uses of f7 in this buffer will cycle through the existing shell buffers. If you want a new shell buffer press C-u f7. – Matthias
(global-set-key [f7] 'alt-shell-dwim)
(defun alt-shell-dwim (arg) "Run an inferior shell like `shell'. If an inferior shell as its I/O through the current buffer, then pop the next buffer in `buffer-list' whose name is generated from the string \"*shell*\". When called with an argument, start a new inferior shell whose I/O will go to a buffer named after the string \"*shell*\" using `generate-new-buffer-name'." (interactive "P") (let* ((shell-buffer-list (let (blist) (dolist (buff (buffer-list) blist) (when (string-match "^\\*shell\\*" (buffer-name buff)) (setq blist (cons buff blist)))))) (name (if arg (generate-new-buffer-name "*shell*") (car shell-buffer-list)))) (shell name)))
The command above didn’t work for me, so I modified the original shell-dwim code.
First, you’ll want to customize same-window-regexps to include
"\\*shell.*\\*\\(\\|<[0-9]+>\\)" to make sure that when you cycle through the shell buffers, they all stay in the same window. Then, put shell-dwim and the helper my-filter in your .emacs and bind to a key (f7, as suggested above, is one good option).
(defun my-filter (condp lst) (delq nil (mapcar (lambda (x) (and (funcall condp x) x)) lst))) (defun shell-dwim (&optional create) "Start or switch to an inferior shell process, in a smart way. If a buffer with a running shell process exists, simply switch to that buffer. If a shell buffer exists, but the shell process is not running, restart the shell. If already in an active shell buffer, switch to the next one, if any. With prefix argument CREATE always start a new shell." (interactive "P") (let ((next-shell-buffer) (buffer) (shell-buf-list (identity ;;used to be reverse (sort (my-filter (lambda (x) (string-match "^\\*shell\\*" (buffer-name x))) (buffer-list)) '(lambda (a b) (string< (buffer-name a) (buffer-name b))))))) (setq next-shell-buffer (if (string-match "^\\*shell\\*" (buffer-name buffer)) (get-buffer (cadr (member (buffer-name) (mapcar (function buffer-name) (append shell-buf-list shell-buf-list))))) nil)) (setq buffer (if create (generate-new-buffer-name "*shell*") next-shell-buffer)) (shell buffer)))
Another take on multiple shells, one shell per tramp host. If you already have a shell for that user@host then raise it.
(defun my-shell (&optional buffer) (interactive) (let* ((tramp-path (when (tramp-tramp-file-p default-directory) (tramp-dissect-file-name default-directory))) (host (tramp-file-name-real-host tramp-path)) (user (if (tramp-file-name-user tramp-path) (format "%s@" (tramp-file-name-user tramp-path)) "")) (new-buffer-name (format "*shell:%s%s*" user host))) (shell (if host new-buffer-name buffer))))
Take a look at AnsiColor.
By default, tap-completion in shell-mode can complete commands and files, but there is no support for context-sensitive completion. The following modules extend tap-completion:
You might find it difficult to background a process that’s started, once you’re in shell mode.
If you hit
‘C-z’, you end up backgrounding Emacs!
To solve this, just execute
M-x local-set-key RET C-z self-insert-command
‘C-z’ actually transmits to the shell.
And if you want to background Emacs, just go to a different buffer.
‘C-q C-z’ doesn’t work? - No, but C-c C-z should.
Inside the a
*shell* buffer I often SSH to other machines. It’s the nature of one’s work. Anyway, you lose completion. You can partially get it back by running `M-x cd /$HOSTNAME:$PWD’ where $HOSTNAME is the host you’ve SSH’d to, and $PWD is your current working directory on the machine. This requires TrampMode. Unfortunately, completiong for root-relative paths doesn’t work, since the root for Tramp doesn’t translate to the root of a file system –
(not (equal "/host:/" "/")). Really handy otherwise.
A. I feel your pain. Doesn’t work, would be nice if it did: SubprocessCompletion
Any new shell created when the current buffer is visiting a remote file/dir will automatically ssh to the remote default-directory for that file, however if you try this a second time in any other remote file/dir, it hangs. The way around it is to just create a local shell and ssh, but it would be nice to not have to do this.
The built-in mechanism for keeping Emacs apprised of the shell’s current directory is not very reliable, and can be thrown off by any command which it doesn’t recognize as a directory-changing command (i.e., shell aliases).
I can’t get dir tracking to work correctly. Either the regex isn’t catching the prompt, or the prompt doesn’t get read at the correct time. Either way, it doesn’t work. Can someone point me to what I’m doing wrong?
My bash shell prompt is defined this way in .bashrc:
export PS1='\h:\w\n> '
…which looks like this in practice:
I use this dir tracking code in my .emacs file:
(defun my-current-directory (text) (if (string-match "\\w*:\\([^\n]+\\)\n> " text) (setq cur-dir (substring text (match-beginning 1) (match-end 1))) (cd cur-dir) (message "dir tracking %s" cur-dir)))
(defun my-shell-setup () "Track current directory" (add-hook 'comint-output-filter-functions 'my-current-directory nil t))
(setq shell-mode-hook 'my-shell-setup)
Restore some sanity to your PS1 by putting the full working directory in the mode-line: ModeLineDirtrack
You can use Icicles completion in Shell mode. Whenever there are multiple completion candidates, Icicles completion is used (if Icicle minor mode is on). This means you can cycle to choose a candidate, complete using one or more substrings or regexps (progressive completion), and so on. See Icicles - Completion in Comint Modes.
You can also use `
C-`’ to quickly find, reuse, and edit a previous shell input, matching it in several ways. See Icicles - Reuse Shell Inputs.
This is what I use to clear the shell output.
(defun clear-shell () (interactive) (let ((old-max comint-buffer-maximum-size)) (setq comint-buffer-maximum-size 0) (comint-truncate-buffer) (setq comint-buffer-maximum-size old-max)))
Shouldn’t this work?
(defun clear-shell () (interactive) (let ((comint-buffer-maximum-size 0)) (comint-truncate-buffer)))
Below is a function which allows you to switch between Term mode and Shell mode, in the same buffer.
Notice that it works properly only if started from an term buffer (started with
‘ansi-term’) which properly initializes bash for working in a terminal.
(require 'shell) (require 'term)
(defun term-switch-to-shell-mode () (interactive) (if (equal major-mode 'term-mode) (progn (shell-mode) (set-process-filter (get-buffer-process (current-buffer)) 'comint-output-filter ) (local-set-key (kbd "C-j") 'term-switch-to-shell-mode) (compilation-shell-minor-mode 1) (comint-send-input) ) (progn (compilation-shell-minor-mode -1) (font-lock-mode -1) (set-process-filter (get-buffer-process (current-buffer)) 'term-emulate-terminal) (term-mode) (term-char-mode) (term-send-raw-string (kbd "C-l")) )))
I bound it to C-j to easily switch between the two modes:
(define-key term-raw-map (kbd "C-j") 'term-switch-to-shell-mode)
[Question] Why not simply shifting between character mode and line mode? Is there a bigger reason to really shift to a real Shell buffer?