From 728869fef806437bed25c7c02829675e48af6719 Mon Sep 17 00:00:00 2001 From: Eric Schulte Date: Sat, 9 May 2009 09:34:55 -0700 Subject: [PATCH] now passing arguments to source-blocks when the source-block is used to initialize a header-argument variable before this is useful need to implement params merging in litorgy-execute-src-block, see the TODO infile --- litorgy/litorgy-ref.el | 99 ++++++++++++++++++++++-------------------- litorgy/litorgy.el | 20 +++------ rorg.org | 40 ++++++++++------- 3 files changed, 83 insertions(+), 76 deletions(-) diff --git a/litorgy/litorgy-ref.el b/litorgy/litorgy-ref.el index 5cca2fed3..6c73f142c 100644 --- a/litorgy/litorgy-ref.el +++ b/litorgy/litorgy-ref.el @@ -69,54 +69,59 @@ return nil." (if (string-match "\"\\(.+\\)\"" ref) (read ref) ;; string nil)))) ;; reference -(defun litorgy-ref-parse (reference) - "Parse the assignment REFERENCE of a variable specified in a -header argument. If the assignment has a literal value return -that value, otherwise interpret REFERENCE as a reference to an -external resource returning a list with two elements. The first -element of the list will be the name of the variable, and the -second will be an emacs-lisp representation of the value of the -variable." +(defun litorgy-ref-parse (assignment) + "Parse a variable ASSIGNMENT in a header argument. If the +right hand side of the assignment has a literal value return that +value, otherwise interpret as a reference to an external resource +and find it's value using `litorgy-ref-resolve-reference'. +Return a list with two elements. The first element of the list +will be the name of the variable, and the second will be an +emacs-lisp representation of the value of the variable." + (if (string-match "\\(.+\\)=\\(.+\\)" assignment) + (let ((var (match-string 1 assignment)) + (ref (match-string 2 assignment))) + (cons (intern var) + (or (litorgy-ref-literal ref) + (litorgy-ref-resolve-reference ref)))))) + +(defun litorgy-ref-resolve-reference (ref) + "Resolve the reference and return it's value" (save-excursion - (if (string-match "\\(.+\\)=\\(.+\\)" reference) - (let* ((var (match-string 1 reference)) - (ref (match-string 2 reference)) - (lit (litorgy-ref-literal ref)) - direction type) - (when (string-match "\\(.+\\):\\(.+\\)" reference) - (find-file (match-string 1 reference)) - (setf ref (match-string 2 reference))) - (cons (intern var) - (or lit - (progn - (cond ;; follow the reference in the current file - ((string= ref "previous") (setq direction -1)) - ((string= ref "next") (setq direction 1)) - (t - (goto-char (point-min)) - (setq direction 1) - (unless (let ((regexp (concat "^#\\+\\(TBL\\|SRC\\)NAME:[ \t]*" - (regexp-quote ref) "[ \t]*$"))) - (or (re-search-forward regexp nil t) - (re-search-backward regexp nil t))) - ;; ;; TODO: allow searching for names in other buffers - ;; (setq id-loc (org-id-find ref 'marker) - ;; buffer (marker-buffer id-loc) - ;; loc (marker-position id-loc)) - ;; (move-marker id-loc nil) - (error (format "reference '%s' not found in this buffer" ref))))) - (while (not (setq type (litorgy-ref-at-ref-p))) - (forward-line direction) - (beginning-of-line) - (if (or (= (point) (point-min)) (= (point) (point-max))) - (error "reference not found"))) - (case type - ('table - (mapcar (lambda (row) - (mapcar #'litorgy-read row)) - (org-table-to-lisp))) - ('source-block - (litorgy-execute-src-block t)))))))))) + (let (direction type args) + (when (string-match "\\(.+\\):\\(.+\\)" ref) + (find-file (match-string 1 ref)) + (setf ref (match-string 2 ref))) + (cond ;; follow the reference in the current file + ((string= ref "previous") (setq direction -1)) + ((string= ref "next") (setq direction 1)) + (t + (goto-char (point-min)) + (setq direction 1) + (unless (let ((regexp (concat "^#\\+\\(TBL\\|SRC\\)NAME:[ \t]*" + (regexp-quote ref) "[ \t]*$"))) + (or (re-search-forward regexp nil t) + (re-search-backward regexp nil t))) + ;; ;; TODO: allow searching for names in other buffers + ;; (setq id-loc (org-id-find ref 'marker) + ;; buffer (marker-buffer id-loc) + ;; loc (marker-position id-loc)) + ;; (move-marker id-loc nil) + (error (format "reference '%s' not found in this buffer" ref))))) + (while (not (setq type (litorgy-ref-at-ref-p))) + (forward-line direction) + (beginning-of-line) + (if (or (= (point) (point-min)) (= (point) (point-max))) + (error "reference not found"))) + (case type + ('table + (mapcar (lambda (row) + (mapcar #'litorgy-read row)) + (org-table-to-lisp))) + ('source-block + ;; assign any arguments to pass to source block + (when (string-match "\(\\(.+\\)\)" ref) + (setq args (mapcar (lambda (ref) (cons :var ref)) (split-string ref ",[ \f\t\n\r\v]*")))) + (litorgy-execute-src-block t nil args)))))) (defun litorgy-ref-at-ref-p () "Return the type of reference located at point or nil of none diff --git a/litorgy/litorgy.el b/litorgy/litorgy.el index 22faa56f9..86b0077e6 100644 --- a/litorgy/litorgy.el +++ b/litorgy/litorgy.el @@ -96,7 +96,7 @@ lisp code use the `litorgy-add-interpreter' function." (const "ruby"))) ;;; functions -(defun litorgy-execute-src-block (&optional arg info) +(defun litorgy-execute-src-block (&optional arg info params) "Execute the current source code block, and dump the results into the buffer immediately following the block. Results are commented by `org-toggle-fixed-width-section'. With optional @@ -105,7 +105,10 @@ results in raw elisp (this is useful for automated execution of a source block). Optionally supply a value for INFO in the form returned by -`litorgy-get-src-block-info'." +`litorgy-get-src-block-info'. + +Optionally supply a value for PARAMS which will be merged with +the header arguments specified at the source code block." ; TODO implement!! (interactive "P") (let* ((info (or info (litorgy-get-src-block-info))) (lang (first info)) @@ -167,18 +170,7 @@ of the following form. (language body header-arguments-alist)" (mapcar (lambda (arg) (if (string-match "\\([^ \f\t\n\r\v]+\\)[ \f\t\n\r\v]*\\([^ \f\t\n\r\v]+.*\\)" arg) (cons (intern (concat ":" (match-string 1 arg))) (match-string 2 arg)))) - (let (matches holder) - (mapcar (lambda (part) - (if (string= (substring part -1) "(") - (setq holder part) - (if holder - (progn - (setq matches (cons (concat holder " :" part) matches)) - (setq holder nil)) - (setq matches (cons part matches))))) - (split-string (concat " " arg-string) "[ \f\t\n\r\v]+:" t)) - (message (format "%S" matches)) - matches)))) + (split-string (concat " " arg-string) "[ \f\t\n\r\v]+:" t)))) (defun litorgy-insert-result (result &optional insert) "Insert RESULT into the current buffer after the end of the diff --git a/rorg.org b/rorg.org index 4a724052e..d8e771d8e 100644 --- a/rorg.org +++ b/rorg.org @@ -3,7 +3,7 @@ #+SEQ_TODO: TODO OPEN PROPOSED | DONE RESOLVED REJECTED #+STARTUP: oddeven -* Tasks [6/14] +* Tasks [7/14] ** TODO test for litorgy since we are accumulating this nice collection of source-code blocks @@ -19,17 +19,6 @@ I have the feeling that this should be possible using only litorgical functions with minimal or no additional elisp. It would be very cool for litorgy to be able to test itself. -** TODO re-implement helper functions from org-R -Much of the power of org-R seems to be in it's helper functions for -the quick graphing of tables. Should we try to re-implement these -functions on top of litorgy? - -I'm thinking this may be useful both to add features to litorgy-R and -also to potentially suggest extensions of the framework. For example -one that comes to mind is the ability to treat a source-code block -like a function which accepts arguments and returns results. Actually -this can be it's own TODO (see [[* source blocks as functions][source blocks as functions]]). - ** TODO source blocks as functions Allow source code blocks to be called like functions, with arguments @@ -52,6 +41,9 @@ Sweave? Would/Should we just mimic the behavior of Sweave with the addition of support for poping up graphics during live evaluation of a source code block. +I think the best way to approach this would be to start with an +example R source-code block and then work up from there. + ** TODO ability to select which of multiple sessions is being used Increasingly it is looking like we're going to want to run all source code blocks in comint buffer (sessions). Which will have @@ -108,7 +100,18 @@ source code block. posterity. Same for a shell session either in a *shell* buffer, or pasted from another terminal emulator. And python of course. -** TODO folding of code blocks? [1/2] +** PROPOSED re-implement helper functions from org-R +Much of the power of org-R seems to be in it's helper functions for +the quick graphing of tables. Should we try to re-implement these +functions on top of litorgy? + +I'm thinking this may be useful both to add features to litorgy-R and +also to potentially suggest extensions of the framework. For example +one that comes to mind is the ability to treat a source-code block +like a function which accepts arguments and returns results. Actually +this can be it's own TODO (see [[* source blocks as functions][source blocks as functions]]). + +** DONE folding of code blocks? [2/2] [DED] In similar way to using outline-minor-mode for folding function bodies, can we fold code blocks? #+begin whatever statements are pretty ugly, and in any case when you're thinking about the overall @@ -119,9 +122,13 @@ source code block. now be fold-able in the same manner as headlines (by pressing TAB on the first line). -*** TODO folding of results +*** REJECTED folding of results So, lets do a three-stage tab cycle... First fold the src block, then fold the results, then unfold. + + There's no way to tell if the results are a table or not w/o + actually executing the block which would be too expensive of an + operation. ** DONE inline source code blocks [2/2] Like the =\R{ code }= blocks @@ -286,6 +293,9 @@ recognition of ruby arrays as such. * Sandbox + :PROPERTIES: + :CUSTOM_ID: sandbox + :END: This is a place for code examples ** litorgy.el beginning functionality @@ -624,7 +634,7 @@ inline source code blocks) [[file:test-export.org]] : 15 -#+begin_src emacs-lisp :var result=triple(:n => 8) +#+begin_src emacs-lisp :var result=triple(n=8) result #+end_src