Làm thế nào để liên tục di chuyển con trỏ trong bộ đệm khác với bộ đệm hiện tại?


8

NB: Bài viết Làm thế nào để di chuyển điểm đến cuối bộ đệm khác, sử dụng `with-current-buffer` và` goto-char`? có lẽ hỏi cùng một câu hỏi như câu hỏi này, nhưng câu trả lời cho nó không dễ dàng áp dụng cho trường hợp của tôi ở đây. Ví dụ: những câu trả lời liên quan đến việc chèn văn bản vào bộ đệm khác, v.v ... Câu hỏi tôi đang hỏi ở đây đơn giản hơn đáng kể và tôi hy vọng câu trả lời cho nó cũng tương tự đơn giản.


Giả sử rằng

  • khung Emacs được chia thành hai cửa sổ, trong đó một trong các cửa sổ giữ một bộ đệm được gọi *whatever*và một cửa sổ khác giữ *scratch*bộ đệm tiêu chuẩn ;
  • các *whatever*bộ đệm chứa một số dòng văn bản;
  • con trỏ trong *whatever*bộ đệm nằm ở đầu bộ đệm đó (tức là tại bộ đệm (point-min));
  • các *scratch*bộ đệm là một trong những hiện hành;

Nếu bây giờ tôi đánh giá bất kỳ điều nào sau đây trong *scratch*bộ đệm, vị trí của con trỏ trong *whatever*bộ đệm vẫn không thay đổi:

 (with-current-buffer "*whatever*"
   (goto-char (point-max)))
 (with-current-buffer "*whatever*"
   (end-of-buffer))
 (save-excursion
   (set-buffer "*whatever*")
   (goto-char (point-max)))
 (save-excursion
   (set-buffer "*whatever*")
   (end-of-buffer))

Tôi cho rằng, bất cứ điều gì (goto-char (point-max))hoặc (end-of-buffer)không làm cho *whatever*vị trí của con trỏ sẽ bị loại bỏ sau đó.

  1. Tôi phải sửa đổi bất kỳ đoạn mã nào ở trên để con trỏ*whatever* của bộ đệm được định vị (liên tục!) Ở cuối bộ đệm đó.

  2. Tôi nên làm gì để tự trả lời câu hỏi này bằng tài liệu Emacs? Tôi đã thử mọi thứ tôi có thể nghĩ ra.


Sau khi đọc câu trả lời soi sáng của Jules Tamagnan, tôi nhận ra rằng tôi cần đưa ra một quy định rõ ràng hơn:

Tôi đang tìm kiếm một giải pháp sẽ hoạt động bất kể liệu bộ đệm trong câu hỏi có thể nhìn thấy trong một cửa sổ hay không.

Rốt cuộc, nếu tôi xem bộ đệm B trong cửa sổ W , hãy di chuyển con trỏ đến một vị trí cụ thể L , sau đó xem một số bộ đệm C khác trong cùng cửa sổ W và cuối cùng trỏ W trở lại bộ đệm B , tôi hy vọng sẽ thấy con trỏ tại cùng một vị trí L nơi tôi rời nó. IOW, phải có một cách để bộ đệm ghi nhớ điểm của nó ở đâu, bất kể nó có được liên kết với cửa sổ hay không.

Còn trường hợp bộ đệm đích hiện đang hiển thị trong hai hoặc nhiều cửa sổ ( W1 , W2 , W3 , ...) thì sao? Có nhiều khả năng hợp lý cho trường hợp này. Giải pháp đề xuất có thể, ví dụ, thay đổi vị trí của con trỏ

  • trong cửa sổ hoạt động gần đây nhất trong số W1 , W2 , W3 , ...;
  • trong tất cả các cửa sổ W1 , W2 , W3 , ...; hoặc là
  • Vân vân.

(Tôi không có ý kiến ​​mạnh mẽ về trường hợp góc này, vì tôi hy vọng nó sẽ cực kỳ hiếm trong thực tế.)


1
Các phần chính trong hướng dẫn liên quan đến vấn đề này là ĐiểmĐiểm cửa sổ .
cjm

Câu trả lời:


9

Đây là một câu hỏi khá hay, tôi đã học được rất nhiều điều mà tôi không biết trong khi cố gắng tìm hiểu điều này. Điều tôi học được là mỗi cửa sổ có giá trị riêng point. Điều này rất quan trọng vì nó có nghĩa là điểm không được liên kết với bộ đệm mà thay vào đó là cửa sổ thực tế. Như chúng ta đã thấy điều này làm cho một sự khác biệt lớn.

Những gì chúng ta cần làm sau đó là đặt giá trị của điểm trong cửa sổ, chức năng cho điều đó là set-window-point(Tôi đã tìm thấy điều này qua google, tôi thấy rằng nếu tôi không biết bắt đầu tìm kiếm trong bản dựng trong emacs-docs tìm kiếm trên google có thể làm sáng tỏ một số). Sau đó chúng ta cần cho biết set-window-pointcửa sổ nào sẽ chọn. Để làm điều đó tôi đã sử dụng get-buffer-window(một lần nữa tôi đã sử dụng google để tìm cái này).

