Khởi động lại emacs từ bên trong emacs


44

Tôi khởi động lại emacs của tôi rất nhiều. Tất cả những gì tôi muốn làm là tạo ra một chức năng giết chết các emacs hiện tại, chỉ để sinh ra một cái mới thay cho nó. Lý tưởng nhất, điều này cũng sẽ làm việc trong một TTY.


8
Vì tò mò, tại sao bạn giết và ngay lập tức khởi động lại thường xuyên như vậy?
Dân

2
Tôi rất tích cực phát triển .emacs.d, điều đó có nghĩa là tôi khởi động lại emacs để loại bỏ bất kỳ rác nào tôi đã thổi vào môi trường của mình. Có một vài trường hợp sử dụng khác mà tôi làm điều này, nhưng đó là trường hợp lớn nhất.
PythonNut

1
@PythonNut, tôi nghĩ bạn cần điều chỉnh lại câu hỏi của mình một chút. Bạn có thể nói bashđể khởi động lại sau khi chấm dứt? Hay là vi? Hoặc bất kỳ quá trình khác, như là một quy tắc? Không, bởi vì điều đó nằm ngoài phạm vi quan tâm của họ và được xử lý bên ngoài đúng cách. Trong mọi trường hợp, những gì bạn thực sự muốn là một cách để xác định lại các emacs, bằng cách xóa VM của nó và chạy lại mã init của bạn ( mà không làm hỏng quá trình của nó). Điều đó sẽ hữu ích và thích hợp cho emacs. Tôi không biết nếu nó tồn tại, mặc dù :)
harpo 16/12/14

4
@harpo có, tôi có thể bashkhởi động lại với exec bash. Tôi không có ý tưởng về vim.
PythonNut

11
FWIW, tôi có xu hướng bắt đầu một phiên bản mới của Emacs để kiểm tra các thay đổi cấu hình, thay vào đó là thoát và khởi động lại. Tại sao? Bởi vì nếu mã của tôi có lỗi thì Emacs có thể không tải được cấu hình của tôi khi tôi khởi động lại và lúc đó tôi thực sự không thể có được một phiên bản đang chạy với các cài đặt thông thường của mình, vì vậy tôi phải sử dụng một chỉnh sửa ít quen thuộc hơn môi trường để sửa lỗi. Nó sẽ không xảy ra thường xuyên, nhưng nó gây phiền nhiễu khi nó xảy ra. Tôi có thể chạy emacs -qvà khắc phục sự cố tất nhiên, nhưng tôi thích giữ một ví dụ 'tốt' luôn hoạt động khi hack vào cấu hình của mình, để an toàn.
phils

Câu trả lời:


25

Lưu ý: Tôi đã gói các thứ sau đây trong một gói restart-emacscó sẵn ở đây .


Đây là một cách khác để đạt được những gì bạn muốn bằng cách sử dụng elisp thuần túy (không thực sự vì bạn dựa vào vỏ). Bí quyết là sinh ra một quá trình emacs khác ngay trước khi emacs hiện tại bị giết.

(defun launch-separate-emacs-in-terminal ()
  (suspend-emacs "fg ; emacs -nw"))

(defun launch-separate-emacs-under-x ()
  (call-process "sh" nil nil nil "-c" "emacs &"))

