วิธีการปรับเปลี่ยนบัฟเฟอร์โดยไม่เลิกทำการสังเกต?


11

ถาม:ฉันจะแทรก / แก้ไขข้อความในบัฟเฟอร์โดยไม่undoสังเกตเห็นได้อย่างไร

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

เหตุผลที่ฉันต้องการลัดวงจรundoที่นี่เนื่องจากกรณีขอบต่อไปนี้ซึ่งเกิดขึ้นเมื่อมีการแก้ไข / รวบรวมเอกสาร LaTeX (และอาจอื่น ๆ แต่นี่คือสิ่งที่ผลักดันฉันถั่วบ่อยที่สุด):

  1. ทำการเปลี่ยนแปลงเล็กน้อยในไฟล์เพื่อดูว่ามันจะส่งผลกระทบต่อเอกสารที่รวบรวม
  2. บันทึกไฟล์ (ซึ่งอัปเดตการประทับเวลา)
  3. ทำงานlatexกับไฟล์
  4. ตัดสินใจว่าการเปลี่ยนแปลงนั้นไม่ดี
  5. undo การเปลี่ยนแปลง

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

ฉันขว้างคำถามด้วยความเคารพไฟล์ที่ฉันกำลังเยี่ยมชม แต่โดยทั่วไปเกี่ยวกับการแก้ไขบัฟเฟอร์

ดังนั้น: ฉันจะป้องกันไม่ให้undoสังเกตเห็นการดัดแปลงเฉพาะกับบัฟเฟอร์ได้อย่างไร?


1
สิ่งนี้ไม่เกี่ยวข้องกับคำถามเลิกทำของคุณ แต่อาจช่วยแก้ปัญหา "เลิกทำการย้ายประเด็น": stackoverflow.com/a/20510025/1279369
พี่เลี้ยงเด็ก

2
จะเป็นการดีที่สุดหรือไม่ถ้าการเปลี่ยนการประทับวันที่นี้ถูกผนวกเข้ากับรายการล่าสุดในการเลิกทำประวัติ วิธีundoนั้นจะยกเลิกทั้งสองอย่าง
Malabarba

atomic-change-groupผมคิดว่าสิ่งที่คุณต้องการจริงๆคือ

@john: มันจะช่วยได้อย่างไร? การเปลี่ยนแปลงสองรายการในกลุ่มจะถูกเรียกใช้โดยคำสั่งแยกต่างหาก:“ การเปลี่ยนแปลงเล็กน้อย” (เช่นการแทรก) และการอัพเดตการประทับเวลาเสร็จในขณะที่บันทึก
Gilles 'หยุดความชั่วร้าย'

โปรดทราบว่าด้วยเหตุผลบางอย่างไม่มีวิธีการเหล่านี้ในคำตอบที่มีอยู่สำหรับฉันอย่างไรก็ตามคำตอบนี้กำหนดwith-undo-collapseแมโครที่มีประโยชน์มาก: emacs.stackexchange.com/a/7560/2418
ideasman42

คำตอบ:


6

@ คำตอบของ stsquad พาฉันไปในเส้นทางที่ถูกต้อง โดยทั่วไปขั้นตอนคือ:

  1. บันทึก buffer-undo-list
  2. ปิดการใช้งาน undo
  3. ทำในสิ่งที่คุณ
  4. เปิดใช้งานundoและกู้คืนbuffer-undo-list

ดังนั้นนี่คือภาพร่างของฟังก์ชันดังกล่าว:

(defun disable-undo-one-off ()
  (let ((undo buffer-undo-list))        ; save the undo list
    (buffer-disable-undo)               ; disable undo
    (do-some-stuff)                     ; do your thing
    (buffer-enable-undo)                ; re-enable undo
    (setq buffer-undo-list undo)))      ; restore the undo list

แก้ไข:จริง ๆ แล้วมันกลับกลายเป็นว่าวิธีแก้ปัญหาที่ง่ายกว่านั้นยังคงเป็นเพียงการletผูกbuffer-undo-listเพื่อให้การเปลี่ยนแปลงในรายการในเนื้อความของการletอุดตันเมื่อรายการเดิมถูกกู้คืน:

(defun disable-undo-one-off ()
  (let (buffer-undo-list)
    (do-some-stuff)))

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


คุณอาจต้องการห่อสิ่งนั้นด้วยการป้องกันอย่างผ่อนคลายในกรณีที่คุณแยกตัวออกจากกิจกรรมระหว่างทาง ฉันไม่ทราบว่าคุณกำลังทำสิ่งนี้ทั้งหมดในฟังก์ชั่นซึ่งทำให้การติดตามสิ่งต่างๆง่ายขึ้น
stsquad

คุณสามารถเพิ่มในโซลูชันสำหรับการอัปเดตการประทับเวลาเพื่อไม่อัปเดตประวัติเลิกทำ (และประวัติจุดถ้าเป็นไปได้) หรือไม่
Kaushal Modi

@stsquad: ความคิดที่ดีจะพยายามทำในภายหลัง ขอขอบคุณอีกครั้งสำหรับเคล็ดลับเกี่ยวกับฟังก์ชั่นและรายการที่เป็นปัญหา
ด่าน

@kaushalmodi: คำถามที่ชัดเจน: ความหมายที่คุณต้องการเห็นฟังก์ชั่นการอัพเดทเวลาจริง?
แดน

@Dan ต้องการดูวิธีการแก้ไขฟังก์ชั่นการอัพเดตเวลาประทับเพื่อไม่อัปเดตการเลิกทำหรือประวัติจุด
Kaushal Modi

3

การดำเนินการยกเลิกการรวมองค์ประกอบหลายอย่างจากการเลิกทำรายการ nilรายการในเครื่องหมายรายการเขตแดนระหว่างสองกลุ่มการเปลี่ยนแปลง ด้วยการลบnilจุดเริ่มต้นของรายการซึ่งถูกแทรกโดยลูประดับบนโดยอัตโนมัติคุณสามารถจัดกลุ่มการอัพเดตเวลาประทับด้วยการเปลี่ยนบัฟเฟอร์สุดท้ายซึ่งในทางเทคนิคไม่ตรงกับคำขอของคุณ แต่ในทางปฏิบัติควรแก้ไขปัญหาในสถานการณ์ของคุณ

(defun time-stamp-group-undo ()
  (if (eq nil (car buffer-undo-list))
      (setq buffer-undo-list (cdr buffer-undo-list)))
  (time-stamp))

(คำเตือน: ยังไม่ได้ทดสอบรายการเลิกทำอาจต้องการการนวดมากกว่า)

นอกจากนี้คุณยังสามารถเล่นกับรายการเลิกทำในวิธีที่แตกต่างกันโดยการแก้ไขรายการตำแหน่ง (จำนวนเต็ม) สำหรับการปรับปรุงการประทับเวลา

¹ ไม่กำจัดคล้ายกับการแทรกกลุ่ม self-insert-command


2

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

(defun my-toggle-buffer-undo ()
  "Toggle undo tracking in current buffer."
  (interactive)
  (with-current-buffer (current-buffer)
    (if (eq buffer-undo-list t)
        (setq buffer-undo-list nil)
      (buffer-disable-undo (current-buffer)))))

(define-key my-toggle-map "u" 'my-toggle-buffer-undo)

buffer-disable-ยกเลิกจริงเพียงชุดbuffer-ยกเลิกรายการที่จะเป็นศูนย์ บางทีถ้าคุณบันทึกสถานะของbuffer-undo-listในการสลับคุณสามารถเรียกคืนได้ในภายหลัง

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