Lặp lại bất kỳ lệnh cuối cùng (phức tạp hay không)


8

Emacs có repeatrepeat-complex-command, rút ​​ra các lệnh khác nhau từ lịch sử lệnh và bị ràng buộc với các khóa khác nhau. Làm thế nào để bạn lặp lại bất kỳ lệnh cuối cùng - cho dù nó phức tạp hay không - với một phím duy nhất? Nói cách khác, một lệnh lặp lại như vậy sẽ hoạt động như thế nào repeat-complex-commandnếu lệnh cuối cùng yêu cầu đầu vào, nếu không nó sẽ hoạt động như thế nào repeat.

EDIT : Nói cách khác, tôi đang tìm cách đọc lệnh cuối cùng, phức tạp hay không, và sau đó gọi một trong hai repeat-complex-commandhoặc repeattrên đó, tùy theo cách nào phù hợp. Ví dụ, giả sử rằng một lệnh mới như vậy bị ràng buộc <f8>. Sau đó:

  • (bắt chước C-x M-: (repeat-complex-command)với M-z (zap-to-char)): C-u M-z a <f8> <f8>sẽ tương đương vớiC-u M-z a C-x M-: RET C-x M-: RET

  • (bắt chước C-x z (repeat)với C-f (forward-char)): C-u C-f <f8> <f8>sẽ tương đương vớiC-u C-f C-x z z

Bây giờ, repeat-complex-commandyêu cầu bạn xác nhận biểu mẫu Lisp sẽ được thực thi. Để cho phép lặp lại một lệnh phức tạp mà không cần xác nhận, tôi đã viết một phiên bản thay thế repeat-complex-command, được gọi repeat-complex-command-no-confirm(xem bên dưới để thực hiện). Vấn đề là tôi không thể hiểu làm thế nào để xác định xem tôi nên gọi repeathay repeat-complex-command-no-confirmkhi nhấn <f8>.

-

(defun repeat-complex-command-no-confirm (arg)
  "Like `repeat-complex-command' but does not require confirmation."
  ;; Adapted from `repeat-complex-command' of Emacs 24.5.1.
  (interactive "p")
  (let ((elt (nth (1- arg) command-history))
        newcmd)
    (if elt
        (progn
          (setq newcmd elt)

          ;; If command to be redone does not match front of history,
          ;; add it to the history.
          (or (equal newcmd (car command-history))
              (setq command-history (cons newcmd command-history)))
          (unwind-protect
              (progn
                ;; Trick called-interactively-p into thinking that `newcmd' is
                ;; an interactive call (bug#14136).
                (add-hook 'called-interactively-p-functions
                          #'repeat-complex-command--called-interactively-skip)
                (eval newcmd))
            (remove-hook 'called-interactively-p-functions
                         #'repeat-complex-command--called-interactively-skip)))
      (if command-history
          (error "Argument %d is beyond length of command history" arg)
        (error "There are no previous complex commands to repeat")))))

Câu trả lời:


5

Những người khác chắc chắn sẽ cung cấp các giải pháp khác nhau. Đây là của tôi, từ thư viện misc-cmds.el.

