emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Pascal Fleury <fleury@google.com>
To: emacs-orgmode@gnu.org
Subject: Export arrays for 'sh' code blocks when using bash
Date: Thu, 27 Mar 2014 11:26:55 +0100	[thread overview]
Message-ID: <CACc7+8asJQLQ3j=hCC-72quQTMt54E9dA=Wft6SrfP_pxyXkEQ@mail.gmail.com> (raw)


[-- Attachment #1.1: Type: text/plain, Size: 2084 bytes --]

Hello,

I'dl like to propose a patch for inclusion into org-mode (ob-shell.el in
particular).

*TL;DR:* use arrays and associative arrays when exporting variables to bash
in 'sh' code blocks.

*Details:*
When variables are defined in a 'sh' code block, they are exported as
strings. when the variable itself is an array or a table, then we simply
get a shell variable that contains the list of all values in a
non-structured form. E.g.

#+NAME: my_list
| one   |
| two   |
| three |

#+NAME: experiment
| name | first_attempt    |
| date | [2014-03-27 Thu] |
| user | fleury           |

#+BEGIN_SRC sh :var scalar="some value" :var array=my_list :var table=config
echo ${scalar}  # -> prints 'some value'
echo ${array}   # -> prints 'one two three'
echo ${table}   # -> prints 'first attempt [2014-03-27 Thu] fleury'
#+END_SRC

This will print simple strings. Also, there is no easy way to access the
date of the experiment, for example. Now bash has things like arrays and
associative arrays, but the current ob-shell.el does not use these.
Probably because their syntax is bash-specific, and ob-shell.el is
shell-agnostic.

My patch (attached) changes this in the case you have
(setq org-babel-sh-command "bash")
in your emacs config somewhere. If any other value is used, it continues to
export them as we do today (I don't know enough about other shells).

In that case, it will export the list as an array, the table as an
associative array, and the scalar as it does already. So the 'sh' code
block could then use

#+BEGIN_SRC sh :var scalar="some value" :var array=my_list :var table=config
echo ${scalar}
echo ${array[1]} # -> prints "two"
echo ${table[user]} # -> prints "fleury"
#+END_SRC

In the case we have a bigger table, then the first row is used as key, the
others are represented as a string with all the values (as it is for array
currently). bash does not have multi-dimensional arrays, so it needs to be
a string.

This makes writing shell snippets much easier in my experience, and there
I'd like to propose this fix for the org-mode community at large.

--paf

[-- Attachment #1.2: Type: text/html, Size: 3882 bytes --]

[-- Attachment #2: orgmode-bash.patch --]
[-- Type: text/x-patch, Size: 2036 bytes --]

diff --git a/lisp/ob-shell.el b/lisp/ob-shell.el
index 3ede701..0a691e2 100644
--- a/lisp/ob-shell.el
+++ b/lisp/ob-shell.el
@@ -106,6 +106,30 @@ This function is called by `org-babel-execute-src-block'."
 
 ;; helper functions
 
+(defun org-babel-variable-assignments:bash_array (varname values &optional sep hline)
+  "Returns a list of statements declaring the values as a bash array."
+  (format "declare -a %s=( \"%s\" )"
+     varname
+     (mapconcat 'identity
+       (mapcar
+         (lambda (value) (org-babel-sh-var-to-sh value sep hline))
+         values)
+       "\" \"")))
+
+(defun org-babel-variable-assignments:bash_associative (varname values &optional sep hline)
+  "Returns a list of statements declaring the values as bash associative array."
+  (format "declare -A %s\n%s"
+    varname
+    (mapconcat 'identity
+      (mapcar
+        (lambda (items)
+          (format "%s[\"%s\"]=%s"
+            varname
+            (org-babel-sh-var-to-sh (car items) sep hline)
+            (org-babel-sh-var-to-sh (cdr items) sep hline)))
+        values)
+      "\n")))
+
 (defun org-babel-variable-assignments:sh (params)
   "Return list of shell statements assigning the block's variables."
   (let ((sep (cdr (assoc :separator params)))
@@ -114,9 +138,17 @@ This function is called by `org-babel-execute-src-block'."
 		     "hline"))))
     (mapcar
      (lambda (pair)
-       (format "%s=%s"
-	       (car pair)
-	       (org-babel-sh-var-to-sh (cdr pair) sep hline)))
+       (if (and (string= org-babel-sh-command "bash") (listp (cdr pair)))
+         (if (listp (car (cdr pair)))
+           (org-babel-variable-assignments:bash_associative
+	      (car pair) (cdr pair) sep hline)
+           (org-babel-variable-assignments:bash_array
+	      (car pair) (cdr pair) sep) hline)
+         (format "%s=%s"
+	    (car pair)
+	    (org-babel-sh-var-to-sh (cdr pair) sep hline))
+       )
+     )
      (mapcar #'cdr (org-babel-get-header params :var)))))
 
 (defun org-babel-sh-var-to-sh (var &optional sep hline)

             reply	other threads:[~2014-03-27 10:27 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-27 10:26 Pascal Fleury [this message]
2014-03-27 17:43 ` Export arrays for 'sh' code blocks when using bash Eric Schulte
2014-03-27 22:52   ` Pascal Fleury
2014-03-29 19:37     ` Eric Schulte
2014-04-06 23:25       ` Pascal Fleury
2014-04-11  2:38         ` Eric Schulte
2014-04-11  9:33           ` Bastien
2014-04-14  8:48             ` Pascal Fleury
2014-04-15  3:35               ` Eric Schulte
2014-04-15 11:15                 ` Pascal Fleury
2014-04-22 14:47                 ` Skip Collins
2014-04-22 15:37                   ` Bastien
2014-04-22 17:19                     ` Skip Collins
2014-04-22 20:59                       ` Bastien
2014-04-22 21:04                         ` Skip Collins
2014-04-22 21:09                           ` Skip Collins
2014-04-22 21:22                             ` Bastien
2014-04-23 13:51                               ` Skip Collins
2014-04-23 14:13                                 ` Pascal Fleury
2014-04-23 16:31                                   ` Skip Collins
2014-04-24  1:23                                     ` Eric Schulte
2014-04-24  7:44                                       ` Pascal Fleury
2014-04-22 21:15                           ` Bastien
2014-04-15  3:37             ` Eric Schulte
2014-04-15 15:37               ` Nick Dokos
2014-04-17  6:31               ` Bastien

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='CACc7+8asJQLQ3j=hCC-72quQTMt54E9dA=Wft6SrfP_pxyXkEQ@mail.gmail.com' \
    --to=fleury@google.com \
    --cc=emacs-orgmode@gnu.org \
    /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).