Arquivo Org Tangle contendo # + INCLUDE diretivas e vários alvos tangle
Contexto
Estou usando org-babel-tanglepara gerar minha configuração a partir de um arquivo Org config.org. Recentemente, fiz uma limpeza por
- envio
config.orgpara vários arquivos Orgconfig/*.org; - substitua o conteúdo de
config.orgpor várias#+INCLUDE: config/*.orgdiretivas.
Para ilustrar um pouco, a árvore de diretórios é a seguinte:
config/
|______ A.org
|______ B.org
|______ C.org
|
config.org
Onde
## 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 tentativa
No entanto, encontrei o problema que org-babel-tanglenão trata das #+INCLUDEdiretivas. Então, eu sigo a ideia deste post que consiste em
- exportar
config.orgpara um arquivo Orgconfig-export.orgcomorg-export-to-file; org-babel-tangleo arquivo Org exportadoconfig-export.orgpara emaranhar destinos.
Essa abordagem substitui as várias #+INCLUDEdiretivas de config.orgpelo conteúdo de config/*.org, mas todas as opções de emaranhado são apagadas . Ou seja, o exportado se config-export.orgparece com isto (todos os nomes de arquivo de destino emacs-lisp emaranhados são perdidos):
## 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
...
Pergunta
Como criar org-babel-tangleum arquivo Org com #+INCLUDEdiretivas conforme pretendido?
( ou seja, (1) inclui todos os arquivos org (preservando :tangle target.el) e (2) org-babel-tangletodo o arquivo org.)
Questão relacionada
Uma questão semelhante foi levantada na lista de e-mails do modo Org.
Respostas
Não sei como fazer isso sem alterar o código (pode ser possível com, org-babel-pre-tangle-hookmas não parecia nada simples, então não tentei fazer isso). Mas assim que você aceita as alterações de código, não parece tão ruim.
A maneira mais simples possível que eu poderia pensar era emular o org-babel-tangleque org-export-asestá fazendo o WRT incluir arquivos. Um teste simples (semelhante ao que você descreveu acima) foi bem-sucedido facilmente (mas veja as advertências no final), então, se você quiser tentar replicar a mudança, incluo o patch abaixo.
O patch em si pareceria grande, mas isso é apenas porque estou pegando todo o código org-babel-tanglee colocando-o em outra camada, o que muda o recuo e essa é a maior parte da mudança. Ignorando as mudanças de espaço em branco, a mudança "real" é muito menor: eu peguei o patch abaixo com a git diff -bfim de ignorar os espaços em branco. Você pode então ver que é muito pequeno: nós apenas incluímos quase todo o corpo de org-babel-tanglein (org-export-with-buffer-copy ...), para que possamos fazer transformações no texto em um buffer temporário e não atrapalhar o original e então adicionar mais uma transformação para processar as #+INCLUDE:diretivas, antes o buffer resultante é então emaranhado:
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'.
Isso produz os resultados esperados WRT os arquivos emaranhados, eu acho, mas você deve verificar para ter certeza de que faz a coisa certa no seu caso: meus testes são testes de brinquedo, então eles podem perder situações complicadas que podem surgir em seus testes do "mundo real" .
Há um problema que eu ainda não entendo: o config.orgbuffer em si é alterado em meus testes, apesar do org-export-with-copy-buffer, então no final do emaranhado eu tenho que desfazer a alteração com C-x ue salvá-lo. Provavelmente porque não entendo o que org-export-with-copy-bufferrealmente está acontecendo , mas ainda não verifiquei esse código.
OTOH, se isso for resolvido e todos os testes passarem, podemos propor isso como uma melhoria para a lista de e-mail do modo Org e deixar esse problema (de 2010!) Para trás.
EDIT: Eu não vejo nenhum problema com org-babel-tangle-file- ele chama org-babel-tangleembaixo, então em teoria ele deve fazer a coisa (quase) certa e testá-lo com um exemplo simples funciona bem para mim. Talvez você possa postar um (pequeno) exemplo que lhe dê problemas ao editar sua pergunta?
Também estou testando a seguinte solução alternativa para contornar o problema de config.orgser alterado:
#+begin_src emacs-lisp
(copy-file "./config.org.orig" "./config.org")
(org-babel-tangle-file "./config.org")
(delete-file "./config.org")
#+end_src
Feio, mas parece funcionar (exceto que eu tenho que responder à pergunta "alterado no disco").
Método 1
Método manual usando atalhos de teclado do modo org padrão
Configurar
Adicione
OrgàOrg Babel Load Languagesconfiguração e, em seguida, aplique e salve a nova configuração.Adicione uma
#+EXPORT_FILE_NAME:palavra-chave próximo ao topo deconfig.org.por exemplo
#+EXPORT_FILE_NAME: temp.orgAdicione uma
#+PROPERTY: header-args:org :results drawer replacepalavra-chave próximo ao topo deconfig.org.por exemplo
#+PROPERTY: header-args:org :results drawer replaceAtualize
#+INCLUDE:para incluir asrc orgsintaxe.por exemplo
#+INCLUDE: config/A.org src org #+INCLUDE: config/B.org src org #+INCLUDE: config/C.org src orgAdicione
:eval nevercabeçalho a cada um dosSRCblocos que serão emaranhados dentro dosconfig/*.orgarquivos incluídos .por exemplo
#+BEGIN_SRC elisp :tangle tangle1.el :eval never ;; Code goes here #+END_SRC
Etapas de execução manual
Abra
config.orgno emacs.O
config.orgarquivo deve ser semelhante ao exemplo abaixo:#+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 orgExporte
config.orgusandoC-cC-eOvacorde chave. Isso criará um novotemp.orgarquivo e abrirá no emacs.O
temp.orgarquivo deve ser semelhante ao exemplo abaixo:#+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_srcExecute todos os blocos no acorde
temp.orgusando aC-cC-vC-bchave.O
temp.orgarquivo deve ser semelhante ao exemplo abaixo:#+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:Execute o emaranhado no acorde da tecla
temp.orgusingC-cC-vC-t. Isso confundirá osSRCblocos importados dosconfig/*.orgarquivos.Isso criará os arquivos emaranhados semelhantes aos arquivos listados abaixo:
config.org tangle1.el tangle2.el tangle3.el temp.org ./config: A.org B.org C.org
Esta resposta foi testada usando:
versão emacs: GNU Emacs 27.1
org-mode version: 9.3.7