Greetings everyone,
After I proposed a new customization interface for Emacs [1], I jumped on the occasion to rewrite my literate org configuration to replicate this interface idea there. I saw many and various configurations files using org, (from where I took some inspiration when I first started), but I did not came across the approach I am presenting below. I am sure it will interest many people already using org to configure emacs (and maybe others to jump into org and try it). What I had before: ------------------ * package1 #+begin_src emacs-lisp (use-package package1 ...) #+end_src * package2 #+begin_src emacs-lisp (use-package package2 ...) #+end_src What I have after: ------------------ #+TAGS: [ group1 : tag1 tag2 tag3 tag4 tag5 ] #+TAGS: [ group2 : tag6 tag7 tag8 tag9 ] filters --------- group1 : tag1 tag2 tag3 tag4 tag5 group2 : tag6 tag7 tag8 tag9 * package1 :tag1:tag2: ** option1 :tag3:tag4:tag5: - [ ] choice1 - [X] choice2 - [ ] choice3 ** option2 :tag4:tag5:tag6: ** option3 :tag5:tag6:tag7: ** install ** load/enable feature ** keymap/keybinding * package2 same here. So what I did, is that, I removed almost all (use-package) declarations. Some of the main advantages are : - allow tagging options individually, and easily find them later. - allow adding org comments for each option separatly, (and even sometimes for a given choice). - easily reference (via org links) other options individually, from within org comments. - Also IMO, for new users for example, it is easier to read and understand this org configuration, than to see a (use-package) declaration. It is true that org comments will help, but also new users won’t have an additional step to learn use-package. - it introduces new users directly to Emacs Lisp functions, like hook functions, etc, which make it easier for them to learn Emacs Lisp, and also to easily hack things to their preferences. - this also allows sharing more granular code snippets (as needed), instead of having to copy a whole (use-package) declaration, and sometimes without really understanding what the declaration (or a part of it) is supposed to do, and how someone is supposed to tweak it, without breaking anything (and without having to learn use-package, as a prerequisite). This is not a with/against use-package discussion at all (please don’t divert from the main idea). The main reason I removed use-package is to be able to _tag options individually, to easily find them later_ , (for this, I wanted each org code-block to be totally independent from all others code-blocks). This is the fundamental idea behind this new literate config approach (besides the other advantages it provides, which are numerous) I will explain briefly each part : Filters: -------- These are org links (ex. [[mytagfilter:tag1][tag1]]). Clicking on tag1 for example, will show only options tagged as “tag1” (and at the same time, will hide other irrelevant tags that makes no sense to select anymore). It is a known filter mechanism, and is not specific to this approach. (I hope if org maintainers and/or contributors can implement this in org, because I find it useful in all my org files. I think many would find it useful too.) Install: -------- Is how to install the package. This is still work in progress, but this is how I imagine it : ** install - [ ] immediately call package functions directly. - [ ] at the end of the init append the package name in a variable and install the packages at the end. - [ ] etc other installation methods. Maybe use-package or others can be (temporary) used here, if someone wants to (for its installation part). Use-package can still be used, anywhere someone find it useful, it is not mandatory to completely remove use-package (but only for a single purpose). Emacs is hackable after all, and everyone can use whatever they want. Options: -------- ** option - [ ] choice1 (default) The default value should not be tangled into the init file. #+begin_src emacs-lisp (setopt option defaultvalue) #+end_src - [ ] choice2 #+begin_src emacs-lisp (setopt option value2) #+end_src - [ ] choice3 #+begin_src emacs-lisp Sometimes user needs to write complex regex. #+end_src - [X] choice4 #+begin_src emacs-lisp Sometimes user needs to add/remove hooks. Sometimes user needs to do that for specific mode(s). #+end_src - [ ] choice5 #+begin_src emacs-lisp Sometimes user needs to write a complex functions. #+end_src - [ ] etc Some may say it is sometimes difficult to divide some options into more granular choices that can be checked/selected individually, (ex. when the option is a hook, list, etc.), but I managed to do so successfully for the moment. (Maybe because my setup is not too complicated ?). If someone can think of, or find in their config, an option that cannot be divided into comprehensive choices like above, we can maybe discuss it, but I think there should be a way to do that, even if sometimes there is little bit of overlapping (not mutually exclusive choices). load/enable feature: -------------------- This is to load/enable a package/feature. Example : * which-key ** load/enable feature - [ ] disable (default) [ ] enable immediately #+begin_src emacs-lisp (which-key-mode) #+end_src - [X] enabled after emacs idle delay #+begin_src emacs-lisp (run-with-idle-timer 2 nil #'which-key-mode t) #+end_src - [ ] enabled immediately after feature1 is loaded #+begin_src emacs-lisp (eval-after-load 'feature1 '(which-key-mode)) #+end_src - [ ] enable manually (autoload when which-key-mode is called) [ This is just an example. which-key-mode is already autoloaded ] #+begin_src emacs-lisp (unless (fboundp 'which-key-mode) (autoload #'which-key-mode "which-key" nil t)) #+end_src - [ ] etc These are also general choices examples, no need to add them all for every package, only when it make sense. (I usually tend to defer loading features, in a way or other, so emacs starts faster). I wish I could share my org config file, but it is still work in progress, and I also need to do a lot of cleanups before having something shareable, and I don’t really have time to do so. So I preferred at least, to share the idea with you all, so you can explore it from now, and convert your config, if you find it useful. Also for people who wants to jump into org literate config and haven’t done so yet, maybe they can consider this approach from the very start. Also, if someone have time, and can start a project including an org file, and begin with few packages, then we can start sharing our code snippets (specially for complex configurations), so we can have a central configuration for everyone to use (new/non-new users), while being able to pick and choose the needed package(s), and how to install them, and also to easily tweak everything, with many choices to select from. We can also add buttons/links (for new users) to select a given choice, and to save/tangle the modifications into the init file. (I am adding/removing “tangle” header arguments, and calling ‘org-babel-tangle’ manually for the moment. Not complicated after all). The org file can also be enhanced in many other ways. If we want to also tag and/or reference individual option’s choices, (which I find very useful in many cases), we should use org headings instead of org lists. There is not need to argue which archive, package or option to include/exclude, etc. We can include literally everything. Anyone can send his favorite package(s), option(s), and even individual choice(s), and also the favorite method to install a package, etc. A problem I can see, is when we will have a lot of packages. So maybe then we can separate each package into his own org file, while having a single main org file containing the tags/filters. The tag filtering should be made to work just like it works today for org agenda files. If org experts can give us some advice on if it is something reasonable to do, and what is the best approach. Another thing, is how we can implement a way to keep someone’s local config org file(s) synced with the central config org file(s)’s modifications, without loosing local customizations. (Maybe we can assign an org id to each choice). There may be other things to take into account too. But we should not consider anything as blocking. Because having a central place where we can share all our config efficiently, is already a good thing in itself, and outweigh any other secondary inconvenience. So if someone has time to do so, I think it is a very good idea, instead of every person struggling on his own through the exact same difficulties, and spending the same amount of time and energy in building their individual configuration file over the years, and without having a way to share them efficiently, so everyone can benefits from each other valuable work. If an org file like this can exist, I think the “emacs is difficult to start with” will be from the past, and the same can be said for “maintaining one’s init file over time”. If I could find an org file like this when I first started, it would have spared me an enormous amount of work and research, and I think this would be the same for others. Although there are a lot of org literate config everywhere, (and non-literate too), they almost all use use-package declarations, which _as a new user_ , I found difficult to understand and tweak, unless I learn use-package and some Emacs Lisp before-hand. With this approach, all you have to learn is org markup (not really after all, it is just a normal text file). You open emacs, then you open this org file, then you read a 2min quick intro about how to use it, and you are ready to go : - you can directly customize emacs (even with very advanced customizations) - you gradually learn Emacs Lisp, by looking at the code-blocks from time to time. - you can even change some customizations, by copying code-blocks and modifying them as needed, when you have enough Emacs Lisp knowledge. I tried to keep the presentation as short as possible, while still being clear enough. If there is something unclear or important but missing, let me know. Thanks in advance, [1] https://lists.gnu.org/archive/html/emacs-devel/2024-12/msg00344.html [ I am not sure which mailing list is the appropriate one. ] [ Maybe this can be a step before implementing option’s tagging and filtering natively into Emacs. ]