WEBVTT captioned by jc, checked by sachac NOTE Introduction 00:00:00.000 --> 00:00:04.320 Hello, everyone. 00:00:04.320 --> 00:00:07.280 This talk is on literate documentation 00:00:07.280 --> 00:00:10.320 with Emacs and org-mode. 00:00:10.320 --> 00:00:12.080 I'm going to take just a moment here 00:00:12.080 --> 00:00:14.279 to unpack what I just said. 00:00:14.280 --> 00:00:17.800 Emacs, as most of us probably already know, 00:00:17.800 --> 00:00:21.360 is a powerful text editor and list programming environment 00:00:21.360 --> 00:00:23.480 from the 1970s. 00:00:23.480 --> 00:00:25.800 Chances are, if you're attending this talk, 00:00:25.800 --> 00:00:28.819 you already know a bit about Emacs. 00:00:28.820 --> 00:00:32.640 org-mode is an Emacs major mode and authoring tool 00:00:32.640 --> 00:00:36.360 that helps you write documents in a plain text markup 00:00:36.360 --> 00:00:37.739 language called Org. 00:00:37.740 --> 00:00:40.200 These Org documents can be exported 00:00:40.200 --> 00:00:42.520 to a number of different document formats, 00:00:42.520 --> 00:00:48.520 like HTML, PDF, ODT, Markdown, and more. 00:00:48.520 --> 00:00:51.160 org-mode has a lot of features. 00:00:51.160 --> 00:00:54.240 It can be an outliner, a to-do list manager, 00:00:54.240 --> 00:00:57.760 an agenda, organizer, and much more. NOTE Org Babel and literate programming 00:00:57.760 --> 00:00:59.600 Today, we're going to be demonstrating 00:00:59.600 --> 00:01:03.360 what I consider to be org-mode's killer feature called 00:01:03.360 --> 00:01:04.840 Org Babel. 00:01:04.840 --> 00:01:07.879 Babel allows you to take human language prose, 00:01:07.880 --> 00:01:11.400 computer language source code blocks, and their outputs 00:01:11.400 --> 00:01:13.840 and weave them together seamlessly 00:01:13.840 --> 00:01:16.160 to form a cohesive document. 00:01:16.160 --> 00:01:19.080 It is seriously cool. 00:01:19.080 --> 00:01:21.880 Literate documentation is a play on the term 00:01:21.880 --> 00:01:25.280 literate programming, popularized by Donald Knuth 00:01:25.280 --> 00:01:27.379 in the early 1980s. 00:01:27.380 --> 00:01:29.280 Knuth's literate programming idea 00:01:29.280 --> 00:01:31.920 was that computer programs could be 00:01:31.920 --> 00:01:34.880 expressed in a natural language and be 00:01:34.880 --> 00:01:38.800 human-readable documents rather than written exclusively 00:01:38.800 --> 00:01:40.799 for machines to read. 00:01:40.800 --> 00:01:43.000 In a traditional program, you might 00:01:43.000 --> 00:01:45.680 have a bunch of machine-readable source code 00:01:45.680 --> 00:01:48.560 and a handful of human-readable comments, 00:01:48.560 --> 00:01:51.600 which attempt to describe what the program is doing. 00:01:51.600 --> 00:01:54.360 Literate programming flips this on its head. 00:01:54.360 --> 00:01:56.680 A literate program is a document that 00:01:56.680 --> 00:02:01.160 describes how the program works with machine-readable source 00:02:01.160 --> 00:02:02.880 code blocks inside of it. 00:02:02.880 --> 00:02:04.800 These source code blocks are later 00:02:04.800 --> 00:02:08.440 tangled out of the document and submitted to the machine 00:02:08.440 --> 00:02:14.080 either to be compiled or interpreted and ultimately run. NOTE This presentation 00:02:14.080 --> 00:02:15.600 Throughout this presentation, you'll 00:02:15.600 --> 00:02:19.400 see my browser window here on the left side of the screen. 00:02:19.400 --> 00:02:22.240 And on the right side, I've got a terminal session 00:02:22.240 --> 00:02:23.960 running tmux. 00:02:23.960 --> 00:02:28.039 This allows us to have a virtual terminal window connected 00:02:28.040 --> 00:02:35.040 to two separate Linux machines, one running Ubuntu Server 2204 00:02:35.040 --> 00:02:39.720 and another running Fedora Server 38. 00:02:39.720 --> 00:02:43.240 I've specifically chosen these two distributions for my demo 00:02:43.440 --> 00:02:46.720 because they are representative of the two dominant flavors 00:02:46.720 --> 00:02:49.880 of GNU Linux, Debian and RedHat. 00:02:49.880 --> 00:02:53.120 In both cases, these are bare-bones server additions 00:02:53.120 --> 00:02:55.440 with the stock packages installed. 00:02:55.440 --> 00:03:00.200 I've manually installed a few packages like Git, emacs-noex 00:03:00.200 --> 00:03:04.000 to get the terminal version of emacs, and tmux. 00:03:04.000 --> 00:03:06.000 But otherwise, these Linux installs 00:03:06.000 --> 00:03:08.719 are what you'd get right out of the box. 00:03:08.720 --> 00:03:12.480 For this demo, I've created a literate org-mode document 00:03:12.480 --> 00:03:16.360 that describes how to build GNU Emacs from its source code 00:03:16.360 --> 00:03:19.939 on both Debian and RedHat-based systems. 00:03:19.940 --> 00:03:22.920 While both operating systems are very similar, 00:03:22.920 --> 00:03:25.440 they differ substantially on which packages 00:03:25.440 --> 00:03:29.080 are installed out of the box, how optional packages are 00:03:29.080 --> 00:03:32.600 named, searched, and installed, and of course, 00:03:32.600 --> 00:03:34.240 the distributions have different names, 00:03:34.240 --> 00:03:36.800 like Ubuntu or Fedora. 00:03:36.800 --> 00:03:39.200 I chose building Emacs from source 00:03:39.200 --> 00:03:41.640 as a topic for this demonstration 00:03:41.640 --> 00:03:43.800 because while the process is largely 00:03:43.800 --> 00:03:46.880 the same on both RedHat and Debian, 00:03:46.880 --> 00:03:49.360 there are a lot of minor little differences 00:03:49.360 --> 00:03:52.680 that need to be accounted for, which really prohibits you 00:03:52.680 --> 00:03:57.120 from hard coding names of packages and package management 00:03:57.120 --> 00:04:01.200 tools and distributions into your document. 00:04:01.200 --> 00:04:05.320 I suppose you could create two versions of the same document, 00:04:05.320 --> 00:04:09.960 one specifically for RedHat and one specifically for Debian, 00:04:09.960 --> 00:04:13.280 but that would be really tedious to maintain. 00:04:13.280 --> 00:04:16.280 Like if, for example, you updated some prose 00:04:16.280 --> 00:04:18.720 in one document, you'd have to remember 00:04:18.720 --> 00:04:20.280 to do it in the other one too. 00:04:20.280 --> 00:04:22.920 And if you weren't careful, the two documents 00:04:22.920 --> 00:04:25.259 could drift out of sync. 00:04:25.260 --> 00:04:27.720 In this demo, I'll show you techniques 00:04:27.720 --> 00:04:30.960 for creating dynamic, literate documents that 00:04:30.960 --> 00:04:34.619 can change based on parameters and constants embedded 00:04:34.620 --> 00:04:38.439 into the non-exported regions of the document. 00:04:38.440 --> 00:04:41.800 I'll show how with a single org-mode source document, 00:04:41.800 --> 00:04:44.800 you can press a couple of keys to configure 00:04:44.800 --> 00:04:48.720 it to export a RedHat-specific version of my building 00:04:48.720 --> 00:04:53.479 Emacs from source essay or a Debian-specific version. NOTE Getting started 00:04:53.480 --> 00:04:55.320 All right, let's get started. 00:04:55.320 --> 00:04:58.720 We'll begin by firing up a new terminal Emacs session 00:04:58.720 --> 00:05:00.639 on my Ubuntu machine. 00:05:00.640 --> 00:05:04.600 Now, I installed Emacs on this machine using apt-get. 00:05:04.600 --> 00:05:07.960 And doing that, you get version 27.1, 00:05:07.960 --> 00:05:10.640 which is, hey, only two major versions 00:05:10.640 --> 00:05:13.010 behind the current version of Emacs. 00:05:13.011 --> 00:05:15.000 This is another reason why I thought 00:05:15.000 --> 00:05:18.080 writing a guide on how to build Emacs from source code 00:05:18.080 --> 00:05:19.719 might be a good idea. 00:05:19.720 --> 00:05:22.720 You can get a much newer version of Emacs on Ubuntu 00:05:22.720 --> 00:05:25.800 if you install it via Snap, but, uh, Snaps. 00:05:25.800 --> 00:05:28.239 Don't get me started. 00:05:28.240 --> 00:05:30.921 Now, I wanted to use a completely vanilla 00:05:30.922 --> 00:05:34.619 terminal mode install of Emacs for this demonstration 00:05:34.620 --> 00:05:38.040 because my personal Emacs config has a ton of packages 00:05:38.040 --> 00:05:41.199 installed and is heavily modified. 00:05:41.200 --> 00:05:43.640 I want folks to be able to follow along 00:05:43.640 --> 00:05:47.579 with a bog-standard, out-of-the-box Emacs config. 00:05:47.580 --> 00:05:49.520 The Emacs config on this Ubuntu machine 00:05:49.520 --> 00:05:51.200 has just two settings. 00:05:51.200 --> 00:05:55.240 I require org-tempo because my fingers are hardwired 00:05:55.240 --> 00:05:58.719 to use some of the handy shortcuts that it provides. 00:05:58.720 --> 00:06:00.520 And I also turn off the menu bar 00:06:00.520 --> 00:06:03.139 because I just can't stand to look at it. 00:06:03.140 --> 00:06:07.040 Let's begin by opening a file called buildemacs.org, 00:06:07.040 --> 00:06:08.480 which will be the source code 00:06:08.480 --> 00:06:11.079 for our literate org-mode document. 00:06:11.080 --> 00:06:12.840 Now, in preparation for this talk, 00:06:12.840 --> 00:06:14.960 I've already written this document, 00:06:14.960 --> 00:06:17.979 and we'll take a look at the finished product 00:06:17.980 --> 00:06:19.160 here in a bit, but let's first take a look 00:06:19.160 --> 00:06:22.408 at how we might approach this task. 00:06:22.409 --> 00:06:24.400 We'll start at the top of the document 00:06:24.400 --> 00:06:27.119 by filling out some export keywords. 00:06:27.120 --> 00:06:30.520 These keywords are something that every backend exporter, 00:06:30.520 --> 00:06:35.000 be it LaTeX or plain text or ODT or whatever, understands, 00:06:35.000 --> 00:06:38.120 and they're essentially document metadata. 00:06:38.120 --> 00:06:42.120 As you can see, I'm typing `#+` 00:06:42.120 --> 00:06:43.760 followed by a couple characters 00:06:43.760 --> 00:06:45.880 and then `M-TAB` to auto-complete. 00:06:45.880 --> 00:06:50.360 If you hit #+ by itself and then M-TAB, 00:06:50.360 --> 00:06:53.119 you can see all the possible completions. 00:06:53.120 --> 00:06:55.779 And as you can see, there's a lot. NOTE README 00:06:55.780 --> 00:06:58.520 The next thing we're gonna do is make a README section 00:06:58.520 --> 00:06:59.760 at the top of this document. 00:06:59.760 --> 00:07:02.240 This section is intended for folks 00:07:02.240 --> 00:07:04.280 who are looking at the org-mode document, 00:07:04.280 --> 00:07:06.679 trying to figure out what it's for. 00:07:06.680 --> 00:07:09.600 We don't want to actually export the section heading, 00:07:09.600 --> 00:07:13.859 so we're gonna tag it with the :noexport: tag. 00:07:13.860 --> 00:07:15.640 And then here, we just write something quick 00:07:15.640 --> 00:07:17.760 to let folks know that this document 00:07:17.760 --> 00:07:19.800 can potentially execute code 00:07:19.800 --> 00:07:23.499 and just a little something about what the document is for. NOTE Writing a code block 00:07:23.500 --> 00:07:26.059 Okay, so now that we've written some text, 00:07:26.060 --> 00:07:29.599 let's try our hand at writing a code block. 00:07:29.600 --> 00:07:31.288 I'm getting pretty sick of looking at 00:07:31.289 --> 00:07:32.939 the default Emacs theme. 00:07:32.940 --> 00:07:35.440 All that blue and purple in the document 00:07:35.440 --> 00:07:37.879 makes it look bruised. 00:07:37.880 --> 00:07:40.320 Let's make an Emacs Lisp code block 00:07:40.320 --> 00:07:41.400 that switches the theme 00:07:41.400 --> 00:07:44.560 to one of my favorite built-in themes, Leuven. 00:07:44.560 --> 00:07:48.400 Leuven was created by my man, Fabrice Niessen, 00:07:48.400 --> 00:07:52.120 who I personally have learned a ton of org-mode stuff about 00:07:52.120 --> 00:07:54.039 just by studying his work. 00:07:54.040 --> 00:07:56.360 Now, if we cruise back up to the code block, 00:07:56.360 --> 00:07:58.840 we should be able to hit `C-c C-c`, 00:07:58.840 --> 00:08:00.379 and have it execute. 00:08:00.380 --> 00:08:03.880 And there you have it, a high-contrast color theme 00:08:03.880 --> 00:08:06.979 that was designed to look great in org-mode. 00:08:06.980 --> 00:08:08.080 So that's great and all, 00:08:08.080 --> 00:08:10.459 but there are a couple of things I don't like. NOTE :results none 00:08:10.460 --> 00:08:13.599 First of all, we don't need to see a #+RESULTS block here, 00:08:13.600 --> 00:08:15.280 and that's because we're not really interested 00:08:15.280 --> 00:08:18.720 in what the Emacs Lisp function `load-theme` returns. 00:08:18.720 --> 00:08:22.200 I mean, it's great it returned t and all to indicate success, 00:08:22.200 --> 00:08:23.720 we just don't need to see it. 00:08:23.720 --> 00:08:26.560 We can slap a `:results none` header arg 00:08:26.560 --> 00:08:30.039 on the code block to keep things nice and clean. 00:08:30.040 --> 00:08:32.560 There are a lot of different header args, 00:08:32.560 --> 00:08:35.360 and I often confuse and misremember them. 00:08:35.360 --> 00:08:38.920 So I'll always refer back to the org-mode manual 00:08:38.920 --> 00:08:40.319 when working with them. NOTE Confirmation 00:08:40.320 --> 00:08:42.160 The second thing I don't like is that 00:08:42.160 --> 00:08:45.999 when we hit C-c C-c to execute the block, 00:08:46.000 --> 00:08:49.600 Emacs prompted us if we really wanted to run the block. 00:08:49.600 --> 00:08:52.040 Emacs Lisp is Emacs' mother tongue, 00:08:52.040 --> 00:08:53.920 and I don't wanna be hassled when speaking 00:08:53.920 --> 00:08:55.379 my native language. 00:08:55.380 --> 00:08:57.520 There's a variable that controls this 00:08:57.520 --> 00:09:00.680 called `org-confirm-babel-evaluate`. 00:09:00.680 --> 00:09:03.960 And this can be either set to t or nil 00:09:03.960 --> 00:09:06.840 to either always confirm or never confirm. 00:09:06.840 --> 00:09:10.920 If however, you provided a lambda, an anonymous function, 00:09:10.920 --> 00:09:14.560 Org will call your function with the name of the language 00:09:14.560 --> 00:09:16.840 and the source block that it's about to run. 00:09:16.840 --> 00:09:19.080 And your function can make the decision 00:09:19.080 --> 00:09:24.200 about if Emacs should ask you for confirmation or not. 00:09:24.200 --> 00:09:27.840 What I'm doing here is setting `org-confirm-babel-evaluate` 00:09:27.840 --> 00:09:30.539 as a "file local variable". 00:09:30.540 --> 00:09:33.320 This means whenever the file is opened by Emacs, 00:09:33.320 --> 00:09:38.059 it'll set this variable to be a lambda that returns nil, 00:09:38.060 --> 00:09:42.859 meaning don't confirm, on Elisp code blocks. 00:09:42.860 --> 00:09:45.920 As you can see, the variable is currently set 00:09:45.920 --> 00:09:50.879 to its default value of t, meaning always confirm. 00:09:50.880 --> 00:09:53.640 Now if we save the buffer, exit Emacs, 00:09:53.640 --> 00:09:55.040 and pop back in again, 00:09:55.040 --> 00:10:00.120 `org-confirm-babel-evaluate` should be set how we like it. 00:10:00.120 --> 00:10:02.640 We were however prompted for confirmation 00:10:02.640 --> 00:10:04.400 on setting the file-local variable, 00:10:04.400 --> 00:10:06.280 which controls if we're prompted 00:10:06.280 --> 00:10:09.699 for Elisp source code block evaluation. 00:10:09.700 --> 00:10:12.679 I feel like there's a Yo Dawg joke here somewhere. 00:10:12.680 --> 00:10:15.240 When we were prompted, we hit the exclamation mark, 00:10:15.240 --> 00:10:18.400 which automatically marks this variable as being safe. 00:10:18.400 --> 00:10:21.520 So you won't be bothered the next time you open this file. 00:10:21.520 --> 00:10:26.760 This variable is called `safe-local-variable-values` 00:10:26.760 --> 00:10:29.560 and if we pop over to our .emacs file, 00:10:29.560 --> 00:10:32.520 you can see that Emacs' customize tooling 00:10:32.520 --> 00:10:36.959 helpfully updated this variable in our config file for us. NOTE Running blocks automatically 00:10:36.960 --> 00:10:38.120 Now that's great and all, 00:10:38.120 --> 00:10:42.120 but I really don't like having to hit `C-c C-c` 00:10:42.120 --> 00:10:45.160 on that source block every time I open this document 00:10:45.160 --> 00:10:47.739 just to bring up the Leuven theme. 00:10:47.740 --> 00:10:50.520 Let's have this source block run automatically 00:10:50.520 --> 00:10:53.179 every time the document is opened. 00:10:53.180 --> 00:10:54.999 Now I know what you're thinking. 00:10:55.000 --> 00:10:57.640 Shouldn't you just put all of this configuration stuff 00:10:57.640 --> 00:11:01.159 in your .emacs file and keep it out of the document? 00:11:01.160 --> 00:11:04.760 Well, that's what I've done with my personal Emacs config, 00:11:04.760 --> 00:11:08.160 but we want this document to be able to be used by folks 00:11:08.160 --> 00:11:11.040 with a completely vanilla Emacs setup, 00:11:11.040 --> 00:11:13.440 or even a completely tricked out Emacs setup, 00:11:13.440 --> 00:11:16.059 so we can't assume anything. 00:11:16.060 --> 00:11:19.800 The idea is if the Emacs user who opens the document 00:11:19.800 --> 00:11:22.400 agrees to setting all of the variables 00:11:22.400 --> 00:11:24.359 and running all of the code within, 00:11:24.360 --> 00:11:26.560 they'll be able to export the document 00:11:26.560 --> 00:11:28.840 as well as run all of the code blocks inside of it 00:11:28.840 --> 00:11:30.799 just as we intended. 00:11:30.800 --> 00:11:33.880 And the differences in base Emacs configuration 00:11:33.880 --> 00:11:35.979 will be completely minimized. 00:11:35.980 --> 00:11:39.080 Now it's worth pointing out that the file-local variables 00:11:39.080 --> 00:11:43.023 we're setting here are local, in this case, buffer-local. 00:11:43.024 --> 00:11:45.280 The configuration we use in this document 00:11:45.280 --> 00:11:48.280 won't override someone's carefully constructed 00:11:48.280 --> 00:11:49.499 org-mode setup. 00:11:49.500 --> 00:11:50.800 The first thing we're gonna wanna do 00:11:51.000 --> 00:11:53.080 in order to make this block execute 00:11:53.080 --> 00:11:55.988 when the document is loaded is to give it a name. 00:11:55.989 --> 00:11:58.800 It's always a good idea to give every source block 00:11:58.800 --> 00:12:01.337 you create in your document a unique name, 00:12:01.338 --> 00:12:03.400 even if you don't refer to it elsewhere. 00:12:03.700 --> 00:12:06.960 I do this because when I'm debugging my documents, 00:12:07.160 --> 00:12:10.019 Emacs will prompt me about running a block. 00:12:10.020 --> 00:12:12.960 If the block has a name, Emacs mentions it, 00:12:12.960 --> 00:12:15.960 and I know there's a problem with the result caching 00:12:15.960 --> 00:12:17.840 or something with the "foo" block. 00:12:17.840 --> 00:12:20.280 But if the block doesn't have a name, 00:12:20.280 --> 00:12:22.160 it can be really hard to figure out 00:12:22.160 --> 00:12:24.579 which block Emacs is complaining about. 00:12:24.580 --> 00:12:27.459 So I always name my blocks. 00:12:27.460 --> 00:12:30.360 Now we're gonna add another file local variable, 00:12:30.360 --> 00:12:32.115 but this one is special. 00:12:32.116 --> 00:12:34.360 If your "variable" 00:12:34.360 --> 00:12:36.320 just happens to be named "eval", 00:12:36.320 --> 00:12:38.760 it means that Emacs should evaluate 00:12:38.760 --> 00:12:40.800 the Lisp expression that follows. 00:12:40.800 --> 00:12:43.240 Here we'll use the progn function 00:12:43.240 --> 00:12:46.040 to sequentially run two elisp functions 00:12:46.040 --> 00:12:48.760 and return the value of the last one executed. 00:12:48.760 --> 00:12:53.320 The first function is `org-babel-goto-named-source-block`, 00:12:53.320 --> 00:12:55.440 which jumps us to the startup block. 00:12:55.440 --> 00:12:59.280 The second one is `org-babel-execute-src-block`, 00:12:59.280 --> 00:13:02.092 which executes the current source block. 00:13:02.093 --> 00:13:03.630 That should get the job done. 00:13:03.631 --> 00:13:05.840 Now all we have to do is save the document, 00:13:05.840 --> 00:13:08.199 exit Emacs, jump back in, 00:13:08.200 --> 00:13:10.280 and once we've confirmed that we're willing 00:13:10.280 --> 00:13:14.239 to run the new "eval" line in our file local variables, 00:13:14.240 --> 00:13:15.859 we're good to go. 00:13:15.860 --> 00:13:18.480 Now if we want to add new configuration stuff 00:13:18.480 --> 00:13:21.839 to the document, we can just add it to the startup block 00:13:21.840 --> 00:13:24.880 and not have to muck about with confirmations 00:13:24.880 --> 00:13:28.679 or adding new file-local variables or whatever. 00:13:28.680 --> 00:13:31.960 And just like before, we'll let Emacs' customize system 00:13:31.960 --> 00:13:34.939 save this decision to our .emacs file. 00:13:34.940 --> 00:13:37.760 Now that all that business with confirmations, 00:13:37.760 --> 00:13:40.080 file-local variables, and the startup block 00:13:40.080 --> 00:13:41.120 are out of the way, 00:13:41.120 --> 00:13:44.120 we can get on with writing our introduction. 00:13:44.120 --> 00:13:47.880 We'll create a new top level headline called introduction 00:13:47.880 --> 00:13:51.440 and explain to the reader of the exported document 00:13:51.440 --> 00:13:52.600 what this is all about. NOTE Export options 00:13:53.000 --> 00:13:55.640 Now as you can see, we've actually hard-coded 00:13:55.640 --> 00:13:58.280 the name of the Linux distro in our prose. 00:13:58.280 --> 00:14:00.880 I promised you a single document that could be 00:14:00.880 --> 00:14:03.720 for either RedHat or Debian distros, 00:14:03.720 --> 00:14:05.319 so we can't have this. 00:14:05.320 --> 00:14:08.840 Astute members in the audience have probably been uneasy 00:14:08.840 --> 00:14:11.280 ever since I hard coded the name "Debian" 00:14:11.280 --> 00:14:13.859 in the README section above. 00:14:13.860 --> 00:14:17.520 One way of solving this problem is by using exclude tags. 00:14:17.520 --> 00:14:21.960 Let's add the `#+EXCLUDE_TAGS` export keyword to our document. 00:14:21.960 --> 00:14:24.200 This keyword tells the exporter, 00:14:24.200 --> 00:14:27.959 "Hey, if you see a headline tagged with any of these tags, 00:14:27.960 --> 00:14:29.600 don't export it." 00:14:29.600 --> 00:14:33.559 By default, the tag `:noexport:` is excluded. 00:14:33.560 --> 00:14:36.480 And if you'll notice, we tagged our README section 00:14:36.480 --> 00:14:38.360 with that tag, so it doesn't show up 00:14:38.360 --> 00:14:40.339 in the exported document. 00:14:40.340 --> 00:14:42.280 We'll keep this tag in the list, 00:14:42.280 --> 00:14:47.080 but we'll also add the tag `:redhat:` as a tag to exclude. 00:14:47.080 --> 00:14:50.400 Now it's just a matter of creating two introduction 00:14:50.400 --> 00:14:53.960 sections, one for Debian, one for RedHat. 00:14:53.960 --> 00:14:56.520 And if you want the RedHat version of the document, 00:14:56.520 --> 00:14:59.200 you can just modify the `#+EXCLUDE_TAGS` line 00:14:59.200 --> 00:15:00.440 at the top of the document. 00:15:00.440 --> 00:15:02.339 Awesome, right? 00:15:02.340 --> 00:15:03.539 Right? 00:15:03.540 --> 00:15:05.544 OK, this is not that great. 00:15:05.545 --> 00:15:07.387 Well, it does work. 00:15:07.388 --> 00:15:10.081 And you can see if we export the document, 00:15:10.082 --> 00:15:12.840 we'll get something that only references Debian, 00:15:12.840 --> 00:15:15.188 and the `:noexport:` and `:redhat:` 00:15:15.189 --> 00:15:17.450 tagged headlines are omitted. 00:15:17.451 --> 00:15:19.319 This strategy would work great 00:15:19.320 --> 00:15:22.120 when the RedHat- and Debian-specific sections 00:15:22.120 --> 00:15:24.400 are substantially different, but that's not 00:15:24.400 --> 00:15:26.198 the case with the introduction. 00:15:26.199 --> 00:15:28.640 We definitely don't want to have to maintain 00:15:28.640 --> 00:15:30.824 two distinct introductions. 00:15:30.825 --> 00:15:34.080 I also noticed that the export tags are included 00:15:34.080 --> 00:15:36.519 in the exported document. 00:15:36.520 --> 00:15:38.720 That's a terrible default. We'll fix that, 00:15:38.720 --> 00:15:42.040 and we'll also ensure that my email address appears 00:15:42.040 --> 00:15:43.371 at the top of the document. 00:15:43.372 --> 00:15:45.440 Let's also take this opportunity to get rid 00:15:45.440 --> 00:15:47.354 of the table of contents. 00:15:47.355 --> 00:15:48.867 We don't need it. 00:15:48.868 --> 00:15:51.120 These are all export option settings 00:15:51.120 --> 00:15:53.800 and can be modified using the options keyword 00:15:53.800 --> 00:15:55.508 at the top of the doc. 00:15:55.509 --> 00:15:57.480 The manual is really your friend here, 00:15:57.480 --> 00:16:00.979 as there are a ton of export options. 00:16:00.980 --> 00:16:03.120 Now when we export the document again, 00:16:03.120 --> 00:16:05.699 it should look a lot better. NOTE Substituting constants 00:16:05.700 --> 00:16:09.059 Now that we've cleaned up the look of the exported document, 00:16:09.060 --> 00:16:10.640 we'll take a look at a better way 00:16:10.640 --> 00:16:13.377 of solving the problem with the introduction. 00:16:13.378 --> 00:16:15.518 Thinking like a programmer for a moment, 00:16:15.519 --> 00:16:19.734 what I really want here is a way of specifying a constant. 00:16:19.735 --> 00:16:22.640 Rather than hard-coding the name "Debian" or "RedHat" 00:16:22.640 --> 00:16:24.569 or whatever into my document, 00:16:24.570 --> 00:16:28.234 I want to substitute that text with a symbolic constant, 00:16:28.235 --> 00:16:31.960 named something like "distro", that can dynamically change 00:16:31.960 --> 00:16:36.120 to "Debian" or "RedHat" or "Slackware" or whatever, 00:16:36.120 --> 00:16:38.689 depending on how the document is configured. 00:16:38.690 --> 00:16:41.640 In the past, I've come up with some pretty cumbersome ways 00:16:41.640 --> 00:16:44.640 of doing this, but eventually I stumbled upon the idea 00:16:44.640 --> 00:16:46.639 of using Org-mode properties 00:16:46.640 --> 00:16:49.409 as a way of storing these constants. 00:16:49.410 --> 00:16:53.059 Like it says in the docs, properties are key-value pairs 00:16:53.060 --> 00:16:55.169 that are associated with an entry 00:16:55.170 --> 00:16:58.379 and they live in a collapsible properties drawer. 00:16:58.380 --> 00:17:00.699 Let's do a bit of cleanup on our document 00:17:00.700 --> 00:17:02.600 and we'll put things into sections. 00:17:02.600 --> 00:17:14.000 We'll also add a section for document constants. 00:17:14.000 --> 00:17:19.560 And that's where we'll put the properties drawer 00:17:19.560 --> 00:17:25.739 with the "distro" property. NOTE Getting the properties 00:17:25.740 --> 00:17:27.120 Now the question is, 00:17:27.120 --> 00:17:30.099 how do we reference these properties in the document? 00:17:30.100 --> 00:17:32.520 It turns out there's an Elisp function 00:17:32.520 --> 00:17:35.440 called `org-property-values`, which does what we want. 00:17:35.440 --> 00:17:38.840 If we run it and give it the name of our property, 00:17:38.840 --> 00:17:42.679 it returns a list with the string "Debian" in it. 00:17:42.680 --> 00:17:45.919 It's worth noting that this function is named 00:17:45.920 --> 00:17:49.989 `org-property-values` with values being plural. 00:17:49.990 --> 00:17:52.889 In org-mode, there could be a property named "foo" 00:17:52.890 --> 00:17:55.880 that has different values depending on which heading level 00:17:55.880 --> 00:17:57.609 you're at in the document, 00:17:57.610 --> 00:17:59.720 which is why the function returns a list. 00:17:59.720 --> 00:18:01.289 For our purposes though, 00:18:01.290 --> 00:18:04.480 we can just pull off the first value in the list with car 00:18:04.480 --> 00:18:05.680 and we're good to go. 00:18:05.680 --> 00:18:10.040 Now we'll make an Emacs Lisp list function called `get_prop` 00:18:10.040 --> 00:18:11.440 that does just that. 00:18:11.440 --> 00:18:14.160 This function takes one argument called `prop`, 00:18:14.160 --> 00:18:15.920 which is the property to look up 00:18:15.920 --> 00:18:18.519 and we'll give it a default value of "distro". 00:18:18.520 --> 00:18:20.960 So we can hit `C-c C-c` on the block 00:18:20.960 --> 00:18:23.149 to verify that it works. 00:18:23.150 --> 00:18:25.480 Now we just have to make an inline call 00:18:25.480 --> 00:18:26.920 to our `get_prop` function 00:18:26.920 --> 00:18:29.559 within the prose of the introduction section. 00:18:29.560 --> 00:18:31.659 And that should get us much closer 00:18:31.660 --> 00:18:35.619 to not hard coding distro names into our document. 00:18:35.620 --> 00:18:36.869 But before we do that, 00:18:36.870 --> 00:18:39.849 I need to clean up something that's been bothering me. 00:18:39.850 --> 00:18:42.909 By default, Emacs' `fill-column` variable 00:18:42.910 --> 00:18:44.989 is set to 70 characters, 00:18:44.990 --> 00:18:47.720 which may have been appropriate for 1970, 00:18:47.720 --> 00:18:51.319 but it's not great for 2023. 00:18:51.320 --> 00:18:53.920 We'll just cruise up to our startup block 00:18:53.920 --> 00:18:56.539 and set the variable there. 00:18:56.540 --> 00:18:58.800 We'll hit `C-c C-c`, 00:18:58.800 --> 00:19:02.289 and now our document will wrap at 100 columns, 00:19:02.290 --> 00:19:05.829 which for our purposes, I think is much more reasonable. 00:19:05.830 --> 00:19:09.320 The org-mode syntax for making an inline function call 00:19:09.320 --> 00:19:13.059 within the prose of your document is `call_`, 00:19:13.060 --> 00:19:15.000 followed by the name of the function, 00:19:15.000 --> 00:19:17.040 some optional header arguments, 00:19:17.040 --> 00:19:19.719 and then the function arguments. 00:19:19.720 --> 00:19:21.680 Now, when we export the document, 00:19:21.680 --> 00:19:26.049 we see that it's replaced our previously hard coded "Debian" 00:19:26.050 --> 00:19:29.409 with the value from the property. Huzzah! 00:19:29.410 --> 00:19:32.959 Now this is close to, but not exactly what we want. 00:19:32.960 --> 00:19:36.720 You can see that "Debian" is surrounded by a backtick 00:19:36.720 --> 00:19:37.800 and a single quote, 00:19:37.800 --> 00:19:40.320 which is the plain text exporters way 00:19:40.320 --> 00:19:43.029 of showing you verbatim text. 00:19:43.030 --> 00:19:45.600 In more sophisticated document backends, 00:19:45.600 --> 00:19:49.379 verbatim text is rendered in monospace. 00:19:49.380 --> 00:19:54.080 We can fix that by adding a ":results raw" header argument 00:19:54.080 --> 00:19:56.459 to the inline call. 00:19:56.460 --> 00:19:58.239 Now, when we export the document, 00:19:58.240 --> 00:20:00.289 it looks like what we'd expect. 00:20:00.290 --> 00:20:02.960 Now this is getting better, but it's still not great. NOTE Macros 00:20:03.060 --> 00:20:05.840 The `call_` syntax is pretty cumbersome, 00:20:05.840 --> 00:20:08.560 and it's a lot to type every time we want 00:20:08.560 --> 00:20:09.849 to reference a constant 00:20:09.850 --> 00:20:13.219 and not have it be marked up as verbatim. 00:20:13.220 --> 00:20:17.169 This is where org-mode macros come to our rescue. 00:20:17.170 --> 00:20:19.469 If we head to the top of the document, 00:20:19.470 --> 00:20:21.480 we can create a couple of macros 00:20:21.480 --> 00:20:24.699 using the `#+MACRO:` export keyword. 00:20:24.700 --> 00:20:27.600 We'll define two macros with short names. 00:20:27.600 --> 00:20:30.240 One named "p" for "property", 00:20:30.240 --> 00:20:34.640 and the other one named "pr" for "property raw". 00:20:34.640 --> 00:20:39.160 Org-mode macros are expanded when the document is exported, 00:20:39.160 --> 00:20:41.640 and any positional arguments provided 00:20:41.640 --> 00:20:43.559 are referenced by their number. 00:20:43.860 --> 00:20:45.160 Now in the introduction, 00:20:45.160 --> 00:20:47.880 we can use the macro replacement syntax, 00:20:47.880 --> 00:20:49.800 which is three curly braces, 00:20:49.800 --> 00:20:52.760 followed by the macro name and any arguments, 00:20:52.760 --> 00:20:55.559 and then three ending curly braces. 00:20:55.560 --> 00:20:58.699 You see why I kept the macro name short. 00:20:58.700 --> 00:21:01.280 That's six curly braces in total we're typing, 00:21:01.280 --> 00:21:05.239 which still takes up a fair amount of space. NOTE Properties in practice 00:21:05.240 --> 00:21:07.120 Now let's take a look at how we might use 00:21:07.120 --> 00:21:09.159 these properties in practice. 00:21:09.160 --> 00:21:10.920 Debian and RedHat distros differ 00:21:11.120 --> 00:21:12.929 on how they install packages. 00:21:12.930 --> 00:21:16.120 So we're gonna want an "install" property, 00:21:16.120 --> 00:21:24.579 where in Debian we use `sudo apt-get install -qq`, 00:21:24.580 --> 00:21:26.939 and on RedHat we'll use something like 00:21:26.940 --> 00:21:33.119 `sudo dnf install -y`. 00:21:33.120 --> 00:21:35.329 Now development packages 00:21:35.330 --> 00:21:38.049 also have a different naming convention. 00:21:38.050 --> 00:21:40.760 For example, the `ncurses` library on Debian 00:21:40.760 --> 00:21:43.520 is called `libncurses-dev`, 00:21:43.520 --> 00:21:48.259 where on RedHat it's called `ncurses-devel`. 00:21:48.260 --> 00:21:49.640 There are likely going to be 00:21:49.640 --> 00:21:52.120 many more little differences like this 00:21:52.120 --> 00:21:55.339 that we'll need to solve with properties. 00:21:55.340 --> 00:21:58.609 Now I already don't like where this is going. 00:21:58.610 --> 00:22:00.880 Switching between the Debian and RedHat 00:22:00.880 --> 00:22:03.160 versions of the document is gonna mean 00:22:03.160 --> 00:22:05.200 commenting and uncommenting out 00:22:05.200 --> 00:22:06.989 a bunch of different properties, 00:22:06.990 --> 00:22:09.019 which is pretty janky. NOTE Using a prefix 00:22:09.020 --> 00:22:11.079 Luckily we can solve this problem 00:22:11.080 --> 00:22:14.439 with a little bit of Emacs Lisp. 00:22:14.440 --> 00:22:16.879 We'll start by modifying our properties, 00:22:16.880 --> 00:22:19.140 so their property names are prefixed 00:22:19.141 --> 00:22:23.119 with either `deb_` or `rh_` 00:22:23.120 --> 00:22:27.719 to signify which distro the property applies to.` 00:22:27.720 --> 00:22:31.160 We'll also create a single property called "prefix", 00:22:31.160 --> 00:22:34.589 which will be prepended to the property name 00:22:34.590 --> 00:22:36.529 by the `get_prop` function 00:22:36.530 --> 00:22:39.509 if the requested property is not found. 00:22:39.510 --> 00:22:42.200 This way, when we want to switch between 00:22:42.200 --> 00:22:45.349 the Debian and RedHat versions of the document, 00:22:45.350 --> 00:22:49.029 we just need to change the prefix property. 00:22:49.030 --> 00:22:51.379 So now we'll change the Elisp code. 00:22:51.380 --> 00:22:55.209 So we'll use a let expression with two bound variables. 00:22:55.210 --> 00:22:56.919 The first one is called ret, 00:22:56.920 --> 00:22:59.160 which determines if the initial call 00:22:59.160 --> 00:23:01.949 to `org-property-values` succeeds. 00:23:01.950 --> 00:23:04.039 The second variable is called prefix, 00:23:04.040 --> 00:23:06.219 which is the prefix property. 00:23:06.220 --> 00:23:09.120 If the first call to `org-property-values` succeeds, 00:23:09.120 --> 00:23:11.159 we return it as normal. 00:23:11.160 --> 00:23:14.249 If not, we concatenate the property value 00:23:14.250 --> 00:23:15.920 that was passed into the function 00:23:15.920 --> 00:23:18.969 onto the prefix and try again. 00:23:18.970 --> 00:23:23.800 Now when we call the `get_prop` function with "distro" 00:23:23.800 --> 00:23:26.360 as the prop argument, it won't be found. 00:23:26.360 --> 00:23:29.689 So the code will slap our prefix tag on the front, 00:23:29.690 --> 00:23:33.249 making it something like `rh_distro`, 00:23:33.250 --> 00:23:35.329 and it will be found and returned. 00:23:35.330 --> 00:23:39.999 Let's see that in action. 00:23:40.000 --> 00:23:42.009 All right, now we're talking. NOTE Switching distributions 00:23:42.010 --> 00:23:44.419 This setup is starting to look pretty good, 00:23:44.420 --> 00:23:46.040 but there are just a few things 00:23:46.040 --> 00:23:48.659 that I want to add before we move on. 00:23:48.660 --> 00:23:51.240 First of all, I think the document should have a subtitle, 00:23:51.240 --> 00:23:53.960 something that tells you if you're looking at the RedHat 00:23:53.960 --> 00:23:56.160 or the Debian version of the document. 00:23:56.160 --> 00:23:57.880 I also think it would be great 00:23:57.880 --> 00:24:00.520 if the file name of the exported document 00:24:00.520 --> 00:24:04.999 reflected the distribution as well. 00:24:05.000 --> 00:24:08.040 I also want to add a quick Debian only section 00:24:08.040 --> 00:24:11.799 to the document that explains how it got its name. 00:24:11.800 --> 00:24:17.739 Now let's see what happens when we export the document. 00:24:17.740 --> 00:24:20.439 This did not work out as we wanted. 00:24:20.440 --> 00:24:23.360 As you can see, the macro we used in the subtitles 00:24:23.360 --> 00:24:24.959 didn't expand properly, 00:24:24.960 --> 00:24:28.640 and as a result, our subtitle didn't render right. 00:24:28.640 --> 00:24:30.640 Sadly, you can't use macros 00:24:30.640 --> 00:24:32.909 or inline function calls everywhere. 00:24:32.910 --> 00:24:34.680 And one place where they don't work 00:24:34.680 --> 00:24:37.189 is inside of certain export keywords. 00:24:37.190 --> 00:24:43.219 So we're gonna have to hard code them here. 00:24:43.220 --> 00:24:46.320 Another mistake that we made is we forgot to update 00:24:46.320 --> 00:24:49.099 the `#+EXCLUDE_TAGS` export keyword, 00:24:49.100 --> 00:24:51.439 because with the RedHat version of the document, 00:24:51.440 --> 00:24:54.509 we want to exclude the Debian tag. 00:24:54.510 --> 00:24:56.400 Now when we export the document, 00:24:56.400 --> 00:24:57.839 everything should be correct. 00:24:57.840 --> 00:25:00.619 The word RedHat should appear in the subtitle, 00:25:00.620 --> 00:25:04.799 and the Debian fun fact section should not be present. 00:25:04.800 --> 00:25:06.960 Now we just need to add a section to the README 00:25:06.960 --> 00:25:09.280 that explains the steps you need to take 00:25:09.280 --> 00:25:11.000 in order to switch the document 00:25:11.000 --> 00:25:12.759 from RedHat to Debian. 00:25:12.760 --> 00:25:14.000 Okay, let's see here. 00:25:14.000 --> 00:25:18.309 We have to change `#+SUBTITLE`, change the `#+EXCLUDE_TAGS`, 00:25:18.310 --> 00:25:20.429 change the `#+EXPORT_FILE_NAME`, 00:25:20.430 --> 00:25:23.289 and change the `prefix` property. 00:25:23.290 --> 00:25:26.289 This is OK, but it's not great. 00:25:26.290 --> 00:25:29.429 Emacs Lisp can once again come to our rescue. 00:25:29.430 --> 00:25:32.080 What we'll do is make an Elisp code block 00:25:32.080 --> 00:25:35.480 that will invite the user to hit `C-c C-c` on. 00:25:35.480 --> 00:25:39.520 And the code block will essentially make all these changes 00:25:39.520 --> 00:25:40.919 in the document for them. 00:25:40.920 --> 00:25:43.280 This code block, which we'll call `switch_distro`, 00:25:43.280 --> 00:25:45.680 takes one argument called `os`, 00:25:45.680 --> 00:25:48.689 which by default is set to "Debian". 00:25:48.690 --> 00:25:50.760 It starts out with a let expression 00:25:50.760 --> 00:25:53.029 that defines three bound variables. 00:25:53.030 --> 00:25:55.969 The `debian` variable is a boolean that is true 00:25:55.970 --> 00:25:58.699 if the distro we're switching to is Debian. 00:25:58.700 --> 00:26:00.360 Based on the value of this boolean, 00:26:00.360 --> 00:26:04.169 we'll set the `noexport` and `prefix` variables accordingly. 00:26:04.170 --> 00:26:06.720 The `save-excursion` block tells Emacs 00:26:06.720 --> 00:26:09.199 that we're going to be moving around in the document 00:26:09.200 --> 00:26:11.680 and to remember to put our point back where we started 00:26:11.680 --> 00:26:13.429 when the block finishes. 00:26:13.430 --> 00:26:16.249 After that, we essentially go to the top of the document 00:26:16.250 --> 00:26:19.839 and search and replace the subtitle, `exclude_tags`, 00:26:19.840 --> 00:26:22.499 `export_file_name`, and the `prefix`. 00:26:22.500 --> 00:26:23.389 Pretty cool. 00:26:23.390 --> 00:26:25.029 Let's see this in action. 00:26:25.030 --> 00:26:27.869 If we hit `C-c C-c` on this block, 00:26:27.870 --> 00:26:30.480 we should see the document automatically change a bit. 00:26:30.480 --> 00:26:32.320 And now when we export it, 00:26:32.320 --> 00:26:36.089 we get the Debian version of the doc. 00:26:36.090 --> 00:26:37.629 If we want to change it back, 00:26:37.630 --> 00:26:39.880 we can just head back over to the code block 00:26:39.880 --> 00:26:43.149 and change the default value for the os variable 00:26:43.150 --> 00:26:47.619 from "Debian" to "RedHat" and hit `C-c C-c` again. 00:26:47.620 --> 00:26:49.919 And now when we re-export, 00:26:49.920 --> 00:26:52.909 we're looking at the RedHat version of the document. 00:26:52.910 --> 00:26:55.859 Just as an aside, if you ever thought to yourself, 00:26:55.860 --> 00:26:58.159 "I should learn Emacs Lisp someday" 00:26:58.160 --> 00:27:01.289 Make it someday soon. You'll be happy you did. 00:27:01.290 --> 00:27:03.769 Not only is it a fun programming language, 00:27:03.770 --> 00:27:06.679 but you can do powerful things with it in Emacs, 00:27:06.680 --> 00:27:12.149 which I hope is a point that folks take away from this talk. 00:27:12.150 --> 00:27:14.149 All right, that was a lot. NOTE A tour 00:27:14.150 --> 00:27:16.840 Now that we've spent the past 20 minutes or so 00:27:16.840 --> 00:27:19.409 digging into some of the tips and tricks I used 00:27:19.410 --> 00:27:22.879 when creating my build Emacs from source document, 00:27:22.880 --> 00:27:26.279 we'll say goodbye to this document we've been working on 00:27:26.280 --> 00:27:27.480 and we'll start a tour 00:27:27.480 --> 00:27:29.960 of the actual literate document I wrote. 00:27:29.960 --> 00:27:33.080 A document that I'll demonstrate actually downloading 00:27:33.080 --> 00:27:35.659 and building a new Emacs when I export it 00:27:35.660 --> 00:27:38.959 on both my Ubuntu and RedHat virtual machines. 00:27:38.960 --> 00:27:41.689 I'll also show you how org-mode can generate 00:27:41.690 --> 00:27:44.519 slick professional looking PDF files 00:27:44.520 --> 00:27:46.579 through the power of LaTeX. 00:27:46.580 --> 00:27:49.619 We'll start here at the orgdemo2 directory, 00:27:49.620 --> 00:27:51.229 which I've cloned from GitLab. 00:27:51.230 --> 00:27:55.599 This repository has all the source materials for this talk. 00:27:55.600 --> 00:27:59.040 The buildemacs.org file is where most of the good stuff is. 00:27:59.040 --> 00:28:01.479 So that's where we'll start. 00:28:01.480 --> 00:28:03.360 There's a lot of file-local variables 00:28:03.360 --> 00:28:04.800 that we'll need to confirm. 00:28:04.800 --> 00:28:06.439 So we'll do that too. 00:28:06.440 --> 00:28:07.560 So the first thing we're gonna do 00:28:07.560 --> 00:28:10.080 is hit `C-u TAB` twice, 00:28:10.780 --> 00:28:13.360 which will give us a top-level overview 00:28:13.360 --> 00:28:15.139 of all of our headings. 00:28:15.140 --> 00:28:16.600 As you can see, we've got a lot 00:28:16.600 --> 00:28:20.119 of the same familiar export keywords we had before. 00:28:20.120 --> 00:28:23.099 `#+TITLE`, `#+SUBTITLE`, `#+AUTHOR`, `#+EMAIL`, 00:28:23.100 --> 00:28:25.359 plus a few we haven't seen before. 00:28:25.360 --> 00:28:27.720 For example, I've squirreled away 00:28:27.720 --> 00:28:30.619 a lot of the `#+LATEX_HEADER` export keywords 00:28:30.620 --> 00:28:33.539 in this file called latex.setup. 00:28:33.540 --> 00:28:36.539 And I did this just so they don't clutter up the document. 00:28:36.540 --> 00:28:38.320 Much of the LaTeX magic 00:28:38.320 --> 00:28:40.909 that makes the exported document look good 00:28:40.910 --> 00:28:42.589 is in these headers. 00:28:42.590 --> 00:28:45.119 LaTeX commands begin with a backslash. 00:28:45.120 --> 00:28:49.679 And a common one we use a lot here is `\usepackage`. 00:28:49.680 --> 00:28:52.200 This lets us bring in packages like geometry, 00:28:52.200 --> 00:28:56.539 svg for the cool SeaGL SVG logo, 00:28:56.540 --> 00:28:58.440 `fancyhdr` and fancy verbatim [`fancyvrb`] 00:28:58.440 --> 00:29:00.689 to keep things looking pretty fancy. 00:29:00.690 --> 00:29:03.200 Using a scalable vector image format 00:29:03.200 --> 00:29:05.720 makes it possible for us to do really cool things 00:29:05.720 --> 00:29:09.269 like having a scaled-down version of the SeaGL logo 00:29:09.270 --> 00:29:11.979 appear in the fancy footer below. 00:29:11.980 --> 00:29:15.360 I also include some macros in a separate file 00:29:15.360 --> 00:29:18.120 just to help keep things tidy in the main document. 00:29:18.120 --> 00:29:20.600 Here I've got the familiar macros 00:29:20.600 --> 00:29:23.399 we've seen before for `get_prop`. 00:29:23.400 --> 00:29:25.520 But here I use different permutations 00:29:25.520 --> 00:29:28.160 depending on if I want results raw 00:29:28.160 --> 00:29:31.869 or raw verbatim or just verbatim. 00:29:31.870 --> 00:29:35.069 I also have a couple of macros here at the top of the file 00:29:35.070 --> 00:29:40.280 that are for pulling strings out of results blocks 00:29:40.280 --> 00:29:41.920 and then trimming them 00:29:41.920 --> 00:29:44.719 so there's no white space on either side. 00:29:44.720 --> 00:29:46.440 Like in the version of the document 00:29:46.440 --> 00:29:48.429 we worked on at the start of this talk, 00:29:48.430 --> 00:29:51.079 the real document also has a README section 00:29:51.080 --> 00:29:53.469 marked with the `:noexport:` tag. 00:29:53.470 --> 00:29:55.400 It also has a section about choosing 00:29:55.400 --> 00:29:57.909 which version of the document to export 00:29:57.910 --> 00:30:00.599 and a code block on how to switch between them. 00:30:00.600 --> 00:30:03.000 It's also got a lot of helpful information in it 00:30:03.000 --> 00:30:05.819 like what OS and Emacs versions 00:30:05.820 --> 00:30:09.559 the document has been tested to "run" on, 00:30:09.560 --> 00:30:12.329 a section on the LaTeX prerequisites 00:30:12.330 --> 00:30:14.080 and the section on executing 00:30:14.080 --> 00:30:16.199 the document's various code blocks. NOTE TeX and LaTeX 00:30:16.200 --> 00:30:19.199 The latter two sections we'll take a look at now. 00:30:19.200 --> 00:30:22.579 Out of the box on Fedora and Ubuntu server distros, 00:30:22.580 --> 00:30:24.709 the TeX typesetting system 00:30:24.710 --> 00:30:27.669 also by noted computer scientist Donald Knuth 00:30:27.670 --> 00:30:28.859 is not installed. 00:30:28.860 --> 00:30:31.719 So we'll need to install some packages. 00:30:31.720 --> 00:30:34.449 Starting out we'll need the `texlive` package 00:30:34.450 --> 00:30:37.459 which gets you a fully featured TeX setup. 00:30:37.460 --> 00:30:39.289 This also gets you LaTeX 00:30:39.290 --> 00:30:42.789 which can be viewed as a distribution of TeX macros. 00:30:42.790 --> 00:30:44.899 You'll also need XeTeX. 00:30:44.900 --> 00:30:49.779 This gets you Unicode support and lets you use modern fonts. 00:30:49.780 --> 00:30:52.809 We'll also want to install pdfTeX. 00:30:52.810 --> 00:30:57.209 This gets us the ability to generate PDFs from TeX sources. 00:30:57.210 --> 00:31:01.299 And finally, we're gonna need to install latexmk 00:31:01.300 --> 00:31:02.400 which is a Perl script 00:31:02.400 --> 00:31:05.139 that knows how to run LaTeX multiple times 00:31:05.140 --> 00:31:09.249 in order to properly deal with intra-document links. NOTE Other prerequisites 00:31:09.250 --> 00:31:11.069 But wait, there's more. 00:31:11.070 --> 00:31:12.960 We're also gonna need Inkscape 00:31:12.960 --> 00:31:15.520 to rasterize our SeaGL vector logo 00:31:15.520 --> 00:31:17.339 at different resolutions. 00:31:17.340 --> 00:31:20.360 And we're gonna need the JetBrains Mono font 00:31:20.360 --> 00:31:23.059 to make our source code look snazzy. 00:31:23.060 --> 00:31:24.680 We'll also need the Inter font 00:31:24.680 --> 00:31:28.039 to make our prose look snazzy as well. 00:31:28.040 --> 00:31:31.299 I've helpfully added a bash code block in the README 00:31:31.300 --> 00:31:35.739 that you can hit C-c C-c on to install. 00:31:35.740 --> 00:31:38.520 This really does lock up Emacs for a few minutes 00:31:38.520 --> 00:31:40.329 and it's sort of annoying. 00:31:40.330 --> 00:31:43.040 When we export the document and turn off all caching 00:31:43.040 --> 00:31:45.599 and it actually builds Emacs for real, 00:31:45.600 --> 00:31:48.769 Emacs can be locked up for tens of minutes. 00:31:48.770 --> 00:31:50.880 There's a package called ob-async 00:31:50.880 --> 00:31:54.259 that I've been meaning to check out that might help here. 00:31:54.260 --> 00:31:55.760 But since I wanted this document 00:31:55.760 --> 00:31:58.000 to work on bog-standard Emacs setups, 00:31:58.000 --> 00:32:00.059 I didn't get around to it. NOTE Caching 00:32:00.060 --> 00:32:03.139 Before we get into talking about running the document, 00:32:03.140 --> 00:32:06.449 let's talk briefly about results caching. 00:32:06.450 --> 00:32:08.839 We'll take a look at the section of the document 00:32:08.840 --> 00:32:13.139 where we talk about Git tags for an example. 00:32:13.140 --> 00:32:15.760 The `num_tags` bash code block determines 00:32:15.760 --> 00:32:19.039 how many tags there are in the Emacs Git repo. 00:32:19.040 --> 00:32:21.600 And when I hit C-c C-c on that block 00:32:21.600 --> 00:32:25.059 several days ago, when I was first creating the document, 00:32:25.060 --> 00:32:28.019 that number was 183. 00:32:28.020 --> 00:32:32.169 That result has remained cached in the document since then. 00:32:32.170 --> 00:32:34.899 And you can see a snippet of the SHA1 hash 00:32:34.900 --> 00:32:38.389 of the contents of the source block below. 00:32:38.390 --> 00:32:40.800 You can see where I referenced the result 00:32:40.800 --> 00:32:44.960 using the `sr` for string raw macro in the prose below, 00:32:44.960 --> 00:32:50.509 and how it gets rendered in the exported PDF document. 00:32:50.510 --> 00:32:52.880 All the source blocks in the exported sections 00:32:52.880 --> 00:32:56.559 of the document include cached results like this. 00:32:56.560 --> 00:33:01.389 If I export the document now, it won't take that long to do 00:33:01.390 --> 00:33:03.800 because while there are a ton of code blocks 00:33:03.800 --> 00:33:09.069 in the exported sections, they're all cached. 00:33:09.070 --> 00:33:11.560 Now let's get back to the section of the README 00:33:11.560 --> 00:33:14.909 that explains how to execute the code in the document. 00:33:14.910 --> 00:33:17.640 Here I explain that if you want to build Emacs 00:33:17.640 --> 00:33:20.189 on your computer using this document, 00:33:20.190 --> 00:33:22.019 you've got a couple of options. 00:33:22.020 --> 00:33:25.649 The first option is to manually invalidate the caches 00:33:25.650 --> 00:33:28.960 and take C-c C-c on every code block 00:33:28.960 --> 00:33:30.959 in the main document. 00:33:30.960 --> 00:33:33.160 This lets you supervise the entire process, 00:33:33.160 --> 00:33:36.939 and it also creates new cached result blocks, 00:33:36.940 --> 00:33:39.239 but it's time consuming. 00:33:39.240 --> 00:33:43.440 There is also an internal link to the main document here, 00:33:43.440 --> 00:33:47.379 and you can jump to it with C-c C-o. 00:33:47.380 --> 00:33:50.040 This is one of those intra-document links 00:33:50.040 --> 00:33:52.999 that is really tricky to get right with LaTeX, 00:33:53.000 --> 00:33:56.989 and is why we opted to use the latexmk Perl script 00:33:56.990 --> 00:34:00.049 to build the PDF version of the document. 00:34:00.050 --> 00:34:01.920 I'm mentioning it specifically here 00:34:01.920 --> 00:34:05.629 because it took me forever to figure this out. 00:34:05.630 --> 00:34:07.269 The second option you've got 00:34:07.270 --> 00:34:09.280 is to change the default header arg 00:34:09.280 --> 00:34:13.739 from `:cache yes` to `:cache no` at the top of the document. 00:34:13.740 --> 00:34:16.269 If we cruise up to the top of the document, 00:34:16.270 --> 00:34:19.129 you can see that this header argument property 00:34:19.130 --> 00:34:22.440 basically says that unless a code block 00:34:22.440 --> 00:34:24.160 explicitly says otherwise, 00:34:24.160 --> 00:34:27.118 it's by default supposed to be cached. 00:34:27.119 --> 00:34:29.440 That's how we were able to export the document 00:34:29.440 --> 00:34:31.558 before so quickly. 00:34:31.559 --> 00:34:34.819 The code block named `no_cache_no_confirm` 00:34:34.820 --> 00:34:38.618 uses the `save-excursion` and regex replace trick 00:34:38.619 --> 00:34:40.348 that I demonstrated earlier 00:34:40.349 --> 00:34:42.819 to munch the default cache header arg 00:34:42.820 --> 00:34:45.409 from "cache yes" to "cache no". 00:34:45.410 --> 00:34:49.299 And it also turns off confirmations on bash code blocks. 00:34:49.300 --> 00:34:51.939 Let's do that now. 00:34:51.940 --> 00:34:54.559 Now we'll export the document to PDF, 00:34:54.560 --> 00:34:57.439 which will ignore the cache result blocks 00:34:57.440 --> 00:35:00.319 and clone the Git repository on Savannah, 00:35:00.320 --> 00:35:01.760 create a branch that points 00:35:01.760 --> 00:35:05.459 to the most recently tagged version of Emacs 29, 00:35:05.460 --> 00:35:07.759 run configure a handful of times, 00:35:07.760 --> 00:35:10.720 installing packages to fix missing dependencies 00:35:10.720 --> 00:35:12.399 along the way, 00:35:12.400 --> 00:35:16.099 build Emacs, install Emacs in our home directory, 00:35:16.100 --> 00:35:19.339 verify that it has successfully built a binary, 00:35:19.340 --> 00:35:22.549 run it in batch mode with some sample Elisp 00:35:22.550 --> 00:35:26.869 and show the file sizes and dates of the generated files. 00:35:26.870 --> 00:35:28.339 This is gonna take a while. 00:35:28.340 --> 00:35:32.829 And while it's running, we'll pop over to our Fedora box. 00:35:32.830 --> 00:35:34.680 All right, now we'll fire up Emacs, 00:35:34.680 --> 00:35:39.280 hit `C-c C-c` on the `configure_document` code block 00:35:39.280 --> 00:35:41.849 to configure the document for RedHat 00:35:41.850 --> 00:35:45.709 since Fedora here is a RedHat based distro. 00:35:45.710 --> 00:35:47.040 Then what we'll do is we'll pop down 00:35:47.040 --> 00:35:49.589 and hit `C-c C-c` 00:35:49.590 --> 00:35:53.699 on the `rh_install_latex` code block 00:35:53.700 --> 00:35:56.229 to install the LaTeX prerequisites 00:35:56.230 --> 00:35:58.459 for this Fedora virtual machine. 00:35:58.460 --> 00:36:02.589 Finally, we'll execute the `no_cache_no_confirm` block 00:36:02.590 --> 00:36:05.049 and then kick off the export. 00:36:05.050 --> 00:36:07.280 Then we'll go and check back on what's happening 00:36:07.280 --> 00:36:09.529 on the Ubuntu box. 00:36:09.530 --> 00:36:11.240 Ooh, top looks pretty quiet. 00:36:11.240 --> 00:36:14.039 I think the export is complete. 00:36:14.040 --> 00:36:17.559 Ooh, those are the words I love to see in the status area, 00:36:17.560 --> 00:36:20.609 PDF file produced! NOTE Looking at the PDF 00:36:20.610 --> 00:36:22.600 Now I can't use my web browser 00:36:22.600 --> 00:36:24.959 to take a look at this PDF file 00:36:24.960 --> 00:36:27.080 because I haven't set up a web server 00:36:27.080 --> 00:36:30.759 or anything like that on the Ubuntu virtual machine. 00:36:30.760 --> 00:36:34.439 I can, however, use TRAMP with the ssh method 00:36:34.440 --> 00:36:36.560 to poke around on the ubuntu host 00:36:36.560 --> 00:36:39.120 on my personal version of Emacs. 00:36:39.120 --> 00:36:40.939 So let's do that. 00:36:40.940 --> 00:36:44.809 Okay, so now if we go into the source directory 00:36:44.810 --> 00:36:48.039 and then we hop into the orgdemo2 directory 00:36:48.040 --> 00:36:51.619 and then we look at the deb version of the PDF, 00:36:51.620 --> 00:36:54.149 there she blows. 00:36:54.150 --> 00:36:58.160 Now, if we go down to the Building Emacs section, 00:36:58.160 --> 00:37:00.129 we can see that it built. 00:37:00.130 --> 00:37:03.839 And if we look in the bin directory, 00:37:03.840 --> 00:37:06.779 we can see that at 17:01, 00:37:06.780 --> 00:37:11.379 that's when all of those files got created. 00:37:11.380 --> 00:37:15.589 Also the file creation date on the PDF is 17:01. 00:37:15.590 --> 00:37:18.720 So all of this code executed roughly the same time 00:37:18.720 --> 00:37:21.159 the PDF was created. 00:37:21.160 --> 00:37:25.339 All right, so now let's head back over to the Fedora box 00:37:25.340 --> 00:37:27.920 and then we'll navigate to the source directory, 00:37:27.920 --> 00:37:30.119 the orgdemo2 directory, 00:37:30.120 --> 00:37:35.719 and there is our RedHat version of the built Emacs PDF. 00:37:35.720 --> 00:37:38.219 And Bob's your uncle. 00:37:38.220 --> 00:37:42.549 And you can see it is the RedHat version of the document 00:37:42.550 --> 00:37:44.939 because this is a RedHat box. 00:37:44.940 --> 00:37:51.639 And if we go over to the What did we install? section, 00:37:51.640 --> 00:37:56.049 you can see that these binaries were built at 17:35. 00:37:56.050 --> 00:37:58.699 And now if we pop open dired 00:37:58.700 --> 00:38:00.739 and we take a look at the PDF, 00:38:00.740 --> 00:38:07.329 we can see it also was created at 17:35. 00:38:07.330 --> 00:38:10.039 All right, in the couple minutes remaining, 00:38:10.040 --> 00:38:11.640 I thought it would be a good idea 00:38:11.640 --> 00:38:15.739 just to take a look at the document 00:38:15.740 --> 00:38:19.000 and maybe just go through some of what it actually does 00:38:19.000 --> 00:38:22.579 in explaining how to build Emacs from source. 00:38:22.580 --> 00:38:27.139 We'll look at the RedHat version since we're here. 00:38:27.140 --> 00:38:28.160 And the first thing you do is 00:38:28.160 --> 00:38:31.539 you have to get access to the source code. 00:38:31.540 --> 00:38:32.840 And before you can do anything, 00:38:32.840 --> 00:38:35.419 this is a RedHat-specific section 00:38:35.420 --> 00:38:38.299 where you need to install some development tools. 00:38:38.300 --> 00:38:41.539 And this development tools group actually has Git. 00:38:41.540 --> 00:38:44.640 Now I installed Git earlier, but if you didn't do that, 00:38:44.640 --> 00:38:46.939 that would be the first thing that you need to do. 00:38:46.940 --> 00:38:50.039 We create a source directory, we cd into it, 00:38:50.040 --> 00:38:53.059 we clone the repo from Savannah. 00:38:53.060 --> 00:38:56.059 And then we start to take a look at some of the Git tags. 00:38:56.060 --> 00:38:58.560 And we showed this before where we check out 00:38:58.560 --> 00:39:00.369 how many different tags there are. 00:39:00.370 --> 00:39:02.400 And then we run this kind of funky Git command 00:39:02.400 --> 00:39:06.040 to sort of list all the tags that begin with 'emacs-29', 00:39:06.040 --> 00:39:08.759 and we sort them by when they were tagged. 00:39:08.760 --> 00:39:12.400 So we can see that Emacs 29.1.pretest 00:39:12.400 --> 00:39:14.439 is the most recent version. 00:39:14.440 --> 00:39:15.880 So that's the one we grab 00:39:15.880 --> 00:39:18.659 and that's the one we decide to build. 00:39:18.660 --> 00:39:22.779 And then we create a branch that is based on this tag. 00:39:22.780 --> 00:39:27.479 And this is dynamically generated based on what we saw here. 00:39:27.480 --> 00:39:29.439 So that's what we use here. NOTE Errors 00:39:29.440 --> 00:39:32.920 In this case, we're piping standard error 00:39:32.920 --> 00:39:35.099 to where standard out goes. 00:39:35.100 --> 00:39:36.069 That's another trick. 00:39:36.070 --> 00:39:39.559 If you want to actually see an error get created, 00:39:39.560 --> 00:39:44.119 org-mode will capture any errors that code blocks produce, 00:39:44.120 --> 00:39:46.819 and it will show you the error message in a buffer. 00:39:46.820 --> 00:39:49.240 So if you actually wanna show what it looks like 00:39:49.240 --> 00:39:53.059 when something errors out, this is the trick you have to use. 00:39:53.060 --> 00:39:56.200 And then what we do is we look for a configure script 00:39:56.200 --> 00:39:57.419 and there isn't one. 00:39:57.420 --> 00:39:58.599 And then we realize, 00:39:58.600 --> 00:40:00.909 uh-oh, we're gonna have to deal with autotools. 00:40:00.910 --> 00:40:05.560 So, you know, we run the autogen script and it complains 00:40:05.560 --> 00:40:08.679 because we're missing some prerequisites. 00:40:08.680 --> 00:40:11.349 So we have to install autoconf, 00:40:11.350 --> 00:40:13.019 and then we run it again, 00:40:13.020 --> 00:40:15.959 and finally it generates a configure script. 00:40:15.960 --> 00:40:19.019 And this is another case where I pull this number 00:40:19.020 --> 00:40:21.979 right here into the actual prose. 00:40:21.980 --> 00:40:24.840 And I can see it's, oh, it's, you know, this how many bytes. 00:40:24.840 --> 00:40:26.800 When was the last time you wrote a shell script 00:40:26.800 --> 00:40:29.579 that was this many bytes long? 00:40:29.580 --> 00:40:31.320 And then we configure the build process. 00:40:31.320 --> 00:40:33.760 And, you know, it's not gonna work right away 00:40:33.760 --> 00:40:36.699 because we don't have GNU Texinfo installed. 00:40:36.700 --> 00:40:41.439 So we gotta do that, which we do with `dnf install` here. 00:40:41.440 --> 00:40:44.320 And then there's this section that is either RedHat- 00:40:44.320 --> 00:40:48.919 or Debian-specific that talks about, like, 00:40:48.920 --> 00:40:51.240 if you don't know the name of a package 00:40:51.240 --> 00:40:55.160 that contains a given file name, how do you query it? 00:40:55.160 --> 00:40:59.519 And in the RedHat world, you use `dnf provides makeinfo`. 00:40:59.520 --> 00:41:02.289 In the Debian world, you do something entirely different. 00:41:02.290 --> 00:41:06.639 And then we have to install the `ncurses` binary. 00:41:06.640 --> 00:41:10.299 And finally we get like a minimal configuration 00:41:10.300 --> 00:41:13.699 and you can see that there's a whole bunch of nos here. 00:41:13.700 --> 00:41:15.200 So, you know, we don't have cairo, 00:41:15.200 --> 00:41:18.799 we don't have imagemagick, we don't have dbus, 00:41:18.800 --> 00:41:20.600 you know, there's a whole bunch of stuff we don't have. 00:41:20.600 --> 00:41:23.880 We don't have X, we don't have libjansson, no tree-sitter. 00:41:23.880 --> 00:41:25.960 This is really a bare-bones Emacs 00:41:25.960 --> 00:41:28.639 that is strictly terminal mode. 00:41:28.640 --> 00:41:30.800 Then we actually build Emacs, which is, you know, 00:41:30.800 --> 00:41:33.259 kind of boring, we're just gonna type make 00:41:33.260 --> 00:41:35.259 and then make is gonna run successfully. 00:41:35.260 --> 00:41:37.880 And make is gonna spew a ton of output, right? 00:41:37.880 --> 00:41:41.099 So here's where I do that /dev/null trick, 00:41:41.100 --> 00:41:42.600 where I pipe everything to /dev/null 00:41:42.600 --> 00:41:45.819 and then I, or I pipe standard output to /dev/null 00:41:45.820 --> 00:41:47.520 and then I pipe standard error 00:41:47.520 --> 00:41:50.239 to wherever standard output's going. 00:41:50.240 --> 00:41:52.799 And then at the end to say that it ran successfully, 00:41:52.800 --> 00:41:55.379 I say "Make ran successfully!" 00:41:55.380 --> 00:41:57.799 Then we take a look at the Emacs binary 00:41:57.800 --> 00:41:59.879 and you know, it's an elf binary. 00:41:59.880 --> 00:42:01.720 And, you know, because this is running on my Mac, 00:42:01.720 --> 00:42:06.619 this is an ARM-based machine, this virtual machine is. 00:42:06.620 --> 00:42:10.519 Oops, and this is a bug. 00:42:10.520 --> 00:42:12.200 This really should be a macro call, 00:42:12.200 --> 00:42:14.800 but I think I have the wrong number of curly braces 00:42:14.800 --> 00:42:16.159 or something in there. 00:42:16.160 --> 00:42:19.129 I need to figure out why that's not right. 00:42:19.130 --> 00:42:21.109 I'll look into that later. 00:42:21.110 --> 00:42:23.979 And then we install Emacs and then we kind of show 00:42:23.980 --> 00:42:27.719 like the file sizes of everything in the home directory. 00:42:27.720 --> 00:42:31.989 And then we, you know, show the binaries that got installed. NOTE Final thoughts 00:42:31.990 --> 00:42:35.599 Anyway, so this is the final thoughts section. 00:42:35.600 --> 00:42:39.219 And my final thoughts are, is I hope you enjoyed this talk 00:42:39.220 --> 00:42:42.379 and I hope you actually learned a thing or two. 00:42:42.380 --> 00:42:43.360 All right, thanks everybody. 00:42:43.360 --> 00:42:45.200 And I'll see you all next time.