Làm thế nào để ngăn chặn sự chậm lại khi một quá trình kém hơn tạo ra các dòng dài?


14

Tôi sử dụng Emacs với Geiser để hack một số mã Scheme. Khi tôi chơi xung quanh trong REPL, đôi khi tôi đánh giá các biểu thức dẫn đến rất nhiều đầu ra, thường là tất cả trên một dòng.

Ví dụ: tôi chỉ chơi với SRFI-41 (luồng) và tạo luồng ký tự từ một tệp lớn; sau đó tôi buộc luồng và Geiser đã chặn toàn bộ nội dung của tệp dưới dạng luồng ký tự vào bộ đệm của tôi. Gần như ngay lập tức, Emacs dừng lại khi ngày càng có nhiều nhân vật gắn vào dòng đầu ra, và cho dù tôi có nhấn liên tục bao lâu C-ghay C-c C-ckhông thể khiến Emacs (hoặc Geiser) dừng lại.

Điều này đã phá vỡ toàn bộ phiên Emacs của tôi khi Emacs hoàn toàn bỏ qua đầu vào của tôi, nghĩ rằng nó cần ưu tiên in luồng ký tự lớn này trên một dòng vào bộ đệm Geiser REPL không phản hồi.

Có điều gì tôi có thể làm để bảo vệ phiên Emacs khỏi sự tò mò phá hoại của mình không? (Tại sao Emacs lại bị chậm như vậy khi hiển thị các dòng rất dài?) Tôi có thể đặt giới hạn cho các dòng dài và nói với Emacs rằng đơn giản là không cố gắng hiển thị các dòng rất dài?



2
Vâng, câu hỏi của tôi không phải là về việc hiển thị các dòng dài mỗi se; Tôi muốn biết làm thế nào tôi có thể tránh loại điều này ngay từ đầu (Emacs đọc dòng từ quá trình suy diễn, nó không đọc từ tệp tôi có thể sửa); và đó là về cách tôi có thể ngăn chặn mất phiên Emacs của mình vào sự cống hiến của Emacs cho một bộ đệm động duy nhất.
rekado

"Chà, câu hỏi của tôi không phải là về việc hiển thị những dòng dài" Vậy thì có lẽ bạn nên thay đổi tiêu đề của mình. Có lẽ bạn muốn lọc đầu ra quá trình kém hơn và thêm dòng mới sau một số lượng ký tự nhất định?
mẫu

Thực sự, điều này có ít liên quan đến các dòng dài. yestrong một ansi-termví dụ có một hiệu ứng tương tự (nhưng không phải khủng khiếp). Thực sự đó chỉ là khối lượng văn bản khiến emacs tạm dừng.
PythonNut

Chèn văn bản vào bộ đệm khá nhanh, đó là các thao tác hiển thị lại làm cho nó xuất hiện chậm hơn so với thực tế. Thành thật mà nói, chạy yestrong trình giả lập thiết bị đầu cuối VTE sẽ tối đa hóa tất cả các lõi CPU của tôi, vì vậy tôi không sử dụng nó làm ví dụ.
wasamasa

Câu trả lời:


12

Như đã trả lời trong các bình luận, Emacs trở nên rất chậm trong việc hiển thị lại các dòng dài là một vấn đề nổi tiếng . Sửa nó sẽ rất hay, nhưng cần nhiều suy nghĩ để được rút ra một cách chính xác. Tôi có ý tưởng về cách thực hiện nó dựa trên phần 6.3 của tài liệu này (về cơ bản, lưu trữ thông tin dòng hình ảnh trong bộ đệm hiện tại và cập nhật nó khi chèn khoảng trắng, thuộc tính hiển thị, thay đổi cửa sổ, v.v., sau đó sử dụng thông tin đó trong mã hiển thị lại để tránh quét mọi lúc), nhưng không đủ quen thuộc với các phần bên trong C để kéo nó đi.

