Wie exportiere ich Überschriften des Organisationsmodus-Puffers auf oberster Ebene in separate Dateien?

17

Wie kann jede Überschrift eines org-modePuffers auf oberster Ebene in eine separate Datei exportiert werden, die nach dem Wert des entsprechenden CUSTOM_ID+ (bereinigten) Titels benannt ist?

Angenommen, ein Puffer enthält:

* Title of Heading 1
  :PROPERTIES:
  :CUSTOM_ID: fibrillogenesis
  :END:
  Suspendisse potenti. Mauris ac felis vel velit tristique imperdiet.  

** Sub-Heading
   Nullam rutrum.

* Another Title for Heading 2
  :PROPERTIES:
  :CUSTOM_ID: mitochondrion
  :END:
  Mauris mollis tincidunt felis.  Sed bibendum.

Das Endergebnis wäre ein Verzeichnis mit zwei Dateien, eine für jede der beiden Überschriften der obersten Ebene, mit dem beim Export ausgewählten Format (HTML, LaTeX usw.) und den folgenden Dateinamen und Inhalten:

  1. Dateiname der ersten exportierten Überschrift: fibrillogenesis-title-of-heading-1.[ext]

    Exportierter Inhalt, der der ursprünglichen Überschrift der obersten Ebene entspricht:

    * Title of Heading 1
      :PROPERTIES:
      :CUSTOM_ID: fibrillogenesis
      :END:
      Suspendisse potenti. Mauris ac felis vel velit tristique imperdiet.  
    
    ** Sub-Heading 
       Nullam rutrum.
    
  2. Dateiname der zweiten exportierten Überschrift: mitochondrion-another-title-for-heading-2.[ext]

    Exportierter Inhalt, der der ursprünglichen Überschrift der zweiten obersten Ebene entspricht:

    * Another Title for Heading 2
    :PROPERTIES:
    :CUSTOM_ID: mitochondrion
    :END:
    Mauris mollis tincidunt felis.  Sed bibendum. 
    

Ich wäre für jeden Hinweis, jede Anweisung, jeden Pseudocode oder (besseren) echten Code sehr dankbar.

gsl
quelle

Antworten:

27

Mit dem folgenden Befehl können Sie ein Back-End auswählen und anschließend jeden Unterbaum der obersten Ebene in eine separate Datei exportieren:

