* [babel] how to pass data to gnuplot from another block
@ 2013-11-22 9:57 Eric S Fraga
2013-11-22 15:00 ` Eric Schulte
0 siblings, 1 reply; 21+ messages in thread
From: Eric S Fraga @ 2013-11-22 9:57 UTC (permalink / raw
To: emacs-orgmode
Hello,
everything I have seen on the list and on Worg seems to indicate that it
should be possible to pass data from a babel src block to a gnuplot src
block. See, for instance, the excellent article on data collection and
analysis at
http://orgmode.org/worg/org-contrib/babel/examples/data-collection-analysis.html
I don't have R so I have not tried the examples on this page. However,
I have tried the following using octave and gnuplot:
#+begin_src org
,#+TITLE: examplebug.org
,#+AUTHOR: Eric S Fraga
,* bubble and dew points
,#+name: bubble-point-temperatures
,#+begin_src octave :results raw output
A = [ 6.86880 6.84941]';
B = [1154.646 1206.001]';
C = [ 226.046 223.148]';
pv = @(T) 10.^(A-B./(T+C));
x = 0;
res = [];
while x<(1+1e-3)
f = @(T) 760 - [x (1-x)]*pv(T);
T = fsolve(f, 70);
printf("| %5.2f | %7.2f | \n", x, T);
res = [res; [x T] ];
x = x + 0.05;
endwhile
,#+end_src
,#+begin_src gnuplot :var data=bubble-point-temperatures :file "bubble.pdf"
set terminal pdfcairo mono enhanced font ",12" size 10cm,6cm
plot data
,#+end_src
,#+results:
[[file:bubble.pdf]]
#+end_src
Trying to execute the gnuplot block leads to an error in gnuplot because
the output of the octave data block is being put directly into the data
variable instead of into a file whose name is passed to the data
variable. The latter happens if the source of the data is a table
instead of a src block.
I have tried various combinations of output directives for the first src
block but to no avail.
I have tried this with "emacs -Q", by the way, and my org is up to date
as of a few minutes ago!
What am I doing wrong please?
Thanks,
eric
--
: Eric S Fraga (0xFFFCF67D), Emacs 24.3.50.1, Org release_8.2.3c-266-g7a726d
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-11-22 9:57 [babel] how to pass data to gnuplot from another block Eric S Fraga
@ 2013-11-22 15:00 ` Eric Schulte
2013-11-22 17:27 ` Nick Dokos
2013-12-05 7:35 ` Eric S Fraga
0 siblings, 2 replies; 21+ messages in thread
From: Eric Schulte @ 2013-11-22 15:00 UTC (permalink / raw
To: emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 80 bytes --]
Hi Eric,
The attached works fine for me (using sh since I don't have octave).
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: sh-to-gnuplot.org --]
[-- Type: text/x-org, Size: 372 bytes --]
#+name: uptime
#+begin_src sh
paste <(echo -e "1\n5\n15") <(uptime|sed 's/^.*average: //;s/,//g'|tr ' ' '\n')
#+end_src
#+RESULTS: uptime
| 1 | 0.02 |
| 5 | 0.06 |
| 15 | 0.05 |
#+begin_src gnuplot :var data=uptime :results silent
set xrange [0:]
set yrange [0:]
set title "uptime"
set xlabel "minutes ago"
set ylabel "load"
plot data w lines
#+end_src
[-- Attachment #3: Type: text/plain, Size: 2268 bytes --]
Ensure that the data you're passing into gnuplot is a table and not a
string. Gnuplot blocks handle tables by writing them to a file, and
then replacing the variable with the file name. As I recall gnuplot
blocks assume string data already is a file name, so the variable is
replaced directly.
Best,
Eric S Fraga <e.fraga@ucl.ac.uk> writes:
> Hello,
>
> everything I have seen on the list and on Worg seems to indicate that it
> should be possible to pass data from a babel src block to a gnuplot src
> block. See, for instance, the excellent article on data collection and
> analysis at
>
> http://orgmode.org/worg/org-contrib/babel/examples/data-collection-analysis.html
>
> I don't have R so I have not tried the examples on this page. However,
> I have tried the following using octave and gnuplot:
>
> #+begin_src org
> ,#+TITLE: examplebug.org
> ,#+AUTHOR: Eric S Fraga
> ,* bubble and dew points
> ,#+name: bubble-point-temperatures
> ,#+begin_src octave :results raw output
> A = [ 6.86880 6.84941]';
> B = [1154.646 1206.001]';
> C = [ 226.046 223.148]';
> pv = @(T) 10.^(A-B./(T+C));
> x = 0;
> res = [];
> while x<(1+1e-3)
> f = @(T) 760 - [x (1-x)]*pv(T);
> T = fsolve(f, 70);
> printf("| %5.2f | %7.2f | \n", x, T);
> res = [res; [x T] ];
> x = x + 0.05;
> endwhile
> ,#+end_src
>
> ,#+begin_src gnuplot :var data=bubble-point-temperatures :file "bubble.pdf"
> set terminal pdfcairo mono enhanced font ",12" size 10cm,6cm
> plot data
> ,#+end_src
>
> ,#+results:
> [[file:bubble.pdf]]
> #+end_src
>
> Trying to execute the gnuplot block leads to an error in gnuplot because
> the output of the octave data block is being put directly into the data
> variable instead of into a file whose name is passed to the data
> variable. The latter happens if the source of the data is a table
> instead of a src block.
>
> I have tried various combinations of output directives for the first src
> block but to no avail.
>
> I have tried this with "emacs -Q", by the way, and my org is up to date
> as of a few minutes ago!
>
> What am I doing wrong please?
>
> Thanks,
> eric
--
Eric Schulte
https://cs.unm.edu/~eschulte
PGP: 0x614CA05D
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-11-22 15:00 ` Eric Schulte
@ 2013-11-22 17:27 ` Nick Dokos
2013-11-23 16:15 ` Eric Schulte
2013-12-05 7:35 ` Eric S Fraga
1 sibling, 1 reply; 21+ messages in thread
From: Nick Dokos @ 2013-11-22 17:27 UTC (permalink / raw
To: emacs-orgmode
Eric Schulte <schulte.eric@gmail.com> writes:
> The attached works fine for me (using sh since I don't have octave).
>
> #+name: uptime
> #+begin_src sh
> paste <(echo -e "1\n5\n15") <(uptime|sed 's/^.*average: //;s/,//g'|tr ' ' '\n')
> #+end_src
>
Just an fyi: I had to set org-babel-sh-command to "bash" for this to
work. Why is "sh" the default value of this variable?
> #+RESULTS: uptime
> | 1 | 0.02 |
> | 5 | 0.06 |
> | 15 | 0.05 |
>
> #+begin_src gnuplot :var data=uptime :results silent
> set xrange [0:]
> set yrange [0:]
> set title "uptime"
> set xlabel "minutes ago"
> set ylabel "load"
> plot data w lines
> #+end_src
>
> Ensure that the data you're passing into gnuplot is a table and not a
> string. Gnuplot blocks handle tables by writing them to a file, and
> then replacing the variable with the file name. As I recall gnuplot
> blocks assume string data already is a file name, so the variable is
> replaced directly.
>
Ah, that explains everything! I also didn't have octave on this machine
so I wrote a python block. Initially, I had
--8<---------------cut here---------------start------------->8---
#+name: foo
#+begin_src python
x = ((1, 1), (2, 4), (3, 9))
return "\n".join(["|%d | %d |" % (y[0], y[1]) for y in x])
#+end_src
#+RESULTS: foo
| 1 | 1 |
| 2 | 4 |
| 3 | 9 |
--8<---------------cut here---------------end--------------->8---
which looks like a table, but isn't: the gnuplot block was blowing
up just like Eric F's. I replaced it with
--8<---------------cut here---------------start------------->8---
#+name: foo
#+begin_src python
x = ((1, 1), (2, 4), (3, 9))
return x
#+end_src
#+RESULTS: foo
| 1 | 1 |
| 2 | 4 |
| 3 | 9 |
--8<---------------cut here---------------end--------------->8---
and everything is working. The only problem is that the results
*look* the same, so it's hard to see what the type is.
Nick
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-11-22 17:27 ` Nick Dokos
@ 2013-11-23 16:15 ` Eric Schulte
2013-12-13 15:23 ` Greg Troxel
0 siblings, 1 reply; 21+ messages in thread
From: Eric Schulte @ 2013-11-23 16:15 UTC (permalink / raw
To: Nick Dokos; +Cc: emacs-orgmode
Nick Dokos <ndokos@gmail.com> writes:
> Eric Schulte <schulte.eric@gmail.com> writes:
>
>
>> The attached works fine for me (using sh since I don't have octave).
>>
>> #+name: uptime
>> #+begin_src sh
>> paste <(echo -e "1\n5\n15") <(uptime|sed 's/^.*average: //;s/,//g'|tr ' ' '\n')
>> #+end_src
>>
>
> Just an fyi: I had to set org-babel-sh-command to "bash" for this to
> work. Why is "sh" the default value of this variable?
>
I think sh is more portable, but I guess almost any system should have
bash as well, I've just changed this default to bash.
Cheers,
>
>> #+RESULTS: uptime
>> | 1 | 0.02 |
>> | 5 | 0.06 |
>> | 15 | 0.05 |
>>
>> #+begin_src gnuplot :var data=uptime :results silent
>> set xrange [0:]
>> set yrange [0:]
>> set title "uptime"
>> set xlabel "minutes ago"
>> set ylabel "load"
>> plot data w lines
>> #+end_src
>>
>> Ensure that the data you're passing into gnuplot is a table and not a
>> string. Gnuplot blocks handle tables by writing them to a file, and
>> then replacing the variable with the file name. As I recall gnuplot
>> blocks assume string data already is a file name, so the variable is
>> replaced directly.
>>
>
> Ah, that explains everything! I also didn't have octave on this machine
> so I wrote a python block. Initially, I had
>
> --8<---------------cut here---------------start------------->8---
> #+name: foo
> #+begin_src python
> x = ((1, 1), (2, 4), (3, 9))
> return "\n".join(["|%d | %d |" % (y[0], y[1]) for y in x])
> #+end_src
>
>
> #+RESULTS: foo
> | 1 | 1 |
> | 2 | 4 |
> | 3 | 9 |
> --8<---------------cut here---------------end--------------->8---
>
> which looks like a table, but isn't: the gnuplot block was blowing
> up just like Eric F's. I replaced it with
>
> --8<---------------cut here---------------start------------->8---
> #+name: foo
> #+begin_src python
> x = ((1, 1), (2, 4), (3, 9))
> return x
> #+end_src
>
>
> #+RESULTS: foo
> | 1 | 1 |
> | 2 | 4 |
> | 3 | 9 |
> --8<---------------cut here---------------end--------------->8---
>
> and everything is working. The only problem is that the results
> *look* the same, so it's hard to see what the type is.
>
> Nick
>
>
>
>
--
Eric Schulte
https://cs.unm.edu/~eschulte
PGP: 0x614CA05D
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-11-22 15:00 ` Eric Schulte
2013-11-22 17:27 ` Nick Dokos
@ 2013-12-05 7:35 ` Eric S Fraga
2013-12-05 18:29 ` Eric Schulte
1 sibling, 1 reply; 21+ messages in thread
From: Eric S Fraga @ 2013-12-05 7:35 UTC (permalink / raw
To: Eric Schulte; +Cc: emacs-orgmode
Eric Schulte <schulte.eric@gmail.com> writes:
> Hi Eric,
>
> The attached works fine for me (using sh since I don't have octave).
Dear Eric,
thanks for your quick reply and sorry for taking so long to get back to
you. I ended up going to Chile for a week the day after sending my
original email and had very little Internet access (and, actually, no
time even if I had had proper connectivity). Back now!
[...]
> Ensure that the data you're passing into gnuplot is a table and not a
> string. Gnuplot blocks handle tables by writing them to a file, and
> then replacing the variable with the file name. As I recall gnuplot
> blocks assume string data already is a file name, so the variable is
> replaced directly.
Ah ha, this is a subtle one! The output looks the same in either case,
as Nick D. also notes. By changing the results generated to value and
not output and adding an expression at the end of my octave code to
generate the value required got things working.
The subtlety makes this a rather frustrating experience, however. Is
there any way to convince babel to treat a string output as an org table
so that subsequent chaining works in this case as well?
Thanks again,
eric
--
: Eric S Fraga (0xFFFCF67D), Emacs 24.3.50.1, Org release_8.2.2-181-gf31eb4.dirty
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-12-05 7:35 ` Eric S Fraga
@ 2013-12-05 18:29 ` Eric Schulte
2013-12-05 19:59 ` Eric S Fraga
0 siblings, 1 reply; 21+ messages in thread
From: Eric Schulte @ 2013-12-05 18:29 UTC (permalink / raw
To: emacs-orgmode
Eric S Fraga <e.fraga@ucl.ac.uk> writes:
> Eric Schulte <schulte.eric@gmail.com> writes:
>
>> Hi Eric,
>>
>> The attached works fine for me (using sh since I don't have octave).
>
> Dear Eric,
>
> thanks for your quick reply and sorry for taking so long to get back to
> you. I ended up going to Chile for a week the day after sending my
> original email and had very little Internet access (and, actually, no
> time even if I had had proper connectivity). Back now!
>
> [...]
>
>> Ensure that the data you're passing into gnuplot is a table and not a
>> string. Gnuplot blocks handle tables by writing them to a file, and
>> then replacing the variable with the file name. As I recall gnuplot
>> blocks assume string data already is a file name, so the variable is
>> replaced directly.
>
> Ah ha, this is a subtle one! The output looks the same in either case,
> as Nick D. also notes. By changing the results generated to value and
> not output and adding an expression at the end of my octave code to
> generate the value required got things working.
>
> The subtlety makes this a rather frustrating experience, however. Is
> there any way to convince babel to treat a string output as an org table
> so that subsequent chaining works in this case as well?
>
I'm not familiar with ob-octave, but I'd imagine ":results vector"
should do the trick. If not then it might be worth adding something
like the following (borrowed from ob-sh.el) to ob-octave.
(org-babel-result-cond (cdr (assoc :result-params params))
results
(let ((tmp-file (org-babel-temp-file "sh-")))
(with-temp-file tmp-file (insert results))
(org-babel-import-elisp-from-file tmp-file)))
Best,
>
> Thanks again,
> eric
--
Eric Schulte
https://cs.unm.edu/~eschulte
PGP: 0x614CA05D
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-12-05 18:29 ` Eric Schulte
@ 2013-12-05 19:59 ` Eric S Fraga
2013-12-06 2:06 ` Eric Schulte
0 siblings, 1 reply; 21+ messages in thread
From: Eric S Fraga @ 2013-12-05 19:59 UTC (permalink / raw
To: Eric Schulte; +Cc: emacs-orgmode
Eric Schulte <schulte.eric@gmail.com> writes:
[...]
> I'm not familiar with ob-octave, but I'd imagine ":results vector"
> should do the trick.
Nope. Unfortunately, this doesn't work.
If the result I want is what is actually "output" by octave, then this
ignores that output. If I put ":results output vector", this doesn't
work either for chaining although at least the results come out looking
right.
Thanks,
eric
--
: Eric S Fraga (0xFFFCF67D), Emacs 24.3.50.1, Org release_8.2.3c-266-g7a726d
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-12-05 19:59 ` Eric S Fraga
@ 2013-12-06 2:06 ` Eric Schulte
2013-12-06 11:59 ` Eric S Fraga
0 siblings, 1 reply; 21+ messages in thread
From: Eric Schulte @ 2013-12-06 2:06 UTC (permalink / raw
To: emacs-orgmode
Eric S Fraga <e.fraga@ucl.ac.uk> writes:
> Eric Schulte <schulte.eric@gmail.com> writes:
>
> [...]
>
>> I'm not familiar with ob-octave, but I'd imagine ":results vector"
>> should do the trick.
>
> Nope. Unfortunately, this doesn't work.
>
> If the result I want is what is actually "output" by octave, then this
> ignores that output. If I put ":results output vector", this doesn't
> work either for chaining although at least the results come out looking
> right.
>
> Thanks,
> eric
Sounds like someone with an interest in octave support should take a
look at ob-octave.el, this shouldn't be a difficult fix and there are
many examples of other languages (e.g., sh) handling the combination of
output and vectors.
--
Eric Schulte
https://cs.unm.edu/~eschulte
PGP: 0x614CA05D
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-12-06 2:06 ` Eric Schulte
@ 2013-12-06 11:59 ` Eric S Fraga
0 siblings, 0 replies; 21+ messages in thread
From: Eric S Fraga @ 2013-12-06 11:59 UTC (permalink / raw
To: Eric Schulte; +Cc: emacs-orgmode
Eric Schulte <schulte.eric@gmail.com> writes:
[...]
> Sounds like someone with an interest in octave support should take a
> look at ob-octave.el, this shouldn't be a difficult fix and there are
> many examples of other languages (e.g., sh) handling the combination of
> output and vectors.
Okay. I'll add it to my todo list... but with low priority given that
using a value output works just fine.
thanks,
eric
--
: Eric S Fraga (0xFFFCF67D), Emacs 24.3.50.1, Org release_8.2.3c-333-g487c74
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-11-23 16:15 ` Eric Schulte
@ 2013-12-13 15:23 ` Greg Troxel
2013-12-13 15:30 ` Eric Schulte
0 siblings, 1 reply; 21+ messages in thread
From: Greg Troxel @ 2013-12-13 15:23 UTC (permalink / raw
To: Eric Schulte; +Cc: Nick Dokos, emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 879 bytes --]
Eric Schulte <schulte.eric@gmail.com> writes:
>> Just an fyi: I had to set org-babel-sh-command to "bash" for this to
>> work. Why is "sh" the default value of this variable?
>>
>
> I think sh is more portable, but I guess almost any system should have
> bash as well, I've just changed this default to bash.
(Assuming you mean that you changed the default in the org sources, not
in your config files.)
Please don't, at least without discussion of the consequences of adding
a dependency that is beyond POSIX.. sh is specified by posix, and bash
is a) sometimes not present and b) behaves differently than as specified
by POSIX, leading people to write nonportable code.
If someone wants to run bash explicitly, it makes sense to have a bash
language block that they can use. But the sh language block should be
sh. The real point is that bash is a different language.
[-- Attachment #2: Type: application/pgp-signature, Size: 194 bytes --]
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-12-13 15:23 ` Greg Troxel
@ 2013-12-13 15:30 ` Eric Schulte
2013-12-13 15:48 ` Greg Troxel
2013-12-13 16:32 ` Achim Gratz
0 siblings, 2 replies; 21+ messages in thread
From: Eric Schulte @ 2013-12-13 15:30 UTC (permalink / raw
To: Greg Troxel; +Cc: Nick Dokos, emacs-orgmode
Greg Troxel <gdt@ir.bbn.com> writes:
> Eric Schulte <schulte.eric@gmail.com> writes:
>
>>> Just an fyi: I had to set org-babel-sh-command to "bash" for this to
>>> work. Why is "sh" the default value of this variable?
>>>
>>
>> I think sh is more portable, but I guess almost any system should have
>> bash as well, I've just changed this default to bash.
>
> (Assuming you mean that you changed the default in the org sources, not
> in your config files.)
>
> Please don't, at least without discussion of the consequences of adding
> a dependency that is beyond POSIX.. sh is specified by posix, and bash
> is a) sometimes not present and b) behaves differently than as specified
> by POSIX, leading people to write nonportable code.
>
> If someone wants to run bash explicitly, it makes sense to have a bash
> language block that they can use. But the sh language block should be
> sh. The real point is that bash is a different language.
I understand your point, but in reality I doubt there are many systems
on which people use Org-mode with code blocks and on which sh is
available but no bash is installed.
Bash is the new normal shell and I would argue is what most users expect
from a shell code block. E.g., the default value of `shell-file-name'
used by M-x shell is "/bin/bash".
It is possible to explicitly set shell code blocks to use sh.
Best,
--
Eric Schulte
https://cs.unm.edu/~eschulte
PGP: 0x614CA05D
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-12-13 15:30 ` Eric Schulte
@ 2013-12-13 15:48 ` Greg Troxel
2013-12-13 16:20 ` Eric Schulte
2013-12-13 16:32 ` Achim Gratz
1 sibling, 1 reply; 21+ messages in thread
From: Greg Troxel @ 2013-12-13 15:48 UTC (permalink / raw
To: Eric Schulte; +Cc: Nick Dokos, emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 3523 bytes --]
Eric Schulte <schulte.eric@gmail.com> writes:
> Greg Troxel <gdt@ir.bbn.com> writes:
>
>> Eric Schulte <schulte.eric@gmail.com> writes:
>>
>>>> Just an fyi: I had to set org-babel-sh-command to "bash" for this to
>>>> work. Why is "sh" the default value of this variable?
>>>
>>> I think sh is more portable, but I guess almost any system should have
>>> bash as well, I've just changed this default to bash.
>>
>> (Assuming you mean that you changed the default in the org sources, not
>> in your config files.)
>>
>> Please don't, at least without discussion of the consequences of adding
>> a dependency that is beyond POSIX.. sh is specified by posix, and bash
>> is a) sometimes not present and b) behaves differently than as specified
>> by POSIX, leading people to write nonportable code.
>>
>> If someone wants to run bash explicitly, it makes sense to have a bash
>> language block that they can use. But the sh language block should be
>> sh. The real point is that bash is a different language.
>
> I understand your point, but in reality I doubt there are many systems
> on which people use Org-mode with code blocks and on which sh is
> available but no bash is installed.
That may be true on some flavors of Linux, but on BSDs:
bash is not the normal shell (and is not part of the base system, at
least on NetBSD, and I think that's still true on the others). When
it does exist it's not in /bin.
It's not so odd to have a system without bash.
I am also under the impression that Debian does not use bash as the
/bin/sh.
org, like anything else, should be OS-agnostic, and follow open
standards whenever that's at all reasonable.
> Bash is the new normal shell and I would argue is what most users expect
> from a shell code block.
I find that pretty astounding. In a block labeled sh it is obvious that
a shell conforming to the POSIX sh standard is expected, and it's not so
different from a file with "#!/bin/sh". Users who expect bash in a
block labeled sh are wrong, although I agree that many people have been
misled this way by the culture of using "test ==" in a file that starts
#!/bin/sh.
The real issue is that org files that actually expect bash (test ==,
etc.) become nonportable to other environments. If someone is writing
a script and not intending to use beyond-posix features, it's harmful to
let them work (in cases where they are published).
> E.g., the default value of `shell-file-name' used by M-x shell is
> "/bin/bash".
I just checked on my system (NetBSD 6 i386, emacs 23.4.1), and
shell-file-name is documented to inherit from SHELL if present, which it
does. It's /bin/sh if SHELL is unset, which complies with the
documentation:
*File name to load inferior shells from.
Initialized from the SHELL environment variable, or to a system-dependent
default if SHELL is not set.
which doesn't promise bash (or even a Bourne-style shell!). (The emacs
package doesn't depend on the bash package.) But shell-file-name is
about giving the user of emacs their shell, not using a particular
programming language, so this fuzz is fine.
> It is possible to explicitly set shell code blocks to use sh.
Sure, but that wasn't my point; it's the encouragement of nonportability
that is problematic.
I should point out that I'm not a bash hater --- I actually use it as my
interactive shell, and have done so since around 1990. But I don't
write scripts in it.
Greg
[-- Attachment #2: Type: application/pgp-signature, Size: 194 bytes --]
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-12-13 15:48 ` Greg Troxel
@ 2013-12-13 16:20 ` Eric Schulte
2013-12-13 17:13 ` Eric Schulte
2013-12-13 18:38 ` Greg Troxel
0 siblings, 2 replies; 21+ messages in thread
From: Eric Schulte @ 2013-12-13 16:20 UTC (permalink / raw
To: Greg Troxel; +Cc: Nick Dokos, emacs-orgmode
>>
>> I understand your point, but in reality I doubt there are many systems
>> on which people use Org-mode with code blocks and on which sh is
>> available but no bash is installed.
>
> That may be true on some flavors of Linux, but on BSDs:
>
> bash is not the normal shell (and is not part of the base system, at
> least on NetBSD, and I think that's still true on the others). When
> it does exist it's not in /bin.
>
> It's not so odd to have a system without bash.
>
> I am also under the impression that Debian does not use bash as the
> /bin/sh.
>
> org, like anything else, should be OS-agnostic, and follow open
> standards whenever that's at all reasonable.
>
>> Bash is the new normal shell and I would argue is what most users expect
>> from a shell code block.
>
> I find that pretty astounding. In a block labeled sh it is obvious that
> a shell conforming to the POSIX sh standard is expected, and it's not so
> different from a file with "#!/bin/sh". Users who expect bash in a
> block labeled sh are wrong, although I agree that many people have been
> misled this way by the culture of using "test ==" in a file that starts
> #!/bin/sh.
>
> The real issue is that org files that actually expect bash (test ==,
> etc.) become nonportable to other environments. If someone is writing
> a script and not intending to use beyond-posix features, it's harmful to
> let them work (in cases where they are published).
>
Points well made, I was not aware of the BSD default.
Although purely semantically, in my opinion the "sh" in "#+begin_src sh"
indicates generic "shell-script", not the POSIX sh. E.g., there is no
ob-bash.el or ob-csh.el.
See the first line in ob-sh.el,
,----
| ;;; ob-sh.el --- org-babel functions for shell evaluation
`----
>
>> E.g., the default value of `shell-file-name' used by M-x shell is
>> "/bin/bash".
>
> I just checked on my system (NetBSD 6 i386, emacs 23.4.1), and
> shell-file-name is documented to inherit from SHELL if present, which it
> does. It's /bin/sh if SHELL is unset, which complies with the
> documentation:
>
> *File name to load inferior shells from.
> Initialized from the SHELL environment variable, or to a system-dependent
> default if SHELL is not set.
>
> which doesn't promise bash (or even a Bourne-style shell!). (The emacs
> package doesn't depend on the bash package.) But shell-file-name is
> about giving the user of emacs their shell, not using a particular
> programming language, so this fuzz is fine.
>
And this is where we disagree. Sh code blocks don't currently promise
POSIX sh, they promise a shell. This is certainly a much more dangerous
generalization than say Perl code blocks possibly using Perl 5 or 6.
How about the following resolution? We rename ob-sh.el to ob-shell.el.
New "shell" code blocks could use the value of the
`org-babel-sh-command' environment variable. Then sh, bash, zsh, csh,
ash, dash (am I missing any other common ones) use the specific shell
specified.
What do you think?
In the mean time, I don't believe the change in default value for
`org-babel-sh-command' has been included in any maintenance releases, so
I've just reverted this to minimize any further confusion.
>
>> It is possible to explicitly set shell code blocks to use sh.
>
> Sure, but that wasn't my point; it's the encouragement of nonportability
> that is problematic.
>
> I should point out that I'm not a bash hater --- I actually use it as my
> interactive shell, and have done so since around 1990. But I don't
> write scripts in it.
>
And I should say that I've argued the same point your making myself in
the past (on a project making the much more serious error of using bash
notation ">&" in a shell script starting with "#!/bin/sh"). I think we
only disagree on the current meaning of "sh" in code blocks, which
hopefully the suggestion above will rectify.
Best,
>
> Greg
--
Eric Schulte
https://cs.unm.edu/~eschulte
PGP: 0x614CA05D
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-12-13 15:30 ` Eric Schulte
2013-12-13 15:48 ` Greg Troxel
@ 2013-12-13 16:32 ` Achim Gratz
1 sibling, 0 replies; 21+ messages in thread
From: Achim Gratz @ 2013-12-13 16:32 UTC (permalink / raw
To: emacs-orgmode
Eric Schulte writes:
> I understand your point, but in reality I doubt there are many systems
> on which people use Org-mode with code blocks and on which sh is
> available but no bash is installed.
You might want to widen your horizon on the "many systems" front a bit.
The typical BSD system has no Bash at all and Debian specifically avoids
the use of any bashisms in any system related scripts in order to be
able to use something else but Bash as /bin/sh… and this is just talking
about the UN*Xoid part of the world.
> Bash is the new normal shell and I would argue is what most users expect
> from a shell code block.
Or mksh or fish or whatever is the shiny new shell thing of today.
While we are inventing statistics, I would argue that most users have no
idea what a shell is and that there are different kinds of those.
Regards,
Achim.
--
+<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+
SD adaptation for Waldorf microQ V2.22R2:
http://Synth.Stromeko.net/Downloads.html#WaldorfSDada
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-12-13 16:20 ` Eric Schulte
@ 2013-12-13 17:13 ` Eric Schulte
2013-12-13 19:32 ` Nick Dokos
` (2 more replies)
2013-12-13 18:38 ` Greg Troxel
1 sibling, 3 replies; 21+ messages in thread
From: Eric Schulte @ 2013-12-13 17:13 UTC (permalink / raw
To: Greg Troxel; +Cc: Nick Dokos, emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 635 bytes --]
>
> How about the following resolution? We rename ob-sh.el to ob-shell.el.
> New "shell" code blocks could use the value of the
> `org-babel-sh-command' environment variable. Then sh, bash, zsh, csh,
> ash, dash (am I missing any other common ones) use the specific shell
> specified.
>
The attached patches make this change and continue to pass the entire
test suite. The problem being that with ob-sh, no longer present many
users may have to change their configuration and possible the value of
their local.mk file. One solution there is to add a dummy ob-sh.el with
a deprecation message for some transition time. Thoughts?
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-multiple-code-block-types-for-multiple-shells.patch --]
[-- Type: text/x-diff, Size: 2054 bytes --]
From 7a6c0e35415c4a173d101336029262f3a09abb91 Mon Sep 17 00:00:00 2001
From: Eric Schulte <schulte.eric@gmail.com>
Date: Fri, 13 Dec 2013 09:52:05 -0700
Subject: [PATCH 1/4] multiple code block types for multiple shells
* lisp/ob-sh.el (org-babel-sh-command): Now set from
`shell-file-name'.
(org-babel-shell-names): List of specific shells known to Org mode
shell code blocks.
(org-babel-execute:shell): New generic shell execution function.
---
lisp/ob-sh.el | 24 +++++++++++++++++++++---
1 file changed, 21 insertions(+), 3 deletions(-)
diff --git a/lisp/ob-sh.el b/lisp/ob-sh.el
index 4984ff9..a115f38 100644
--- a/lisp/ob-sh.el
+++ b/lisp/ob-sh.el
@@ -38,9 +38,12 @@
(defvar org-babel-default-header-args:sh '())
-(defvar org-babel-sh-command "sh"
+(defcustom org-babel-sh-command shell-file-name
"Command used to invoke a shell.
-This will be passed to `shell-command-on-region'")
+Set by default to the value of `shell-file-name'. This will be
+passed to `shell-command-on-region'"
+ :group 'org-babel
+ :type 'string)
(defcustom org-babel-sh-var-quote-fmt
"$(cat <<'BABEL_TABLE'\n%s\nBABEL_TABLE\n)"
@@ -48,7 +51,22 @@ This will be passed to `shell-command-on-region'")
:group 'org-babel
:type 'string)
-(defun org-babel-execute:sh (body params)
+(defcustom org-babel-shell-names '("sh" "bash" "csh" "ash" "dash")
+ "List of names of shell supported by babel shell code blocks."
+ :group 'org-babel
+ :type 'string
+ :initialize
+ (lambda (symbol value)
+ (set-default symbol (second value))
+ (mapc
+ (lambda (name)
+ (eval `(defun ,(intern (concat "org-babel-execute:" name)) (body params)
+ ,(format "Execute a block of %s commands with Babel." name)
+ (let ((org-babel-sh-command ,name))
+ (org-babel-execute:shell body params)))))
+ (second value))))
+
+(defun org-babel-execute:shell (body params)
"Execute a block of Shell commands with Babel.
This function is called by `org-babel-execute-src-block'."
(let* ((session (org-babel-sh-initiate-session
--
1.8.5.1
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-rename-ob-sh-to-ob-shell.patch --]
[-- Type: text/x-diff, Size: 20447 bytes --]
From 583e7ab1757f54a656acb52ef60c6069d060cbe1 Mon Sep 17 00:00:00 2001
From: Eric Schulte <schulte.eric@gmail.com>
Date: Fri, 13 Dec 2013 09:54:28 -0700
Subject: [PATCH 2/4] rename ob-sh to ob-shell
---
lisp/ob-sh.el | 230 ---------------------------------------------
lisp/ob-shell.el | 230 +++++++++++++++++++++++++++++++++++++++++++++
testing/lisp/test-ob-sh.el | 2 +-
3 files changed, 231 insertions(+), 231 deletions(-)
delete mode 100644 lisp/ob-sh.el
create mode 100644 lisp/ob-shell.el
diff --git a/lisp/ob-sh.el b/lisp/ob-sh.el
deleted file mode 100644
index a115f38..0000000
--- a/lisp/ob-sh.el
+++ /dev/null
@@ -1,230 +0,0 @@
-;;; ob-sh.el --- org-babel functions for shell evaluation
-
-;; Copyright (C) 2009-2013 Free Software Foundation, Inc.
-
-;; Author: Eric Schulte
-;; Keywords: literate programming, reproducible research
-;; Homepage: http://orgmode.org
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Org-Babel support for evaluating shell source code.
-
-;;; Code:
-(require 'ob)
-(require 'shell)
-(eval-when-compile (require 'cl))
-
-(declare-function org-babel-comint-in-buffer "ob-comint" (buffer &rest body))
-(declare-function org-babel-comint-wait-for-output "ob-comint" (buffer))
-(declare-function org-babel-comint-buffer-livep "ob-comint" (buffer))
-(declare-function org-babel-comint-with-output "ob-comint" (meta &rest body))
-(declare-function orgtbl-to-generic "org-table" (table params))
-
-(defvar org-babel-default-header-args:sh '())
-
-(defcustom org-babel-sh-command shell-file-name
- "Command used to invoke a shell.
-Set by default to the value of `shell-file-name'. This will be
-passed to `shell-command-on-region'"
- :group 'org-babel
- :type 'string)
-
-(defcustom org-babel-sh-var-quote-fmt
- "$(cat <<'BABEL_TABLE'\n%s\nBABEL_TABLE\n)"
- "Format string used to escape variables when passed to shell scripts."
- :group 'org-babel
- :type 'string)
-
-(defcustom org-babel-shell-names '("sh" "bash" "csh" "ash" "dash")
- "List of names of shell supported by babel shell code blocks."
- :group 'org-babel
- :type 'string
- :initialize
- (lambda (symbol value)
- (set-default symbol (second value))
- (mapc
- (lambda (name)
- (eval `(defun ,(intern (concat "org-babel-execute:" name)) (body params)
- ,(format "Execute a block of %s commands with Babel." name)
- (let ((org-babel-sh-command ,name))
- (org-babel-execute:shell body params)))))
- (second value))))
-
-(defun org-babel-execute:shell (body params)
- "Execute a block of Shell commands with Babel.
-This function is called by `org-babel-execute-src-block'."
- (let* ((session (org-babel-sh-initiate-session
- (cdr (assoc :session params))))
- (stdin (let ((stdin (cdr (assoc :stdin params))))
- (when stdin (org-babel-sh-var-to-string
- (org-babel-ref-resolve stdin)))))
- (full-body (org-babel-expand-body:generic
- body params (org-babel-variable-assignments:sh params))))
- (org-babel-reassemble-table
- (org-babel-sh-evaluate session full-body params stdin)
- (org-babel-pick-name
- (cdr (assoc :colname-names params)) (cdr (assoc :colnames params)))
- (org-babel-pick-name
- (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params))))))
-
-(defun org-babel-prep-session:sh (session params)
- "Prepare SESSION according to the header arguments specified in PARAMS."
- (let* ((session (org-babel-sh-initiate-session session))
- (var-lines (org-babel-variable-assignments:sh params)))
- (org-babel-comint-in-buffer session
- (mapc (lambda (var)
- (insert var) (comint-send-input nil t)
- (org-babel-comint-wait-for-output session)) var-lines))
- session))
-
-(defun org-babel-load-session:sh (session body params)
- "Load BODY into SESSION."
- (save-window-excursion
- (let ((buffer (org-babel-prep-session:sh session params)))
- (with-current-buffer buffer
- (goto-char (process-mark (get-buffer-process (current-buffer))))
- (insert (org-babel-chomp body)))
- buffer)))
-
-;; helper functions
-
-(defun org-babel-variable-assignments:sh (params)
- "Return list of shell statements assigning the block's variables."
- (let ((sep (cdr (assoc :separator params))))
- (mapcar
- (lambda (pair)
- (format "%s=%s"
- (car pair)
- (org-babel-sh-var-to-sh (cdr pair) sep)))
- (mapcar #'cdr (org-babel-get-header params :var)))))
-
-(defun org-babel-sh-var-to-sh (var &optional sep)
- "Convert an elisp value to a shell variable.
-Convert an elisp var into a string of shell commands specifying a
-var of the same value."
- (format org-babel-sh-var-quote-fmt (org-babel-sh-var-to-string var sep)))
-
-(defun org-babel-sh-var-to-string (var &optional sep)
- "Convert an elisp value to a string."
- (let ((echo-var (lambda (v) (if (stringp v) v (format "%S" v)))))
- (cond
- ((and (listp var) (or (listp (car var)) (equal (car var) 'hline)))
- (orgtbl-to-generic var (list :sep (or sep "\t") :fmt echo-var)))
- ((listp var)
- (mapconcat echo-var var "\n"))
- (t (funcall echo-var var)))))
-
-(defun org-babel-sh-table-or-results (results)
- "Convert RESULTS to an appropriate elisp value.
-If the results look like a table, then convert them into an
-Emacs-lisp table, otherwise return the results as a string."
- (org-babel-script-escape results))
-
-(defun org-babel-sh-initiate-session (&optional session params)
- "Initiate a session named SESSION according to PARAMS."
- (when (and session (not (string= session "none")))
- (save-window-excursion
- (or (org-babel-comint-buffer-livep session)
- (progn (shell session) (get-buffer (current-buffer)))))))
-
-(defvar org-babel-sh-eoe-indicator "echo 'org_babel_sh_eoe'"
- "String to indicate that evaluation has completed.")
-(defvar org-babel-sh-eoe-output "org_babel_sh_eoe"
- "String to indicate that evaluation has completed.")
-
-(defun org-babel-sh-evaluate (session body &optional params stdin)
- "Pass BODY to the Shell process in BUFFER.
-If RESULT-TYPE equals 'output then return a list of the outputs
-of the statements in BODY, if RESULT-TYPE equals 'value then
-return the value of the last statement in BODY."
- (let ((results
- (cond
- (stdin ; external shell script w/STDIN
- (let ((script-file (org-babel-temp-file "sh-script-"))
- (stdin-file (org-babel-temp-file "sh-stdin-"))
- (shebang (cdr (assoc :shebang params)))
- (padline (not (string= "no" (cdr (assoc :padline params))))))
- (with-temp-file script-file
- (when shebang (insert (concat shebang "\n")))
- (when padline (insert "\n"))
- (insert body))
- (set-file-modes script-file #o755)
- (with-temp-file stdin-file (insert stdin))
- (with-temp-buffer
- (call-process-shell-command
- (if shebang
- script-file
- (format "%s %s" org-babel-sh-command script-file))
- stdin-file
- (current-buffer))
- (buffer-string))))
- (session ; session evaluation
- (mapconcat
- #'org-babel-sh-strip-weird-long-prompt
- (mapcar
- #'org-babel-trim
- (butlast
- (org-babel-comint-with-output
- (session org-babel-sh-eoe-output t body)
- (mapc
- (lambda (line)
- (insert line)
- (comint-send-input nil t)
- (while (save-excursion
- (goto-char comint-last-input-end)
- (not (re-search-forward
- comint-prompt-regexp nil t)))
- (accept-process-output
- (get-buffer-process (current-buffer)))))
- (append
- (split-string (org-babel-trim body) "\n")
- (list org-babel-sh-eoe-indicator))))
- 2)) "\n"))
- ('otherwise ; external shell script
- (if (and (cdr (assoc :shebang params))
- (> (length (cdr (assoc :shebang params))) 0))
- (let ((script-file (org-babel-temp-file "sh-script-"))
- (shebang (cdr (assoc :shebang params)))
- (padline (not (equal "no" (cdr (assoc :padline params))))))
- (with-temp-file script-file
- (when shebang (insert (concat shebang "\n")))
- (when padline (insert "\n"))
- (insert body))
- (set-file-modes script-file #o755)
- (org-babel-eval script-file ""))
- (org-babel-eval org-babel-sh-command (org-babel-trim body)))))))
- (when results
- (let ((result-params (cdr (assoc :result-params params))))
- (org-babel-result-cond result-params
- results
- (let ((tmp-file (org-babel-temp-file "sh-")))
- (with-temp-file tmp-file (insert results))
- (org-babel-import-elisp-from-file tmp-file)))))))
-
-(defun org-babel-sh-strip-weird-long-prompt (string)
- "Remove prompt cruft from a string of shell output."
- (while (string-match "^% +[\r\n$]+ *" string)
- (setq string (substring string (match-end 0))))
- string)
-
-(provide 'ob-sh)
-
-
-
-;;; ob-sh.el ends here
diff --git a/lisp/ob-shell.el b/lisp/ob-shell.el
new file mode 100644
index 0000000..a115f38
--- /dev/null
+++ b/lisp/ob-shell.el
@@ -0,0 +1,230 @@
+;;; ob-sh.el --- org-babel functions for shell evaluation
+
+;; Copyright (C) 2009-2013 Free Software Foundation, Inc.
+
+;; Author: Eric Schulte
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Org-Babel support for evaluating shell source code.
+
+;;; Code:
+(require 'ob)
+(require 'shell)
+(eval-when-compile (require 'cl))
+
+(declare-function org-babel-comint-in-buffer "ob-comint" (buffer &rest body))
+(declare-function org-babel-comint-wait-for-output "ob-comint" (buffer))
+(declare-function org-babel-comint-buffer-livep "ob-comint" (buffer))
+(declare-function org-babel-comint-with-output "ob-comint" (meta &rest body))
+(declare-function orgtbl-to-generic "org-table" (table params))
+
+(defvar org-babel-default-header-args:sh '())
+
+(defcustom org-babel-sh-command shell-file-name
+ "Command used to invoke a shell.
+Set by default to the value of `shell-file-name'. This will be
+passed to `shell-command-on-region'"
+ :group 'org-babel
+ :type 'string)
+
+(defcustom org-babel-sh-var-quote-fmt
+ "$(cat <<'BABEL_TABLE'\n%s\nBABEL_TABLE\n)"
+ "Format string used to escape variables when passed to shell scripts."
+ :group 'org-babel
+ :type 'string)
+
+(defcustom org-babel-shell-names '("sh" "bash" "csh" "ash" "dash")
+ "List of names of shell supported by babel shell code blocks."
+ :group 'org-babel
+ :type 'string
+ :initialize
+ (lambda (symbol value)
+ (set-default symbol (second value))
+ (mapc
+ (lambda (name)
+ (eval `(defun ,(intern (concat "org-babel-execute:" name)) (body params)
+ ,(format "Execute a block of %s commands with Babel." name)
+ (let ((org-babel-sh-command ,name))
+ (org-babel-execute:shell body params)))))
+ (second value))))
+
+(defun org-babel-execute:shell (body params)
+ "Execute a block of Shell commands with Babel.
+This function is called by `org-babel-execute-src-block'."
+ (let* ((session (org-babel-sh-initiate-session
+ (cdr (assoc :session params))))
+ (stdin (let ((stdin (cdr (assoc :stdin params))))
+ (when stdin (org-babel-sh-var-to-string
+ (org-babel-ref-resolve stdin)))))
+ (full-body (org-babel-expand-body:generic
+ body params (org-babel-variable-assignments:sh params))))
+ (org-babel-reassemble-table
+ (org-babel-sh-evaluate session full-body params stdin)
+ (org-babel-pick-name
+ (cdr (assoc :colname-names params)) (cdr (assoc :colnames params)))
+ (org-babel-pick-name
+ (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params))))))
+
+(defun org-babel-prep-session:sh (session params)
+ "Prepare SESSION according to the header arguments specified in PARAMS."
+ (let* ((session (org-babel-sh-initiate-session session))
+ (var-lines (org-babel-variable-assignments:sh params)))
+ (org-babel-comint-in-buffer session
+ (mapc (lambda (var)
+ (insert var) (comint-send-input nil t)
+ (org-babel-comint-wait-for-output session)) var-lines))
+ session))
+
+(defun org-babel-load-session:sh (session body params)
+ "Load BODY into SESSION."
+ (save-window-excursion
+ (let ((buffer (org-babel-prep-session:sh session params)))
+ (with-current-buffer buffer
+ (goto-char (process-mark (get-buffer-process (current-buffer))))
+ (insert (org-babel-chomp body)))
+ buffer)))
+
+;; helper functions
+
+(defun org-babel-variable-assignments:sh (params)
+ "Return list of shell statements assigning the block's variables."
+ (let ((sep (cdr (assoc :separator params))))
+ (mapcar
+ (lambda (pair)
+ (format "%s=%s"
+ (car pair)
+ (org-babel-sh-var-to-sh (cdr pair) sep)))
+ (mapcar #'cdr (org-babel-get-header params :var)))))
+
+(defun org-babel-sh-var-to-sh (var &optional sep)
+ "Convert an elisp value to a shell variable.
+Convert an elisp var into a string of shell commands specifying a
+var of the same value."
+ (format org-babel-sh-var-quote-fmt (org-babel-sh-var-to-string var sep)))
+
+(defun org-babel-sh-var-to-string (var &optional sep)
+ "Convert an elisp value to a string."
+ (let ((echo-var (lambda (v) (if (stringp v) v (format "%S" v)))))
+ (cond
+ ((and (listp var) (or (listp (car var)) (equal (car var) 'hline)))
+ (orgtbl-to-generic var (list :sep (or sep "\t") :fmt echo-var)))
+ ((listp var)
+ (mapconcat echo-var var "\n"))
+ (t (funcall echo-var var)))))
+
+(defun org-babel-sh-table-or-results (results)
+ "Convert RESULTS to an appropriate elisp value.
+If the results look like a table, then convert them into an
+Emacs-lisp table, otherwise return the results as a string."
+ (org-babel-script-escape results))
+
+(defun org-babel-sh-initiate-session (&optional session params)
+ "Initiate a session named SESSION according to PARAMS."
+ (when (and session (not (string= session "none")))
+ (save-window-excursion
+ (or (org-babel-comint-buffer-livep session)
+ (progn (shell session) (get-buffer (current-buffer)))))))
+
+(defvar org-babel-sh-eoe-indicator "echo 'org_babel_sh_eoe'"
+ "String to indicate that evaluation has completed.")
+(defvar org-babel-sh-eoe-output "org_babel_sh_eoe"
+ "String to indicate that evaluation has completed.")
+
+(defun org-babel-sh-evaluate (session body &optional params stdin)
+ "Pass BODY to the Shell process in BUFFER.
+If RESULT-TYPE equals 'output then return a list of the outputs
+of the statements in BODY, if RESULT-TYPE equals 'value then
+return the value of the last statement in BODY."
+ (let ((results
+ (cond
+ (stdin ; external shell script w/STDIN
+ (let ((script-file (org-babel-temp-file "sh-script-"))
+ (stdin-file (org-babel-temp-file "sh-stdin-"))
+ (shebang (cdr (assoc :shebang params)))
+ (padline (not (string= "no" (cdr (assoc :padline params))))))
+ (with-temp-file script-file
+ (when shebang (insert (concat shebang "\n")))
+ (when padline (insert "\n"))
+ (insert body))
+ (set-file-modes script-file #o755)
+ (with-temp-file stdin-file (insert stdin))
+ (with-temp-buffer
+ (call-process-shell-command
+ (if shebang
+ script-file
+ (format "%s %s" org-babel-sh-command script-file))
+ stdin-file
+ (current-buffer))
+ (buffer-string))))
+ (session ; session evaluation
+ (mapconcat
+ #'org-babel-sh-strip-weird-long-prompt
+ (mapcar
+ #'org-babel-trim
+ (butlast
+ (org-babel-comint-with-output
+ (session org-babel-sh-eoe-output t body)
+ (mapc
+ (lambda (line)
+ (insert line)
+ (comint-send-input nil t)
+ (while (save-excursion
+ (goto-char comint-last-input-end)
+ (not (re-search-forward
+ comint-prompt-regexp nil t)))
+ (accept-process-output
+ (get-buffer-process (current-buffer)))))
+ (append
+ (split-string (org-babel-trim body) "\n")
+ (list org-babel-sh-eoe-indicator))))
+ 2)) "\n"))
+ ('otherwise ; external shell script
+ (if (and (cdr (assoc :shebang params))
+ (> (length (cdr (assoc :shebang params))) 0))
+ (let ((script-file (org-babel-temp-file "sh-script-"))
+ (shebang (cdr (assoc :shebang params)))
+ (padline (not (equal "no" (cdr (assoc :padline params))))))
+ (with-temp-file script-file
+ (when shebang (insert (concat shebang "\n")))
+ (when padline (insert "\n"))
+ (insert body))
+ (set-file-modes script-file #o755)
+ (org-babel-eval script-file ""))
+ (org-babel-eval org-babel-sh-command (org-babel-trim body)))))))
+ (when results
+ (let ((result-params (cdr (assoc :result-params params))))
+ (org-babel-result-cond result-params
+ results
+ (let ((tmp-file (org-babel-temp-file "sh-")))
+ (with-temp-file tmp-file (insert results))
+ (org-babel-import-elisp-from-file tmp-file)))))))
+
+(defun org-babel-sh-strip-weird-long-prompt (string)
+ "Remove prompt cruft from a string of shell output."
+ (while (string-match "^% +[\r\n$]+ *" string)
+ (setq string (substring string (match-end 0))))
+ string)
+
+(provide 'ob-sh)
+
+
+
+;;; ob-sh.el ends here
diff --git a/testing/lisp/test-ob-sh.el b/testing/lisp/test-ob-sh.el
index 1025ecf..ca94c9e 100644
--- a/testing/lisp/test-ob-sh.el
+++ b/testing/lisp/test-ob-sh.el
@@ -24,7 +24,7 @@
;;; Code:
(org-test-for-executable "sh")
-(unless (featurep 'ob-sh)
+(unless (featurep 'ob-shell)
(signal 'missing-test-dependency "Support for Sh code blocks"))
(ert-deftest test-ob-sh/dont-insert-spaces-on-expanded-bodies ()
--
1.8.5.1
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: 0003-finish-rename-split-up-for-git.patch --]
[-- Type: text/x-diff, Size: 860 bytes --]
From 3b3dbca13c668299a24c93eae27059703361d789 Mon Sep 17 00:00:00 2001
From: Eric Schulte <schulte.eric@gmail.com>
Date: Fri, 13 Dec 2013 09:54:48 -0700
Subject: [PATCH 3/4] finish rename (split up for git)
---
lisp/ob-shell.el | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lisp/ob-shell.el b/lisp/ob-shell.el
index a115f38..d1c2130 100644
--- a/lisp/ob-shell.el
+++ b/lisp/ob-shell.el
@@ -1,4 +1,4 @@
-;;; ob-sh.el --- org-babel functions for shell evaluation
+;;; ob-shell.el --- org-babel functions for shell evaluation
;; Copyright (C) 2009-2013 Free Software Foundation, Inc.
@@ -223,8 +223,8 @@ return the value of the last statement in BODY."
(setq string (substring string (match-end 0))))
string)
-(provide 'ob-sh)
+(provide 'ob-shell)
-;;; ob-sh.el ends here
+;;; ob-shell.el ends here
--
1.8.5.1
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #5: 0004-fix-tests-with-the-renamed-ob-shell.el.patch --]
[-- Type: text/x-diff, Size: 925 bytes --]
From b319475a86451defbdbac064684dd59fd6b0b7d0 Mon Sep 17 00:00:00 2001
From: Eric Schulte <schulte.eric@gmail.com>
Date: Fri, 13 Dec 2013 10:03:05 -0700
Subject: [PATCH 4/4] fix tests with the renamed ob-shell.el
Note, users may have to edit their local.mk files to change the
value of BTEST_OB_LANGUAGES to remove sh and include shell.
---
mk/default.mk | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mk/default.mk b/mk/default.mk
index 886efc6..a1f42f8 100644
--- a/mk/default.mk
+++ b/mk/default.mk
@@ -63,7 +63,7 @@ BTEST = $(BATCH) \
--eval '(setq \
org-batch-test t \
org-babel-load-languages \
- (quote ($(foreach ob-lang,$(BTEST_OB_LANGUAGES) emacs-lisp sh org,$(lst-ob-lang)))) \
+ (quote ($(foreach ob-lang,$(BTEST_OB_LANGUAGES) emacs-lisp shell org,$(lst-ob-lang)))) \
org-test-select-re "$(BTEST_RE)" \
)' \
-l org-loaddefs.el \
--
1.8.5.1
[-- Attachment #6: Type: text/plain, Size: 63 bytes --]
--
Eric Schulte
https://cs.unm.edu/~eschulte
PGP: 0x614CA05D
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-12-13 16:20 ` Eric Schulte
2013-12-13 17:13 ` Eric Schulte
@ 2013-12-13 18:38 ` Greg Troxel
2013-12-13 19:08 ` Sebastien Vauban
1 sibling, 1 reply; 21+ messages in thread
From: Greg Troxel @ 2013-12-13 18:38 UTC (permalink / raw
To: Eric Schulte; +Cc: Nick Dokos, emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 3048 bytes --]
Eric Schulte <schulte.eric@gmail.com> writes:
> Although purely semantically, in my opinion the "sh" in "#+begin_src sh"
> indicates generic "shell-script", not the POSIX sh. E.g., there is no
> ob-bash.el or ob-csh.el.
I see your point. But stepping back, I have always felt that
"#+begin_src foo" referred to a language, sometimes where that language
and a particular program are inseparable (e.g. gnuplot). But sh is a
first-class language.
> See the first line in ob-sh.el,
> ,----
> | ;;; ob-sh.el --- org-babel functions for shell evaluation
> `----
Sure, but that's just repeated the ambiguity :-)
> And this is where we disagree. Sh code blocks don't currently promise
> POSIX sh, they promise a shell. This is certainly a much more dangerous
> generalization than say Perl code blocks possibly using Perl 5 or 6.
For shell, I see that there are two concepts to detangle:
a shell is a particular command interpreter, particularly useful for
humans
there are multiple shell languages, but far fewer than the number of
interpreters.
For languages, I see
POSIX sh
the bash flavor of POSIX sh
csh
While bash and POSIX sh are close, csh isn't at all close, and is only
similar in that people also use it for a shell.
In an org document, I think it's better if the result depends less on
variables not set in the document. So a code block in a document is
really written in some language. And it therefore makes sense to
specify that in the begin_src wrapper.
I don't see that there is any call for csh, as the received wisdom is
that one shouldn't write scripts in it (at least in modern times). (It
was originally a BSD thing, and BSD culture is very much POSIX sh now.)
So separately from how the lisp works, I would favor
#+begin_src sh # posix sh
#+begin_src bash # bash (leaving version ambiguous??)
#+begin_src csh # csh, but not sure there's a need
> How about the following resolution? We rename ob-sh.el to ob-shell.el.
> New "shell" code blocks could use the value of the
> `org-babel-sh-command' environment variable. Then sh, bash, zsh, csh,
> ash, dash (am I missing any other common ones) use the specific shell
> specified.
Are you aware of any significant use of "zsh scripts"? I see that as
POSIX sh, with spiffy user-facing features.
> In the mean time, I don't believe the change in default value for
> `org-babel-sh-command' has been included in any maintenance releases, so
> I've just reverted this to minimize any further confusion.
Thanks. It's good to be having the larger discussion first.
> And I should say that I've argued the same point your making myself in
> the past (on a project making the much more serious error of using bash
> notation ">&" in a shell script starting with "#!/bin/sh"). I think we
> only disagree on the current meaning of "sh" in code blocks, which
> hopefully the suggestion above will rectify.
I forgot about "&>", even though I type it all the time interactively
but I'm pretty careful in scripts :-)
Thanks,
Greg
[-- Attachment #2: Type: application/pgp-signature, Size: 194 bytes --]
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-12-13 18:38 ` Greg Troxel
@ 2013-12-13 19:08 ` Sebastien Vauban
0 siblings, 0 replies; 21+ messages in thread
From: Sebastien Vauban @ 2013-12-13 19:08 UTC (permalink / raw
To: emacs-orgmode-mXXj517/zsQ
Greg Troxel wrote:
> Eric Schulte <schulte.eric-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> writes:
>
>> Although purely semantically, in my opinion the "sh" in "#+begin_src sh"
>> indicates generic "shell-script", not the POSIX sh. E.g., there is no
>> ob-bash.el or ob-csh.el.
>
> I see your point. But stepping back, I have always felt that
> "#+begin_src foo" referred to a language
I'd say, personally, that `foo' would refer to a mode (`foo-mode') [1]
which supports one (or multiple) language(s).
And I guess that, in Emacs, `sh' is the mode for editing Shell scripts
(in sh, bash, zsh, etc.). Though, I'm not 100% sure of what I'm saying
here...
> sometimes where that language and a particular program are inseparable
> (e.g. gnuplot). But sh is a first-class language.
>
>> See the first line in ob-sh.el,
>> ,----
>> | ;;; ob-sh.el --- org-babel functions for shell evaluation
>> `----
Best regards,
Seb
[1] Do C-c ' and see that Org (tries to) call(s) the mode foo-mode.
--
Sebastien Vauban
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-12-13 17:13 ` Eric Schulte
@ 2013-12-13 19:32 ` Nick Dokos
2013-12-13 22:40 ` Achim Gratz
2013-12-13 23:18 ` Eric Schulte
2 siblings, 0 replies; 21+ messages in thread
From: Nick Dokos @ 2013-12-13 19:32 UTC (permalink / raw
To: emacs-orgmode
Eric Schulte <schulte.eric@gmail.com> writes:
>>
>> How about the following resolution? We rename ob-sh.el to ob-shell.el.
>> New "shell" code blocks could use the value of the
>> `org-babel-sh-command' environment variable. Then sh, bash, zsh, csh,
>> ash, dash (am I missing any other common ones) use the specific shell
>> specified.
>>
>
> The attached patches make this change and continue to pass the entire
> test suite. The problem being that with ob-sh, no longer present many
> users may have to change their configuration and possible the value of
> their local.mk file. One solution there is to add a dummy ob-sh.el with
> a deprecation message for some transition time. Thoughts?
>
>
Since I'm the de facto instigator of the original change in the default,
let me add my 2 cents. I'm fine with this change (or without it). I'd be
fine with changing the org-babel-sh-command setting in my config and
leaving the default alone.
And I sympathize with Greg's wish for portability in general, although
imo it's not particularly important in this case (ducking and donning
my asbestos underwear here).
I write short scripts in org files to document some process: I can't
remember anything any longer, so putting the details in a file is the
only way for me to figure out what I did six months (or even two days)
ago (finding the file again two days hence is another matter...) In most
cases, what I put in there is some sequence of commands, which will be
interpreted correctly no matter which shell is used. If I have anything
more complicated (non-trivial control flow, non-trivial i/o redirection,
etc etc), I put it in a script in ~/bin and invoke that in the source
code block. I may not be typical here of course, but that's why I think
that portability is not particularly important in this case - so leave
the default at sh and be done with it.
But when I tried and failed to run Eric's script in the original email,
I had to do a little digging to figure out what went wrong and how to
fix it (I don't remember running across org-babel-sh-command before
this). So I asked the question about sh and the rest is history. I
probably should have made the observation that org-babel-sh-command had
to be modified to run the code block (which was plainly true) and left
the question (which could be interpreted in various ways) out. OTOH,
there is now this discussion and presumably the end result will be
better than what we started with.
Nick
PS. I haven't tried out the patch but I plan to do so over the weekend.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-12-13 17:13 ` Eric Schulte
2013-12-13 19:32 ` Nick Dokos
@ 2013-12-13 22:40 ` Achim Gratz
2013-12-13 23:18 ` Eric Schulte
2 siblings, 0 replies; 21+ messages in thread
From: Achim Gratz @ 2013-12-13 22:40 UTC (permalink / raw
To: emacs-orgmode
Eric Schulte writes:
>> How about the following resolution? We rename ob-sh.el to ob-shell.el.
>> New "shell" code blocks could use the value of the
>> `org-babel-sh-command' environment variable. Then sh, bash, zsh, csh,
>> ash, dash (am I missing any other common ones) use the specific shell
>> specified.
I've also seen ksh, mksh, posh (the latter specifically for POSIX
compatibility checks). But trying to enumerate all possible shell names
is futile, especially when the same shell dialect can have different
names on different systems and you'll only find a handful of those on
each particular system installed. Then there are those systems where at
least two different shells exist with the same name in different paths
and you'll get one or the other depending on which way your path is set
up.
> The attached patches make this change and continue to pass the entire
> test suite. The problem being that with ob-sh, no longer present many
> users may have to change their configuration and possible the value of
> their local.mk file. One solution there is to add a dummy ob-sh.el with
> a deprecation message for some transition time. Thoughts?
I'm not sure this does the right thing (if that is even possible in this
case). It looks overcomplicated to me, anyway.
There are two sides to a shell: the programming language / scripting
part and the interactive part. Of those shells that are somewhat POSIX
compatible, the programming language part isn't all that much different
(at least no more than, say, different C dialects). Even csh does the
right thing with a lot of POSIX stuff and you shouldn't really use it
for serious scripting anyway. The interactive part shouldn't really
figure into Babel, even though the particular choice will introduce one
or the other quirk in certain areas of scripting if you're not careful.
Emacs' shell-mode recognizes that ambiguity: it looks up the bang line
to decide which dialect to chose and waits for a user decision if it
can't find one. I'd have no problem if ob-sh did the same and simply
ran with whatever it can get away with (assuming close-enough-to-POSIX)
and only chose a specific shell when asked (via bang line or otherwise).
Regards,
Achim.
--
+<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+
Factory and User Sound Singles for Waldorf Q+, Q and microQ:
http://Synth.Stromeko.net/Downloads.html#WaldorfSounds
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-12-13 17:13 ` Eric Schulte
2013-12-13 19:32 ` Nick Dokos
2013-12-13 22:40 ` Achim Gratz
@ 2013-12-13 23:18 ` Eric Schulte
2013-12-14 10:21 ` Achim Gratz
2 siblings, 1 reply; 21+ messages in thread
From: Eric Schulte @ 2013-12-13 23:18 UTC (permalink / raw
To: Greg Troxel; +Cc: Nick Dokos, emacs-orgmode
It sounds as though most people don't particularly care which shell is
used. However, I believe Greg is correct and the *right* thing to do is
to have specific names (bash, sh, etc...) denote specific shells. I'd
also like "#+begin_src shell" to specify the "don't care" option. That
is what these patches do, with relatively little churn in the code (the
one huge commit just renames a file).
I just applied these patches. The worst case is that users may have to
change "ob-sh" to "ob-shell" in their config (although some initial
testing seems to indicate that even this change won't be required), and
possibly replace "sh" with "shell" in their local.mk file (if they have
one) to run tests at the command line. In my mind this short-term
hassle is worth the long-term correctness.
I've just applied these patches. At this point I'll borrow Nick's
asbestos underwear and place it on my head.
Best Regards,
--
Eric Schulte
https://cs.unm.edu/~eschulte
PGP: 0x614CA05D
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [babel] how to pass data to gnuplot from another block
2013-12-13 23:18 ` Eric Schulte
@ 2013-12-14 10:21 ` Achim Gratz
0 siblings, 0 replies; 21+ messages in thread
From: Achim Gratz @ 2013-12-14 10:21 UTC (permalink / raw
To: emacs-orgmode
Eric Schulte writes:
> I just applied these patches. The worst case is that users may have to
> change "ob-sh" to "ob-shell" in their config (although some initial
> testing seems to indicate that even this change won't be required), and
> possibly replace "sh" with "shell" in their local.mk file (if they have
> one) to run tests at the command line. In my mind this short-term
> hassle is worth the long-term correctness.
Since "sh" is redundant there and has been for some time (like
emacs-lisp and org it is always loaded since some non-Babel tests need
it), it would be easier to just delete it from BTEST_OB_LANGUAGES if
present.
Regards,
Achim.
--
+<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+
Factory and User Sound Singles for Waldorf Q+, Q and microQ:
http://Synth.Stromeko.net/Downloads.html#WaldorfSounds
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2013-12-14 10:21 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-11-22 9:57 [babel] how to pass data to gnuplot from another block Eric S Fraga
2013-11-22 15:00 ` Eric Schulte
2013-11-22 17:27 ` Nick Dokos
2013-11-23 16:15 ` Eric Schulte
2013-12-13 15:23 ` Greg Troxel
2013-12-13 15:30 ` Eric Schulte
2013-12-13 15:48 ` Greg Troxel
2013-12-13 16:20 ` Eric Schulte
2013-12-13 17:13 ` Eric Schulte
2013-12-13 19:32 ` Nick Dokos
2013-12-13 22:40 ` Achim Gratz
2013-12-13 23:18 ` Eric Schulte
2013-12-14 10:21 ` Achim Gratz
2013-12-13 18:38 ` Greg Troxel
2013-12-13 19:08 ` Sebastien Vauban
2013-12-13 16:32 ` Achim Gratz
2013-12-05 7:35 ` Eric S Fraga
2013-12-05 18:29 ` Eric Schulte
2013-12-05 19:59 ` Eric S Fraga
2013-12-06 2:06 ` Eric Schulte
2013-12-06 11:59 ` Eric S Fraga
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.