emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [O] layout org-babel menu WAS: About org-babel menu


From: Eric Schulte
Subject: Re: [O] layout org-babel menu WAS: About org-babel menu
Date: Tue, 10 Apr 2012 21:40:39 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.1.50 (gnu/linux)

address@hidden (Thomas S. Dye) writes:

> Eric Schulte <address@hidden> writes:
>
>> Torsten Wagner <address@hidden> writes:
>>
>>> Hi,
>>>
>>> for me the biggest "trouble" with babel is to remember the possible
>>> keywords in the header for different languages.
>>> There were a lot of ongoing syntax change which did not make it easier
>>> for me to remember all this.
>>> Thus a menu which is organised by languages offering all possible
>>> settings for each language would be very helpful.
>>> |
>>> Python
>>> |    |
>>> |  export - code - result - both - none
>>> |    |
>>> |  tangle - no - yes- filename
>>> |   |
>>> |  result - value - output
>>> |  |
>>> | ...
>>> |
>>> ...
>>>
>>> Not sure how effectual this would be in a main menu. It would be
>>> definitely awesome in a context menu
>>>
>>> That would be (copied from worg) [*] indicates cursor position
>>>
>>> #+NAME: factorial
>>> #+BEGIN_SRC haskell [*] :results silent :exports code :var n=0
>>>
>>> a context menu would appear presenting all possible header arguments for 
>>> haskell
>>>
>>> #+NAME: factorial
>>> #+BEGIN_SRC haskell :results [*] :exports code :var n=0
>>>
>>> a context menu presenting all possible values for the header argument
>>> :results in haskell
>>> I guess that together with the possibility to call this menu by
>>> keyboard strokes or alternatively show the same infos in the
>>> minibuffer would be a great win for babel and it would make many
>>> questions here on the list unnecessary.
>>> Furthermore, any change or extension in the syntax for a certain
>>> language would be directly reflected to the end-user. E.g., If I
>>> suddenly see the menu entry :exports 3dprint, I would be curious and
>>> check it out on worg and the manual ;)
>>>
>>> Totti
>>>
>>
>> Hi,
>>
>> I've put together a first pass at such support for interactive header
>> argument look up.  Please evaluate this elisp code [1] in your *scratch*
>> buffer, then in an Org-mode buffer insert a code block like the
>> following with the point at [*], and press tab.
>>
>> #+begin_src R :[*]
>>   :foo
>> #+end_src
>>
>> You should see an auto-completion list showing which header arguments
>> are available and (for those with known arguments) which arguments may
>> be specified.  This includes language specific header arguments, i.e.,
>> the R code block above suggests about twice as many possible header
>> arguments as an elisp block.  Note this "expand on tab after :" behavior
>> is active on "#+headers:" lines as well.
>>
>> This makes use of the `org-babel-common-header-args-w-values' variable
>> which holds header argument names and completions, as well as the
>> org-babel-header-arg-names:lang variables.
>>
>> Does this seem like a good interface?
>>
>> Is it missing any important functionality?
>>
>> Best,
>>
>> Footnotes: 
>> [1]  
>> ;; Add support for completing-read insertion of header arguments after ":"
>> (defun org-babel-header-arg-expand ()
>>   "Call `org-babel-enter-header-arg-w-completion' in appropriate contexts."
>>   (when (and (= (char-before) ?\:) (org-babel-where-is-src-block-head))
>>     (org-babel-enter-header-arg-w-completion (match-string 2))))
>>
>> (defun org-babel-enter-header-arg-w-completion (&optional lang)
>>   "Insert header argument appropriate for LANG with completion."
>>   (let* ((lang-headers-var (intern (concat "org-babel-header-arg-names:" 
>> lang)))
>>          (lang-headers (when (boundp lang-headers-var)
>>                          (mapcar #'symbol-name (eval lang-headers-var))))
>>          (headers (append (mapcar #'symbol-name org-babel-header-arg-names)
>>                           lang-headers))
>>          (header (org-completing-read "Header Arg: " headers))
>>          (args (cdr (assoc (intern header)
>>                            org-babel-common-header-args-w-values)))
>>          (arg (when (and args (listp args))
>>                 (org-completing-read
>>                  (format "%s: " header)
>>                  (mapcar #'symbol-name (car args))))))
>>     (insert (concat header " " (or arg "")))
>>     (cons header arg)))
>>
>> (add-hook 'org-tab-first-hook 'org-babel-header-arg-expand)
>
> Hi Eric,
>
> This is potentially much nicer than a function template.  I tried
> filling out an R source code block's header arguments, but I couldn't
> find a way to get :results output graphics, which I use frequently for
> ggplot2 graphics.  With TAB I could see type arguments, but not
> collection or handling arguments.  Is there some way to cycle through
> the various completion lists?
>
> All the best,
> Tom

Hi Tom,

Currently language specific arguments for header arguments are not
stored in any elisp variables so there is no way to provide this
information to the auto completion function.  I'm adding a new suite of
language-specific variables which may be customized by each language to
provide information on language-specific header-argument arguments.

I've just put together this new code into a patch.  I'm not currently
able to run the test suite without massive failures (with or without
this patch), so I'm just attaching the patch here rather than pushing it
up directly.  If it works well on other people's systems I think it
should be committed.

After this is applied the language-specific header argument variables
will need to be fleshed out.  For example see the value of the
`org-babel-header-args:R' which includes the "graphics" results option.
The arguments of these variables will override the arguments of specific
headers in the global `org-babel-common-header-args-w-values' variable.

Best,

>From ff3d974ff4d0aa93d3c241709557f6858ebf284f Mon Sep 17 00:00:00 2001
From: Eric Schulte <address@hidden>
Date: Tue, 10 Apr 2012 19:03:37 -0400
Subject: [PATCH] code-block languages may specify their own headers and
 values

* lisp/ob-R.el (org-babel-header-args:R): Adding values.
* lisp/ob-clojure.el (org-babel-header-args:clojure): Adding values.
* lisp/ob-lisp.el (org-babel-header-args:lisp): Adding values.
* lisp/ob-sql.el (org-babel-header-args:sql): Adding values.
* lisp/ob-sqlite.el (org-babel-header-args:sqlite): Adding values.
* lisp/ob.el (org-babel-combine-header-arg-lists): Combine lists of
  arguments and values.
  (org-babel-insert-header-arg): Use new combined header argument
  lists.
  (org-babel-header-arg-expand): Add support for completing-read
  insertion of header arguments after ":"
  (org-babel-enter-header-arg-w-completion): Completing read insertion
  of header arguments
  (org-tab-first-hook): Adding header argument completion.
  (org-babel-params-from-properties): Combining header argument lists.
* testing/lisp/test-ob.el (ob-test/org-babel-combine-header-arg-lists):
  Test the new header argument combination functionality.
---
 lisp/ob-R.el            |   29 +++++++++++++++++++---
 lisp/ob-clojure.el      |    2 +-
 lisp/ob-lisp.el         |    2 +-
 lisp/ob-sql.el          |    5 ++--
 lisp/ob-sqlite.el       |   14 +++++++++--
 lisp/ob.el              |   62 +++++++++++++++++++++++++++++++++++++----------
 testing/lisp/test-ob.el |   18 ++++++++++++++
 7 files changed, 109 insertions(+), 23 deletions(-)

diff --git a/lisp/ob-R.el b/lisp/ob-R.el
index 49a8a85..9538dc4 100644
--- a/lisp/ob-R.el
+++ b/lisp/ob-R.el
@@ -40,10 +40,31 @@
 (declare-function ess-eval-buffer "ext:ess-inf" (vis))
 (declare-function org-number-sequence "org-compat" (from &optional to inc))
 
-(defconst org-babel-header-arg-names:R
-  '(width height bg units pointsize antialias quality compression
-         res type family title fonts version paper encoding
-         pagecentre colormodel useDingbats horizontal)
+(defconst org-babel-header-args:R
+  '((width              . :any)
+    (height             . :any)
+    (bg                         . :any)
+    (units              . :any)
+    (pointsize          . :any)
+    (antialias          . :any)
+    (quality            . :any)
+    (compression        . :any)
+    (res                . :any)
+    (type               . :any)
+    (family             . :any)
+    (title              . :any)
+    (fonts              . :any)
+    (version            . :any)
+    (paper              . :any)
+    (encoding           . :any)
+    (pagecentre                 . :any)
+    (colormodel                 . :any)
+    (useDingbats        . :any)
+    (horizontal                 . :any)
+    (results             . ((file list vector table scalar verbatim)
+                           (raw org html latex code pp wrap)
+                           (replace silent append prepend)
+                           (output value graphics))))
   "R-specific header arguments.")
 
 (defvar org-babel-default-header-args:R '())
diff --git a/lisp/ob-clojure.el b/lisp/ob-clojure.el
index 69d3db8..f389404 100644
--- a/lisp/ob-clojure.el
+++ b/lisp/ob-clojure.el
@@ -45,7 +45,7 @@
 (add-to-list 'org-babel-tangle-lang-exts '("clojure" . "clj"))
 
 (defvar org-babel-default-header-args:clojure '())
-(defvar org-babel-header-arg-names:clojure '(package))
+(defvar org-babel-header-args:clojure '((package . :any)))
 
 (defun org-babel-expand-body:clojure (body params)
   "Expand BODY according to PARAMS, return the expanded body."
diff --git a/lisp/ob-lisp.el b/lisp/ob-lisp.el
index 8fb6721..89dbe24 100644
--- a/lisp/ob-lisp.el
+++ b/lisp/ob-lisp.el
@@ -41,7 +41,7 @@
 (add-to-list 'org-babel-tangle-lang-exts '("lisp" . "lisp"))
 
 (defvar org-babel-default-header-args:lisp '())
-(defvar org-babel-header-arg-names:lisp '(package))
+(defvar org-babel-header-args:lisp '((package . :any)))
 
 (defcustom org-babel-lisp-dir-fmt
   "(let ((*default-pathname-defaults* #P%S)) %%s)"
diff --git a/lisp/ob-sql.el b/lisp/ob-sql.el
index 20fbad3..e3f6edd 100644
--- a/lisp/ob-sql.el
+++ b/lisp/ob-sql.el
@@ -51,8 +51,9 @@
 
 (defvar org-babel-default-header-args:sql '())
 
-(defvar org-babel-header-arg-names:sql
-  '(engine out-file))
+(defvar org-babel-header-args:sql
+  '((engine   . :any)
+    (out-file . :any)))
 
 (defun org-babel-expand-body:sql (body params)
   "Expand BODY according to the values of PARAMS."
diff --git a/lisp/ob-sqlite.el b/lisp/ob-sqlite.el
index 84d6bb2..2106072 100644
--- a/lisp/ob-sqlite.el
+++ b/lisp/ob-sqlite.el
@@ -37,8 +37,18 @@
 
 (defvar org-babel-default-header-args:sqlite '())
 
-(defvar org-babel-header-arg-names:sqlite
-  '(db header echo bail csv column html line list separator nullvalue)
+(defvar org-babel-header-args:sqlite
+  '((db        . :any)
+    (header    . :any)
+    (echo      . :any)
+    (bail      . :any)
+    (csv       . :any)
+    (column    . :any)
+    (html      . :any)
+    (line      . :any)
+    (list      . :any)
+    (separator . :any)
+    (nullvalue . :any))
   "Sqlite specific header args.")
 
 (defun org-babel-expand-body:sqlite (body params)
diff --git a/lisp/ob.el b/lisp/ob.el
index 726245c..df401b0 100644
--- a/lisp/ob.el
+++ b/lisp/ob.el
@@ -622,6 +622,19 @@ arguments and pop open the results in a preview buffer."
                   (mmin (in (1- i) j) (in i (1- j)) (in (1- i) (1- j)))))))
       (in l1 l2))))
 
+(defun org-babel-combine-header-arg-lists (original &rest others)
+  "Combine a number of lists of header argument names and arguments."
+  (let ((results (copy-sequence original)))
+    (dolist (new-list others)
+      (dolist (arg-pair new-list)
+       (let ((header (car arg-pair))
+             (args (cdr arg-pair)))
+         (setq results
+               (cons arg-pair (org-remove-if
+                               (lambda (pair) (equal header (car pair)))
+                               results))))))
+    results))
+
 ;;;###autoload
 (defun org-babel-check-src-block ()
   "Check for misspelled header arguments in the current code block."
@@ -649,12 +662,10 @@ arguments and pop open the results in a preview buffer."
   "Insert a header argument selecting from lists of common args and values."
   (interactive)
   (let* ((lang (car (org-babel-get-src-block-info 'light)))
-        (lang-headers (intern (concat "org-babel-header-arg-names:" lang)))
-        (headers (append (if (boundp lang-headers)
-                             (mapcar (lambda (h) (cons h :any))
-                                     (eval lang-headers))
-                           nil)
-                         org-babel-common-header-args-w-values))
+        (lang-headers (intern (concat "org-babel-header-args:" lang)))
+        (headers (org-babel-combine-header-arg-lists
+                  org-babel-common-header-args-w-values
+                  (if (boundp lang-headers) (eval lang-headers) nil)))
         (arg (org-icompleting-read
              "Header Arg: "
              (mapcar
@@ -679,6 +690,30 @@ arguments and pop open the results in a preview buffer."
                  "")))
            vals ""))))))))
 
+;; Add support for completing-read insertion of header arguments after ":"
+(defun org-babel-header-arg-expand ()
+  "Call `org-babel-enter-header-arg-w-completion' in appropriate contexts."
+  (when (and (= (char-before) ?\:) (org-babel-where-is-src-block-head))
+    (org-babel-enter-header-arg-w-completion (match-string 2))))
+
+(defun org-babel-enter-header-arg-w-completion (&optional lang)
+  "Insert header argument appropriate for LANG with completion."
+  (let* ((lang-headers-var (intern (concat "org-babel-header-args:" lang)))
+         (lang-headers (when (boundp lang-headers-var) (eval 
lang-headers-var)))
+        (headers-w-values (org-babel-combine-header-arg-lists
+                           org-babel-common-header-args-w-values lang-headers))
+         (headers (mapcar #'symbol-name (mapcar #'car headers-w-values)))
+         (header (org-completing-read "Header Arg: " headers))
+         (args (cdr (assoc (intern header) headers-w-values)))
+         (arg (when (and args (listp args))
+                (org-completing-read
+                 (format "%s: " header)
+                 (mapcar #'symbol-name (apply #'append args))))))
+    (insert (concat header " " (or arg "")))
+    (cons header arg)))
+
+(add-hook 'org-tab-first-hook 'org-babel-header-arg-expand)
+
 ;;;###autoload
 (defun org-babel-load-in-session (&optional arg info)
   "Load the body of the current source-code block.
@@ -1153,13 +1188,14 @@ may be specified in the properties of the current 
outline entry."
                     (cons (intern (concat ":" header-arg))
                           (org-babel-read val))))
              (mapcar
-              'symbol-name
-              (append
-               org-babel-header-arg-names
-               (progn
-                 (setq sym (intern (concat "org-babel-header-arg-names:"
-                                           lang)))
-                 (and (boundp sym) (eval sym)))))))))))
+              #'symbol-name
+              (mapcar
+               #'car
+               (org-babel-combine-header-arg-lists
+                org-babel-common-header-args-w-values
+                (progn
+                  (setq sym (intern (concat "org-babel-header-args:" lang)))
+                  (and (boundp sym) (eval sym))))))))))))
 
 (defvar org-src-preserve-indentation)
 (defun org-babel-parse-src-block-match ()
diff --git a/testing/lisp/test-ob.el b/testing/lisp/test-ob.el
index 4dac696..5cf689a 100644
--- a/testing/lisp/test-ob.el
+++ b/testing/lisp/test-ob.el
@@ -87,6 +87,24 @@
          '((:session . "none") (:results . "replace") (:exports . "results"))
          org-babel-default-inline-header-args)))
 
+(ert-deftest ob-test/org-babel-combine-header-arg-lists ()
+  (let ((results (org-babel-combine-header-arg-lists
+                  '((foo  . :any)
+                    (bar)
+                    (baz  . ((foo bar) (baz)))
+                    (qux  . ((foo bar baz qux)))
+                    (quux . ((foo bar))))
+                  '((bar)
+                    (baz  . ((baz)))
+                    (quux . :any)))))
+    (dolist (pair '((foo  . :any)
+                   (bar)
+                   (baz  . ((baz)))
+                   (quux . :any)
+                   (qux  . ((foo bar baz qux)))))
+      (should (equal (cdr pair)
+                     (cdr (assoc (car pair) results)))))))
+
 ;;; ob-get-src-block-info
 (ert-deftest test-org-babel/get-src-block-info-language ()
   (org-test-at-marker nil org-test-file-ob-anchor
-- 
1.7.10

-- 
Eric Schulte
http://cs.unm.edu/~eschulte/

reply via email to

[Prev in Thread] Current Thread [Next in Thread]