WEBVTT 00:00:00.000 --> 00:00:04.556 Hello, everyone. I am Andrew Tropin. 00:00:04.556 --> 00:00:06.622 I am a professional software engineer 00:00:06.622 --> 00:00:11.622 I was playing with NixOS 00:00:11.622 --> 00:00:15.322 It's an operating system based on the Nix package manager. 00:00:15.322 --> 00:00:21.089 I came up with this interesting approach for configuring Emacs. 00:00:21.089 --> 00:00:24.056 I want to share it with you. 00:00:24.056 --> 00:00:27.756 I will start with the bold statement that 00:00:27.756 --> 00:00:30.822 Emacs configuration is almost the same 00:00:30.822 --> 00:00:33.022 as system configuration. 00:00:33.022 --> 00:00:37.262 It's not related to that Emacs joke 00:00:37.262 --> 00:00:39.922 about Emacs being an operating system. 00:00:39.922 --> 00:00:44.489 It's more about Emacs being integrated 00:00:44.489 --> 00:00:48.589 with so many tools inside the environment. 00:00:48.589 --> 00:00:53.089 For example, if you don't even use any fancy workflows, 00:00:53.089 --> 00:00:57.256 you use only plain Emacs without any configuration, 00:00:57.256 --> 00:01:02.556 dired uses ls, grep.el uses grep, 00:01:02.556 --> 00:01:09.356 and info files placed somewhere in your system. 00:01:09.356 --> 00:01:15.489 Also Emacs can interact with gpg, git, make, and other stuff. 00:01:15.489 --> 00:01:20.789 When you grow your Emacs Lisp 00:01:20.789 --> 00:01:23.189 init.el file 00:01:23.189 --> 00:01:27.222 or other files in your .emacs.d directory, 00:01:27.222 --> 00:01:29.989 you get much more integration 00:01:29.989 --> 00:01:31.389 with underlying operating system. 00:01:31.389 --> 00:01:36.922 The question is: how to manage such configuration? 00:01:36.922 --> 00:01:40.922 Because you can't just take a bunch of .el files 00:01:40.922 --> 00:01:43.456 and move to a different machine 00:01:43.456 --> 00:01:47.122 and be sure that everything will work. 00:01:47.122 --> 00:01:50.577 Because you didn't move your executables. 00:01:50.577 --> 00:01:53.522 You didn't move configuration of other programs. 00:01:53.522 --> 00:01:55.089 You didn't move your service configurations. 00:01:55.089 --> 00:02:01.889 And you can't even just create dotfiles for each program 00:02:01.889 --> 00:02:05.022 and move it with your .el files. 00:02:05.022 --> 00:02:08.622 The approach would be a little broader. 00:02:08.622 --> 00:02:13.056 Everything that I am showing today 00:02:13.056 --> 00:02:15.322 is available on Github. 00:02:15.322 --> 00:02:18.022 Any source code, you can find here. 00:02:18.022 --> 00:02:21.589 but my copy of the repository 00:02:21.589 --> 00:02:23.722 is on my local machine. 00:02:23.722 --> 00:02:27.722 As you can see, the font is a little small. 00:02:27.722 --> 00:02:31.122 And also, my terminal font is also a little small. 00:02:31.122 --> 00:02:36.756 I can do a quick fix and increase the font. 00:02:36.756 --> 00:02:40.789 But imagine how cool it will be 00:02:40.789 --> 00:02:45.756 if you can have a file which contains the configuration for a system. 00:02:45.756 --> 00:02:52.489 You change some value. Here, for example, fontSize = 16 00:02:52.489 --> 00:02:54.589 and run some command 00:02:54.589 --> 00:02:58.489 and based on this file 00:02:58.489 --> 00:03:00.322 and some other includes 00:03:00.322 --> 00:03:02.422 your operating system is built 00:03:02.422 --> 00:03:06.389 and all your environment is set up 00:03:06.389 --> 00:03:07.656 and ready for use. 00:03:07.656 --> 00:03:11.622 For example here, we already built the new operating system, 00:03:11.622 --> 00:03:17.856 and everything is already installed in my SSD. 00:03:17.856 --> 00:03:21.322 Now I can run the program and you can see that 00:03:21.322 --> 00:03:29.422 my alacrity terminal has much bigger font 00:03:29.422 --> 00:03:31.789 and also if I restart my Emacs instance 00:03:31.789 --> 00:03:34.089 it by default uses 00:03:34.089 --> 00:03:36.889 a much bigger font for any buffer. 00:03:36.889 --> 00:03:41.089 Practical, and as you can see, it's already working, 00:03:41.089 --> 00:03:45.889 thanks to Nix and NixOS. 00:03:45.889 --> 00:03:50.722 I will explain a little later how it works inside, 00:03:50.722 --> 00:03:57.089 but for now, let's specify a little more 00:03:57.089 --> 00:04:00.789 what happened right now. 00:04:00.789 --> 00:04:08.156 I fed my... Oh. It doesn't work. Sorry. I want... 00:04:08.156 --> 00:04:13.056 I have my whole operating system 00:04:13.056 --> 00:04:15.589 defined in a few Nix files. 00:04:15.589 --> 00:04:18.689 For example, here you saw the file 00:04:18.689 --> 00:04:22.522 which defines some variables for my environment 00:04:22.522 --> 00:04:24.256 and then a few more files 00:04:24.256 --> 00:04:25.722 for different programs. 00:04:25.722 --> 00:04:30.056 There is a folder which contains all Emacs-related configuration. 00:04:30.056 --> 00:04:36.989 Also, there are package definitions defined in Nix package repositories 00:04:36.989 --> 00:04:42.522 which is also included for the function which generates 00:04:42.522 --> 00:04:44.556 the operating system. 00:04:44.556 --> 00:04:47.622 Getting all my configurations written in Nix language 00:04:47.622 --> 00:04:51.174 and a few firewalls in ?? languages, 00:04:51.174 --> 00:04:54.700 everything is gathered together, 00:04:54.700 --> 00:04:56.722 and from that input 00:04:56.722 --> 00:04:58.322 and only from that input, 00:04:58.322 --> 00:05:00.489 the new operating system is built. 00:05:00.489 --> 00:05:03.856 Emacs now is a part of this operating system. 00:05:03.856 --> 00:05:08.422 I can distribute this Emacs configuration 00:05:08.422 --> 00:05:11.689 with all the environment that I want. 00:05:11.689 --> 00:05:18.389 Practical so far. Let's clarify which problems does it solve. 00:05:18.389 --> 00:05:21.756 First of all, the integration problem. 00:05:21.756 --> 00:05:27.389 For example, a few minutes ago, you saw that I changed one variable. 00:05:27.389 --> 00:05:31.348 That was to update... The first one, for my terminal, 00:05:31.348 --> 00:05:33.889 and the second one, for my Emacs. 00:05:33.889 --> 00:05:40.322 It's pretty good that a few different programs can share some data. 00:05:40.322 --> 00:05:43.822 For example, you can have one of them for every application, 00:05:43.822 --> 00:05:45.222 or something like that 00:05:45.222 --> 00:05:48.356 and you change only one value in one place 00:05:48.356 --> 00:05:50.789 and the whole operating system is updated. 00:05:50.789 --> 00:05:56.422 Also, another problem is reproducibility. 00:05:56.422 --> 00:06:00.156 00:06:00.156 --> 00:06:06.600 For example, when you install your new instance of Emacs 00:06:06.600 --> 00:06:11.089 on your laptop or something like that, 00:06:11.089 --> 00:06:14.289 you can be sure that you will get the same package versions 00:06:14.289 --> 00:06:17.189 and you can be sure that the configuration of your work 00:06:17.189 --> 00:06:20.856 results in newly-updated or newly-installed packages. 00:06:20.856 --> 00:06:25.056 Also, if you update packages 00:06:25.056 --> 00:06:27.656 sometimes it's hard to revert, 00:06:27.656 --> 00:06:36.289 because it's the way your package manager almost every time works. 00:06:36.289 --> 00:06:38.722 You're just getting the latest available packages. 00:06:38.722 --> 00:06:43.256 If they are broken, you need to wait for the maintainer to update them. 00:06:43.256 --> 00:06:50.989 And also, your basic configuration almost always doesn't contain 00:06:50.989 --> 00:06:56.156 any native dependencies, like executables or something else. 00:06:56.156 --> 00:07:00.689 Recently, I saw some attempts to make it possible to 00:07:00.689 --> 00:07:03.089 use use-package for those needs, 00:07:03.089 --> 00:07:06.356 like ensuring native dependencies or something like that. 00:07:06.356 --> 00:07:11.134 It's obviously... If your configuration isn't reproducible 00:07:11.134 --> 00:07:15.322 and it doesn't have your whole environment, 00:07:15.322 --> 00:07:19.522 placed in one repository, 00:07:19.522 --> 00:07:22.322 it's very hard to share such configuration. 00:07:22.322 --> 00:07:27.089 You can share part of your configuration and some instruction 00:07:27.089 --> 00:07:32.222 how to get a similar environment, but it doesn't always work. 00:07:32.222 --> 00:07:39.656 Let's go closer to actually Emacs configuration itself. 00:07:39.656 --> 00:07:45.306 I had some experience with Spacemacs and Doom Emacs distributions. 00:07:45.306 --> 00:07:50.414 I also watched a lot of videos and articles by Protesilaos 00:07:50.414 --> 00:07:56.756 and a lot of other custom configurations of many different cool people. 00:07:56.756 --> 00:08:03.039 And also I was inspired by use-package 00:08:03.039 --> 00:08:10.839 and decided that I will create a folding structure for my Emacs configuration. 00:08:10.839 --> 00:08:16.172 I will be using subconfigs. It's almost the same as layers in Spacemacs, 00:08:16.172 --> 00:08:20.972 or modules in Doom Emacs, which are self-contained. 00:08:20.972 --> 00:08:26.287 They contain Emacs Lisp code which configures all packages necessary 00:08:26.287 --> 00:08:28.789 for this part of configuration. 00:08:28.789 --> 00:08:33.493 It contains all Emacs dependencies like Emacs packages. 00:08:33.493 --> 00:08:36.572 It contains all native dependencies 00:08:36.572 --> 00:08:40.039 like binaries or maybe info pages or something like that. 00:08:40.039 --> 00:08:45.115 It also contains variables that can be shared between 00:08:45.115 --> 00:08:47.989 Emacs and other applications, 00:08:47.989 --> 00:08:52.072 and it can contain service or system definitions 00:08:52.072 --> 00:08:56.072 which configure your systemd service or something like that 00:08:56.072 --> 00:09:01.306 that you use in your workflow. For example, for synchronizing your e-mails. 00:09:01.306 --> 00:09:06.239 Let's start from just the example 00:09:06.239 --> 00:09:16.618 that I already am... I have a folding structure for my configuration. 00:09:16.618 --> 00:09:25.789 I have some files here. early-init just has this. 00:09:25.789 --> 00:09:33.006 Nothing changes. It will be copied to that .emacs.d directory later 00:09:33.006 --> 00:09:37.306 with some exceptions that 00:09:37.306 --> 00:09:40.789 it will replace the Nix dir and a symlink will be created to it. 00:09:40.789 --> 00:09:47.889 I have use-package-init.el. It's part of configuration 00:09:47.889 --> 00:09:51.522 that will be on top of everything 00:09:51.522 --> 00:09:55.589 to be able to use use-package in my subconfigurations. 00:09:55.589 --> 00:10:01.156 And actually some Nix code to glue everything up 00:10:01.156 --> 00:10:06.922 and config dirs which contain all my subconfigs. 00:10:06.922 --> 00:10:11.389 Let's start from faces subconfig. 00:10:11.389 --> 00:10:14.556 Let's start from config.el 00:10:14.556 --> 00:10:20.022 which can be familiar for many people. 00:10:20.022 --> 00:10:23.556 Just use-package definition for faces package 00:10:23.556 --> 00:10:24.122 and some configuration for it 00:10:24.122 --> 00:10:29.589 which are setting some attributes. 00:10:29.589 --> 00:10:32.156 It reads some variables. 00:10:32.156 --> 00:10:36.922 Those variables are actually defined in a different place. 00:10:36.922 --> 00:10:44.422 If I open default.nix file, you can see that it contains 00:10:44.422 --> 00:10:52.689 the definition or subconfig, and it should contain a definition of variables 00:10:52.689 --> 00:10:55.322 that it uses by... I forgot to move it from 00:10:55.322 --> 00:11:01.889 my original default.nix file somewhere here. 00:11:01.889 --> 00:11:10.105 You probably can find definition of those variables just right here. 00:11:10.105 --> 00:11:13.722 I took values from my Nix expressions. 00:11:13.722 --> 00:11:23.956 Those values will be shared across my alacrity, Emacs, and other applications. 00:11:23.956 --> 00:11:27.789 Later, they will be placed in generated Emacs configuration. 00:11:27.789 --> 00:11:32.856 They will be available for faces config. 00:11:32.856 --> 00:11:38.422 Here I will be referencing them just like Emacs variables. 00:11:38.422 --> 00:11:43.356 Let's take a look at another more complicated example. 00:11:43.356 --> 00:11:45.922 For example, org-roam package. 00:11:45.922 --> 00:11:49.922 Just a basic use-package configuration 00:11:49.922 --> 00:11:54.607 which uses a variable and the definition. 00:11:54.607 --> 00:12:00.322 It's a little more complex than the previous one. 00:12:00.322 --> 00:12:04.222 Elisp configuration in the same file. 00:12:04.222 --> 00:12:08.856 emacsPackages specified here. 00:12:08.856 --> 00:12:12.289 Those two packages: org-roam and company-org-roam. 00:12:12.289 --> 00:12:16.956 systemPackages: it's something that should be available 00:12:16.956 --> 00:12:18.456 on your host operating system. 00:12:18.456 --> 00:12:24.756 And for emacsPackages, you need sqlite package, 00:12:24.756 --> 00:12:27.922 and also the definition of the variable 00:12:27.922 --> 00:12:31.556 which will be passed in my Emacs configuration later. 00:12:31.556 --> 00:12:37.722 It's equal to my workDir, which is defined in my environment, 00:12:37.722 --> 00:12:39.222 and a subdirectory of it. 00:12:39.222 --> 00:12:43.222 ([Amin:] Andrew, you have about five minutes including questions.) 00:12:43.222 --> 00:12:50.822 Oh, okay. I'm almost finished. It was last example. 00:12:50.822 --> 00:12:56.556 Let me open my Org file. Okay. 00:12:56.556 --> 00:13:02.222 Right here. I won't give you an introduction to Nix itself 00:13:02.222 --> 00:13:06.922 and the underlying mechanism, 00:13:06.922 --> 00:13:11.140 but I can say that there's already a proof of concept framework 00:13:11.140 --> 00:13:14.622 for utilizing Nix and NixOS 00:13:14.622 --> 00:13:18.389 for configuring Emacs and making a very complex workflow 00:13:18.389 --> 00:13:22.056 reproducible on other machines. 00:13:22.056 --> 00:13:26.222 It gives everything that we saw right now. 00:13:26.222 --> 00:13:31.522 For the future work, I plan to reimplement it in Guile, 00:13:31.522 --> 00:13:36.189 which is a Scheme dialect, which is another Lisp language, 00:13:36.189 --> 00:13:39.199 for the GNU Guix operating system, 00:13:39.199 --> 00:13:41.856 because I like Lisp languages 00:13:41.856 --> 00:13:46.822 a little more than Nix languages and I want to make 00:13:46.822 --> 00:13:50.089 this project from proof of concept to some state which 00:13:50.089 --> 00:13:54.189 will be user-friendly and available for other people. 00:13:54.189 --> 00:13:59.156 If I will have a lot of time, I will make an operating system 00:13:59.156 --> 00:14:01.356 which will be inspired by Lisp machines 00:14:01.356 --> 00:14:05.389 to make the whole experience very Lispy. 00:14:05.389 --> 00:14:08.556 Thank you for your attention 00:14:08.556 --> 00:14:12.189 and now I will answer questions. 00:14:12.189 --> 00:14:22.622 Oh. There is a lot of... Okay. I see some questions. 00:14:22.622 --> 00:14:29.222 Did you release some config files such as Emacs custom.el, some of which have sensitive data? 00:14:29.222 --> 00:14:39.922 Ideally, in the folding way, I create a separate directory called local/share/emacs, 00:14:39.922 --> 00:14:45.089 and I place custom el files here. It's not synchronized in any way, 00:14:45.089 --> 00:14:48.922 and it will be just lost in case you move to a separate machine. 00:14:48.922 --> 00:14:52.456 I do it for a purpose, because I don't use custom.el. 00:14:52.456 --> 00:14:59.456 It's hard to make it reproducible if you're using such mechanism as custom.el. 00:14:59.456 --> 00:15:06.656 How do you learn the Nix language basics? Just from the manual? 00:15:06.656 --> 00:15:10.141 I read a lot of documentation. 00:15:10.141 --> 00:15:15.989 Also, I saw the course like Learn Nix in 15 minutes. 00:15:15.989 --> 00:15:19.289 And also there was another resource. 00:15:19.289 --> 00:15:25.689 Better to ask this question in Nix or NixOS channel in IRC, 00:15:25.689 --> 00:15:32.989 which will be treated in more details. 00:15:32.989 --> 00:15:36.656 What are the main advantages besides switching computers, 00:15:36.656 --> 00:15:38.909 which most people rarely do? 00:15:38.909 --> 00:15:44.422 For example, the original idea was to make part of configurations 00:15:44.422 --> 00:15:46.422 available for projects. 00:15:46.422 --> 00:15:48.156 For example, you have some project, 00:15:48.156 --> 00:15:51.914 you made the setup, and want other developers 00:15:51.914 --> 00:15:55.256 to use the same setup on their machine, 00:15:55.256 --> 00:15:58.122 but you implement only the part of stuff, 00:15:58.122 --> 00:16:01.156 like one subconfig especially for this language 00:16:01.156 --> 00:16:05.389 for this project. With such approach, you can easily 00:16:05.389 --> 00:16:10.556 share such subconfig with other people. 00:16:10.556 --> 00:16:15.239 Have you tried Guix in place of Nix? 00:16:15.239 --> 00:16:22.272 Yes, I tried it, and currently I am in the state of switching from Nix to Guix. 00:16:22.272 --> 00:16:26.739 You can follow my Youtube channel, I think, 00:16:26.739 --> 00:16:32.522 I do streams twice in a month 00:16:32.522 --> 00:16:35.922 talking about reproducibility and related stuff. 00:16:35.922 --> 00:16:39.306 Probably soon I will be talking about installation of Guix 00:16:39.306 --> 00:16:41.239 and configuration of it. 00:16:41.239 --> 00:16:44.956 In case you're watching this video later, 00:16:44.956 --> 00:16:47.972 you can find me somewhere on the network using those contacts. 00:16:47.972 --> 00:16:50.406 It's my nickname and my e-mail address. 00:16:54.072 --> 00:16:56.556 ([Amin:] Awesome. I think we're wrapping up just on time. 00:16:56.556 --> 00:17:00.889 Thank you so much, Andrew, for your great talk, 00:17:00.889 --> 00:17:04.622 and for hanging out to answer the questions live.) 00:17:04.622 --> 00:17:08.022 [Andrew:] Thank you for organizing the conference 00:17:08.022 --> 00:17:11.572 and thank you all participants for questions and participation. 00:17:11.572 --> 00:17:18.000 See you soon!