Jak zmodyfikować bufor bez cofania powiadomienia?

11

P: Jak wstawić / zmodyfikować tekst w buforze bez undozauważenia?

Oto przypadek użycia. Na początku każdego pliku mam blok komentarza, który między innymi aktualizuje znacznik czasu ostatniej zmiany pliku. Chciałbym móc modyfikować ten znacznik czasu bez undozauważania go przez urządzenia.

Powodem, dla którego chcę undotutaj zewrzeć , jest następujący przypadek krawędzi, który pojawia się podczas edytowania / kompilowania dokumentów LaTeX (i prawdopodobnie innych, ale to ten, który najbardziej mnie doprowadza do szału):

  1. Wprowadź niewielką zmianę w pliku, aby zobaczyć, jak wpłynie on na skompilowany dokument
  2. Zapisz plik (który aktualizuje znacznik czasu)
  3. Uruchom latexna pliku
  4. Zdecyduj, że zmiana jest zła
  5. undo zmiany

Problem w kroku (5) ( undo) polega na tym, że nie powoduje to cofnięcia zmiany dokonanej w kroku (1), a raczej cofnięcie aktualizacji znacznika czasu w kroku (2). To by mi nie przeszkadzało (mógłbym jeszcze undoraz), z wyjątkiem tego, że przesuwa się on aż do znacznika czasu na górze pliku, który prawie zawsze jest o wiele, wiele linii od faktycznej zmiany merytorycznej. To bardzo denerwujące i całkowicie zaburza moją koncentrację.

Zadaję pytanie dotyczące pliku, który odwiedzam, ale ogólnie chodzi o modyfikację buforów.

Więc: jak mogę zapobiec undozauważeniu określonej modyfikacji bufora?

Dan
źródło
1
Nie ma to związku z pytaniem o cofnięcie, ale może pomóc w rozwiązaniu problemu „cofnij przesunięcie punktu”: stackoverflow.com/a/20510025/1279369
niania
2
Czy nie byłoby najlepiej, gdyby ta zmiana datownika została dodana do najnowszego elementu w historii cofania? W ten sposób undocofnęłoby się jedno i drugie.
Malabarba,
Myślę, że tak naprawdę chcesz atomic-change-group.
@john: Jak to by pomogło? Dwie zmiany w grupie są wywoływane przez osobne polecenia: „niewielka zmiana” (np. Wstawienie) i aktualizacja znacznika czasu dokonanego podczas zapisywania.
Gilles „SO- przestań być zły”
Zauważ, że z jakiegoś powodu żadna z tych metod w istniejących odpowiedziach nie działała dla mnie, jednak ta odpowiedź definiuje with-undo-collapsemakro, które było bardzo przydatne: emacs.stackexchange.com/a/7560/2418
ideasman42

Odpowiedzi:

6

Odpowiedź @ stsquad doprowadziła mnie na właściwą ścieżkę. Zasadniczo kroki są następujące:

  1. zapisać buffer-undo-list
  2. wyłączyć undo
  3. Rób swoje
  4. włącz ponownie undoi przywróćbuffer-undo-list

Oto szkic takiej funkcji:

(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

Edycja: w rzeczywistości okazuje się, że prostszym rozwiązaniem jest po prostu let-bindowanie buffer-undo-list, aby zmiany na liście w treści letzostały zablokowane po przywróceniu oryginalnej listy:

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

Głównym ograniczeniem jest to, że wydaje się, że działa w przypadku modyfikacji, które nie zmieniają liczby znaków w buforze (np. Zmieniają „kocięta” na „szczenięta”, ale nie „koty”), ponieważ w przeciwnym razie reszta cofania lista odnosi się teraz do niewłaściwych punktów. Dlatego jest to tylko częściowe rozwiązanie .

Dan
źródło
Możesz owijać to w ochronę przed odprężeniem na wypadek, gdybyś wyszedł z aktywności w połowie drogi. Nie zdawałem sobie sprawy, że robisz to wszystko w funkcji, która ułatwia śledzenie rzeczy.
stsquad
Czy możesz również dodać rozwiązanie aktualizacji sygnatury czasowej, aby nie aktualizować historii cofania (i historii punktów, jeśli to możliwe)?
Kaushal Modi
@stsquad: dobry pomysł, spróbuję to zrobić później. Jeszcze raz dziękuję za podpowiedź na temat omawianych funkcji i listy.
Dan
@kaushalmodi: wyjaśnienie pytania: co oznacza, że ​​chcesz zobaczyć aktualną funkcję aktualizacji sygnatury czasowej?
Dan
@ Dan Chciałbym zobaczyć, jak zmodyfikować funkcję aktualizacji znacznika czasu, aby nie aktualizować cofania lub historii punktów.
Kaushal Modi
3

Operacja cofania łączy kilka elementów z listy cofania . nilWpis znaków lista granica między dwiema grupami zmiana. Usuwając nilpoczątek listy, która jest automatycznie wstawiana przez pętlę najwyższego poziomu¹, możesz zgrupować aktualizację znacznika czasu z ostatnią zmianą bufora, która technicznie nie odpowiada twojemu żądaniu, ale praktycznie powinna rozwiązać problem w twoim scenariuszu.

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

(Ostrzeżenie: nieprzetestowane, lista cofnięć może wymagać więcej masowania.)

Możesz także grać z listą cofnięć w inny sposób, modyfikując wpis pozycji (liczbę całkowitą) dla aktualizacji sygnatury czasowej.

¹ robi podobne usuwanie do wstawiania grup. self-insert-command

Gilles „SO- przestań być zły”
źródło
2

Problem z tym, co sugerujesz, polega na tym, że cofnięcie drzewa jest listą delt, które można dostać z miejsca, w którym się znajdujesz, do miejsca, w którym chcesz się znaleźć. Chociaż można całkowicie wyłączyć śledzenie cofania w buforze, nie jestem pewien, jaki byłby efekt nieaktywnego rejestrowania zmian. Obecnie mam przełącznik, aby włączyć / wyłączyć cofanie w określonym buforze, ponieważ nie ma sensu, aby cofać informacje w rosnącym dzienniku lub odświeżającej stronie. Jednak niweluje zmiany przy przełączaniu:

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

bufor-wyłącz-cofnij tak naprawdę ustawia bufor-cofnij listę na zero . Może jeśli zapisałeś stan przełączania buforów na liście , możesz go później przywrócić?

stsquad
źródło