# Make Org-Babel-Sh-Evaluate Handle Noop Lines

fleeting

See how to org babel process the output in shell’s sessions for the analysis. Also I assume we have set an explicit prompt in comint-prompt-regexp, as explained here.

As a reminder, the problem is that org-babel, due to the fact it relies on comint-prompt-regexp in sh, expects all the prompts in the output to have a newline before them. In the case of noop line, only the prompt is output but no newline.

In the following example:

• echo a
• # noop
• echo b

comint gives

• a\n:theprompt:
• :theprompt:
• b\n:theprompt:
• org_babel_sh_eoe\n:theprompt:

Or, once concatenated:

a
:theprompt::theprompt:b
:theprompt:org_babel_sh_eoe
:theprompt:


And, after split and trim

• a

• b

• org_babel_sh_eoe

And thus in the end we should get

a

b


Let’s try it to make sure we got it right.

echo a
# noop
echo b

a

b


Ok, it looks like we understand correctly what happens.

Notice that, by setting the prompt exactly, like suggested in here, we already have sensible output. Without this fix, the output would be:

a
\$b


One solution could be to find out the output associated to the noop and remove the associated output prompt. If the case of the example, we would get

• a\n:theprompt:
• b\n:theprompt:
• org_babel_sh_eoe\n:theprompt:

Or, once concatenated:

a
:theprompt:b
:theprompt:org_babel_sh_eoe
:theprompt:


And finally we would get

a
b


To remove the noop commands, we could rewrite the comint-output-filter-functions part to add this behavior.

Because I did not want to mess too much with the function, I created a patch that runs a custom function instead of the inline code.

The patch is available on ipfs, at the location https://ipfs.iohttps//konubinix.eu/ipfs/QmNR4cY6EEj7RqVeb81F2uaC6HbwQaBPtn77fMtgf96NXB?filename=ob-comint.el

Note that because I patched a macro, you need to reload it but also recompile all the files that used it.

This patch makes org-babel-comint-with-output use the function konix/org-babel-comint-with-output/comint-output-filter-function to filter the comint output.

We could have the exact same behavior as the current one by defining the following

(defun konix/org-babel-comint-with-output/comint-output-filter-function (string-buffer text)
(concat string-buffer text)
)


Now, let’s try to erase the lines that match exactly the prompt. Thanks to our previous work, comint-prompt-regexp is no more a regexp and this is quite easy to write:

(defun konix/org-babel-comint-with-output/comint-output-filter-function (string-buffer text)
(when (string-equal comint-prompt-regexp text)
(setq text "")
)
(concat string-buffer text)
)


Then we get

echo a
# noop
echo b

a
b


Now, let’s see if we to mix some commands not outputting a newline as well as noop to challenge this solution.

• echo -n a
• # noop
• echo b

would result in the output

• a:theprompt:
• :theprompt:
• b\n:theprompt:
• org_babel_sh_eoe\n:theprompt:

The noop workaround would remove the second line, then

• a:theprompt:
• b\n:theprompt:
• org_babel_sh_eoe\n:theprompt:

and after concatenation

a:theprompt:b
:theprompt:org_babel_sh_eoe
:theprompt:


and then, after splitting and stripping

• a
• b

Let’s try it for real

echo -n a
# noop
echo b
# noop
echo c
echo -n d

a
b
c
d


As you can see, the outputs are correctly shown now.

Actually, there is one subtlety that needs to be taken care of: the prompt may come some time after the last output, giving the following pattern:

• some output
• :theprompt:

For example, the following program don’t return anything

echo a && sleep 2


That case may be captured by simply remembering whether the last command was finished, meaning it ended by the prompt.

(defvar konix/org-babel-comint-with-output/comint-output-filter-function/not-finished-yet nil)

(defun konix/org-babel-comint-with-output/comint-output-filter-function (string-buffer text)
;; see https://konubinix.eu/braindump/posts/25b52cc8-71f8-420f-9161-5c60030cede9/
;; for an explanation
(when (and
(string-equal ":theprompt:" text)
(not konix/org-babel-comint-with-output/comint-output-filter-function/not-finished-yet)
)
(setq text "")
)
(setq konix/org-babel-comint-with-output/comint-output-filter-function/not-finished-yet
(not (string-suffix-p text ":theprompt:"))
)
(concat string-buffer text)
)


Now, the delay between the output and the prompt is not a problem anymore.

echo a && sleep 2

a