Bagaimana cara mengubah buffer tanpa membatalkan pemberitahuan?

11

T: Bagaimana cara saya menyisipkan / memodifikasi teks dalam buffer tanpa undomemperhatikan?

Ini kasus penggunaannya. Saya memiliki blok komentar di awal setiap file yang, antara lain, memperbarui stempel waktu untuk perubahan terbaru ke file. Saya ingin dapat memodifikasi stempel waktu tanpa undofasilitas menyadarinya.

Alasan saya ingin melakukan hubungan arus pendek di undosini adalah karena kasus tepi berikut, yang muncul saat mengedit / mengkompilasi dokumen LaTeX (dan mungkin yang lain, tetapi ini adalah yang paling sering membuat saya gila):

  1. Buat perubahan kecil pada file untuk melihat bagaimana itu akan mempengaruhi dokumen yang dikompilasi
  2. Simpan file (yang memperbarui cap waktu)
  3. Jalankan latexpada file
  4. Putuskan bahwa perubahan itu buruk
  5. undo perubahan

Masalah pada langkah (5) ( undo) adalah bahwa hal itu tidak membatalkan perubahan yang dibuat pada langkah (1), melainkan membatalkan pembaruan timestamp pada langkah (2). Itu tidak akan mengganggu saya (saya bisa saja undolagi) kecuali bahwa itu juga bergerak menunjuk ke stempel waktu di bagian atas file, yang hampir selalu banyak, banyak baris dari perubahan substantif yang sebenarnya. Ini sangat menggelegar dan benar-benar merusak konsentrasi saya.

Saya mengajukan pertanyaan sehubungan dengan file yang saya kunjungi, tetapi lebih umum tentang memodifikasi buffer.

Jadi: bagaimana saya bisa mencegah undodari melihat modifikasi spesifik ke buffer?

Dan
sumber
1
Ini tidak terkait dengan pertanyaan undo Anda, tetapi mungkin membantu dengan masalah "undo move the point": stackoverflow.com/a/20510025/1279369
pengasuh
2
Bukankah lebih baik jika perubahan cap tanggal ini ditambahkan ke item terbaru dalam sejarah undo? Dengan cara itu undoakan membatalkan keduanya.
Malabarba
Saya pikir apa yang Anda inginkan sebenarnya atomic-change-group.
@ John: Bagaimana itu membantu? Dua perubahan pada grup dipicu oleh perintah yang terpisah: "perubahan kecil" (misalnya penyisipan) dan pembaruan cap waktu yang dilakukan saat menyimpan.
Gilles 'SO- stop being evil'
Perhatikan bahwa karena alasan tertentu tidak ada metode ini dalam jawaban yang ada yang berfungsi untuk saya, namun jawaban ini menentukan with-undo-collapsemakro yang sangat berguna: emacs.stackexchange.com/a/7560/2418
ideasman42

Jawaban:

6

@ stsquad menjawab saya di jalan yang benar. Pada dasarnya, langkah-langkahnya adalah:

  1. menyimpan buffer-undo-list
  2. nonaktifkan undo
  3. lakukan pekerjaanmu
  4. mengaktifkan undokembali dan mengembalikanbuffer-undo-list

Jadi inilah sketsa dari fungsi seperti itu:

(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

Sunting: sebenarnya, ternyata solusi yang lebih sederhana adalah hanya let-bind buffer-undo-listsehingga perubahan ke daftar di badan letget clobbered ketika daftar asli dipulihkan:

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

Keterbatasan utama dengan ini adalah bahwa hal itu tampaknya berfungsi untuk modifikasi yang tidak mengubah jumlah karakter dalam buffer (misalnya, mengubah "anak kucing" menjadi "anak anjing", tetapi bukan "kucing"), karena jika tidak maka sisa undo daftar sekarang mengacu pada poin yang salah. Karenanya, ini hanya solusi parsial .

Dan
sumber
Anda mungkin ingin membungkusnya dalam perlindungan santai jika Anda keluar dari aktivitas di tengah-tengah hal Anda. Saya tidak menyadari Anda melakukan ini semua dalam suatu fungsi yang membuat melacak hal-hal lebih mudah.
stsquad
Bisakah Anda juga menambahkan solusi untuk pembaruan cap waktu untuk tidak memperbarui riwayat undo (dan sejarah titik, jika mungkin)?
Kaushal Modi
@stsquad: ide bagus, akan mencoba melakukannya nanti. Sekali lagi terima kasih atas informasi tentang fungsi dan daftar yang dimaksud.
Dan
@kaushalmodi: pertanyaan klarifikasi: artinya Anda ingin melihat fungsi pembaruan stempel waktu yang sebenarnya?
Dan
@Dan Ingin melihat cara memodifikasi fungsi pembaruan stempel waktu untuk tidak memperbarui undo atau histori titik.
Kaushal Modi
3

Operasi undo menggabungkan beberapa elemen dari daftar undo . Sebuah nilentri dalam daftar tanda batas antara dua kelompok perubahan. Dengan menghapus nildi awal daftar yang secara otomatis disisipkan oleh loop tingkat atas¹, Anda dapat mengelompokkan pembaruan stempel waktu dengan perubahan buffer terakhir, yang secara teknis tidak cocok dengan permintaan Anda, tetapi secara praktis akan menyelesaikan masalah dalam skenario Anda.

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

(Peringatan: belum diuji, daftar undo mungkin memerlukan lebih banyak pemijatan.)

Anda juga dapat bermain dengan daftar undo dengan cara yang berbeda, dengan memodifikasi entri posisi (bilangan bulat) untuk pembaruan cap waktu.

¹ melakukan penghapusan serupa dengan sisipan grup. self-insert-command

Gilles 'SANGAT berhenti menjadi jahat'
sumber
2

Masalah dengan apa yang Anda sarankan adalah bahwa undo-tree adalah daftar delta yang bisa Anda dapatkan di tempat yang Anda inginkan. Meskipun sangat mungkin untuk menonaktifkan membatalkan pelacakan pada buffer, saya tidak yakin apa efek dari tidak secara aktif merekam perubahan. Saat ini saya memiliki sakelar untuk mengaktifkan / menonaktifkan pembatalan pada buffer tertentu karena tidak masuk akal untuk membatalkan informasi pada log yang tumbuh atau halaman yang menyegarkan. Namun itu mengubah perubahan pada toggle:

(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-undo sebenarnya hanya menetapkan buffer-undo-list menjadi nil . Mungkin jika Anda menyimpan status buffer-undo-list pada Anda beralih Anda dapat mengembalikannya setelah itu?

stsquad
sumber