mirror of
https://git.savannah.gnu.org/git/emacs/org-mode.git
synced 2024-11-25 07:27:57 +00:00
moving generalized comint functions to new file org-babel-comint.el
This commit is contained in:
parent
a54c27ec91
commit
c5a58ad6aa
93
lisp/org-babel-comint.el
Normal file
93
lisp/org-babel-comint.el
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
;;; org-babel-comint.el --- org-babel functions for interaction with comint buffers
|
||||||
|
|
||||||
|
;; Copyright (C) 2009 Eric Schulte
|
||||||
|
|
||||||
|
;; Author: Eric Schulte
|
||||||
|
;; Keywords: literate programming, reproducible research, comint
|
||||||
|
;; Homepage: http://orgmode.org
|
||||||
|
;; Version: 0.01
|
||||||
|
|
||||||
|
;;; License:
|
||||||
|
|
||||||
|
;; This program is free software; you can redistribute it and/or modify
|
||||||
|
;; it under the terms of the GNU General Public License as published by
|
||||||
|
;; the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
;; any later version.
|
||||||
|
;;
|
||||||
|
;; This program is distributed in the hope that it will be useful,
|
||||||
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
;; GNU General Public License for more details.
|
||||||
|
;;
|
||||||
|
;; You should have received a copy of the GNU General Public License
|
||||||
|
;; along with GNU Emacs; see the file COPYING. If not, write to the
|
||||||
|
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
;; Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;; This file should provide support for passing commands and results
|
||||||
|
;; to and from `comint-mode' buffers.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
(require 'org-babel)
|
||||||
|
|
||||||
|
(defun org-babel-comint-initiate-buffer (buffer ignite)
|
||||||
|
"If BUFFER does not currently have a process use IGNITE to
|
||||||
|
create one."
|
||||||
|
(unless (and (buffer-live-p buffer) (get-buffer buffer))
|
||||||
|
(save-excursion
|
||||||
|
(eval ignite)
|
||||||
|
(setf buffer (current-buffer))
|
||||||
|
(org-babel-comint-wait-for-output)
|
||||||
|
(org-babel-comint-input-command ""))))
|
||||||
|
|
||||||
|
(defun org-babel-comint-command-to-string (buffer command)
|
||||||
|
"Send COMMEND to BUFFER's process, and return the results as a string."
|
||||||
|
(org-babel-comint-input-command buffer command)
|
||||||
|
(org-babel-comint-last-output buffer))
|
||||||
|
|
||||||
|
(defun org-babel-comint-input-command (buffer command)
|
||||||
|
"Pass COMMAND to the process running in BUFFER."
|
||||||
|
(save-excursion
|
||||||
|
(save-match-data
|
||||||
|
(set-buffer buffer)
|
||||||
|
(goto-char (process-mark (get-buffer-process (current-buffer))))
|
||||||
|
(insert command)
|
||||||
|
(comint-send-input)
|
||||||
|
(org-babel-comint-wait-for-output))))
|
||||||
|
|
||||||
|
(defun org-babel-comint-wait-for-output (buffer)
|
||||||
|
"Wait until output arrives"
|
||||||
|
(save-excursion
|
||||||
|
(save-match-data
|
||||||
|
(set-buffer buffer)
|
||||||
|
(while (progn
|
||||||
|
(goto-char comint-last-input-end)
|
||||||
|
(not (re-search-forward comint-prompt-regexp nil t)))
|
||||||
|
(accept-process-output (get-buffer-process (current-buffer)))))))
|
||||||
|
|
||||||
|
(defun org-babel-comint-last-output (buffer)
|
||||||
|
"Return BUFFER's the last output as a string"
|
||||||
|
(save-excursion
|
||||||
|
(save-match-data
|
||||||
|
(set-buffer buffer)
|
||||||
|
(goto-char (process-mark (get-buffer-process (current-buffer))))
|
||||||
|
(forward-line 0)
|
||||||
|
(let ((raw (buffer-substring comint-last-input-end (- (point) 1)))
|
||||||
|
output output-flag)
|
||||||
|
(mapconcat
|
||||||
|
(lambda (el)
|
||||||
|
(if (stringp el)
|
||||||
|
(format "%s" el)
|
||||||
|
(format "%S" el)))
|
||||||
|
(delq nil
|
||||||
|
(mapcar
|
||||||
|
(lambda (line)
|
||||||
|
(unless (string-match "^>" line)
|
||||||
|
(and (string-match "\\[[[:digit:]]+\\] *\\(.*\\)$" line)
|
||||||
|
(match-string 1 line))))
|
||||||
|
;; drop first, because it's the last line of input
|
||||||
|
(cdr (split-string raw "[\n\r]")))) "\n")))))
|
||||||
|
|
||||||
|
;;; org-babel-comint.el ends here
|
149
org-babel.org
149
org-babel.org
@ -115,6 +115,84 @@ and the results to be collected in the same table.
|
|||||||
|
|
||||||
|
|
||||||
* Tasks [20/32]
|
* Tasks [20/32]
|
||||||
|
** TODO Create objects in top level (global) environment in R?
|
||||||
|
*** initial requirement statement [DED]
|
||||||
|
At the moment, objects created by computations performed in the
|
||||||
|
code block are evaluated in the scope of the
|
||||||
|
code-block-function-body and therefore disappear when the code
|
||||||
|
block is evaluated {unless you employ some extra trickery like
|
||||||
|
assign('name', object, env=globalenv()) }. I think it will be
|
||||||
|
desirable to also allow for a style wherein objects that are
|
||||||
|
created in one code block persist in the R global environment and
|
||||||
|
can be re-used in a separate block.
|
||||||
|
|
||||||
|
This is what Sweave does, and while I'm not saying we have to be
|
||||||
|
the same as Sweave, it wouldn't be hard for us to provide the same
|
||||||
|
behaviour in this case; if we don't, we risk undeservedly being
|
||||||
|
written off as an oddity by some.
|
||||||
|
|
||||||
|
IOW one aspect of org-babel is that of a sort of functional
|
||||||
|
meta-programming language. This is crazy, in a very good
|
||||||
|
way. Nevertheless, wrt R I think there's going to be a lot of value
|
||||||
|
in providing for a working style in which the objects are stored in
|
||||||
|
the R session, rather than elisp/org buffer. This will be a very
|
||||||
|
familiar working style to lots of people.
|
||||||
|
|
||||||
|
There are no doubt a number of different ways of accomplishing
|
||||||
|
this, the simplest being a hack like adding
|
||||||
|
|
||||||
|
#+begin_src R
|
||||||
|
for(objname in ls())
|
||||||
|
assign(objname, get(objname), envir=globalenv())
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
to the source code block function body. (Maybe wrap it in an on.exit() call).
|
||||||
|
|
||||||
|
However this may deserve to be thought about more carefully, perhaps
|
||||||
|
with a view to having a uniform approach across languages. E.g. shell
|
||||||
|
code blocks have the same semantics at the moment (no persistence of
|
||||||
|
variables across code blocks), because the body is evaluated in a new
|
||||||
|
bash shell process rather than a running shell. And I guess the same
|
||||||
|
is true for python. However, in both these cases, you could imagine
|
||||||
|
implementing the alternative in which the body is evaluated in a
|
||||||
|
persistent interactive session. It's just that it's particularly
|
||||||
|
natural for R, seeing as both ESS and org-babel evaluate commands in a
|
||||||
|
single persistent R session.
|
||||||
|
|
||||||
|
*** sessions [Eric]
|
||||||
|
|
||||||
|
Thanks for bringing this up. I think you are absolutely correct that we
|
||||||
|
should provide support for a persistent environment (maybe called a
|
||||||
|
*session*) in which to evaluate code blocks. I think the current setup
|
||||||
|
demonstrates my personal bias for a functional style of programming
|
||||||
|
which is certainly not ideal in all contexts.
|
||||||
|
|
||||||
|
While the R function you mention does look like an elegant solution, I
|
||||||
|
think we should choose an implementation that would be the same across
|
||||||
|
all source code types. Specifically I think we should allow the user to
|
||||||
|
specify an optional *session* as a header variable (when not present we
|
||||||
|
assume a default session for each language). The session name could be
|
||||||
|
used to name a comint buffer (like the *R* buffer) in which all
|
||||||
|
evaluation would take place (within which variables would retain their
|
||||||
|
values --at least once I remove some of the functional method wrappings
|
||||||
|
currently in place-- ).
|
||||||
|
|
||||||
|
This would allow multiple environments to be used in the same buffer,
|
||||||
|
and once this setup was implemented we should be able to fairly easily
|
||||||
|
implement commands for jumping between source code blocks and the
|
||||||
|
related session buffers, as well as for dumping the last N commands from
|
||||||
|
a session into a new or existing source code block.
|
||||||
|
|
||||||
|
Please let me know if you foresee any problems with this proposed setup,
|
||||||
|
or if you think any parts might be confusing for people coming from
|
||||||
|
Sweave. I'll hopefully find some time to work on this later in the
|
||||||
|
week.
|
||||||
|
*** implementation
|
||||||
|
in [[file:lisp/org-babel-comint.el][org-babel-comint.el]]
|
||||||
|
|
||||||
|
Currently I've coppied and begun generalizing the functions for
|
||||||
|
interacting with R buffers.
|
||||||
|
|
||||||
** TODO improve the source-block snippet
|
** TODO improve the source-block snippet
|
||||||
|
|
||||||
[[file:~/src/emacs-starter-kit/src/snippets/text-mode/rst-mode/chap::name%20Chapter%20title][file:~/src/emacs-starter-kit/src/snippets/text-mode/rst-mode/chap::name Chapter title]]
|
[[file:~/src/emacs-starter-kit/src/snippets/text-mode/rst-mode/chap::name%20Chapter%20title][file:~/src/emacs-starter-kit/src/snippets/text-mode/rst-mode/chap::name Chapter title]]
|
||||||
@ -247,77 +325,6 @@ Another example is in the [[*operations%20in%20on%20tables][grades example]].
|
|||||||
** TODO pass mutliple reference arguments into R
|
** TODO pass mutliple reference arguments into R
|
||||||
Can we do this? I wasn't sure how to supply multiple 'var' header
|
Can we do this? I wasn't sure how to supply multiple 'var' header
|
||||||
args. Just delete this TODO if I'm being dense.
|
args. Just delete this TODO if I'm being dense.
|
||||||
** TODO Create objects in top level (global) environment in R?
|
|
||||||
At the moment, objects created by computations performed in the
|
|
||||||
code block are evaluated in the scope of the
|
|
||||||
code-block-function-body and therefore disappear when the code
|
|
||||||
block is evaluated {unless you employ some extra trickery like
|
|
||||||
assign('name', object, env=globalenv()) }. I think it will be
|
|
||||||
desirable to also allow for a style wherein objects that are
|
|
||||||
created in one code block persist in the R global environment and
|
|
||||||
can be re-used in a separate block.
|
|
||||||
|
|
||||||
This is what Sweave does, and while I'm not saying we have to be
|
|
||||||
the same as Sweave, it wouldn't be hard for us to provide the same
|
|
||||||
behaviour in this case; if we don't, we risk undeservedly being
|
|
||||||
written off as an oddity by some.
|
|
||||||
|
|
||||||
IOW one aspect of org-babel is that of a sort of functional
|
|
||||||
meta-programming language. This is crazy, in a very good
|
|
||||||
way. Nevertheless, wrt R I think there's going to be a lot of value
|
|
||||||
in providing for a working style in which the objects are stored in
|
|
||||||
the R session, rather than elisp/org buffer. This will be a very
|
|
||||||
familiar working style to lots of people.
|
|
||||||
|
|
||||||
There are no doubt a number of different ways of accomplishing
|
|
||||||
this, the simplest being a hack like adding
|
|
||||||
|
|
||||||
#+begin_src R
|
|
||||||
for(objname in ls())
|
|
||||||
assign(objname, get(objname), envir=globalenv())
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
to the source code block function body. (Maybe wrap it in an on.exit() call).
|
|
||||||
|
|
||||||
However this may deserve to be thought about more carefully, perhaps
|
|
||||||
with a view to having a uniform approach across languages. E.g. shell
|
|
||||||
code blocks have the same semantics at the moment (no persistence of
|
|
||||||
variables across code blocks), because the body is evaluated in a new
|
|
||||||
bash shell process rather than a running shell. And I guess the same
|
|
||||||
is true for python. However, in both these cases, you could imagine
|
|
||||||
implementing the alternative in which the body is evaluated in a
|
|
||||||
persistent interactive session. It's just that it's particularly
|
|
||||||
natural for R, seeing as both ESS and org-babel evaluate commands in a
|
|
||||||
single persistent R session.
|
|
||||||
|
|
||||||
*** sessions [Eric]
|
|
||||||
|
|
||||||
Thanks for bringing this up. I think you are absolutely correct that we
|
|
||||||
should provide support for a persistent environment (maybe called a
|
|
||||||
*session*) in which to evaluate code blocks. I think the current setup
|
|
||||||
demonstrates my personal bias for a functional style of programming
|
|
||||||
which is certainly not ideal in all contexts.
|
|
||||||
|
|
||||||
While the R function you mention does look like an elegant solution, I
|
|
||||||
think we should choose an implementation that would be the same across
|
|
||||||
all source code types. Specifically I think we should allow the user to
|
|
||||||
specify an optional *session* as a header variable (when not present we
|
|
||||||
assume a default session for each language). The session name could be
|
|
||||||
used to name a comint buffer (like the *R* buffer) in which all
|
|
||||||
evaluation would take place (within which variables would retain their
|
|
||||||
values --at least once I remove some of the functional method wrappings
|
|
||||||
currently in place-- ).
|
|
||||||
|
|
||||||
This would allow multiple environments to be used in the same buffer,
|
|
||||||
and once this setup was implemented we should be able to fairly easily
|
|
||||||
implement commands for jumping between source code blocks and the
|
|
||||||
related session buffers, as well as for dumping the last N commands from
|
|
||||||
a session into a new or existing source code block.
|
|
||||||
|
|
||||||
Please let me know if you foresee any problems with this proposed setup,
|
|
||||||
or if you think any parts might be confusing for people coming from
|
|
||||||
Sweave. I'll hopefully find some time to work on this later in the
|
|
||||||
week.
|
|
||||||
|
|
||||||
** PROPOSED support for passing paths to files between source blocks
|
** PROPOSED support for passing paths to files between source blocks
|
||||||
Maybe this should be it's own result type (in addition to scalars and
|
Maybe this should be it's own result type (in addition to scalars and
|
||||||
|
Loading…
Reference in New Issue
Block a user