Ответ 1
Попробуйте использовать MultiTerm
, чтобы открыть несколько оболочек.
В Emacs я часто оказываюсь в ситуации, когда мне нужно прыгать назад и вперед между различными исходными файлами на различные терминалы. Тем не менее, я чувствую, что у меня нет хорошего способа сделать это эффективно, и это неуклюже, что вы можете открыть только одну оболочку в Emacs (shell
, eshell
или term
).
Кроме того, мне нужен эффективный способ манипулирования несколькими терминалами и исходными файлами.
Как я могу это достичь?
Попробуйте использовать MultiTerm
, чтобы открыть несколько оболочек.
Вы можете открыть несколько интерактивных оболочек. Попробуйте ввести C-u M-x shell
RET RET.
У вас может быть как можно больше терминалов и оболочек одновременно. Просто используйте M-x rename-buffer
, чтобы изменить имя существующего буфера *term*
или *shell*
, а при следующем M-x term
или M-x shell
будет создан новый буфер. В случае M-x shell
, префиксный аргумент заставит вас запрашивать имя нового буфера оболочки, как указано в offby1.
Несколько лет назад у меня была работа, где мне приходилось регулярно регистрироваться на разных производственных серверах с именем "host01.foo.com", "host02.foo.com" и т.д. Я написал небольшую функцию, подобную этой упростить управление ими:
(defun ssh-to-host (num)
(interactive "P")
(let* ((buffer-name (format "*host%02d*" num))
(buffer (get-buffer buffer-name)))
(if buffer
(switch-to-buffer buffer)
(term "/bin/bash")
(term-send-string
(get-buffer-process (rename-buffer buffer-name))
(format "ssh host%02d.foo.com\r" num)))))
Затем я привязал эту команду (скажем) s-h (супер H), позволяя мне просто набрать M-5 s-h. Если у меня еще не было буфера с именем *host05*
, он запустил новый буфер эмулятора терминала, переименовал его в *host05*
и ssh me в host05.foo.com. Если буфер *host05*
уже существует, он просто переключит меня на него. Очень удобно!
Вы можете использовать Emacs Lisp Screen, который эмулирует экран GNU и обеспечивает удобные привязки клавиш к прыгать в разные ракеты и между ними.
Я использую много методов для включения моей терминальной жизни в Emacs:
elscreen.el
является спасателем жизни, если у вас сложный макет окна, например gdb
или просто переполнены беспорядком, вы просто открываете новый экран. В вашем случае вы можете выделить один экран для терминалов.multi-term.el
упрощает управление терминалами.shell-pop.el
- отличный инструмент для быстрого доступа к терминалу. shell-pop
позволяет назначить ключ для открытия и закрытия определенного окна буфера оболочки, если вы использовали выпадающие терминалы, такие как tilda
вы знаете, насколько это невероятно удобно:Здесь и пример моей конфигурации shell-pop
я использую ключ C-t
для отображения eshell
:
(require 'shell-pop)
(shell-pop-set-internal-mode "eshell") ; Or "ansi-term" if you prefer
(shell-pop-set-window-height 60) ; Give shell buffer 60% of window
;; If you use "ansi-term" and want to use C-t
;; (defvar ansi-term-after-hook nil)
;; (add-hook 'ansi-term-after-hook
;; '(lambda ()
;; (define-key term-raw-map (kbd "C-t") 'shell-pop)))
;; (defadvice ansi-term (after ansi-term-after-advice (org))
;; (run-hooks 'ansi-term-after-hook))
;; (ad-activate 'ansi-term)
(global-set-key (kbd "C-t") 'shell-pop)
Я обычно делаю a M - x server-start
, а затем используйте emacsclient --no-wait
для открытия файлов. Я наложил это на e
с некоторыми украшениями, чтобы он стал немного более удобным.
Я выполняю всю свою работу в одном терминале и просто "бросаю" файлы, которые я хочу редактировать в Emacs, используя e
. Внутри Emacs я жонглирую, используя iswitchb
, и он работает отлично. YMMV.
Я регулярно использовал 10 или около того оболочек на своем рабочем месте. Секрет в том, что вам нужно переименовать дополнительные буферы оболочки. Я сделал это автоматически, хотя в моих .emacs, создавая и называя оболочки логически (у меня были projnameRun и projnameBuild для каждого проекта). Хорошо работает вместе с чем угодно, упрощая переделку правильной оболочки (вы используете конец имени проекта в сочетании с r или b для запуска/сборки).
Вместо того, чтобы иметь несколько окон терминала в emacs, я создаю другой xterm всякий раз, когда мне нужен новый терминал. Это, конечно, терпимо, потому что я использую очень легкий эмулятор терминала (urxvt), который начинается с менее 0,2 с.
Затем я использую мой оконный менеджер для переключения между ними и emacs. Конфигурируемый оконный менеджер будет иметь множество возможностей для настройки для переключения между окнами (чрезвычайно) эффективно. Внутри emacs я использую windmove и ido-mode и привязываю к C-tab функцию, которая переключается на последний буфер (потому что я использую C-x b в этом способе).
Итак, не уверен, насколько он полезен для вас, так как он сильно отличается от вашего шаблона использования, но это то, что работает для меня.
У меня была точно такая же проблема несколько лет назад, и я не нашел ничего, что меня удовлетворило; поэтому я написал свою собственную функцию "переключить оболочку". Он переключается между текущей конфигурацией кадра или окна и буфером системной оболочки. Он также может поместить оболочку в выделенный фрейм и ввести pushd
в текущий каталог буфера.
Это выдержка из моих .emacs:
(defvar --toggle-shell-last-window-conf nil "The last window configuration.")
(defvar --toggle-shell-last-buf nil "The last buffer object in case there no last window configuration.")
(defvar --toggle-shell-last-frame nil "The frame that was selected when opening a shell buffer.")
(defun --toggle-shell-have-conf ()
(window-configuration-p --toggle-shell-last-window-conf))
(defun --toggle-shell-store-last-conf ()
(setq --toggle-shell-last-buf (current-buffer)
--toggle-shell-last-frame (selected-frame)
--toggle-shell-last-window-conf (current-window-configuration)))
(defun --toggle-shell-restore-last-conf ()
(if (--toggle-shell-have-conf)
(progn (raise-frame --toggle-shell-last-frame)
(set-window-configuration --toggle-shell-last-window-conf))
(let ((bufnam (if (bufferp --toggle-shell-last-buf)
(buffer-name --toggle-shell-last-buf) --toggle-shell-last-buf)))
(if bufnam
(if (get-buffer bufnam) (switch-to-buffer bufnam t)
(message "%s: buffer not available" bufnam))))))
(defun --toggle-shell (&optional display inject-cd)
"Toggles between current buffers and a system shell buffer. With prefix-arg
close the shell.
When DISPLAY is 'vertical splits the shell as vertical window; when 'frame uses
a dedicated frame (default: single window). When INJECT-CD executes a `pushd'
to the working directory of the buffer from which you toggled the shell."
(interactive)
(let* ((shell-buf (get-buffer "*shell*"))
(shell-window ; non-nil when currently displayed
(if shell-buf (get-buffer-window shell-buf t)))
(shell-frame
(if shell-window (window-frame shell-window)))
(in-shell (eq (current-buffer) shell-buf))
(vertical (string= display 'vertical))
(popup-frame (or (string= display 'frame)
(and inject-cd (not (bufferp shell-buf)))
(and (framep shell-frame)
(not (eq shell-frame (selected-frame)))))))
;; With prefix-arg close shell, restore windows. Otherwise (no prefix-arg)
;; toggle shell window; restore windows when called twice in a row, or the
;; current buffer is the shell buffer (`in-shell').
(if current-prefix-arg
(if (bufferp shell-buf)
(progn (message "Exiting shell '%s'" (buffer-name shell-buf))
(kill-buffer shell-buf)
(if in-shell (--toggle-shell-restore-last-conf)))
(error "No shell buffer to kill."))
;; If already in shell-buffer toggle back to stored frame-configuration.
(if (and in-shell (not inject-cd))
(progn
(--toggle-shell-restore-last-conf)
;; Recurse to reopen the shell-buffer in a dedicated frame, or
;; close the dedicated frame and reopen the buffer in a window.
(if (and popup-frame (eq shell-frame (selected-frame)))
(--toggle-shell 'frame inject-cd)
(when (and popup-frame shell-frame)
(delete-frame shell-frame)
(--toggle-shell nil inject-cd))))
;; Not in shell buffer. Warp to it or create new one.
(unless in-shell
(--toggle-shell-store-last-conf))
(if popup-frame
(progn (switch-to-buffer-other-frame (or shell-buf "*shell*"))
(raise-frame
(or shell-frame (window-frame (get-buffer-window "*shell*" t)))))
(if (> (count-windows) 1)
(delete-other-windows)))
;; Finally `cd' into the working directory the current buffer.
(let ((new-shell (not (bufferp shell-buf)))
(new-dir ; `default-directory' of `--toggle-shell-last-buf'
(if --toggle-shell-last-buf
(buffer-local-value 'default-directory --toggle-shell-last-buf))))
;; Open shell, move point to end-of-buffer. The new shell-buffer's
;; `default-directory' will be that of the buffer the shell was
;; launched from.
(when vertical
(if (> (count-windows) 1)
(delete-other-windows))
(split-window-vertically) (other-window 1))
(funcall 'shell)
(when new-shell
(message "New shell %s (%s)" (buffer-name (current-buffer)) new-dir)
(if inject-cd (sit-for 2))) ; wait for prompt
(goto-char (point-max))
;; If on a command-prompt insert and launch a "cd" command (assume no
;; job is running).
(when (and inject-cd new-dir)
(save-excursion
(backward-line-nomark) (end-of-line)
(unless (setq inject-cd (re-search-forward comint-prompt-regexp (point-max) t))
(error "Cannot `pushd', shell is busy")))
(when (and inject-cd)
(let* ((cmd (format
"pushd '%s' %s" (comint-quote-filename new-dir)
(if (buffer-file-name --toggle-shell-last-buf)
(format "# '%s'" (file-name-directory (buffer-file-name --toggle-shell-last-buf)))
""))))
;; `shell-process-cd' set new `default-directory' and set
;; `shell-last-dir' to old. (If the pushd command is
;; successful, a dirs is performed as well; >nul discards this
;; output.)
(shell-process-cd new-dir)
(insert cmd)
(comint-send-input)
(message "%s: cd '%s'" (buffer-name --toggle-shell-last-buf) new-dir))
)
)
)
)
)
)
)
--toggle-shell
- это функция, выполняющая трюк. Я привязываю его к F12:
;; F12 toggle between shell buffer and current window configuration
;; SHIFT-F12 like before, but let shell buffer appear in a dedicated frame
;; ALT-F12 inject a pushd to change to directory of current buffer
;; CTRL-F12 `shell-command'
(global-set-key [(f12)] '--toggle-shell)
(global-set-key [(shift f12)] '(lambda()(interactive)(--toggle-shell 'frame)))
(global-set-key [(meta f12)] '(lambda()(interactive)(--toggle-shell nil t)))
(global-set-key [(meta f10)] '(lambda()(interactive)(--toggle-shell nil t)))
(global-set-key [(control f12)] 'shell-command) ; alias M-!
Это значительный кусок кода, который будет опубликован здесь. Но он будет работать хорошо.
Полусвязь - вы можете быстро запустить команду оболочки в выбранном файле с помощью
M-shift-!
Это экономит много времени для небольших команд chmod и т.д.
И, возможно, моя быстрая всплывающая оболочка также может вам помочь. Быстрая всплывающая оболочка для emacs
Ecb + eshell будет тем, что вы хотите точно!
Я использую vi, но надеюсь, что это поможет. Я могу открыть столько терминалов, сколько хочу (например, в Ubuntu 16.04):
ctrl + alt + t
Я обычно открываю 2 терминала и перемещаю (позицию) один терминал вправо:
ctrl + super + right-arrow
и переместите другой терминал влево:
ctrl + super + left-arrow
так что у меня есть разделенный экран на 2 терминала.