Bagaimana cara mengekspor judul tingkat atas dari buffer mode-org ke file yang terpisah?

17

Bagaimana setiap tajuk tingkat atas dari org-modebuffer diekspor ke file terpisah yang dinamai sesuai dengan nilai judul CUSTOM_ID+ yang disanitasi?

Katakanlah buffer berisi:

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

Hasil akhirnya adalah direktori yang berisi dua file, satu untuk masing-masing dari dua judul tingkat atas, dengan format yang dipilih pada waktu ekspor (HTML, LaTeX, dll.), Dengan nama file dan konten berikut:

  1. Nama file dari pos yang diekspor pertama: fibrillogenesis-title-of-heading-1.[ext]

    Konten yang diekspor, sesuai dengan tajuk tingkat atas pertama asli:

    * Title of Heading 1
      :PROPERTIES:
      :CUSTOM_ID: fibrillogenesis
      :END:
      Suspendisse potenti. Mauris ac felis vel velit tristique imperdiet.  
    
    ** Sub-Heading 
       Nullam rutrum.
    
  2. Nama file dari pos yang diekspor kedua: mitochondrion-another-title-for-heading-2.[ext]

    Konten yang diekspor, sesuai dengan tajuk tingkat atas kedua asli:

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

Saya akan sangat berterima kasih atas petunjuk, arah, kodesemu, atau kode nyata (lebih baik).

gsl
sumber

Jawaban:

27

Perintah berikut memungkinkan Anda memilih back-end dan kemudian mengekspor setiap subtree tingkat atas ke file terpisah:

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

Ini saat ini mendukung ekspor HTML ( html), LaTeX ( latex), dan PDF ( pdf). Anda dapat menambahkan dukungan untuk back-end lainnya dengan menambahkan lebih banyak klausa cond.

Seperti kata docstring, untuk setiap subtree Anda perlu mengatur :EXPORT_FILE_NAME:properti ke nama file yang Anda inginkan untuk diekspor. (Lihat di bawah untuk opsi lain.)

Secara otomatis menghasilkan nama file ekspor dari teks judul

Jika Anda tidak ingin menambahkan :EXPORT_FILE_NAME:properti ke setiap tajuk tingkat atas, Anda dapat memodifikasi org-export-alluntuk membuat nama file secara otomatis dari misalnya teks tajuk, pengaturan sementara :EXPORT_FILE_NAME:selama ekspor:

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

Fungsi ini menghasilkan nama file ekspor dengan mengganti spasi dengan "_" dalam teks judul. Jika Anda ingin membuat nama file dengan cara lain, ubah replace-regexp-in-stringsexp menjadi apa pun yang Anda suka.

Menghasilkan :EXPORT_FILE_NAME:saat pengaturan:CUSTOM_ID:

Dengan saran berikut, org-set-propertysecara otomatis akan menetapkan nilai yang sesuai :EXPORT_FILE_NAME:ketika Anda menetapkan :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))))

Perhatikan bahwa ini tidak akan menambahkan ekstensi file ke nilai :EXPORT_FILE_NAME:tetapi itu tidak masalah karena ketika mengekspor ke back-end tertentu, org-mode secara otomatis akan memilih ekstensi yang benar untuk file yang dihasilkan .


Informasi tambahan

Memperbarui subtree yang ada secara massal

Jika Anda memiliki banyak subtree yang ada yang perlu Anda atur :EXPORT_FILE_NAME:untuk properti, Anda bisa menggunakan makro keyboard . Posisikan titik pada subtree pertama, lalu lakukan hal berikut:

  • F3

    ... untuk mulai merekam.

  • C-c C-x p CUSTOM_ID RET RET

    ... untuk membuat Emacs ditetapkan :EXPORT_FILE_NAME:berdasarkan :CUSTOM_ID:.

  • C-c C-f

    ... untuk pindah ke tajuk tingkat atas berikutnya.

  • F4

    ... untuk berhenti merekam.

Untuk mengulang makro untuk subtree berikutnya, tekan F4. Untuk mengulang makro untuk semua subtrees yang tersisa, tekan M-0 F4(itu nol).

Menyimpan makro untuk sesi mendatang

Secara default, makro keyboard tidak disimpan di seluruh sesi. Untuk menyimpan makro di file init Anda untuk digunakan nanti, lakukan ini:

  1. Beri nama makro:

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

  2. Temukan file init Anda dan pindah ke tempat di mana Anda ingin memasukkan makro.

  3. Masukkan makro:

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

    Emacs akan menyisipkan kode berikut pada titik:

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

    Jika Anda menyipitkan mata cukup keras, Anda dapat melihat bahwa argumen kedua fsetberisi urutan tombol yang Anda tekan saat Anda merekam makro :)

  4. (Opsional) Untuk hasil terbaik, Anda mungkin ingin mengikat org-set-export-file-namekunci:

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

itu hanya
sumber
1
Bagus. Bisakah Anda memberi saya petunjuk tentang cara mengatur :EXPORT_FILE_NAME:properti secara terprogram :CUSTOM_ID:+heading-title-lowercaseduntuk setiap heading?
gsl
1
@gsl Anda dapat menyarankan org-set-propertyuntuk membuat :EXPORT_FILE_NAME:properti secara otomatis ketika Anda mengatur :CUSTOM_ID:.
itsjeyd
1
Terima kasih atas sarannya! Saya tidak fasih dengan itu elisp, tetapi saya akan mencoba. Saya perlu mencari tahu bagaimana cara menangkap judul masing-masing judul, mengganti ruang putih dengan tanda hubung, dimasukkan ke huruf kecil, menambahkan string yang bersih ke :CUSTOM_ID:dan akhirnya mengatur properti org.
gsl
1
@gsl saya menambahkan defadviceuntuk jawaban saya yang secara otomatis set :EXPORT_FILE_NAME:untuk <custom-id>-<heading>ketika Anda mengatur :CUSTOM_ID:.
itsjeyd
1
Terima kasih banyak, saya telah belajar banyak dengan kode Anda. Jika seseorang sudah memiliki org-modefile dengan CUSTOM_IDset, bagaimana seseorang dapat menjalankan kode untuk mengatur "EXPORT_FILE_NAME"? Tidak akan ada sisipan baru. Saya defadvicekira tidak akan berhasil? Apakah ada fasilitas pengulangan untuk melintasi semua judul tingkat atas dan menerapkan kode tersebut kepada mereka?
gsl