Специфичный интерпретатор кодовых блоков в Org Babel

13

Возможно ли иметь в одном и том же оргструктуре два кодовых блока на одном и том же языке, которые выполняются в разных интерпретаторах, указав разные параметры в верхней части блока кода?

cefstat
источник
2
Вы имеете в виду, например, разные версии установленного программного обеспечения, например, python26, python27 и python3? Или просто уникальные сессии Python, но все используют один и тот же исполняемый файл? @dgtized объясняет последнее.
Mankoff
2
Я имею в виду разные версии установленного программного обеспечения, т.е. использующие разные исполняемые файлы.
cefstat

Ответы:

10

Первоначальный вопрос был изменен, чтобы касаться запуска нескольких версий исполняемого файла, а не просто независимых интерпретаторов.

Используя find-libraryя проверил источник ob-ruby, который включает этот код:

(defvar org-babel-ruby-command "ruby"
  "Name of command to use for executing ruby code.")

В других местах я видел ссылки на использование Python org-babel-python-command, поэтому он существует в некоторых других языках, проверьте соответствующую ob-$langподдержку, чтобы увидеть.

Это позволяет следующему работать:

#+begin_src emacs-lisp :results none
(setq org-babel-python-command "python3")
#+end_src

#+begin_src python :results output
import sys
print(sys.version)
#+end_src

#+RESULTS:
: 3.4.0 (default, Apr 11 2014, 13:05:11) 
: [GCC 4.8.2]

#+begin_src emacs-lisp :results none
(setq org-babel-python-command "python2")
#+end_src

#+begin_src python :results output
import sys
print(sys.version)
#+end_src

#+RESULTS:
: 2.7.6 (default, Mar 22 2014, 22:59:56) 
: [GCC 4.8.2]

Это можно сочетать с :session python3и :session python2избегать вызова elisp перед каждым блоком. Похоже, что должен быть более простой способ сделать это.

dgtized
источник
2
Существует org-babel-post-tangle-hook. Кто-то должен реализовать в org-babel-pre-tangle-hook.
mankoff
1
Я не очень знаком с внутренностями, но я не уверен, что запутывание было бы подходящей фазой, чтобы сделать это изменение? Честно говоря, похоже, что блок нуждается в :interpreterсобственности.
dgtized
2
Я тоже не слишком знаком с этим. Да :interpreterимеет смысл. Но org-babel-post-tangle-hookзапускается после выполнения кода через C-c C-cблок кода. Я предполагаю, preчто будет работать до выполнения кода. Но теперь я понимаю, что если изменить глобальную переменную, это будет иметь плохие побочные эффекты. :interpreterбыло бы лучше.
Mankoff
1
Спасибо @dgtized и @mankoff за ваши ответы. Они указали мне в правильном направлении. Это была моя ошибка, что я не указал, что меня интересует код JavaScript. На основании ваших ответов я решил добавить :interpreterопцию org-babel-execute:js. Но затем, просматривая источник, org-babel-execute:jsя обнаружил, что уже есть :cmdопция, которая делает именно то, что я хочу. К сожалению, :cmdдоступно не для всех языков, и я также не нашел никакой документации, ob-jsпоэтому я изначально пропустил :cmdсуществование.
cefstat
@cefstat Я заметил :cmd, но похоже, что он использовался только для добавления аргументов к команде интерпретатора. Не могли бы вы ответить на свой вопрос с полным примером, показывающим использование :cmdдля решения проблемы для тех, кто имеет эту проблему в будущем?
dgtized
1

Я считаю, что по умолчанию каждый блок работает в независимом интерпретаторе, даже если это один и тот же язык. Поведение может отличаться для некоторых языков. Например, я не уверен, что блоки emacs-lisp поддерживают свойство сеанса.

#+BEGIN_SRC ruby
  a = "foo"
#+END_SRC

#+RESULTS:
: foo

#+BEGIN_SRC ruby
  a ||= "bar"
#+END_SRC

#+RESULTS:
: bar

#+BEGIN_SRC ruby :session foo
  a ||= "session foo"
#+END_SRC

#+RESULTS:
: session foo

#+BEGIN_SRC ruby :session foo
  a += " with bar"
#+END_SRC

#+RESULTS:
: session foo with bar

Первые два блока используют независимые интерпретаторы, но третий и четвертый блоки совместно используют сеанс :foo, поэтому они оцениваются в одном и том же интерпретаторе.

dgtized
источник
2
Хороший ответ в теории, но не отвечает на вопрос.
mankoff
1

Оказывается, что почти во всех языках, поддерживаемых Org Babel, нет возможности использовать другой интерпретатор для конкретного кодового блока. Одним заметным исключением (и тем, которое меня интересует) является Javascript. В этом случае можно использовать :cmdопцию.

Стандартный интерпретатор JS node, как определено в переменной org-babel-js-cmd. Чтобы запустить определенный блок кода через другой интерпретатор, передайте :cmdопцию, как в следующем примере.

#+begin_src js :cmd "/usr/bin/osascript -l JavaScript"
app = Application.currentApplication()
app.includeStandardAdditions = true
app.say("Hello")
#+end_src
cefstat
источник