Naming and evaluating src blocks

As well as a nifty function for viewing the Info version.
This commit is contained in:
Howard Abrams 2024-08-10 23:33:41 -07:00
parent 36ea4b904e
commit 184ca4acee
2 changed files with 153 additions and 12 deletions

View file

@ -25,3 +25,19 @@ To render and read [[file:lp-in-org.org][the book]] in Info, execute the followi
(Info-mode)
(Info-top-node))
#+end_src
Better yet:
#+begin_src emacs-lisp :results silent
(defun org-view-as-info (file)
"View FILE, an org file, as exported to Info page."
(ignore-errors
(kill-buffer (format "%s.info" (file-name-base file))))
(find-file file)
(find-file (org-texinfo-export-to-info))
(Info-mode)
(Info-top-node))
(defun view-literate-programming-book ()
(interactive)
(org-view-as-info "~/Documents/literate-programming/lp-in-org.org"))
#+end_src

View file

@ -3,14 +3,6 @@
#+EMAIL: howard.abrams@gmail.com
#+DATE: 2016 Oct 06
#+DESCRIPTION: This file is used as the basis for the Info documentation
#+OPTIONS: ':t toc:t author:t email:t
#+LANGUAGE: en
#+MACRO: version 1.0
#+MACRO: updated last updated 1 August 2024
#+TEXINFO_FILENAME: lp-in-org.info
#+TEXINFO_HEADER: @syncodeindex pg cp
#+TEXINFO_HEADER: @syncodeindex vr cp
# NOTE: To create/view info, execute the following with `C-x C-e':
# (progn (find-file (org-texinfo-export-to-info)) (Info-mode) (Info-top-node))
@ -142,7 +134,7 @@ While a classic, not a very good example. Lets try again with the following c
#+begin_example
,#+begin_src emacs-lisp
(truncate (* (sin .438) 100))
(truncate (* (sin 0.438) 100))
,#+end_src
#+end_example
@ -168,10 +160,10 @@ Note: If you are reading this in an Emacs buffer, you can also place your cursor
At this point, you can begin a line with =<s= and hit ~TAB~ to have a src block expanded, with the cursor left at the end of first line, allowing you to type =emacs-lisp=.
This is Emacs, you probably have your favorite template expansion, like [[https://elpa.gnu.org/packages/doc/tempel/tempel.html][TempEL]] or [[https://www.emacswiki.org/emacs/Yasnippet][Yasnippet]], as any system that can generate your text works fine.The magic isnt hidden in markers, but shines plainly in the text itself.
This is Emacs, you probably have your favorite template expansion, like [[https://elpa.gnu.org/packages/doc/tempel/tempel.html][TempEL]] or [[https://www.emacswiki.org/emacs/Yasnippet][Yasnippet]], as any system that can generate your text works fine. Unlike other /notebook applications/, the magic isnt hidden in markers, but shines plainly in the text itself.
** Editing src Blocks
I find editing prose in an Org file quite nice…editing code? Not so much. Many techniques you expect to use, like jumping to code definitions with the [[info:emacs#Looking Up Identifiers][Xref system]] or manipulating s-expressions in a Lisp with =paredit= or =smart-parens=, arent available.
I find editing prose in an Org file quite nice…editing code? Not so much. Many techniques you expect to use arent available, like manipulating s-expressions in a Lisp with =paredit= or =smart-parens=, or jumping to code definitions, [[info:emacs#Looking Up Identifiers][Xref system]].
With your cursor anywhere, the header line, anywhere in the body or one the =end_src= line, type ~C-c '~ to narrow to contents of that block with a mode based on the language on the header line.
@ -186,13 +178,130 @@ Lets add more [[info:org#Languages][languages]] to what is available, by runn
(python . t)))
#+end_src
Feel free to substitute the =python=, for your favorite language, or add more. Use =sh= for shell scripts, and =js= for Javascript. See [[https://orgmode.org/worg/org-contrib/babel/languages/index.html][Babel]] for details on languages that can be supported.
If you arent familiar with Lisp, dont let that magic incantation concern you too much. Just follow the pattern to substitute the =python= for your favorite language. You can add or remove more (use =t= to include it, and =nil= to remove it). Use =sh= for shell scripts, and =js= for Javascript. See [[https://orgmode.org/worg/org-contrib/babel/languages/index.html][Babel]] for details on languages that can be supported.
*Note:* If you dont see you languages pretty colors for its syntax, run this code (and put it in your init file):
#+begin_src emacs-lisp
(setq org-src-fontify-natively t)
#+end_src
** Naming src Blocks
According to Orgs documentation on the [[info:org#Structure of Code Blocks][Structure of Code Blocks]], a =src= block looks like:
#+begin_example
,#+NAME: <name>
,#+BEGIN_SRC <language> <switches> <header arguments>
<body>
,#+END_SRC
#+end_example
The =#+NAME= associates name you can reference later in your document. For instance:
#+begin_example
,#+NAME: the-answer
,#+BEGIN_SRC emacs-lisp
(truncate (* (1- (expt 2 3)) (sqrt 36)))
,#+END_SRC
,#+RESULTS: the-answer
: 42
#+end_example
The named value, =the-answer= isnt a variable, but the following sections, well show how it can be used as one.
Following the /language/, you can add switches and other header arguments (that we will discuss ad nauseam in the following sections). Sometimes, we have too many arguments to /comfortably/ fit on a line, so we can break those long lines:
#+begin_example
,#+NAME: <name>
,#+HEADER: <more header arguments>
,#+BEGIN_SRC <language> <switches> <header arguments>
<body>
,#+END_SRC
#+end_example
You can have as many =#+HEADER= lines as you want.
** Evaluating src Blocks
As described above, typing ~C-c C-c~ in a block, evaluates it, displaying the results.
Why doesnt the following work?
#+begin_example
,#+BEGIN_SRC python
print("Hello World")
,#+end_SRC
,#+RESULTS:
: None
#+end_example
The reason is that Python, by default, only returns the results from the /value/ of an expression, and the =print= function returns =None=. To see the /output/ from a block, we need to add a =:results= header argument:
#+begin_example
,#+BEGIN_SRC python :results output
print("Hello World")
,#+END_SRC
,#+RESULTS:
: Hello World
#+end_example
Some languages, like =sh= (for your shell) default to =output=, so the following works as expected:
#+begin_example
,#+BEGIN_SRC sh
pwd
,#+END_SRC
,#+RESULTS:
: /home/howard/Documents/literate-programming
#+end_example
If a language, like Python, can return either a /value/ or its /standard output/, you can set =:results= to =value= or =output= respectively.
*** Displaying Results as Lists
Our previous examples returned a single number or string. If our code returned an array or list, we can use the =:results= header argument to state you want the results formatted as a list:
#+begin_example
,#+BEGIN_SRC emacs-lisp :results list
(number-sequence 1 5)
,#+END_SRC
,#+RESULTS:
- 1
- 2
- 3
- 4
- 5
#+end_example
In the [[*Evaluating src Blocks][previous section]], we used =:results= to specify whether we wanted the /value/ of the code, or its /standard output/, but the =:results= header argument can take multiple arguments, for instance, all of the following are reasonable:
- =:results value=
- =:results list=
- =:results value list=
*** Displaying Results as Tables
The =:results= header argument accepts the =table= parameter, which is helpful for two-dimensional arrays.
#+begin_example
,#+BEGIN_SRC emacs-lisp :results table
(defun rando (limit) (random limit))
(defun lotso-randos ()
(seq-map 'rando (number-sequence 1 25)))
(seq-partition (lotso-randos) 5)
,#+END_SRC
,#+RESULTS:
| 0 | 0 | 0 | 3 | 1 |
| 4 | 3 | 6 | 6 | 3 |
| 2 | 10 | 9 | 6 | 4 |
| 7 | 13 | 0 | 0 | 10 |
| 20 | 20 | 17 | 3 | 4 |
#+end_example
Shall we talk about state?
*** Displaying Results as Code
* Working with Python
* Calling out to the Shell
@ -248,3 +357,19 @@ And maybe another one for defining unit tests?
(should (= $0)))
,#+END_SRC
#+end_example
** Hacking
Note the function =org-in-block-p= to see if we are in a “src” block.
#+OPTIONS: ':t toc:t author:t email:t
#+LANGUAGE: en_US
#+MACRO: version 1.0
#+MACRO: updated last updated 1 August 2024
#+TEXINFO_FILENAME: lp-in-org.info
#+TEXINFO_HEADER: @syncodeindex pg cp
#+TEXINFO_HEADER: @syncodeindex vr cp
# Local Variables:
# jinx-local-words: "src"
# End: