จะป้องกันไม่ให้ช้าลงเมื่อกระบวนการที่ด้อยกว่าสร้างเส้นยาวได้อย่างไร


14

ฉันใช้ Emacs กับ Geiser เพื่อแฮกรหัส Scheme ขณะที่ฉันเล่นไปรอบ ๆ ใน REPL บางครั้งฉันประเมินนิพจน์ที่ให้ผลลัพธ์จำนวนมากซึ่งมักจะอยู่ในหนึ่งบรรทัด

ตัวอย่างเช่นฉันเพิ่งเล่นกับ SRFI-41 (สตรีม) และสร้างสตรีมตัวละครจากไฟล์ขนาดใหญ่ จากนั้นฉันบังคับสตรีมและ Geiser แก้ไขเนื้อหาทั้งหมดของไฟล์เป็นสตรีมอักขระลงในบัฟเฟอร์ของฉัน เกือบจะในทันที Emacs ต้องหยุดชะงักเหมือนตัวละครมากขึ้นเรื่อย ๆ ที่ต่อท้ายบรรทัดเอาท์พุทและไม่ว่าฉันจะกดค้างไว้นานเท่าไหร่C-gหรือC-c C-cไม่สามารถหยุด Emacs (หรือ Geiser) ได้

สิ่งนี้ทำให้เซสชัน Emacs ของฉันทั้งหมดเสียหายเนื่องจากตอนนี้ Emacs ไม่สนใจอินพุตของฉันอย่างสมบูรณ์โดยคิดว่าจำเป็นต้องให้ความสำคัญกับการพิมพ์สตรีมตัวละครขนาดใหญ่นี้ในบรรทัดเดียวให้เป็นบัฟเฟอร์ Geiser REPL ที่ไม่ตอบสนอง

มีสิ่งที่ฉันสามารถทำได้เพื่อปกป้องเซสชั่น Emacs ของฉันจากความอยากรู้อยากเห็นของฉันทำลาย? (เพราะเหตุใด Emac จึงช้ามากเมื่อแสดงเส้นที่ยาวมากอยู่แล้ว) ฉันสามารถกำหนดขีด จำกัด ของเส้นยาวและบอก Emacs ได้ว่าไม่เป็นไรที่จะไม่พยายามแสดงเส้นที่ยาวมาก ๆ ?



2
คำถามของฉันไม่ได้เกี่ยวกับการแสดงเส้นยาวต่อ se; ฉันต้องการทราบว่าฉันสามารถหลีกเลี่ยงสิ่งนี้ได้อย่างไรในตอนแรก (Emacs อ่านบรรทัดจากกระบวนการที่ต่ำต้อยไม่อ่านจากไฟล์ที่ฉันสามารถแก้ไขได้); และมันเกี่ยวกับวิธีที่ฉันจะป้องกันไม่ให้สูญเสียเซสชัน Emacs ของฉันไปยังการทุ่มเทของ Emacs ให้กับบัฟเฟอร์แบบไดนามิกเดียว
rekado

"คำถามของฉันไม่ได้เกี่ยวกับการแสดงเส้นยาว" บางทีคุณควรเปลี่ยนชื่อของคุณ บางทีคุณต้องการที่จะกรองเอาท์พุทกระบวนการที่ต่ำกว่าและเพิ่มบรรทัดใหม่หลังจากจำนวนอักขระ?
พี่เลี้ยง

แม้ว่าจริงๆแล้วมันมีส่วนเกี่ยวข้องกับสายยาว ๆ เล็กน้อย yesในansi-termตัวอย่างมีผลกระทบที่คล้ายกัน (แต่ไม่น่ากลัวว่า ) จริงๆแล้วมันเป็นเพียงปริมาณของข้อความที่ให้ emacs หยุดชั่วคราว
PythonNut

การแทรกข้อความในบัฟเฟอร์นั้นค่อนข้างเร็วการดำเนินการ redisplay ที่ทำให้มันช้ากว่าที่เป็นจริง ความจริงแล้วการรันyesในเทอร์มินัลอีมูเลเตอร์ VTE จะทำให้ซีพียูคอร์ทั้งหมดของฉันสูงสุดดังนั้นฉันจะไม่ใช้มันเป็นตัวอย่าง
wasamasa

คำตอบ:


12

ในฐานะที่เป็นคำตอบอยู่แล้วในความคิดเห็นที่ Emacs กลายเป็นช้ามากในสต์สำหรับสายยาวเป็นปัญหาที่รู้จักกันดี การแก้ไขมันจะดีมาก แต่ต้องการความคิดจำนวนมากเพื่อดึงออกอย่างถูกต้อง ฉันมีความคิดว่ามันสามารถทำได้อย่างไรตามส่วนที่ 6.3 ของเอกสารนี้ (โดยทั่วไปจัดเก็บข้อมูลบรรทัดภาพในบัฟเฟอร์ปัจจุบันและอัปเดตเมื่อแทรกช่องว่างคุณสมบัติการแสดงผลการเปลี่ยนแปลงหน้าต่าง ฯลฯ จากนั้นใช้ข้อมูลใน รหัส redisplay เพื่อหลีกเลี่ยงการสแกนตลอดเวลา) แต่ฉันไม่คุ้นเคยกับ C internals เพื่อดึงออกมา

มีวิธีแก้ไขเฉพาะหน้า สิ่งที่ชัดเจนที่สุดคือการปรับพารามิเตอร์ที่เกี่ยวข้องกับการแสดงผล (เช่นการเปิดใช้งานการตัดบรรทัดภาพในอินสแตนซ์ Emacs แบบกราฟิกโดยใช้ Emac ที่ไม่ใช่กราฟิกเพื่อทำสิ่งนั้นโดยอัตโนมัติปิดการใช้งานคุณสมบัติ Bidi ฯลฯ ) และประมวลผลเนื้อหาไฟล์ของคุณ การอ่านสิ่งที่ชัดเจนน้อยลงคือการโพสต์ไฟล์โดยอัตโนมัติไม่ว่าจะเป็นการตัดทอนบรรทัดของพวกเขาหรือเพิ่มคุณสมบัติข้อความที่ทำให้บรรทัดปรากฏสั้นกว่าที่เป็นจริง ในการเปลี่ยนให้เป็นคำตอบที่น่าสนใจยิ่งขึ้นฉันจะนำเสนอการแฮ็กที่น่าเกลียดของตัวเลือกเดิมที่จะใช้ได้เฉพาะกับcomintโหมดที่ได้รับการถ่ายทอด:

(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)

my-comint-shorten-long-linesฟังก์ชันนี้กำหนดฟังก์ชันที่ใช้สตริงที่อาจประกอบด้วยหลายบรรทัดและใช้พลังของนิพจน์ทั่วไปเพื่อแทนที่บรรทัดใด ๆ ในนั้นด้วยความยาว 80 อักขระขึ้นไปด้วยเวอร์ชันย่อที่แสดงข้อความต้นฉบับเมื่อวางเมาส์เหนือมัน เมื่อใช้เป็นตะขอใน comint-preoutput-filter-functionsมันจะกรองcomintเอาท์พุททั้งหมดก่อนที่จะแสดง

อย่างไรก็ตามแฮ็คนี้มีจุดอ่อนที่ร้ายแรง ในโหมดที่มีการทำให้แบบอักษรพื้นฐานเกิดขึ้น (เช่น, M-x ielm) มันจะตัดเส้นที่เป็นส่วนหนึ่งของสตริงอย่างมีความสุขและจะทำให้ทุกอย่างเป็นแบบอักษรจนกระทั่งมีการอ้างอิงเป็นสตริงต่อไป! นั่นไม่ใช่สิ่งที่เราต้องการและสามารถแก้ไขได้ด้วยความเชี่ยวชาญของ regex อีกเล็กน้อย (แต่สันนิษฐานได้ว่าอาจแตกภายใน REPL สำหรับภาษาเช่น Python) ในขณะที่เราอยู่ที่นี่เราขอเน้นผลลัพธ์ที่สั้นลงเช่นกัน:

(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)

มันค่อนข้างดีกว่า แต่ก็ยังน่าเกลียดอยู่ดี โฉบในการส่งออกของสิ่งที่ต้องการfind /ในM-x shellไม่น่าสนใจ (เราต้องการนึกคิดเพียงต้องการที่จะแสดงเส้น unshortened ไม่ส่งออกทั้งหมด), การตรวจสอบสตริงเป็นพื้นฐานที่ดีที่สุดและการตัดอาจจะชี้ให้เห็นได้ดีขึ้นด้วยวงรีแทน fontifying ทุกอย่าง ยิ่งไปกว่านั้นไม่รับประกันว่าข้อความที่เข้ามาจะไม่ถูกเปลี่ยนเป็นแบตช์ ทั้งหมดนี้ส่งเสียงกรีดร้องสำหรับการทำขั้นตอนการประมวลผลในบัฟเฟอร์ชั่วคราว แต่จะเหลือไว้สำหรับผู้อ่านว่าเป็นการออกกำลังกาย (หรือผู้เขียนเป็นบล็อกโพสต์ที่มีศักยภาพ)


4

เมื่อสิ่งนี้เกิดขึ้นกับ Python เช่นกันวิธีแก้ปัญหาที่ python-mode.el, https://launchpad.net/python-modeคือการเชื่อมต่อกับกระบวนการโดยตรงไม่ใช่ผ่านโหมด comint

อาศัยstart-processและกระบวนการส่งสตริง

ตัวอย่างเช่นฟังก์ชั่นpy--start-fast-processและpy--fast-send-string-intern

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.