Mã này sẽ chỉ hoạt động nếu bộ đệm được mở trong một cửa sổ. Một phiên bản khác sẽ có thể được thực hiện khi bạn mở bộ đệm trong một cửa sổ, đặt điểm và sau đó quay lại cấu hình cửa sổ ban đầu. Các mã dưới đây mặc dù đơn giản hơn nhiều.

(set-window-point (get-buffer-window "*whatever*") (point-max))

Tôi hy vọng điều này có ích, nếu bạn có bất kỳ câu hỏi nào khác hoặc nếu nó không hoạt động chính xác như bạn muốn, hãy cho tôi biết.


Điều này thật ý nghĩa; nếu bạn mở một bộ đệm trong 2 cửa sổ (ví dụ: thông qua cửa sổ chia nhỏ), bạn có 2 điểm độc lập.
Juancho

@Juancho Vâng, sâu thẳm tôi biết rằng nó hoạt động như thế nào nhưng nó chưa bao giờ thực sự chìm xuống cho đến tận bây giờ
Jules

6

( Câu trả lời của Jules Tamagnan xác định vấn đề, tôi sẽ mở rộng về vấn đề này.)

Giải pháp của bạn với save-excursionhoặc save-excursionlàm trong thực tế công việc! Bạn có thể thấy nó bằng cách kiểm tra giá trị của (point)bộ đệm đó sau đó, vd

(progn
  (with-current-buffer "*whatever*"
    (goto-char 42))
  (with-current-buffer "*whatever*"
    (point)))

luôn trả về 42 (với điều kiện là vị trí hợp lệ trong bộ đệm. Điều đó thậm chí còn được đề cập dưới dạng gotcha trong tài liệu về save-excursion: nó chỉ khôi phục vị trí trong bộ đệm ban đầu, không phải vị trí trong bất kỳ bộ đệm nào khác.

Nếu bạn thấy rằng vị trí bộ đệm không phải là vị trí bạn đặt, đó là vì một thứ khác đang thay đổi nó, và thứ đó rất có thể là một cửa sổ (hoặc một cái móc ở đâu đó, nhưng hầu hết các hook không có vấn đề gì với doanh nghiệp - vẫn, nó có thể là một ví dụ móc đầu ra quá trình). Trong tài liệu về điểm , có một lưu ý:

Mỗi bộ đệm có giá trị điểm riêng, độc lập với giá trị điểm trong các bộ đệm khác. Mỗi cửa sổ cũng có một giá trị điểm, độc lập với giá trị của điểm trong các cửa sổ khác trên cùng một bộ đệm. Đây là lý do tại sao điểm có thể có các giá trị khác nhau trong các cửa sổ khác nhau hiển thị cùng một bộ đệm. Khi một bộ đệm chỉ xuất hiện trong một cửa sổ, điểm của bộ đệm và điểm của cửa sổ thường có cùng giá trị, vì vậy sự khác biệt hiếm khi quan trọng. Xem Window Point , để biết thêm chi tiết.

Nếu bộ đệm được hiển thị trong một cửa sổ, thì điểm của bộ đệm được cập nhật thành điểm của cửa sổ mỗi khi điểm thay đổi hoặc cửa sổ được hiển thị lại. Do đó, việc thiết lập điểm về cơ bản chỉ tồn tại chừng nào mã Lisp của bạn tồn tại: ngay khi vòng lặp lệnh toplevel kiểm soát, cửa sổ sẽ được hiển thị lại (ngay cả khi nó không hiển thị, theo như tôi có thể nói) vị trí đệm bị ghi đè. Trong thực tế, vị trí được chọn của người dùng hơn hẳn vị trí đã chọn của chương trình.

Nếu bạn cũng muốn cập nhật điểm của bất kỳ cửa sổ nào hiển thị bộ đệm, bạn có thể gọi get-buffer-window-listđể liệt kê các cửa sổ:

(with-current-buffer "*whatever*"
  (goto-char …)
  (cl-dolist (window (get-buffer-window-list nil nil t))
    (set-window-point window (point))))

Nhưng hãy xem xét rằng nếu người dùng đang truy cập vào bộ đệm, họ có thể không đánh giá cao việc thay đổi điểm dưới mũi của họ.

Theo như tôi biết thì Emacs không theo dõi khi cửa sổ được chọn (đó là hoạt động của Hồi giáo theo thuật ngữ của Emacs), bạn chỉ có thể biết liệu chúng có được chọn hay không. Nếu bạn bắt đầu quan tâm đến các cửa sổ đã chọn, hãy cẩn thận rằng mỗi khung có một cửa sổ đã chọn và Emacs không phải lúc nào cũng biết khi nào khung được chọn ( (selected-frame)không hoàn toàn khớp với trải nghiệm người dùng cuối, đặc biệt là với các khung bên trong trình giả lập thiết bị đầu cuối vì Emacs không có cách nào để biết khi nào người dùng có cửa sổ mô phỏng đầu cuối hoạt động).

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.