Naming and evaluating src blocks
As well as a nifty function for viewing the Info version.
This commit is contained in:
parent
36ea4b904e
commit
184ca4acee
2 changed files with 153 additions and 12 deletions
16
README.org
16
README.org
|
@ -25,3 +25,19 @@ To render and read [[file:lp-in-org.org][the book]] in Info, execute the followi
|
||||||
(Info-mode)
|
(Info-mode)
|
||||||
(Info-top-node))
|
(Info-top-node))
|
||||||
#+end_src
|
#+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
|
||||||
|
|
149
lp-in-org.org
149
lp-in-org.org
|
@ -3,14 +3,6 @@
|
||||||
#+EMAIL: howard.abrams@gmail.com
|
#+EMAIL: howard.abrams@gmail.com
|
||||||
#+DATE: 2016 Oct 06
|
#+DATE: 2016 Oct 06
|
||||||
#+DESCRIPTION: This file is used as the basis for the Info documentation
|
#+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':
|
# 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))
|
# (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. Let’s try again with the following c
|
||||||
|
|
||||||
#+begin_example
|
#+begin_example
|
||||||
,#+begin_src emacs-lisp
|
,#+begin_src emacs-lisp
|
||||||
(truncate (* (sin .438) 100))
|
(truncate (* (sin 0.438) 100))
|
||||||
,#+end_src
|
,#+end_src
|
||||||
#+end_example
|
#+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=.
|
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 isn’t 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 isn’t hidden in markers, but shines plainly in the text itself.
|
||||||
** Editing src Blocks
|
** 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=, aren’t available.
|
I find editing prose in an Org file quite nice…editing code? Not so much. Many techniques you expect to use aren’t 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.
|
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 @@ Let’s add more [[info:org#Languages][languages]] to what is available, by runn
|
||||||
(python . t)))
|
(python . t)))
|
||||||
#+end_src
|
#+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 aren’t familiar with Lisp, don’t 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 don’t see you language’s pretty colors for its syntax, run this code (and put it in your init file):
|
*Note:* If you don’t see you language’s pretty colors for its syntax, run this code (and put it in your init file):
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(setq org-src-fontify-natively t)
|
(setq org-src-fontify-natively t)
|
||||||
#+end_src
|
#+end_src
|
||||||
|
** Naming src Blocks
|
||||||
|
According to Org’s 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= isn’t a variable, but the following sections, we’ll 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 doesn’t 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
|
* Working with Python
|
||||||
* Calling out to the Shell
|
* Calling out to the Shell
|
||||||
|
@ -248,3 +357,19 @@ And maybe another one for defining unit tests?
|
||||||
(should (= $0)))
|
(should (= $0)))
|
||||||
,#+END_SRC
|
,#+END_SRC
|
||||||
#+end_example
|
#+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:
|
||||||
|
|
Loading…
Reference in a new issue