File Tangle Org contenente le direttive # + INCLUDE e più obiettivi tangle

Oct 18 2020

Contesto

Sto usando org-babel-tangleper generare la mia configurazione da un file Org config.org. Recentemente, ho fatto un po 'di pulizia da

  1. invio config.orga più file Org config/*.org;
  2. sostituire il contenuto di config.orgcon più #+INCLUDE: config/*.orgdirettive.

Per illustrare un po ', l'albero delle directory è il seguente:

config/
|______ A.org
|______ B.org
|______ C.org
|
config.org

dove

## config.org
#+INCLUDE: config/A.org
#+INCLUDE: config/B.org
#+INCLUDE: config/C.org
...

e

## [ABC].org
#+BEGIN_SRC emacs-lisp :tangle target1.el
;; elisp code
#+END_SRC

#+BEGIN_SRC emacs-lisp :tangle target2.el
;; elisp code
#+END_SRC
...

Problema e tentativo

Tuttavia, mi sono imbattuto nel problema che org-babel-tanglenon gestisce le #+INCLUDEdirettive. Quindi, seguo l'idea di questo post che consiste in

  1. esportazione config.orgin un file Org config-export.orgcon org-export-to-file;
  2. org-babel-tangleil file Org esportato config-export.orgper aggrovigliare i bersagli.

Questo approccio sostituisce le #+INCLUDEdirettive multiple di config.orgcon il contenuto di config/*.org, ma tutte le opzioni di tangle vengono cancellate . Vale a dire, l'esportazione ha questo config-export.orgaspetto (tutti i nomi dei file di destinazione tangle di emacs-lisp vengono persi):

## config-export.org
#+BEGIN_SRC emacs-lisp
;; elisp code for target1.el
#+END_SRC

#+BEGIN_SRC emacs-lisp
;; elisp code for target2.el
#+END_SRC
...

Domanda

Come org-babel-tanglecreare un file Org con le #+INCLUDEdirettive come previsto?

(ad es. (1) includi tutti i file Org (preservando :tangle target.el), quindi (2) org-babel-tanglel'intero file Org.)

Domanda correlata

Una domanda simile è stata sollevata nella mailing list della modalità Org.

Risposte

2 NickD Oct 19 2020 at 23:26

Non so come farlo senza cambiare il codice (potrebbe essere possibile con org-babel-pre-tangle-hookma non mi sembrava per niente semplice, quindi non l'ho provato). Ma non appena accetti le modifiche al codice, non sembra poi così male.

Il modo più semplice possibile a cui pensare era emulare org-babel-tangleciò che org-export-assta facendo i file inclusi in WRT. Un semplice test (simile a quello che descrivi sopra) è riuscito facilmente (ma vedi avvertenze alla fine), quindi se vuoi provare a replicare la modifica, includo la patch di seguito.

La patch stessa sembrerebbe grande, ma è solo perché prendo tutto il codice di org-babel-tanglee lo racchiudo in un altro livello, il che cambia il rientro e questa è la maggior parte del cambiamento. Ignorando le modifiche agli spazi, il cambiamento "reale" è molto più piccolo: ho ottenuto la patch qui sotto git diff -bper ignorare gli spazi. Puoi quindi vedere che è molto piccolo: racchiudiamo quasi tutto il corpo di org-babel-tanglein (org-export-with-buffer-copy ...), in modo da poter fare trasformazioni al testo in un buffer temporaneo e non disturbare l'originale e quindi aggiungere un'altra trasformazione per elaborare le #+INCLUDE:direttive, prima il buffer risultante viene quindi aggrovigliato:

diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el
index b74b3fa0c..5e6eebf63 100644
--- a/lisp/ob-tangle.el
+++ b/lisp/ob-tangle.el
@@ -206,6 +206,9 @@ export file for all source blocks.  Optional argument LANG-RE can
 be used to limit the exported source code blocks by languages
 matching a regular expression."
   (interactive "P")
+  (org-export-with-buffer-copy
+   (org-export-expand-include-keyword)
+
    (run-hooks 'org-babel-pre-tangle-hook)
    ;; Possibly Restrict the buffer to the current code block
    (save-restriction
@@ -306,7 +309,7 @@ matching a regular expression."
     (mapc (lambda (pair)
         (when (cdr pair) (set-file-modes (car pair) (cdr pair))))
           path-collector)
-   (mapcar #'car path-collector)))))
+    (mapcar #'car path-collector))))))
 
 (defun org-babel-tangle-clean ()
   "Remove comments inserted by `org-babel-tangle'.

Questo produce i risultati attesi WRT i file aggrovigliati penso, ma dovresti controllare per assicurarti che faccia la cosa giusta nel tuo caso: i miei test sono test di giocattoli, quindi potrebbero perdere situazioni difficili che potrebbero sorgere nei tuoi test "nel mondo reale" .

C'è un problema che ancora non capisco: il config.orgbuffer stesso è cambiato nei miei test, nonostante il org-export-with-copy-buffer, quindi alla fine del groviglio devo annullare la modifica C-x ue salvarla. Probabilmente è perché non capisco cosa org-export-with-copy-bufferstia realmente facendo, ma non ho ancora controllato quel codice.

OTOH, se questo viene risolto e tutti i test superano, possiamo proporlo come un miglioramento alla mailing list della modalità Org e lasciarci quel problema (dal 2010!) Alle spalle.

EDIT: Non vedo alcun problema con org-babel-tangle-file- chiama org-babel-tanglesotto, quindi in teoria dovrebbe fare la cosa (quasi) giusta e testarlo con un semplice esempio funziona bene per me. Forse puoi pubblicare un (piccolo) esempio che ti dà problemi modificando la tua domanda?

Sto anche testando con la seguente soluzione alternativa per aggirare il problema delle config.orgmodifiche:

#+begin_src emacs-lisp
(copy-file "./config.org.orig" "./config.org")
(org-babel-tangle-file "./config.org")
(delete-file "./config.org")
#+end_src

Brutto, ma sembra funzionare (tranne che devo rispondere alla domanda "modificato su disco").

2 Melioratus Oct 26 2020 at 09:30

Metodo 1

Metodo manuale che utilizza le associazioni di tasti della modalità organizzazione predefinite

Impostare

  1. Aggiungi Orgalla Org Babel Load Languagesconfigurazione, quindi applica e salva la nuova configurazione.

  2. Aggiungi #+EXPORT_FILE_NAME:parola chiave nella parte superiore di config.org.

    per esempio

    #+EXPORT_FILE_NAME: temp.org
    
  3. Aggiungi #+PROPERTY: header-args:org :results drawer replaceparola chiave nella parte superiore di config.org.

    per esempio

    #+PROPERTY: header-args:org :results drawer replace
    
  4. Aggiorna #+INCLUDE:per includere la src orgsintassi.

    per esempio

    #+INCLUDE: config/A.org src org
    #+INCLUDE: config/B.org src org
    #+INCLUDE: config/C.org src org
    
  5. Aggiungi l' :eval neverintestazione a ciascuno dei SRCblocchi che verranno aggrovigliati all'interno dei config/*.orgfile inclusi .

    per esempio

    #+BEGIN_SRC elisp :tangle tangle1.el :eval never 
      ;; Code goes here
    #+END_SRC
    

Passaggi di esecuzione manuale

  1. Apri config.orgin emacs.

    Il config.orgfile dovrebbe essere simile all'esempio seguente:

    #+EXPORT_FILE_NAME: temp.org
    #+PROPERTY: header-args:org :results drawer replace 
    
    #+INCLUDE: config/A.org src org
    #+INCLUDE: config/B.org src org
    #+INCLUDE: config/C.org src org
    
  2. Esporta config.orgutilizzando C-c C-e O vun accordo di tonalità. Questo creerà un nuovo temp.orgfile e si aprirà in emacs.

    Il temp.orgfile dovrebbe essere simile all'esempio seguente:

    #+export_file_name: temp.org
    #+property: header-args:org :results drawer replace
    
    #+begin_src org
      ,#+BEGIN_SRC elisp :tangle tangle1.el :eval never 
        ;; Code goes here
      ,#+END_SRC
    #+end_src
    #+begin_src org
      ,#+BEGIN_SRC elisp :tangle tangle2.el :eval never 
        ;; Code goes here
      ,#+END_SRC
    #+end_src
    #+begin_src org
      ,#+BEGIN_SRC elisp :tangle tangle3.el :eval never 
        ;; Code goes here
      ,#+END_SRC
    #+end_src
    
  3. Esegui tutti i blocchi nell'accordo di chiave temp.orgusando C-c C-v C-b.

    Il temp.orgfile dovrebbe essere simile all'esempio seguente:

    #+export_file_name: temp.org
    #+property: header-args:org :results drawer replace
    
    #+begin_src org
      ,#+BEGIN_SRC elisp :tangle tangle1.el :eval never 
        ;; Code goes here
      ,#+END_SRC
    #+end_src
    
    #+RESULTS:
    :results:
    #+BEGIN_SRC elisp :tangle tangle1.el :eval never 
      ;; Code goes here
    #+END_SRC
    :end:
    
    #+begin_src org
      ,#+BEGIN_SRC elisp :tangle tangle2.el :eval never 
        ;; Code goes here
      ,#+END_SRC
    #+end_src
    
    #+RESULTS:
    :results:
    #+BEGIN_SRC elisp :tangle tangle2.el :eval never 
      ;; Code goes here
    #+END_SRC
    :end:
    
    #+begin_src org
      ,#+BEGIN_SRC elisp :tangle tangle3.el :eval never 
        ;; Code goes here
      ,#+END_SRC
    #+end_src
    
    #+RESULTS:
    :results:
    #+BEGIN_SRC elisp :tangle tangle3.el :eval never 
      ;; Code goes here
    #+END_SRC
    :end:
    
  4. Esegui il groviglio nell'accordo chiave temp.orgusando C-c C-v C-t. Questo aggroviglierà i SRCblocchi importati dai config/*.orgfile.

    Questo creerà i file aggrovigliati simili ai file elencati di seguito:

    config.org
    tangle1.el
    tangle2.el
    tangle3.el
    temp.org
    
    ./config:
    A.org
    B.org
    C.org
    

Questa risposta è stata testata usando:
versione emacs: GNU Emacs 27.1
versione in modalità org: 9.3.7