Come esportare le intestazioni di livello superiore del buffer in modalità org in file separati?


17

Come è possibile org-modeesportare ogni intestazione di livello superiore di un buffer in un file separato che prende il nome dal valore corrispondente CUSTOM_ID+ (sanificato)?

Diciamo che un buffer contiene:

* 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.

Il risultato finale sarebbe una directory contenente due file, uno per ciascuna delle due intestazioni di livello superiore, con il formato scelto al momento dell'esportazione (HTML, LaTeX, ecc.), Con i seguenti nomi e contenuti:

  1. Nome file della prima voce esportata: fibrillogenesis-title-of-heading-1.[ext]

    Contenuto esportato, corrispondente alla prima intestazione di primo livello originale:

    * Title of Heading 1
      :PROPERTIES:
      :CUSTOM_ID: fibrillogenesis
      :END:
      Suspendisse potenti. Mauris ac felis vel velit tristique imperdiet.  
    
    ** Sub-Heading 
       Nullam rutrum.
    
  2. Nome file della seconda voce esportata: mitochondrion-another-title-for-heading-2.[ext]

    Contenuto esportato, corrispondente alla seconda intestazione di primo livello originale:

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

Sarei molto grato per qualsiasi suggerimento, direzione, pseudocodice o (migliore) codice reale.

Risposte:


27

Il seguente comando consente di scegliere un back-end e quindi esporta ogni sottostruttura di livello superiore in un file separato:

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

Attualmente supporta l' esportazione HTML ( html), LaTeX ( latex) e PDF ( pdf). È possibile aggiungere supporto per più back-end aggiungendo più clausole a cond.

Come dice il docstring, per ogni sottostruttura è necessario impostare la :EXPORT_FILE_NAME:proprietà sul nome del file in cui si desidera esportare. (Vedi sotto per altre opzioni.)

Generazione automatica del nome del file di esportazione dal testo dell'intestazione

Se non si desidera aggiungere :EXPORT_FILE_NAME:proprietà a tutte le intestazioni di livello superiore, è possibile modificare org-export-allper generare automaticamente il nome file, ad esempio il testo dell'intestazione, impostando temporaneamente :EXPORT_FILE_NAME:durante l'esportazione:

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

Questa funzione genera il nome file di esportazione sostituendo gli spazi con "_" nel testo del titolo. Se vuoi generare il nome del file in un altro modo, cambia il replace-regexp-in-stringsexp come preferisci.

Generazione :EXPORT_FILE_NAME:durante l'impostazione:CUSTOM_ID:

Con il seguente consiglio, org-set-propertyimposterai automaticamente un valore appropriato per :EXPORT_FILE_NAME:quando imposti :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))))

Nota che questo non aggiungerà un'estensione di file al valore di :EXPORT_FILE_NAME:ma che non importa perché quando esporti in un back-end specifico, org-mode sceglierà automaticamente l'estensione corretta per i file risultanti .


Informazioni aggiuntive

Aggiornamento di sottotitoli esistenti in blocco

Se si dispone di un numero elevato di sottotitoli esistenti per i quali è necessario impostare la :EXPORT_FILE_NAME:proprietà, è possibile utilizzare una macro della tastiera . Posizionare il punto sulla prima sottostruttura, quindi effettuare le seguenti operazioni:

  • F3

    ... per iniziare la registrazione.

  • C-c C-x p CUSTOM_ID RET RET

    ... per impostare Emacs in :EXPORT_FILE_NAME:base :CUSTOM_ID:.

  • C-c C-f

    ... per passare al titolo di primo livello successivo.

  • F4

    ... per interrompere la registrazione.

Per ripetere la macro per la sottostruttura successiva, premere F4. Per ripetere la macro per tutti i sottotitoli rimanenti, premere M-0 F4(che è uno zero).

Salvataggio di macro per sessioni future

Per impostazione predefinita, le macro della tastiera non vengono salvate tra le sessioni. Per memorizzare la macro nel file init per uso futuro, procedere come segue:

  1. Denominare la macro:

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

  2. Trova il tuo file init e spostati in un punto in cui desideri inserire la macro.

  3. Inserisci la macro:

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

    Emacs inserirà il seguente codice al punto:

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

    Se strizzi gli occhi abbastanza forte, puoi vedere che il secondo argomento fsetcontiene la sequenza di tasti che hai premuto quando hai registrato la macro :)

  4. (Facoltativo) Per risultati ottimali, potresti voler associare org-set-export-file-nameuna chiave:

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


1
Bello. Potresti darmi un suggerimento su come impostare programmaticamente la :EXPORT_FILE_NAME:proprietà :CUSTOM_ID:+heading-title-lowercasedper ogni intestazione?
gsl

1
@gsl Potresti consigliare org-set-propertydi generare automaticamente la :EXPORT_FILE_NAME:proprietà al momento dell'impostazione :CUSTOM_ID:.
itsjeyd

1
Grazie per il consiglio! Non sono così fluente elisp, ma ci proverò. Devo scoprire come catturare il titolo di ciascuna intestazione, sostituire uno spazio bianco con un trattino, mettere in minuscolo, aggiungere quella stringa disinfettata :CUSTOM_ID:e infine impostare una proprietà org.
gsl

1
@gsl ho aggiunto una defadvicealla mia risposta che imposta automaticamente :EXPORT_FILE_NAME:a <custom-id>-<heading>quando si imposta :CUSTOM_ID:.
itsjeyd

1
Grazie mille, ho imparato molto con il tuo codice. Se uno avesse già un org-modefile con CUSTOM_IDs impostato, come si potrebbe eseguire il codice per impostare "EXPORT_FILE_NAME"? Non ci sarebbero nuovi inserimenti. Immagino defadviceche non funzionerebbe? Esiste una funzione di loop per attraversare tutte le intestazioni di livello superiore e applicare il codice ad esse?
gsl
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.