OK, tôi sẽ thử một câu trả lời mở rộng. Vấn đề là, Emacs Lisp là đơn luồng. Bạn có thể quay nhiều tiến trình hơn, nhưng không phải bên trong trình thông dịch Emacs Lisp. Tuy nhiên, đầu vào bàn phím mà bạn cần đọc từ người dùng để làm gián đoạn chức năng của bạn cần được xử lý bởi cùng một trình thông dịch Emacs Lisp. Điều này có nghĩa là nếu trình thông dịch của bạn bị kẹt khi diễn giải một số mã Lisp thì có thể không có cách nào để bạn làm gián đoạn nó từ bên trong. Đây là một vị trí trong hướng dẫn mô tả tình huống này:
Ở cấp độ mã C, việc bỏ thuốc lá không thể xảy ra ở bất cứ đâu; chỉ ở những nơi đặc biệt kiểm tra cờ bỏ. Lý do cho điều này là việc bỏ việc ở những nơi khác có thể để lại sự không nhất quán trong trạng thái nội bộ của Emacs. Bởi vì việc bỏ thuốc bị trì hoãn cho đến khi một nơi an toàn, việc bỏ thuốc lá không thể khiến Emacs gặp sự cố.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Quits.html
Vì vậy, làm thế nào Emacs vẫn có C-gchức năng / hủy? - Có các bộ định thời và chức năng thực hiện I / O (chờ các sự kiện trong vòng lặp lệnh). Bộ hẹn giờ có thể sắp xếp các tính toán của bạn được thực hiện theo từng khối, do đó bạn sẽ có điểm trong các tính toán của mình, nơi bạn có thể nhìn xung quanh và, nếu cần, ngăn chặn tất cả các tính toán tiếp theo. Chức năng I / O có thể gửi quit
tín hiệu. Macro with-keyboard-quit
chờ tín hiệu này và một khi nhận được sẽ thoát một cách duyên dáng. Tuy nhiên, chức năng của bạn cần biết để gửi tín hiệu này. Điều này có nghĩa là nếu chức năng của bạn ngăn người dùng gửi đầu vào bàn phím, thì bạn sẽ không thể hưởng lợi từ việc ngắt bàn phím.
Dòng dưới cùng: hãy thử bọc mã của hàm của bạn vào while-no-input
. Nếu điều này không hoạt động, hãy thử viết lại chức năng của bạn theo cách nó sẽ cho phép Emacs xử lý các sự kiện bàn phím.
while-no-input
macro. Nó dường như làm những gì bạn muốn: tức là nó hủy bỏ việc thực thi cơ thể của nó khi đầu vào mới xuất hiện.