emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Eric Schulte <eric.schulte@gmx.com>
To: "Thomas S. Dye" <tsd@tsdye.com>
Cc: FengShu <tumashu@gmail.com>, emacs-orgmode@gnu.org
Subject: Re: layout org-babel menu WAS: About org-babel menu
Date: Tue, 10 Apr 2012 21:40:39 -0400	[thread overview]
Message-ID: <87pqbfhwq0.fsf@gmx.com> (raw)
In-Reply-To: m1hawtncp8.fsf@tsdye.com

[-- Attachment #1: Type: text/plain, Size: 5613 bytes --]

tsd@tsdye.com (Thomas S. Dye) writes:

> Eric Schulte <eric.schulte@gmx.com> writes:
>
>> Torsten Wagner <torsten.wagner@gmail.com> 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,


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-code-block-languages-may-specify-their-own-headers-a.patch --]
[-- Type: text/x-patch, Size: 9849 bytes --]

From ff3d974ff4d0aa93d3c241709557f6858ebf284f Mon Sep 17 00:00:00 2001
From: Eric Schulte <eric.schulte@gmx.com>
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


[-- Attachment #3: Type: text/plain, Size: 47 bytes --]


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

  reply	other threads:[~2012-04-11  3:41 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-19 13:22 About org-babel menu FengShu
2012-03-19 14:22 ` Eric Schulte
2012-03-19 14:41   ` Rainer M Krug
2012-03-19 14:52     ` Eric Schulte
2012-03-31  5:50       ` Torsten Wagner
2012-03-31  7:21         ` Nick Dokos
2012-04-01 16:34           ` Bernt Hansen
2012-04-01 20:26             ` Nick Dokos
2012-03-31  8:27         ` Bastien
2012-03-31 10:33           ` Yagnesh Raghava Yakkala
2012-03-19 15:03     ` Jonathan Leech-Pepin
2012-03-27 23:07     ` Bastien
2012-04-05  9:08       ` layout org-babel menu WAS: " Rainer M Krug
2012-04-05 12:44         ` Eric Schulte
2012-04-06  1:51           ` Torsten Wagner
2012-04-06  6:34             ` Rainer M Krug
2012-04-06  6:48               ` Thorsten
2012-04-06  6:58                 ` Rainer M Krug
2012-04-06  7:18                 ` Bastien
2012-04-06  9:29                   ` Thorsten
2012-04-06 15:40             ` Thomas S. Dye
2012-04-06 21:51             ` Eric Schulte
2012-04-08 21:19               ` Thomas S. Dye
2012-04-11  1:40                 ` Eric Schulte [this message]
2012-04-11  7:26                   ` Rainer M Krug
2012-04-11 13:59                     ` Eric Schulte
2012-04-11 20:12                       ` Thomas S. Dye
2012-04-13 12:45                         ` Eric Schulte
2012-04-13 19:37                           ` [bug?] Re: layout " Yagnesh Raghava Yakkala
2012-04-14 13:35                             ` Eric Schulte
2012-04-14 16:21                               ` Nick Dokos
2012-04-10  8:05               ` layout org-babel menu WAS: About " Rainer M Krug
2012-04-10 20:35                 ` Bastien
2012-04-11  7:10                   ` Rainer M Krug
2012-04-11  7:24                     ` Yagnesh Raghava Yakkala
2012-04-11  8:10                       ` Bastien
2012-04-11  8:11                     ` Bastien
2012-04-11  8:13                       ` Rainer M Krug
2012-04-11 13:51                         ` Eric Schulte
2012-04-11 13:43                       ` Eric Schulte

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87pqbfhwq0.fsf@gmx.com \
    --to=eric.schulte@gmx.com \
    --cc=emacs-orgmode@gnu.org \
    --cc=tsd@tsdye.com \
    --cc=tumashu@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).