Come posso valutare elisp in un file orgmode quando viene aperto?


13

Ho un codice elisp che vorrei eseguire nei file orgmode quando vengono caricati (diversi per file diversi e definiti nel file stesso). C'è un modo per fare questo? Non ho visto nulla in http://orgmode.org/manual/In_002dbuffer-settings.html

Se posso aggiungere qualcosa all'inizializzazione di emacs che esegue un blocco di codice con un nome speciale ogni volta che viene caricato un file orgmode, questa potrebbe essere una soluzione, ma non sono sicuro di come farlo, e idealmente c'è qualcosa incorporato.


1
Variabili file-local, forse?
Dan

Che funzioni! Vuoi trasformarlo in una risposta che posso accettare?
avv

Pensando inoltre che è un ambiente molto disordinato in cui modificare, quindi una buona soluzione dovrebbe avere la variabile locale del file che esegue un blocco di codice denominato.
avv

Avvolgerlo in un progn o in un lambda, forse?
Dan

3
Puoi anche usare # -*- eval: (lisp code here) -*-ma devi anche essere consapevole dei pericoli. Anche se non condividi questi documenti con nessun altro, la natura interpretata di Emacs Lisp comporterà che una modifica potrebbe causare la perdita accidentale di dati. Inoltre, l'hook mode sembra un'opzione migliore se si desidera eseguire lo stesso codice per più di un file.
wvxvw,

Risposte:


9

Questa soluzione non richiede cambiamenti in init.el(con modifiche minori). Implica però valutazioni a livello locale, ma è esattamente quello che l'OP ha richiesto. I vantaggi della soluzione sono:

  • chiede conferma per valutare il codice
  • il codice elisp può essere modificato e testato all'interno dell'ambiente org-babel
  • poiché la soluzione non richiede modifiche al init.elfile orgmode può essere condivisa tra utenti (attendibili)

Sto riformulando la soluzione qui.

Aggiungi un blocco src da qualche parte nel tuo file:

#+NAME: startup
#+BEGIN_SRC emacs-lisp
(your-code-here)
#+END_SRC

Quindi, inseriscilo alla fine del file orgmode:

# Local Variables:
# eval: (progn (org-babel-goto-named-src-block "startup") (org-babel-execute-src-block) (outline-hide-sublevels 1))
# End:

Ho aggiunto (outline-hide-sublevels 1)perché mi piace nascondere il blocco src all'interno di un'intestazione e voglio che i sotto-livelli vengano nascosti all'avvio. Senza questa affermazione, i livelli secondari verranno ampliati di (org-babel-goto-named-src-block "startup").

Con questa soluzione, emacs chiederà 2 volte l'autorizzazione per l'esecuzione (1 °: applica variabili locali; 2 °: esegui "avvio" -src-block). Dato che ho molti blocchi src nel mio file, ho impostato un'altra variabile locale-file org-confirm-babel-evaluate, come questa:

# Local Variables:
# org-confirm-babel-evaluate: nil
# eval: (progn (org-babel-goto-named-src-block "startup") (org-babel-execute-src-block) (outline-hide-sublevels 1))
# End:

Avvertenza: con questa aggiunta, emacs richiederà una sola volta l'autorizzazione per l'esecuzione: tutti i blocchi src in quel file ora possono essere eseguiti senza ulteriore conferma. Come altri hanno già sottolineato, questo comportamento potrebbe essere pericoloso e dovresti stare molto attento con questa impostazione.

Tuttavia, direi che questa soluzione (in particolare la prima versione) è più sicura di quella fornita da Joe Corneli perché almeno ti verrà chiesto di confermare l'esecuzione. La soluzione di Joe valuterà il blocco speciale senza conferma, se presente nel file. Un attaccante dovrebbe indovinare il nome del blocco speciale, ovviamente ...

Sto usando questo approccio per scrivere documenti di grandi dimensioni che richiedono, ad esempio, adattamenti ai meccanismi di esportazione dell'organizzazione.


5

org-mode... Oltre a tutti gli hook che outline-modepotrebbe essere stata eseguita la modalità padre , questa modalità esegue l'hook org-mode-hook, come passaggio finale durante l'inizializzazione.

Quindi, nel tuo init.el:

(defun function-that-finds-and-evaluates-special-block ()
;; DWIM :-)
)
(add-hook 'org-mode-hook 'function-that-finds-and-evaluates-special-block)

Questo mi sembra più ragionevole rispetto ai file-local vars, per questo compito. Ma forse mi manca qualcosa.
Estratto il

@Joe Corneli E poi cosa inseriresti nel file org reale?
incandescentman,

Niente di speciale tranne il "blocco speciale".
Joe Corneli,

3

Da quando lo chiedi

(diverso per file diversi e definito nel file stesso)

quindi, prova questa soluzione .


Vuoi spiegare perché il voto negativo?
Utente Emacs

È perché le risposte che sono solo collegamenti ad altre risposte sono scoraggiate. Detto questo, forse questa domanda è una copia di quella a cui ti sei collegato?
Linus Arver

1

Sono d'accordo con il suggerimento di @Joe Corneli sull'uso di un gancio.

Mi viene anche in mente che puoi sfruttare i segnalibri qui: metti un gancio per un segnalibro specifico sul gancio. Un vantaggio di un segnalibro per il blocco di codice è che in genere viene riposizionato automaticamente (ad esempio quando il contenuto del file cambia), quindi la localizzazione del blocco dovrebbe in genere essere curata automaticamente.

[Ma non mi è chiaro il motivo per cui hai il codice nei file in modalità Org, anziché altrove. Lo stiamo prendendo come un dato di fatto, secondo la dichiarazione del problema, ma mi chiedo perché lo stai facendo. Facci sapere di più sul design in questo senso potrebbe portare a un aiuto migliore.]


0

Ho provato a migliorare il codice di Joe Corneli:

È necessario che nel file init.el:

  (defun tdh/eval-startblock ()
    (if (member "startblock" (org-babel-src-block-names))
      (save-excursion
        (org-babel-goto-named-src-block "startblock")
        (org-babel-execute-src-block))
      nil
      )
    )
  (add-hook 'org-mode-hook 'tdh/eval-startblock)

Ogni volta che apri un buffer in modalità org, cercherà un blocco sorgente chiamato startblock, se ne viene trovato uno, lo eseguirà.

Nei tuoi file in modalità org, puoi quindi inserire:

#+NAME: startblock
#+BEGIN_SRC emacs-lisp
  ;; Any code you want
#+END_SRC
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.