(defun restart-emacs ()
  (interactive)
  ;; We need the new emacs to be spawned after all kill-emacs-hooks
  ;; have been processed and there is nothing interesting left
  (let ((kill-emacs-hook (append kill-emacs-hook (list (if (display-graphic-p)
                                                           #'launch-separate-emacs-under-x
                                                         #'launch-separate-emacs-in-terminal)))))
    (save-buffers-kill-emacs)))

Mã để bắt đầu một phiên bản GUI của emacs rất đơn giản. Mã để bắt đầu emacs trong một thiết bị đầu cuối là một chút khó khăn. Nó sử dụng thực tế là bạn có thể truyền một chuỗi suspend-emacsmà sẽ được chuyển làm đầu vào đầu cuối cho tiến trình cha (shell). Từ tài liệu

(đình chỉ-emacs & STUFFSTRING tùy chọn)

Dừng Emacs và trở lại quá trình vượt trội. Bạn có thể tiếp tục sau. Nếu 'không thể tạm ngưng' là không phải hoặc nếu hệ thống không hỗ trợ kiểm soát công việc, thay vào đó hãy chạy một mạng con.

Nếu tùy chọn STUFFSTRING không phải là con số không, các ký tự của nó được nhồi để được đọc như là đầu vào của thiết bị đầu cuối bởi cha mẹ của Emacs, sau khi tạm ngưng.

Vì vậy, về cơ bản chúng tôi đình chỉ các emacs ngay trước khi nó bị giết, hãy nói với shell cha để tiếp tục các emacs đang bị treo (sắp thoát ra) và sau đó khởi chạy một quy trình emacs khác. Lưu ý rằng điều này không hoạt động trên các nền tảng mà các thiết bị đầu cuối có thể / không thực sự tạm ngưng nhưng bắt đầu một mạng con, ví dụ như trên các cửa sổ.


Điều này không hiệu quả với tôi: khi tôi chạy sh -c "emacs &"từ trình bao, nó dừng lại với " emacs: standard input is not a tty". (Khi tôi M-x restart-emacsthậm chí không thấy thông báo lỗi đó, Emacs chỉ chấm dứt.)
Constantine

Hoạt động với tôi dưới X. Không hoạt động trong thiết bị đầu cuối vì nó chuyển hướng stdin và stdout thành / dev / null; chuyển tty cha cho tiến trình con có thể thực hiện được nhưng khó hơn.
Beni Cherniavsky-Paskin

1
Điều này hoạt động hoàn hảo, và nó thực sự làm tôi sợ một chút. Tại sao trên trái đất, Emacs được phép truyền lệnh cho vỏ chứa của nó?
Radon Rosborough

bạn sử dụng keybinding nào cho việc đó?
slk500

32

Theo tôi biết, bạn không thể yêu cầu Emacs khởi động lại sau khi chấm dứt, nhưng bạn có thể đặt mã thoát để quá trình bắt đầu Emacs ở nơi đầu tiên có thể phát hiện ra rằng bạn muốn bắt đầu lại.

Ví dụ, tập lệnh shell này khởi động lại Emacs nếu nó thoát với mã 123.

#!/bin/sh
while emacs -nw "$@"; [ $? = 123 ]; do :; done

Tiếp theo, chúng tôi xác định kill-emacs-and-restartlàm cho Emacs chấm dứt với mã thoát bằng với số ma thuật được nhận dạng bởi tập lệnh:

(defun kill-emacs-and-restart ()
  (interactive)
  (kill-emacs 123))

Bây giờ nếu bạn chạy Emacs thông qua tập lệnh này, bạn có thể bắt đầu lại bằng cách M-x kill-emacs-and-restart(hoặc liên kết nó với một chuỗi khóa).


Cách tốt đẹp của váy xung quanh vấn đề! Tôi sẽ chấp nhận điều này nếu bạn có thể cho tôi biết lý do tại sao you cannot tell Emacs to re-start after terminating. Đây có phải là một hạn chế kỹ thuật?
PythonNut

3
@PythonNut: Theo như tôi biết cách duy nhất để bắt đầu lại một quy trình là sử dụng một trong các chức năng từ exec...gia đình (dù sao trên hệ thống POSIX). Các chức năng kiểm soát quy trình của Emacs Lisp không để lộ các cuộc gọi cấp thấp như vậy. Tuy nhiên, tôi không phải là một chuyên gia, vì vậy, hy vọng ai đó hiểu biết nhiều hơn sẽ kêu vang.
Constantine

2

Bị đánh cắp một cách trắng trợn từ https://unix.stackexchange.com/questions/114238/is-it-possibe-to-change-parent-shells-usiness-directory-programmatically

Giả sử tôi đã có cú pháp đúng để nhúng "trong một chuỗi, điều này sẽ làm điều đó.

(defun restart-emacs ()
  (call-process "sh" nil nil nil "-c" "gdb -p $(ps h -o ppid -p $$) -ex 'call execl(\"/bin/sh\", \"/bin/sh\", \"-c\", \"exec emacs\")'"))

11
Xin đừng. Điều này bỏ qua tất cả các hoạt động dọn dẹp nội bộ của Emacs và loại bỏ tất cả trạng thái hiện tại (ví dụ: bộ đệm đã sửa đổi) mà không cần xác nhận .
lunaryorn

cảnh báo của lunaryorn là chính xác.
Joshua
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.