Como forçar uma sessão de org-babel para redefinir ou inicializar?

8

Se eu executar os seguintes blocos de shell babel

#+BEGIN_SRC sh :session one :results output
  ssh staging
#+END_SRC

#+BEGIN_SRC sh :session one :results output
  hostname
#+END_SRC

A organização cria um buffer de shell chamado one, executa ssh staginge, em seguida, após a conexão, executa hostnamena preparação. No entanto, se eu ajustar o comando ssh e executá-lo novamente, ele tentará executá-lo a partir da sessão um, do host intermediário. Se eu fechar o buffer, oneele redefinirá a sessão como na próxima vez que qualquer comando for executado com esse nome de sessão, ele será recriado. O que não consegui encontrar é um método para forçar um bloco babel específico a sempre inicializar uma nova sessão.

Estou ciente de que, para alguns idiomas (elisp em particular), isso não seria possível. Suponho que eu poderia preceder a sessão com um bloco elisp contendo (kill-buffer "one"), mas preferiria que esse fosse um argumento de cabeçalho, se possível. Também estou ciente de que, para este exemplo, eu poderia simplesmente combinar os dois em um único bloco sem sessão, mas estou interessado em sequências mais complicadas.

Existe um :prologuecomando ou algum outro argumento especial para as :sessionforças que bloqueiam a inicialização de um novo shell em cada chamada?

dgtized
fonte
Não existe essa opção (ou um parâmetro de bloco de código-fonte) na Org 8.2.10, mas deve ser bastante fácil de adicionar. Eu começaria cortando org-babel-initiate-session.
Constantine

Respostas:

5

Tente isto

Force uma sessão org-babel a redefinir ou inicializar usando uma instrução condicional elisp para definir dinamicamente o valor do cabeçalho : session no primeiro bloco de código.

por exemplo :session (if (get-buffer "one") (if (kill-buffer "one") (print "one") (print "one")) (print "one"))

No código acima, a função get-buffer verifica se o buffer denominado um existe. Se verdadeiro, a função kill-buffer mata o único buffer e, em seguida, retorna um valor de tou nilque é passado para a ifinstrução Neste exemplo específico, a ifinstrução aninhada sempre retornará um valor de um . Observe que ainda estou aprendendo elisp.

Abaixo está o código de exemplo atualizado:

#+BEGIN_SRC sh :session (if (get-buffer "one") (if (kill-buffer "one") (print "one") (print "one")) (print "one")) :results output
  ssh staging
#+END_SRC

#+BEGIN_SRC sh :session one :results output
  hostname
#+END_SRC

Cada vez que o primeiro bloco de código é executado, o emacs solicita a eliminação de um buffer , para que você possa redefinir a sessão quando desejar.

EDITAR

Opa perdeu parte que você sempre quis que o buffer fosse morto, ou seja, sem aviso . Execute este bloco primeiro para desativar temporariamente o prompt para eliminar o buffer.

#+BEGIN_SRC elisp
  (setq kill-buffer-query-functions
    (remq 'process-kill-buffer-query-function
           kill-buffer-query-functions))
#+END_SRC

Espero que tenha ajudado!

Nota: Este código foi testado usando as seguintes versões do emacs e do modo organizacional.

GNU Emacs 24.4.1 (x86_64-apple-darwin14.0.0, NS apple-appkit-1343.14)
Org-mode version 8.2.10 (8.2.10-29-g89a0ac-elpa)

Em conclusão, encontrei inspiração técnica para esta resposta no site org-scraps e este código de exemplo de buffer de interrupção no stackoverflow.

Melioratus
fonte
@dgtized esta resposta ajudou?
Melioratus 10/01
2
Eu não sabia que você poderia incorporar o elisp na teleconferência, então obrigado por isso. Dito isto, como mencionei na pergunta original, eu sabia que podia automatizar kill-bufferpara forçar uma nova sessão, mas estava mais interessado em saber se havia um argumento de bloco incorporado no modo organizacional ou em alguma outra convenção estabelecida para fazer isso. que eu não estava ciente. Sua abordagem é uma boa solução, mas espero que exista uma abordagem canônica para isso.
usar o seguinte comando
@dgtized - Você está procurando uma resposta como essa? :session one :session-reset yes?
Melioratus
Algo assim com certeza. Novamente, é uma questão de qual é a prática recomendada para este exemplo. Certamente, outras pessoas têm sessões que precisam ser redefinidas, e se elas simplesmente matarem o buffer, tudo bem, mas quero saber qual é a prática padrão.
usar o seguinte comando
@dgtized - Obrigado por esclarecer! Esta é uma ótima pergunta! Não encontrei uma prática padrão documentada, mas continuarei procurando .
Melioratus
2

Inspirado por @Melioratus.

Atualmente, o org-babel fornece um gancho chamado org-babel-after-execute-hook. Estendi os argumentos suportados do bloco org-babel src usando-o:

(Estou usando o org-babel para elixir. Se você deseja suporte para outros idiomas, estenda condsozinho.)

(add-hook 'org-babel-after-execute-hook 'semacs/ob-args-ext-session-reset)

(defun semacs/ob-args-ext-session-reset()
  (let* ((src-block-info (org-babel-get-src-block-info 'light))
         (language (nth 0 src-block-info))
         (arguments (nth 2 src-block-info))
         (should-reset (member '(:session-reset . "yes") arguments))
         (session (cdr (assoc :session arguments)))
         (session-process
          (cond ((equal language "elixir") (format "*elixir-%s*" session))
                (t nil))))
    (if (and should-reset (get-process session-process))
        (kill-process session-process))))

Após avaliar o código acima, você pode escrever o bloco src assim:

#+begin_src elixir :session-reset yes
  IO.puts("HELLO WORLD")
#+end_src

Após avaliar o bloco src, o org-babel limpará a sessão correspondente.


fonte