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]
|
||||
** 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
|
||||
|
||||
[[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
|
||||
Can we do this? I wasn't sure how to supply multiple 'var' header
|
||||
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
|
||||
Maybe this should be it's own result type (in addition to scalars and
|
||||
|
Loading…
Reference in New Issue
Block a user