Có cách giải quyết mặc dù. Những cái rõ ràng nhất sẽ điều chỉnh các tham số liên quan đến hiển thị (như, cho phép cắt ngắn dòng trực quan trong trường hợp Emacs đồ họa, sử dụng Emacs không có đồ họa để thực hiện tự động, vô hiệu hóa các tính năng Bidi, v.v.) và xử lý trước nội dung tệp bạn ' đang đọc lại. Một điều ít rõ ràng hơn là tự động xử lý hậu kỳ các tệp, bằng cách thực sự cắt bớt các dòng của chúng hoặc thêm các thuộc tính văn bản làm cho các dòng xuất hiện ngắn hơn so với thực tế. Để biến điều này thành một câu trả lời thú vị hơn, tôi sẽ trình bày một bản hack khá xấu xí của tùy chọn trước đây sẽ chỉ hoạt động cho comintcác chế độ được tạo ra:

(defun my-comint-shorten-long-lines (text)
  (let* ((regexp "^\\(.\\{80\\}\\).*?$")
         (shortened-text (replace-regexp-in-string regexp "\\1" text)))
    (if (string= shortened-text text)
        text
      (propertize shortened-text 'help-echo text))))

(add-hook 'comint-preoutput-filter-functions 'my-comint-shorten-long-lines)

Điều này xác định my-comint-shorten-long-lines, một hàm lấy một chuỗi có thể bao gồm nhiều dòng và sử dụng sức mạnh của các biểu thức chính quy để thay thế bất kỳ dòng nào trong đó có độ dài từ 80 ký tự trở lên bằng một phiên bản rút gọn hiển thị văn bản gốc khi di chuột qua nó. Khi được sử dụng như hook trong comint-preoutput-filter-functionsnó sẽ lọc tất cả comintđầu ra trước khi nó được hiển thị.

Tuy nhiên, phiên bản hack này có một điểm yếu khá nghiêm trọng. Trong các chế độ có phông chữ cơ bản đang diễn ra (như, M-x ielm), nó sẽ vui vẻ cắt bỏ các dòng là một phần của chuỗi và theo cách đó sẽ phông chữ mọi thứ cho đến khi trích dẫn tiếp theo dưới dạng chuỗi! Đó không phải là những gì chúng ta muốn và có thể được sửa chữa với một chút thành thạo regex (nhưng có lẽ sẽ phá vỡ bên trong REPL cho một ngôn ngữ như Python). Trong khi chúng ta đang ở đó, chúng ta hãy làm nổi bật đầu ra rút ngắn:

(defun my-comint-shorten-long-lines (text)
  (let* ((regexp "^\\(.\\{80\\}\\).*?\\(\"?\\)$")
         (shortened-text (replace-regexp-in-string regexp "\\1\\2" text)))
    (if (string= shortened-text text)
        text
      (propertize shortened-text 'font-lock-face 'shadow 'help-echo text))))

(add-hook 'comint-preoutput-filter-functions 'my-comint-shorten-long-lines)

Điều đó tốt hơn một chút, nhưng vẫn xấu xí. Di chuột vào đầu ra của một cái gì đó như find /trong M-x shellkhông hấp dẫn (lý tưởng nhất là chúng tôi chỉ muốn hiển thị dòng không được bao bọc, không phải tất cả đầu ra), phát hiện chuỗi là thô sơ nhất và cắt ngắn có thể được chỉ định tốt hơn bằng dấu chấm lửng thay vì phông chữ mọi thứ. Trên hết, nó thậm chí không đảm bảo rằng văn bản đến không được chuyển thành lô. Tất cả điều này hét lên để thực hiện bước xử lý trong một bộ đệm tạm thời, nhưng sẽ được dành cho người đọc dưới dạng bài tập (hoặc tác giả là bài đăng blog tiềm năng).


4

Như điều này đã xảy ra với Python tương tự, giải pháp tại python-mode.el, https://launchpad.net/python-mode , là kết nối để xử lý trực tiếp, không qua chế độ comint.

Dựa vào start-processvà xử lý chuỗi gửi

Ví dụ, xem các chức năng py--start-fast-processpy--fast-send-string-intern

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.