0
0
Fork 1
mirror of https://git.savannah.gnu.org/git/emacs/org-mode.git synced 2024-09-29 20:07:46 +00:00

ob-shell.el: export vars as arrays for 'sh' code blocks

* lisp/ob-shell.el: added support to serialize vars as arrays or associative arrays as appropriate if it is using bash.
* testing/examples/ob-shell-test.org: a file containing a few code blocks both illustrating the use of arrays as well as serving as test for the new export functionality.
* testing/lisp/test-ob-shell.el: added a few unit tests that verify that this new logic only triggers for bash and no other shell at this time.

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.
When calling the code block with bash, however, it will now export the list as an array, the table as an associative array. A scalar is exported the same way as before.

Signed-off-by: Pascal Fleury <fleury@google.com>
This commit is contained in:
Pascal Fleury 2014-04-11 23:27:02 +02:00 committed by Eric Schulte
parent de71f03d2a
commit 3c7e75ab0b
3 changed files with 174 additions and 4 deletions

View file

@ -105,6 +105,44 @@ This function is called by `org-babel-execute-src-block'."
buffer)))
;; helper functions
(defun org-babel-variable-assignments:generic (varname values &optional sep hline)
"Returns a list of statements declaring the values as a generic variable."
(format "%s=%s" varname (org-babel-sh-var-to-sh values sep hline)))
(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 "unset %s\ndeclare -a %s=( \"%s\" )"
varname varname
(mapconcat 'identity
(mapcar
(lambda (value) (org-babel-sh-var-to-sh value sep hline))
values)
"\" \"")))
(defun org-babel-variable-assignments:bash_assoc (varname values &optional sep hline)
"Returns a list of statements declaring the values as bash associative array."
(format "unset %s\ndeclare -A %s\n%s"
varname 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:bash (varname values &optional sep hline)
"Represents the parameters as useful Bash shell variables."
(if (listp values)
(if (and (listp (car values)) (= 1 (length (car values))))
(org-babel-variable-assignments:bash_array varname values sep hline)
(org-babel-variable-assignments:bash_assoc varname values sep hline)
)
(org-babel-variable-assignments:generic varname values sep hline)
)
)
(defun org-babel-variable-assignments:sh (params)
"Return list of shell statements assigning the block's variables."
@ -114,10 +152,15 @@ 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)))
(mapcar #'cdr (org-babel-get-header params :var)))))
(if (string= org-babel-sh-command "bash")
(org-babel-variable-assignments:bash
(car pair) (cdr pair) sep hline)
(org-babel-variable-assignments:generic
(car pair) (cdr pair) sep hline)
)
)
(mapcar #'cdr (org-babel-get-header params :var))))
)
(defun org-babel-sh-var-to-sh (var &optional sep hline)
"Convert an elisp value to a shell variable.

View file

@ -0,0 +1,88 @@
#+Title: a collection of examples for ob-shell tests
#+OPTIONS: ^:nil
* Sample data structures
#+NAME: sample_array
| one |
| two |
| three |
#+NAME: sample_mapping_table
| first | one |
| second | two |
| third | three |
#+NAME: sample_big_table
| bread | 2 | kg |
| spaghetti | 20 | cm |
| milk | 50 | dl |
* Array tests
:PROPERTIES:
:ID: 0ba56632-8dc1-405c-a083-c204bae477cf
:END:
** Generic shell: no arrays
#+begin_src sh :exports results :var array=sample_array
echo ${array}
#+end_src
#+RESULTS:
: one two three
** Bash shell: support for arrays
Bash will see a simple indexed array. In this test, we check that the
returned value is indeed only the first item of the array, as opposed to
the generic serialiation that will return all elements of the array as
a single string.
#+begin_src bash :exports results :var array=sample_array
echo ${array}
#+end_src
#+RESULTS:
: one
* Associative array tests (simple map)
:PROPERTIES:
:ID: bec1a5b0-4619-4450-a8c0-2a746b44bf8d
:END:
** Generic shell: no special handing
The shell will see all values as a single string.
#+begin_src sh :exports results :var table=sample_mapping_table
echo ${table}
#+end_src
#+RESULTS:
: first one second two third three
** Bash shell: support for associative arrays
Bash will see a table that contains the first column as the 'index'
of the associative array, and the second column as the value.
#+begin_src bash :exports results :var table=sample_mapping_table
echo ${table[second]}
#+end_src
#+RESULTS:
: two
* Associative array tests (more than 2 columns)
:PROPERTIES:
:ID: 82320a48-3409-49d7-85c9-5de1c6d3ff87
:END:
** Generic shell: no special handing
#+begin_src sh :exports results :var table=sample_big_table
echo ${table}
#+end_src
#+RESULTS:
: bread 2 kg spaghetti 20 cm milk 50 dl
** Bash shell: support for associative arrays with lists
Bash will see an associative array that contains each row as a single
string. Bash cannot handle lists in associative arrays.
#+begin_src bash :exports results :var table=sample_big_table
echo ${table[spaghetti]}
#+end_src
#+RESULTS:
: 20 cm

View file

@ -47,6 +47,45 @@ ob-comint.el, which was not previously tested."
(should res)
(should (listp res))))
; A list of tests using the samples in ob-shell-test.org
(ert-deftest ob-shell/generic-uses-no-arrays ()
"No arrays for generic"
(org-test-at-id "0ba56632-8dc1-405c-a083-c204bae477cf"
(org-babel-next-src-block)
(should (equal "one two three" (org-babel-execute-src-block)))))
(ert-deftest ob-shell/bash-uses-arrays ()
"Bash arrays"
(org-test-at-id "0ba56632-8dc1-405c-a083-c204bae477cf"
(org-babel-next-src-block 2)
(should (equal "one" (org-babel-execute-src-block)))))
(ert-deftest ob-shell/generic-uses-no-assoc-arrays ()
"No associative arrays for generic"
(org-test-at-id "bec1a5b0-4619-4450-a8c0-2a746b44bf8d"
(org-babel-next-src-block)
(should (equal "first one second two third three"
(org-babel-execute-src-block)))))
(ert-deftest ob-shell/bash-uses-assoc-arrays ()
"Bash associative arrays"
(org-test-at-id "bec1a5b0-4619-4450-a8c0-2a746b44bf8d"
(org-babel-next-src-block 2)
(should (equal "two" (org-babel-execute-src-block)))))
(ert-deftest ob-shell/generic-uses-no-assoc-arrays ()
"No associative arrays for generic"
(org-test-at-id "82320a48-3409-49d7-85c9-5de1c6d3ff87"
(org-babel-next-src-block)
(should (equal "bread 2 kg spaghetti 20 cm milk 50 dl"
(org-babel-execute-src-block)))))
(ert-deftest ob-shell/bash-uses-assoc-arrays ()
"Bash associative arrays as strings for the row"
(org-test-at-id "82320a48-3409-49d7-85c9-5de1c6d3ff87"
(org-babel-next-src-block 2)
(should (equal "20 cm" (org-babel-execute-src-block)))))
(provide 'test-ob-shell)