(defun org-export-all (backend)
  "Export all subtrees that are *not* tagged with :noexport: to
separate files.

Note that subtrees must have the :EXPORT_FILE_NAME: property set
to a unique value for this to work properly."
  (interactive "sEnter backend: ")
  (let ((fn (cond ((equal backend "html") 'org-html-export-to-html)
                  ((equal backend "latex") 'org-latex-export-to-latex)
                  ((equal backend "pdf") 'org-latex-export-to-pdf))))
    (save-excursion
      (set-mark (point-min))
      (goto-char (point-max))
      (org-map-entries (lambda () (funcall fn nil t)) "-noexport" 'region-start-level))))

Dies unterstützt derzeit den Export von HTML ( html), LaTeX ( latex) und PDF ( pdf). Sie können Unterstützung für mehr Back-Ends hinzufügen, indem Sie weitere Klauseln hinzufügen cond.

Wie in der Dokumentation angegeben, müssen Sie für jede Unterstruktur die :EXPORT_FILE_NAME:Eigenschaft auf den Dateinamen festlegen, in den sie exportiert werden soll. (Weitere Optionen siehe unten.)

Der Name der Exportdatei wird automatisch aus dem Überschriftentext generiert

Wenn Sie nicht :EXPORT_FILE_NAME:jeder Überschrift der obersten Ebene Eigenschaften hinzufügen möchten , können Sie org-export-allden Dateinamen so ändern , dass er automatisch aus z. B. dem Überschriftentext generiert wird. Diese Einstellung wird :EXPORT_FILE_NAME:beim Export vorübergehend festgelegt :

(defun org-export-all (backend)
  "Export all subtrees that are *not* tagged with :noexport: to
separate files.

Subtrees that do not have the :EXPORT_FILE_NAME: property set
are exported to a filename derived from the headline text."
  (interactive "sEnter backend: ")
  (let ((fn (cond ((equal backend "html") 'org-html-export-to-html)
                  ((equal backend "latex") 'org-latex-export-to-latex)
                  ((equal backend "pdf") 'org-latex-export-to-pdf)))
        (modifiedp (buffer-modified-p)))
    (save-excursion
      (set-mark (point-min))
      (goto-char (point-max))
      (org-map-entries
       (lambda ()
         (let ((export-file (org-entry-get (point) "EXPORT_FILE_NAME")))
           (unless export-file
             (org-set-property
              "EXPORT_FILE_NAME"
              (replace-regexp-in-string " " "_" (nth 4 (org-heading-components)))))
           (funcall fn nil t)
           (unless export-file (org-delete-property "EXPORT_FILE_NAME"))
           (set-buffer-modified-p modifiedp)))
       "-noexport" 'region-start-level))))

Diese Funktion generiert den Exportdateinamen, indem Leerzeichen im Überschriftentext durch "_" ersetzt werden. Wenn Sie den Dateinamen auf eine andere Weise generieren möchten, ändern Sie das replace-regexp-in-stringSexp nach Ihren Wünschen.

Die Erzeugung :EXPORT_FILE_NAME:bei der Einstellung:CUSTOM_ID:

Mit den folgenden Ratschlägen org-set-propertywird automatisch ein geeigneter Wert für festgelegt, :EXPORT_FILE_NAME:wenn Sie :CUSTOM_ID::

(defadvice org-set-property (after set-export-file-name
                                   (property value) activate compile)
  (when (equal org-last-set-property "CUSTOM_ID")
    (let ((export-file-name
           (concat (org-entry-get nil "CUSTOM_ID")
                   "-"
                   (replace-regexp-in-string " " "-" (downcase (org-get-heading t t))))))
      (org-entry-put nil "EXPORT_FILE_NAME" export-file-name))))

Beachten Sie, dass hierdurch keine Dateierweiterung zum Wert von hinzugefügt wird, dies :EXPORT_FILE_NAME:jedoch keine Rolle spielt, da beim Export in ein bestimmtes Back-End org-mode automatisch die richtige Erweiterung für die resultierenden Dateien ausgewählt wird .


Zusätzliche Information

Aktualisieren vorhandener Teilbäume in großen Mengen

Wenn Sie über eine große Anzahl vorhandener Unterstrukturen verfügen, für die Sie die :EXPORT_FILE_NAME:Eigenschaft festlegen müssen , können Sie ein Tastaturmakro verwenden . Positionieren Sie den Punkt auf dem ersten Teilbaum und gehen Sie dann wie folgt vor:

  • F3

    ... um die Aufnahme zu starten.

  • C-c C-x p CUSTOM_ID RET RET

    ... um Emacs :EXPORT_FILE_NAME:basierend auf :CUSTOM_ID:.

  • C-c C-f

    ... um zur nächsten übergeordneten Überschrift zu gelangen.

  • F4

    ... um die Aufnahme zu stoppen.

Drücken Sie, um das Makro für den nächsten Teilbaum zu wiederholen F4. Um das Makro für alle verbleibenden Teilbäume zu wiederholen , drücken Sie M-0 F4(das ist eine Null).

Speichern von Makros für zukünftige Sitzungen

Standardmäßig werden Tastaturmakros nicht sitzungsübergreifend gespeichert. Gehen Sie folgendermaßen vor, um das Makro zur späteren Verwendung in Ihrer Init-Datei zu speichern:

  1. Nennen Sie das Makro:

    M-x name-last-kbd-macro RET org-set-export-file-name RET

  2. Suchen Sie Ihre Init-Datei und verschieben Sie sie an eine Stelle, an der Sie das Makro einfügen möchten.

  3. Fügen Sie das Makro ein:

    M-x insert-kbd-macro RET org-set-export-file-name RET

    Emacs fügt an dieser Stelle den folgenden Code ein:

    (fset 'org-set-export-file-name
       "\C-c\C-xpCUSTOM_ID\C-m\C-m\C-c\C-f")
    

    Wenn Sie stark genug blinzeln, können Sie sehen, dass das zweite Argument fsetdie Tastenfolge enthält, die Sie beim Aufzeichnen des Makros gedrückt haben :)

  4. (Optional) Die besten Ergebnisse erzielen Sie, wenn Sie org-set-export-file-namean einen Schlüssel binden :

    (define-key org-mode-map (kbd "<f6>") 'org-set-export-file-name)
  5. Speichern.

itsjeyd
quelle
1
Nett. Können Sie mir einen Hinweis geben, wie die :EXPORT_FILE_NAME:Eigenschaften :CUSTOM_ID:+heading-title-lowercasedfür jede Überschrift programmgesteuert festgelegt werden ?
gsl
1
@gsl Sie können empfehlen org-set-property, die :EXPORT_FILE_NAME:Eigenschaft beim Festlegen automatisch zu generieren :CUSTOM_ID:.
itsjeyd
1
Danke für den Ratschlag! Ich bin nicht so fließend elisp, aber ich werde es versuchen. Ich muss herausfinden, wie man den Titel jeder Überschrift erfasst, Leerzeichen durch Bindestriche ersetzt, in Kleinbuchstaben setzt, diese bereinigte Zeichenfolge zu :CUSTOM_ID:einer org-Eigenschaft hinzufügt und schließlich eine org-Eigenschaft festlegt.
gsl
1
@gsl Ich habe eine defadvicezu meiner Antwort hinzugefügt , die automatisch auf festgelegt wird :EXPORT_FILE_NAME:, <custom-id>-<heading>wenn Sie festlegen :CUSTOM_ID:.
itsjeyd
1
Vielen Dank, ich habe viel mit Ihrem Code gelernt. Wenn man schon eine org-modeDatei mit CUSTOM_IDs gesetzt hätte, wie könnte man den Code ausführen, um "EXPORT_FILE_NAME" zu setzen? Es würde keine neuen Einfügungen geben. Ich vermute, defadvicewürde nicht funktionieren? Gibt es eine Schleifenfunktion, um alle Überschriften der obersten Ebene zu durchlaufen und den Code auf sie anzuwenden?
gsl