Kopieren Sie den Inhalt des aktuellen Puffers in einen temporären Puffer und bearbeiten Sie ihn


8

Ich muss den Inhalt des aktuellen Puffers in einen temporären Puffer kopieren, diesen Puffer auf einen bestimmten Hauptmodus einstellen, um seine Vorteile zu nutzen und die benötigten Informationen an die Hauptlogik zurückzugeben.

Ist das völliger Wahnsinn? Und wenn nicht, wie ist die Struktur dafür?

Antworten:


10

Wenn Sie einige Informationen in einen anderen Puffer kopieren und von da an die Puffer unabhängig voneinander entwickeln möchten, können Sie genau das tun .

Wenn Sie jedoch möchten, dass der andere Puffer den ursprünglichen Inhalt in Echtzeit widerspiegelt, stellt Emacs diesen indirekte Puffer zur Verfügung . Ein indirekter Puffer ist ein weiterer Puffer, der den gleichen Inhalt wie das Original hat (Änderungen in einem Puffer werden im anderen Puffer wiedergegeben), jedoch unterschiedliche Einstellungen: ein anderer Hauptmodus, verschiedene Nebenmodi, verschiedene lokale Variablen, ein anderer Punkt, verschiedene Markierungen , eine andere Verengung usw.

So können Sie einen Teil eines Puffers in einem anderen Hauptmodus anzeigen, während Sie Änderungen im ursprünglichen Puffer verfolgen und Änderungen am ursprünglichen Puffer wiedergeben. Machen Sie zuerst einen indirekten Puffer mit M-x clone-indirect buffer; es gibt auch clone-indirect-buffer-other-windowwas gebunden ist C-x 4 c( C-x 4Fensterpräfix und cfür Klon ). In dem geklonten Puffer, verengt , um die gewünschte Region: Wählen Sie den interessanten Teil und Lauf C-x n n( narrow-to-region). Ändern Sie den Hauptmodus wie gewünscht.

Sie können dies mit einem Befehl wie diesem für die interaktive Verwendung automatisieren:

(defun edit-region-in-foo-mode (beg end)
  (interactive "@r")
  (let ((new-buffer (clone-indirect-buffer nil t)))
    (narrow-to-region beg end)
    (foo-mode)))

Zur Programmierung verwenden:

(defmacro with-indirect-buffer-in-foo-mode (beg end &rest body)
  `(with-current-buffer (clone-indirect-buffer nil nil)
     (narrow-to-region beg end)
     (foo-mode)
     (unwind-protect
         ,body
       (kill-buffer (current-buffer)))))

8

Etwas wie das:

(let ((old-buffer (current-buffer)))
  (with-temp-buffer
    (insert-buffer-substring old-buffer)
    (my-favourite-major-mode 1)
    (extract-needed-information)))

2
Schrieb fast genau das auf. Wickeln Sie das einfach in einen Defun, wenn Sie es willkürlich nennen müssen
Jonathan Leech-Pepin

Das sieht ziemlich gut aus. Ich werde ein bisschen warten, nur für den Fall, dass es etwas Besseres gibt, das als akzeptiert markiert werden kann, aber ich denke, das ist es :)
Trevoke

Ich habe tatsächlich vorgeschlagen M-x copy-to-buffer, dann habe ich die @ legoscia-Antwort rot, was wahrscheinlich das ist, was Sie wollen. Wenn der Extraktionsprozess und der
Hauptmodus

2

Mir hat gefallen, was @ Gilles geschrieben hat. Ich habe geändert, was @Gilles geschrieben hat, um den Benutzer zu fragen, welchen Modus er verwenden möchte. Sie können das, was ich geschrieben habe, bearbeiten, um die von Ihnen bevorzugten Modi bereitzustellen, oder den Aufruf sogar so ändern, dass der Lesevorgang abgeschlossen ist, sodass Sie einen Modus bereitstellen können, der nicht in der Standardliste enthalten ist.

(defun edit-region-in-mode (beg end)
  "Create an indirect buffer cloned from the current buffer and
  narrowed to the highlighted region. The cloned indirect buffer
  will have org-mode active. Changes to the indirect buffer will
  be updated in real time in the originating buffer. This is
  useful, for instance, when you are in a non-org-mode mode and
  want to edit table data or in a non-emacs-lisp mode and want to
  write some elisp utilizing code formatting and highlighting."
  (interactive "@r")
  (let ((new-buffer (clone-indirect-buffer nil t)))
    (narrow-to-region beg end)
    (funcall
     (intern
      (completing-read
       "Choose the mode you want to use when editing the highlighted region: "
       '(org-mode emacs-lisp-mode lisp-mode haskell-mode julia-mode
          python-mode mathematica-mode matlab-mode c++-mode))))))

1

Für einen ähnlichen Anwendungsfall hatte ich eine Elisp-Funktion geschrieben modi/switch-to-scratch-and-back, mit der Sie schnell zwischen einer Pufferdatei und einem * Scratch * -Puffer mit demselben Hauptmodus wie der FILE-Puffer wechseln können. Die oben verlinkte Hyperlink-Funktion führt Sie zu einer vorhandenen Emacs SE-Frage.

So können Sie diese Funktion verwenden:

  • Erstellen Sie eine Wrapper-Funktion, um Ihren vorhandenen Puffer zu kopieren, erstellen Sie einen * Scratch * -Puffer mit demselben Hauptmodus und fügen Sie den kopierten Inhalt ein.

Hier ist ein Beispiel für eine Wrapper-Funktion

(defun copy-current-buffer-to-scratch ()
 "Copied the current buffer, open scratch, paste it there."
  (interactive)
  (kill-ring-save (point-min) (point-max))
  (modi/switch-to-scratch-and-back)
  (yank))
  • Sie können dies jetzt copy-current-buffer-to-scratchan einen Schlüssel binden , wenn Sie dies wünschen. Wenn Sie ihn ausführen, erhalten Sie einen * Scratch * -Puffer mit Inhalten aus Ihrem Arbeitspuffer.
  • Sobald Sie mit den Änderungen im Arbeitspuffer zufrieden sind, müssen Sie den erforderlichen Abschnitt manuell in den ursprünglichen Puffer zurückkopieren.

Dies ist nur eine andere Möglichkeit, das zu tun, was Sie wollen. Möglicherweise möchten Sie jedoch indirekte Puffer verwenden, über die die @ Gilles-Lösung spricht. Dieser Ansatz ist nützlich, wenn Sie einige umfangreiche Änderungen in einem temporären Puffer vornehmen müssen, ohne das Risiko eines versehentlichen Speicherns im ursprünglichen Puffer einzugehen, bis Sie eine stabile Lösung erreicht haben.

Ein Beispiel für einen Anwendungsfall ist das Ausprobieren experimenteller Elisp-Funktionen, bevor diese auf Ihrem Emacs-Init gespeichert werden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.