Update Org mode Babel note

This commit is contained in:
Gabriel Arazas 2021-04-22 12:31:24 +08:00
parent 0a244e1580
commit 439764ce63
3 changed files with 112 additions and 108 deletions

View File

@ -1,10 +1,9 @@
((org-mode . ((org-mode .
((org-babel-default-header-args . ((:session . "none") ((org-babel-default-header-args . ((:session . "none")
(:results . "output") (:results . "replace output")
(:exports . "both") (:exports . "both")
(:cache . "yes") (:cache . "no")
(:noweb . "no") (:noweb . "yes")
(:hlines . "no")
(:tangle . "no"))) (:tangle . "no")))
(org-babel-results-keyword . "results") (org-babel-results-keyword . "results")
(org-export-with-toc . t)))) (org-export-with-toc . t))))

View File

@ -1,71 +1,109 @@
#+title: Org mode: Babel #+title: Org mode: Babel
#+date: "2020-04-17 21:41:30 +08:00" #+date: "2020-04-17 21:41:30 +08:00"
#+date_modified: "2021-04-21 17:43:52 +08:00" #+date_modified: "2021-04-22 12:30:38 +08:00"
#+language: en #+language: en
#+properties: header-args :session :exports both
#+tags: research.reproducibility #+tags: research.reproducibility
Org-babel is the framework that enables [[file:2020-04-20-16-51-40.org][Org mode]] to insert output of the code from programming languages. Babel is the framework that enables [[file:2020-04-20-16-51-40.org][Org mode]] to be a [[file:2020-04-12-11-20-53.org][Reproducible research]] tool.
It is also the one thing that makes Org mode to be used as a tool for [[file:2020-04-12-11-20-53.org][Reproducible research]]. It is what makes Org mode [[https://orgmode.org/manual/Working-with-Source-Code.html][works with source code blocks]].
As of 2020-06-08, [[https://orgmode.org/worg/org-contrib/babel/languages.html][Babel supports more than 50 languages]] with the possibility of adding of other languages that are not supported yet. As of 2021-04-22, [[https://orgmode.org/worg/org-contrib/babel/languages/index.html][Babel supports more than 50 languages]] with the ability to support unsupported languages.
Though, it does have its quirks with different languages.
Your mileage may vary.
* The fundamental concepts * Functional and scripting mode
Here's an example of a code block executed with the shell. Babel works in two modes: functional and scripting mode.
#+begin_src sh - Functional mode returns a value either from the last statement or the return statement.
echo "HELLO WORLD" The value can then be used in other source code blocks and appropriately converted into Org mode equivalents.
#+end_src If the return value is a vector type, it will be printed as tables in Org mode which will then be rendered as a vector when used in another source code block.
#+results: - Scripting mode simply prints the output.
: HELLO WORLD Do keep in mind different languages have different ways of capturing the output.
[fn:: Most of them involves capturing the stdout.]
To execute the code block, simply run ~org-babel-execute-src-block~ (by default, this is mapped in ~<C-c> <C-c>~). The default mode is in functional mode but you can change it by setting ~:results~ header argument with the values from the [[https://orgmode.org/manual/Results-of-Evaluation.html][collection class]].
The results will be printed into a result block.
Each of the supported language may also have an exclusive option with each language suitable for certain processes.
For example, with Python 3, you can pretty print it in accordance to Org mode display.
An array will create a table, for instance with ~:results value~ [[https://orgmode.org/manual/Using-Header-Arguments.html#Using-Header-Arguments][header argument]].
* Functional mode values and passing them around
With functional mode, the value return will appear as an appropriate element in the Org mode buffer.
Scalar values will appear as a string and vector values will appear as tables.
The following examples are in [[https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-python.html][Python]].
#+begin_src python :results value #+begin_src python :results value
[["Item", "Value"], ["Baseball bat", 123], ["Baseball glove", 25], ["Printed shirt", 42]] return "The quick brown fox jumps over the lazy dog."
#+end_src #+end_src
#+results: #+results:
: None : The quick brown fox jumps over the lazy dog.
You can also export graphics with tools such as [[http://gnuplot.info/][Gnuplot]], [[https://www.gnu.org/software/octave/][GNU Octave]], [[https://www.r-project.org/][R]], and even [[https://www.latex-project.org/][LaTeX]]. #+name: data
With it, you can export the graphics into a file (commonly with ~:file <PATH>~). #+begin_src python :results value
return [
["Monty", 45],
["Soup", 54],
["Cabbages", 63]
]
#+end_src
#+begin_src gnuplot :exports both :file assets/2020-04-17-21-41-30/gnuplot-demo.png #+results: data
unset arrow | Monty | 45 |
unset label | Soup | 54 |
set grid | Cabbages | 63 |
splot x**2+y**2, x**2-y**2
To pass values between different code blocks, you have to give the blocks a name.
The previous code block was given a name ~data~ and passed it to the next block.
#+begin_src python :results value :var o=data
return o[0]
#+end_src #+end_src
#+results: #+results:
[[file:assets/2020-04-17-21-41-30/gnuplot-demo.png]] | Monty | 45 |
With Org-babel, you can share either the output, the code used to generate the output, or both.
This is commonly set with the ~:exports~ header argument.
[fn:: Again, this varies whether export options are available for each Babel-supported lanaguages.]
Here's an example where I decided to show only the output with ~:exports results~.
#+begin_src gnuplot :exports results :file assets/2020-04-17-21-41-30/gnuplot-3d-demo.png
set title "3D gnuplot demo" * Functions
unset grid
splot x*y with points With [[https://orgmode.org/worg/org-contrib/babel/intro.html][Babel]], you can call named code blocks anywhere from blocks to inline.
This creates a "function" with Babel using different languages.
The following block creates ~init~ function with a default value for its argument.
#+name: init
#+header: :var name="world"
#+begin_src python :results value silent :exports code
return f"Hello {name}"
#+end_src #+end_src
You can then call the ~init~ function inline with ~call_init[${HEADER_ARGS}](${ARGS})~ which should contain "call_init[:results raw]() Hello world".
For blocks, you can use the ~#+call~ block with a similar syntax to inline functions — i.e., ~#+call: init[${HEADER_ARGS}](${ARGS})~.
#+call: init[:results replace]()
#+results: #+results:
[[file:assets/2020-04-17-21-41-30/gnuplot-3d-demo.png]] : Hello world
You can also use it inside of code blocks with ~<<init>>~ which makes it perfect for code blocks templates like configuring paper output for Lilypond blocks.
Though, you have to set ~:noweb yes~ in the header arguments or configure it in ~org-babel-default-header-args~ as one of the default.
#+name: example
#+begin_src shell
echo -n <<init(name="Canavan")>>
#+end_src
#+results: example
: Hello Canavan
Babel functions are commonly used for inserting dynamic values.
Very helpful in reducing places you need to edit (not to mention less prone to errors).
@ -73,84 +111,33 @@ splot x*y with points
* Sessions * Sessions
Each of the source code block runs on an individual session. Each of the source code block runs on an individual session.
However, you can connect source code blocks (with the supported languages) in the same session with ~:session <SESSION NAME>~. However, you can connect source code blocks in the same session with ~:session <SESSION NAME>~.
Let's start with a simple example where we want to demonstrate some Python shenanigans. Let's start with a simple example where we want to demonstrate some Python shenanigans.
Here's one Python code block. Here's one Python code block.
#+begin_src python :results output :session python-example #+begin_src python :session python-example
x = 35 x = 30
print(x) print(x)
#+end_src #+end_src
#+results: #+results:
: 35 : 30
Then here's another code block in the same session. Then here's another code block in the same session.
#+begin_src python :results output :session python-example #+begin_src python :session python-example
for i in range(5): for i in range(5):
x += 5 x += 5
print(x) print(x)
#+end_src #+end_src
#+results: #+results:
: 35
: 40 : 40
: 45 : 45
: 50 : 50
: 55 : 55
: 60
In certain code where the output can still change (for example, try executing the previous code block again), this may not be the desired behavior. In certain code where the output can still change (for example, try executing the previous code block again), this may not be the desired behavior.
To correct this, simply execute ~org-babel-execute-buffer~. To correct this, simply execute ~org-babel-execute-buffer~.
* Integrating between different programming languages
You can also pass Org mode variables (from ~#+NAME: <VAR>~) [fn:: Technically called an internal link (https://orgmode.org/org.html#Internal-Links).] into the source code blocks with the ~:var <NAMEC>=<DATA>~ (though, this may vary among Babel runtimes).
#+name: example_string
This is the string.
#+begin_src python :var example=example_string :results value
example
#+end_src
#+results:
: None
This is the source code from the document, for reference.
#+begin_src org :exports code :results silent
,#+NAME: example_string
This is the string.
,#+BEGIN_SRC python :var example=example_string :outputs value
example
,#+END_SRC
,#+RESULTS:
,: This is the string.
#+end_src
Org mode variables does capture an element as its input.
This has a lot of implications of passing data between different sessions and even different languages.
For example, we could still capture the ~x~ variable from the previous Python code blocks.
#+name: var_from_other_lang
#+begin_src python :results silent :session python-example :exports value
x # Which should be 60 at this point.
#+end_src
Then, pass it to some other Org mode blocks with the variable.
(Since the captured variable are always going to be a string, we have to convert it into the appropriate type.)
#+begin_src R :results output :var python_var=var_from_other_lang
as.numeric(python_var) + 2
#+end_src
#+results:
: [1] 62

View File

@ -7,13 +7,20 @@
Keep taking notes and stop worrying about file organization! Keep taking notes and stop worrying about file organization!
Muh wiki. Muh wiki.
This documents the "infrastructure" of my notes because I like documenting. This documents the "infrastructure" of my notes because I like documenting and I always forget things.
It primarily uses the link:https://zk.zettel.page/[Zettelkasten note-taking method] which means all of my notes are scattered in just one location. It primarily uses the link:https://zk.zettel.page/[Zettelkasten note-taking method] which means all of my notes are scattered in just one location.
Fun. Fun.
NOTE: On another note, this supercedes my link:https://github.com/foo-dogsquared/personal-notes[personal notes]. [NOTE]
====
On another note, this supersedes my link:https://github.com/foo-dogsquared/personal-notes[personal notes].
I'm not going to import them because I want to start on a clean slate. I'm not going to import them because I want to start on a clean slate.
Also, not everything on this Git repo is here (at least yet).
Some of them are private files and so I want them to not appear anywhere else.
Fortunately for me, most of the private files are connected with each other (a separate org-roam instance would be better in this case).
====
@ -45,22 +52,27 @@ footnote:[You can enable the direnv module from the Doom Emacs config.]
=== Setting up === Setting up
Now with the pieces complete and assuming you've already have my wiki in your folder, fire up Emacs, open the wiki folder, and do your thing. Now with the pieces complete and assuming you've already have my wiki in your folder, fire up Emacs, open the wiki folder, and do your thing.
This project has a link:./.dir-locals.el[local Emacs config] (see link:https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html[related section]).
If you've set `enable-local-variables` to `:safe` or any value that makes Emacs to ignore them, you may want to configure related variables in a way either conditionally or simply replacing them.
If you have direnv installed, you can also enable automatic shell environments. If you have direnv installed, you can also enable automatic shell environments by allowing `.entry` to set it up for you.
How? Just run `direnv allow`!
Just add `.envrc`!
[source, shell]
----
echo "use nix" > .envrc && direnv allow
----
If you have link:https://github.com/target/lorri[lorri] installed, you're better to go with the faster startup for the environment.
== Conventions == Conventions
* When create a link between notes, more specific notes should link general notes.
This makes it easier to navigate a graph of back links.
+
IMPORTANT: This is a muddy subject leaning more into explicitly linking a subject without care.
Besides, those are what backlinks are for.
It's not an absolute rule to follow so don't worry about this, it's just a guideline at best.
Otherwise, you'll go through analysis paralysis.
* Uses timestamp (at localtime) as the filename, it is unique enough (for personal purposes) and doesn't need to change. * Uses timestamp (at localtime) as the filename, it is unique enough (for personal purposes) and doesn't need to change.
footnote:[If you use the title as the basis, that'll depend if you have tolerance for the misaligning relation between the filename and the title.] footnote:[If you use the title as the basis, that'll depend if you have tolerance for the misaligning relation between the filename and the title.]
The format for the filename is equivalent to `$(date +%F-%H-%M-%S).org`. The format for the filename is equivalent to `$(date +%F-%H-%M-%S).org`.
@ -118,16 +130,22 @@ For now, I'm not worrying to much on this one.
I did create a publication script back then for a small org-mode-based for testing purposes but it is messy and life happened so I wasn't able to get back on it immediately. I did create a publication script back then for a small org-mode-based for testing purposes but it is messy and life happened so I wasn't able to get back on it immediately.
Here's a link:https://git.sr.ht/~brettgilio/website/[very good example of a org-mode-and-Emacs-powered site] complete with features and without JavaScript! Here's a link:https://git.sr.ht/~brettgilio/website/[very good example of a org-mode-and-Emacs-powered site] complete with features and without JavaScript!
footnote:[link:https://brettgilio.com/[Brett Gilio] is kind enough to answer my noob org-mode related questions back then so big thanks to him for the guidance. :)] footnote:[link:https://brettgilio.com/[Brett Gilio] is kind enough to answer my noob org-mode related questions back then so big thanks to him for the guidance. :)]
The advantage is complete control and the disadvantage is starting from scratch.
Still, you can start from already existing solutions.
** Convert the org documents to commonly-supported text formats like Markdown and use static site generators. ** Convert the org documents to commonly-supported text formats like Markdown and use static site generators.
Most of them supports Markdown and there is an "export to Markdown" option for org-mode. Most of them supports Markdown and there is an "export to Markdown" option for org-mode.
I could whip up an Elisp script and export it by batch then move them over to an SSG setup like Hugo. I could whip up an Elisp script and export it by batch then move them over to an SSG setup like Hugo.
This is also how link:https://github.com/jethrokuan/braindump[Jethro Kuan's org-roam notes] are setup. This is also how link:https://github.com/jethrokuan/braindump[Jethro Kuan's org-roam notes] are setup.
** Use a parser outside of Emacs.
link:https://github.com/rasendubi/uniorg/tree/master/examples/org-braindump[uniorg] has a good example with Next.js as the site generator.
It requires an external JavaScript-based setup but it can also be an advantage.
* Migrate the notes for link:https://org-roam.discourse.group/t/org-roam-major-redesign/1198[org-roam v2]. * Migrate the notes for link:https://org-roam.discourse.group/t/org-roam-major-redesign/1198[org-roam v2].
Though I consider v1 to be feature-complete, I do like v2's reimagining of the plugin with the node (instead of files) as the new atomic unit. Though I consider v1 to be feature-complete, I do like v2's reimagining of the plugin with the node (instead of files) as the new atomic unit.
It is closer to its original inspiration (Roam Research). It is closer to its original inspiration (Roam Research).
It also brings a few simplified options along the way such as choosing to only support `tags` property. It also brings a few simplified options along the way such as choosing to only support `tags` property as well as replacing IDs for linking instead of file links.
Aaaand the primary maintainer said more performance so yay for me. Aaaand the primary maintainer said more performance so yay for me.
** Expect to change the links since it doesn't accept file links anymore. ** Expect to change the links since it doesn't accept file links anymore.