1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
|
WEBVTT captioned by sachac
NOTE Introduction
00:00:00.000 --> 00:00:09.359
Can you believe it's been a decade since I started
00:00:09.360 --> 00:00:12.358
pontificating on literate programming?
00:00:12.359 --> 00:00:17.542
I am Howard Abrams. In 2015, I spoke at this EmacsConf
00:00:17.543 --> 00:00:21.705
where I described my challenges I called Literate DevOps.
00:00:21.706 --> 00:00:25.634
The conference wasn't completely virtual, even though I was.
00:00:25.635 --> 00:00:29.317
My city of Portland was suffering a citywide electrical outage
00:00:29.318 --> 00:00:33.479
and I was without power, so I gave the talk in a corner of my
00:00:33.480 --> 00:00:37.439
friend's living room. People online asking questions and
00:00:37.440 --> 00:00:41.439
wondering about literate programming... I also see comments
00:00:41.440 --> 00:00:44.599
explaining why literate programming hasn't caught on in
00:00:44.600 --> 00:00:49.079
corporate practice. I often don't engage. I mean, is the
00:00:49.080 --> 00:00:51.599
online arguments and chatter over ignorance or
00:00:51.600 --> 00:00:56.719
preference? Sure, we're wired differently. I mean, my
00:00:56.720 --> 00:00:59.559
favorite programming languages put the parentheses
00:00:59.560 --> 00:01:01.939
before the function name.
00:01:01.940 --> 00:01:03.800
Literate programming has come a long way
00:01:03.801 --> 00:01:08.519
since Knuth proposed it in the 19th century. I feel
00:01:08.520 --> 00:01:12.999
it's come a long way just in the last 10 years. Obviously,
00:01:13.000 --> 00:01:16.399
this interest is due to Org. I don't think I would bother if
00:01:16.400 --> 00:01:21.359
all I had was Knuth's original preprocessor. But since I'm
00:01:21.360 --> 00:01:24.839
talking to fellow nerds about an open source project
00:01:24.840 --> 00:01:27.919
without corporate backing, let me change the title of my
00:01:27.920 --> 00:01:32.919
talk and re-pitch Literate Programming in the 24th and a
00:01:32.920 --> 00:01:35.252
Half Century!
NOTE Do I still literate?
00:01:35.253 --> 00:01:36.653
People often ask if I still program that way.
00:01:36.654 --> 00:01:42.759
I guess they want to know if there's any long-term benefits,
00:01:42.760 --> 00:01:45.919
for many of our tools and our workflows, while initially
00:01:45.920 --> 00:01:51.079
tantalizing, often don't last. But yes, when I sit down to
00:01:51.080 --> 00:01:57.759
write a program, I create a file with an extension of .org.
00:01:57.760 --> 00:02:03.799
I guess you can say I program literally.
00:02:03.800 --> 00:02:07.359
Let me be transparent. Do I use literate programming during
00:02:07.360 --> 00:02:12.599
my day job? Yes, but only for personal tools or for initial
00:02:12.600 --> 00:02:16.759
investigation. At the end of the sprint, I tangle the file
00:02:16.760 --> 00:02:21.079
and git commit that. My personal projects, on the other
00:02:21.080 --> 00:02:25.679
hand, are Org files. Since I can't show you the code from
00:02:25.680 --> 00:02:27.839
my day job, I'm afraid my example code will have a lot of
00:02:27.840 --> 00:02:31.159
parentheses.
00:02:31.160 --> 00:02:33.955
I'm sure you won't mind.
00:02:33.956 --> 00:02:37.356
I like having my Emacs configuration in Org.
00:02:37.357 --> 00:02:40.359
It's pretty bling. It has over 8,000
00:02:40.360 --> 00:02:44.559
lines of code. I know, I can hear the screams and gasps over
00:02:44.560 --> 00:02:49.439
the network. However, the surrounding prose in Org adds
00:02:49.440 --> 00:02:53.410
10,000 lines, and those lines are non-wrapped paragraphs.
00:02:53.411 --> 00:02:58.119
I mean, is that large? Sure, we've all worked on
00:02:58.120 --> 00:03:03.639
larger, so I guess it's not huge. Come on, it's still
00:03:03.640 --> 00:03:06.331
significant.
NOTE Advantages
00:03:06.332 --> 00:03:09.799
Advantages? Look who I'm talking to. I'm sure
00:03:09.800 --> 00:03:14.279
you know the advantages, but indulge me. I feel that one
00:03:14.280 --> 00:03:16.799
advantage of literate programming, especially with large
00:03:16.800 --> 00:03:20.279
code bases, is how you can organize and manage the
00:03:20.280 --> 00:03:24.839
complexity. Most programming languages tame large bases
00:03:24.840 --> 00:03:29.119
by putting code in separate files. While Org can too, with
00:03:29.120 --> 00:03:32.279
Org, we can group related functions together under
00:03:32.280 --> 00:03:35.043
expandable headlines.
00:03:35.044 --> 00:03:37.279
Here's one. You can see that
00:03:37.280 --> 00:03:40.706
I've got different sections grouped together.
00:03:40.707 --> 00:03:43.759
In my original talk, I mentioned how I would attempt to organize
00:03:43.760 --> 00:03:47.839
my thoughts before coding. I appreciate how I can look back
00:03:47.840 --> 00:03:53.599
at my notes. In my Emacs configuration, I review the prose to
00:03:53.600 --> 00:03:57.799
help memorize key bindings.
00:03:57.800 --> 00:04:01.039
My section on getting email working with Emacs using
00:04:01.040 --> 00:04:04.079
notmuch means creating small collections of scripts and
00:04:04.080 --> 00:04:08.199
configuration files. I can tangle them all from one Org
00:04:08.200 --> 00:04:16.799
file. I like that I can explain each part separately.
00:04:16.800 --> 00:04:20.879
You just can't beat having links back to Stack Overflow or
00:04:20.880 --> 00:04:25.519
that GitHub repo where you stole, I mean, became inspired to
00:04:25.520 --> 00:04:28.719
write your code.
NOTE Disadvantages
00:04:28.720 --> 00:04:34.279
Literate programming may push the boundaries of our
00:04:34.280 --> 00:04:38.119
workflows and revealing some abrasion, but we aren't
00:04:38.120 --> 00:04:41.239
solely working with Org. We have the flexibility of a Lisp
00:04:41.240 --> 00:04:45.119
engine to file down those rough parts. You may have your
00:04:45.120 --> 00:04:48.159
concerns. Perhaps you could reach out to me, and with
00:04:48.160 --> 00:04:54.239
particular issues, maybe we can figure something out.
00:04:54.240 --> 00:04:57.439
Here is my list of frictions, and the rest of my talk
00:04:57.440 --> 00:05:02.159
demonstrates my answers and my hacks. The goal in literate
00:05:02.160 --> 00:05:05.039
programming with Org is that it should not require more
00:05:05.040 --> 00:05:08.679
effort than non-literate programming. For instance, I
00:05:08.680 --> 00:05:12.119
shouldn't have to type much more than regular programming
00:05:12.120 --> 00:05:15.719
to get my code literate. I also shouldn't have to worry about
00:05:15.720 --> 00:05:20.799
the state between my Org file and the source code. I want
00:05:20.800 --> 00:05:24.132
to be able to jump around my code just as easily.
NOTE Ease of typing
00:05:24.133 --> 00:05:28.654
Let me explain more. I've created some templates using
00:05:28.655 --> 00:05:34.679
yasnippet. Since I was used to the old org-tempo feature,
00:05:34.680 --> 00:05:37.145
my habit has all the snippets starting with a
00:05:37.146 --> 00:05:40.759
< character. I'm not sure if I should demonstrate all of them
00:05:40.760 --> 00:05:45.999
as you may be doing something similar. I like to build on top
00:05:46.000 --> 00:05:49.999
of characters to remind me that if I just enter a <s, I
00:05:50.000 --> 00:05:53.519
need to put in the language. But if I append a mnemonic, I can
00:05:53.520 --> 00:05:56.839
get a full language. Why not do that with a full function
00:05:56.840 --> 00:06:01.199
definition? In this case, I'm smooshing one yasnippet
00:06:01.200 --> 00:06:11.679
inside another one in order to save myself some typing.
00:06:11.680 --> 00:06:15.159
My point here is to pay attention to what slows you down or
00:06:15.160 --> 00:06:24.719
hinders you from getting the advantages you want.
NOTE Keep tangled code sync'd
00:06:24.720 --> 00:06:28.399
Do you ever forget to tangle your code? You can append this
00:06:28.400 --> 00:06:31.519
code to the bottom of your Org file so that it gets tangled
00:06:31.520 --> 00:06:36.159
every time you save. I've written a function so I can visit
00:06:36.160 --> 00:06:40.559
that tangled file and then return. I've grouped all my
00:06:40.560 --> 00:06:45.119
functions together. I've taken a cue from Charles Choi, you
00:06:45.120 --> 00:06:48.639
know, kickingvegas, and his Casual feature set. But
00:06:48.640 --> 00:06:52.374
instead of Transient, I've just made a hydra using
00:06:52.375 --> 00:06:57.399
the major-mode-hydra package. Anyway, this allows me to use and
00:06:57.400 --> 00:07:00.136
remember my micro-optimizations.
00:07:00.137 --> 00:07:03.697
If you set the :comments property to link,
00:07:03.698 --> 00:07:06.999
the tangled output is back-connected.
00:07:07.000 --> 00:07:11.479
This allows us to edit the tangled code and have it update the
00:07:11.480 --> 00:07:16.879
Org file. Personally, I don't like this. My source of truth
00:07:16.880 --> 00:07:22.500
is the Org file, and I tangle as a one-way diode.
NOTE Code evaluation
00:07:22.501 --> 00:07:25.603
Often a block of code will reference a variable
00:07:25.604 --> 00:07:29.046
or call a function to find in another block of code.
00:07:29.047 --> 00:07:31.508
In my original literate DevOps talk,
00:07:31.509 --> 00:07:34.519
I discussed how to use the output from one block into
00:07:34.520 --> 00:07:37.799
another block by naming the first block and referencing it
00:07:37.800 --> 00:07:42.159
with a :var for the second. However, if all the blocks use the
00:07:42.160 --> 00:07:46.039
same language, you can use sessions, which create a
00:07:46.040 --> 00:07:51.479
persistent REPL behind the scenes. Let's evaluate the
00:07:51.480 --> 00:07:53.199
blocks of Python code in this file.
00:07:53.200 --> 00:08:00.119
The evaluation created a Python REPL. It's available in
00:08:00.120 --> 00:08:04.279
another buffer. This buffer matches the name of the
00:08:04.280 --> 00:08:07.959
session, but with surrounding asterisks. Evaluating a
00:08:07.960 --> 00:08:11.399
code block sends it into the REPL, and now I can work with my
00:08:11.400 --> 00:08:19.959
code blocks interactively. (That's not quite right.)
NOTE Has that block been eval'd?
00:08:19.960 --> 00:08:24.039
I primarily hack on Emacs Lisp, and textual changes to
00:08:24.040 --> 00:08:28.199
variables, functions, or macros--unless you habitually
00:08:28.200 --> 00:08:31.679
type C-c C-c--may not represent the state of your
00:08:31.680 --> 00:08:35.439
machine. A similar effect happens in any language that
00:08:35.440 --> 00:08:39.319
uses sessions. Sure, I can move the point to a block and
00:08:39.320 --> 00:08:42.799
evaluate, but I have three functions that allow me to
00:08:42.800 --> 00:08:44.734
evaluate all blocks in a buffer or all blocks in a subtree,
00:08:44.735 --> 00:08:50.199
or I can, without moving the point, evaluate any block I see.
00:08:50.200 --> 00:08:54.919
Now, this function here evaluates all blocks in a buffer.
00:08:54.920 --> 00:08:58.279
Someone mentioned calling this function when you first
00:08:58.280 --> 00:09:02.359
load a file. I'm not sure that's a good policy. I mean, have
00:09:02.360 --> 00:09:05.238
you not written a bug?
NOTE Evaluating code in a subtree
00:09:05.239 --> 00:09:08.559
Since this function right here
00:09:08.560 --> 00:09:12.039
evaluates only visible blocks, we can limit what Emacs
00:09:12.040 --> 00:09:18.799
evaluates to a single Org mode section. For instance, with
00:09:18.800 --> 00:09:23.759
the cursor in one section, I can evaluate just the blocks in
00:09:23.760 --> 00:09:26.871
that header section.
NOTE Evaluating code from a distance
00:09:26.872 --> 00:09:29.399
If I can see a block, why clumsily
00:09:29.400 --> 00:09:33.079
navigate to it when I can extend the avy project to just jump to
00:09:33.080 --> 00:09:40.479
it? For instance, let's pull this file up. I can jump to any of
00:09:40.480 --> 00:09:41.639
the four blocks.
00:09:41.640 --> 00:09:50.319
I think that's quite slick. Now why navigate to a code block
00:09:50.320 --> 00:09:55.799
solely to evaluate it? Yes, this is a terrible example, but
00:09:55.800 --> 00:09:59.679
these three blocks set a variable to different values. So
00:09:59.680 --> 00:10:02.599
without moving the point, I can evaluate any one of them.
00:10:02.600 --> 00:10:09.719
To be honest, the reason why I wrote this is because I often
00:10:09.720 --> 00:10:13.999
forget to evaluate a block after editing it. I've moved on,
00:10:14.000 --> 00:10:17.839
and I just don't want to jump back. Now, I can just evaluate
00:10:17.840 --> 00:10:22.359
from a distance. I apologize for the previous terrible
00:10:22.360 --> 00:10:26.019
examples, but I'm quite pleased with this feature.
NOTE Navigating by headers
00:10:26.020 --> 00:10:30.119
As I mentioned earlier, in a large code base, we organize code by
00:10:30.120 --> 00:10:33.839
library or module, and each file contains a class composed
00:10:33.840 --> 00:10:37.119
of methods, functions, variables, fields, et cetera.
00:10:37.120 --> 00:10:39.999
Literate programming in Org files allows me to add a
00:10:40.000 --> 00:10:43.159
semantic organization layer where I can group related
00:10:43.160 --> 00:10:46.919
concepts under headlines. Now, while this isn't specific
00:10:46.920 --> 00:10:50.799
to literate programming, I wrote a little user interface to
00:10:50.800 --> 00:10:54.296
allow me to jump to any heading in any Org file
00:10:54.297 --> 00:10:57.679
in a particular project.
00:10:57.680 --> 00:11:02.879
These are the headings in my Emacs configuration project.
00:11:02.880 --> 00:11:06.559
Notice the file name beforehand, before the colon
00:11:06.560 --> 00:11:09.759
character. The header name and its parent headers are
00:11:09.760 --> 00:11:14.799
after. Let me search for the LSP sections. Maybe I only want
00:11:14.800 --> 00:11:20.039
the one for Python. Now I use ripgrep to search the files and
00:11:20.040 --> 00:11:24.559
then some Lisp to parse the output. Unless someone has
00:11:24.560 --> 00:11:26.793
already done this, I should package this up on MELPA.
NOTE Navigating by function names
00:11:26.794 --> 00:11:32.199
What about jumping directly to the definition of a function,
00:11:32.200 --> 00:11:36.799
variable, or what have you? We can use Emacs's built-in xref
00:11:36.800 --> 00:11:39.879
library, but these functions don't understand that the
00:11:39.880 --> 00:11:45.319
source code is in Org files. When I started using Emacs
00:11:45.320 --> 00:11:49.479
30-something years ago, I would pre-index my source into
00:11:49.480 --> 00:11:53.799
tag files, but the dumb-jump project uses the newfangled and
00:11:53.800 --> 00:11:58.319
faster text search programs like ripgrep to find a symbol in
00:11:58.320 --> 00:12:02.319
real time. I followed this pattern and wrote an extension
00:12:02.320 --> 00:12:08.119
to the xref API. Now, I want to jump around my code from both
00:12:08.120 --> 00:12:14.519
code block or in the surrounding prose. I'm sure it
00:12:14.520 --> 00:12:18.199
comes as no surprise that my presentation is just an Org
00:12:18.200 --> 00:12:23.919
file. Let's suppose my cursor is on this symbol. I wrote this
00:12:23.920 --> 00:12:28.079
function for this demonstration. We can jump to the
00:12:28.080 --> 00:12:30.759
definition and I can jump back.
00:12:30.760 --> 00:12:37.639
Notice it jumped into an Org file and back out. References,
00:12:37.640 --> 00:12:42.279
unlike definitions, is where something is defined and
00:12:42.280 --> 00:12:46.919
where it's used. Well, you know how the xref system works.
00:12:46.920 --> 00:12:52.679
Here, I can jump to the definition or where it's
00:12:52.680 --> 00:12:59.519
used. Of course, and jump back. I think this is cool. This
00:12:59.520 --> 00:13:04.319
should be a nifty package on MELPA. But my code is specific to
00:13:04.320 --> 00:13:08.799
Lisp, and I'm not completely sure how to make it general. For
00:13:08.800 --> 00:13:13.399
instance, what is a symbol? If you know the language, this is
00:13:13.400 --> 00:13:17.679
obvious. But what should the language be when your cursor is
00:13:17.680 --> 00:13:22.639
in the prose of an Org file? Python only supports sequences
00:13:22.640 --> 00:13:25.559
of alphanumeric and underscores, but in Lisp, a symbol can
00:13:25.560 --> 00:13:30.399
be almost any character sequence. I've been stewing on how
00:13:30.400 --> 00:13:34.479
to do this. I have ideas like prompting during the first
00:13:34.480 --> 00:13:37.719
query or scanning the language based on the nearest code
00:13:37.720 --> 00:13:40.479
block. I think I'm babbling.
NOTE Why literate programming?
00:13:40.480 --> 00:13:47.199
In true geek fashion, I dived into the details before
00:13:47.200 --> 00:13:52.079
answering some better questions. In my original Literate
00:13:52.080 --> 00:13:55.479
DevOps talk, I explained the advantages of initially
00:13:55.480 --> 00:13:58.959
writing down your thoughts, your plans, goals... the
00:13:58.960 --> 00:14:02.879
user requirements. But what do you do with all that luscious
00:14:02.880 --> 00:14:06.359
prose afterwards? Well, you do the same thing you do to your
00:14:06.360 --> 00:14:09.279
initial code. You refactor that prose.
00:14:09.280 --> 00:14:14.759
Just because the tech surrounding your code is now a
00:14:14.760 --> 00:14:18.799
first-class citizen doesn't excuse bad code. You want
00:14:18.800 --> 00:14:23.165
something more from both your code and your prose.
NOTE LP prose isn't comments
00:14:23.166 --> 00:14:25.586
The prose of your literate program isn't
00:14:25.587 --> 00:14:28.667
just regurgitation of the code in the block.
00:14:28.668 --> 00:14:31.527
You want something more helpful.
00:14:31.528 --> 00:14:35.736
You're really writing a research paper to yourself.
00:14:35.737 --> 00:14:38.577
I know what you're thinking. You've seen my Git repos.
00:14:38.578 --> 00:14:41.858
I'm guilty and not always the best example.
00:14:41.859 --> 00:14:44.559
However, I do get great joy
00:14:44.560 --> 00:14:48.680
when I see someone ask about something in Emacs
00:14:48.681 --> 00:14:51.041
and my response is little more than a link
00:14:51.042 --> 00:14:55.799
to my online repo that I've rendered as a website.
NOTE Summary
00:14:55.800 --> 00:15:01.199
I'm out of time. I hope this has been interesting
00:15:01.200 --> 00:15:04.359
philosophically as well as practically, as I think
00:15:04.360 --> 00:15:08.559
literate programming is the cat's meow. I'm afraid this
00:15:08.560 --> 00:15:11.879
summary slide is about my home-baked solutions that fit my
00:15:11.880 --> 00:15:15.119
needs, but hopefully you can recognize your pain points and
00:15:15.120 --> 00:15:17.839
address them. If you don't need my Literate
00:15:17.840 --> 00:15:21.479
DevOps-specific techniques for connecting code blocks, I
00:15:21.480 --> 00:15:25.799
suggest using sessions by default. I highly recommend
00:15:25.800 --> 00:15:28.399
looking at your workflow and writing snippets to give you
00:15:28.400 --> 00:15:33.159
less typing for Org blocks. I now jump by headlines in my
00:15:33.160 --> 00:15:37.479
projects, but extending xref to support Org files made
00:15:37.480 --> 00:15:40.159
literate programming as easy as programming the
00:15:40.160 --> 00:15:44.319
old-fashioned way. I do need to make it more general to put up
00:15:44.320 --> 00:15:47.722
on MELPA, though. Thanks for watching.
00:15:47.723 --> 00:15:51.240
Happy hacking, my friends.
|