ChatGPT解决这个技术问题 Extra ChatGPT

How to run multiple shells on Emacs

I am using Emacs 23.3.1 on windows 7. I know that I can run shell from emacs using M-x shell. I would like to have multiple shell windows in the same time, but typing M-x shell a second time just opens me the same shell window.

Is there a way to have different shell windows?


M
Matt Curtis

C-u M-x shell will do it.

It will prompt for a name for the new shell, just hit return for the default (which will be something like *shell*<2>.

Also works with eshell.

Another trick, if you use eshell: just as M-x eshell takes you back to *eshell* (rather than starting a new eshell), if you use a numeric prefix argument it will take you to that eshell buffer. For instance, C-3M-xeshell will take you to *eshell*<3>. Sadly if you use shell (rather than eshell), this trick doesn't seem to work (in my Emacs 24.0.50.1 at least.)


OK, this one works. C-u M-x shell asks me the name of the new shell. Thanks!
No problems S4M. I added a tip for eshell; as you asked about shell I don't know if you'll find it useful, but eshell users with the same question might find it useful.
Thanks, Matt. What does C-u mean/do here?
C-u runs the command universal-argument. It's a way of injecting an argument into the next command. You can read more about it with C-h k C-u (C-h k runs describe-key, very handy!)
I use this all the time. I have a pet peeve, though which is that I end up with a line in the Ibuffer that says *shell*<2> 3038 Shell (shell<1> run) ~/ and when you are trying to quit, emacs refers to the shell as shell<1> even though the name is shell<2>. Sure, I can edit the suggested default name parameter, but I don't do that.
G
Giann

You can rename the buffer of your shell with M-x rename-buffer. Then you will be able to launch a second shell.


I prefer to go with Matt Curtis's solution. Running a shell under a new name seems to me easier than renaming the current one and then run a new one.
V
Victor Deryagin

Look at MultiTerm, it makes managing multiple terminals in Emacs much easier.


Note that shell mode and term mode are two completely different things.
S
S4M

After more than four years, I see that some people are still looking at this issue sometimes, so I will publish a quick function I wrote to load a shell and ask for its name. That way you can name a shell "sort-files" if it is dedicated to sorting files and another one "hive" if it's dedicated to run hive queries. I use that everyday now (on emacs 24):

(defun create-shell ()
    "creates a shell with a given name"
    (interactive);; "Prompt\n shell name:")
    (let ((shell-name (read-string "shell name: " nil)))
    (shell (concat "*" shell-name "*"))))

T
Trey Jackson

It might also be useful to use a screen-like interface to your shells. I've written my own, but there are others out there, like EmacsScreen.


b
bjsdaiyu

This will autogenerate a new shell instance in whatever buffer you happen to be using; bind it to M-S or somethings like that and instant joy:

(defun new-shell ()
  (interactive)

  (let (
        (currentbuf (get-buffer-window (current-buffer)))
        (newbuf     (generate-new-buffer-name "*shell*"))
       )

   (generate-new-buffer newbuf)
   (set-window-dedicated-p currentbuf nil)
   (set-window-buffer currentbuf newbuf)
   (shell newbuf)
  )
)

Many thanks to phils for recommending a rewrite using let, even though the result is even more awful parentheses...:\


You need to let-bind variables if they're intended for local use. As it is you now have global values for currentbuf and newbuf.
how does the new-shell function compare with my create-shell function?
@S4M it's mainly an issue of preference, I'm lazy and want my shell immediately, in the currently active window and without having to type a buffername up front.
@phils thanks for the tip, i'm not at all familiar with lisp so will rework it using local assignment.:-)
hmm, I think you can take my function and add a default name that would be something like shell_n, where n would be the n-th shell open, while C-u create-shell would prompt a name for the shell.
D
DenverCoder9

This will open a new shell each time you invoke the function and rename it automatically if needed. The added plus is if you are editing files remotely (dired/tramp...), this will open a shell on the remote host and rename it automatically with the remote hostname:

(defun ggshell (&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-nameA (format "*shell:%s*" host))
       (new-buffer-nameB (generate-new-buffer-name new-buffer-nameA))
       (currentbuf (get-buffer-window (current-buffer)))
       )
  (generate-new-buffer new-buffer-nameB)
  (set-window-dedicated-p currentbuf nil)
  (set-window-buffer currentbuf new-buffer-nameB)
  (shell new-buffer-nameB)
  ))