(defun repeat-command (command)
  "Repeat COMMAND."
  (let ((repeat-message-function  'ignore))
    (setq last-repeatable-command  command)
    (repeat nil)))

Sau đó, chỉ cần xác định một lệnh mới, lặp lại cho bất kỳ lệnh không lặp lại nào và ánh xạ lại các phím từ bộ không lặp đến bộ lặp. Ví dụ:

(defun next-buffer-repeat ()
  "Switch to the next buffer in the selected window.
You can repeat this by hitting the last key again..."
  (interactive)
  (require 'repeat)
  (repeat-command 'next-buffer))

(global-set-key [remap next-buffer] 'next-buffer-repeat)

Cụ thể, bạn có thể sử dụng điều này để lặp lại một lệnh nằm trên khóa tiền tố. Ví dụ Remapping next-bufferđể next-buffer-repeatcó nghĩa là bạn có thể sử dụng C-x <right> <right>.... Khóa được ràng buộc, C-x <right>không cần phải là khóa lặp lại (một khóa mà bạn có thể giữ. Tất cả những gì bạn cần là sử dụng C-xmột lần và sau đó nhấn giữ <right>.


Xin lỗi, tôi chỉ nhận ra rằng bạn cũng muốn lặp lại một "lệnh phức tạp". Trên thực tế (IMHO), lặp lại một lệnh phức tạp là một cách viết sai. Nó chỉ có nghĩa là lặp lại một lệnh với (theo mặc định) các đối số tương tự. Nó cố ý cho phép bạn chỉnh sửa sexp Lisp sẽ làm điều đó, ví dụ, bạn có thể thay đổi các đối số.

Tóm lại, lệnh repeat-complex-command(ràng buộc với C-x ESC ESC, ví dụ) làm một cái gì đó đặc biệt và hoàn toàn khác với việc chỉ lặp lại lệnh cuối cùng (nghĩa là, từ loại điều tôi đã trình bày ở trên). Không rõ việc lặp lại một "lệnh phức tạp" có thể có nghĩa là gì hoặc sử dụng nó sẽ là gì. IOW, khái niệm lặp lại một lệnh, ví dụ bằng cách giữ một phím mà nó bị ràng buộc, hoàn toàn khác với việc sử dụng repeat-complex-command, nó khởi tạo một hộp thoại cho phép bạn chỉnh sửa và sau đó gọi một lệnh chỉ định các giá trị đối số cụ thể.

Vì vậy, trừ khi bạn có thể mô tả tốt hơn những gì bạn có trong đầu bằng cách kết hợp việc lặp lại lệnh theo nghĩa thông thường với những gì repeat-complex-commandkhông, tôi sợ tôi không thể giúp với phần câu hỏi đó.


Cập nhật sau khi bạn làm rõ.

Vì vậy, đây thực chất là những gì bạn có, để lặp lại lệnh "phức tạp" cuối cùng, nghĩa là lệnh cuối cùng đọc đầu vào từ bộ thu nhỏ. (Lưu ý rằng bạn cần xóa repeat-complex-command-no-confirmkhỏi lịch sử.)

(defun repeat-complex-command-no-confirm ()
  "..."
  (interactive)
  (let* ((hist  command-history)
         newcmd)
    (while (eq 'repeat-complex-command-no-confirm (caar hist))
      (setq hist  (cdr hist)))
    (setq newcmd  (car hist))
    (if newcmd
        (apply #'funcall-interactively (car newcmd)
               (mapcar (lambda (ee) (eval ee t)) (cdr newcmd)))
      (error "There are no previous complex commands to repeat"))))

Bạn có thể liên kết nó với một khóa có thể lặp lại (ví dụ: C-o'). Or you can define a repeatable command usinglặp lại lệnh (i.e., passlặp-phức-lệnh-không-xác nhận to it), to be able to have it work when bound to a repeatable key that is on a prefix key (e.g.C-x o`).

Nhưng khi bạn sử dụng một khóa như vậy, gọi repeat-complex-command-no-confirm, bạn sẽ lặp lại lệnh cuối cùng đã sử dụng bộ thu nhỏ, không nhất thiết là lệnh cuối cùng.

Dù sao, bạn có thể sử dụng một cái gì đó như sau để có được những gì bạn nói bạn muốn. Dòng cuối cùng ngăn không cho my-repeatlà lệnh cuối cùng, do đó, việc sử dụng lại nó không cố lặp lại my-repeatmà lặp lại lệnh lặp lại cuối cùng.

(defun my-repeat ()
  "..."
  (interactive)
  (if (eq last-command (caar command-history))
      (repeat-complex-command-no-confirm)
    (call-interactively last-command))
  (setq this-command  last-command))

(global-set-key "\C-o" 'my-repeat) ; Bind it to a repeatable key

Câu hỏi này có câu trả lời giải thích sự khác biệt giữa lệnh lặp lại và lệnh lặp lại phức tạp .
Người dùng Emacs

@EmacsUser: Vâng, như bạn có thể thấy, câu hỏi mà bạn liên kết có trên khắp bản đồ - câu hỏi không rõ ràng, vì vậy câu trả lời rất xa. Tất cả đều thích hợp với một số giải thích của câu hỏi, nhưng chúng là một túi hỗn hợp. (Xem bình luận của tôi cho câu trả lời này ở đó.)
vẽ

vâng, cảm ơn đã làm rõ. Phản ứng đó chắc chắn giúp bất cứ ai đào sâu hơn.
Người dùng Emacs

@Drew Cảm ơn câu trả lời chi tiết của bạn. Tôi đã mở rộng câu hỏi của mình và hy vọng, bây giờ nó đã rõ ràng hơn.
Elena
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.