Based on the .emacs.d
config in the guix-home branch of daviwil/dotfiles. His
config allows you to easily combine dependencies pulled from straight or guix.
Considering the guix packages just updated Emacs 29 -> 30 underneath me while I was migrating dotfiles and I only noticed in the `guix pull` output…
… then I think that this system may work out alright.
Note: the Guix manifest for this project – the emacs-g.scm
file which should
be manifest.scm
– probably includes some custom packages only found in my
dotfiles channel. As soon as you nix.flake, everone else will too.
Doom Emacs wasn’t built in a day.
… So expect some snags along the way.
Not a bene: maintaining the profile currently requires (in this order).
- Run
M-x straight-pull-all
before closing the emacs server- Run
gmacs -- -q
for a fresh process. Keep the server open for a great good.M-:
and run(load (expand-file-name "init.el" dc/emacs-d))
- Then
M-x straight-rebuild-all
Or maybe just delete
~/.emacs.g/straight/repos/straight.el/straight.eln
and runM-x straight-rebuild-all
after probably one error, followed bystraight-rebuild-all
. This avoids the need forobarray
gymnastics.Or travel in time and try to fix Doom Emacs environment/dotfiles from configuring Guile scheme incorrectly.
If the Guix profile contains an updated version of Emacs whose *.eln
is no
longer compatible, you may get weird behavior. I’m not sure what kind of wierd
that is, which is exactly the kind of undefined that I’d prefer to avoid. I
haven’t had many problems in the past, but keeping ~/.emacs.g/straight
does
seem to improve performance.
Assumed file paths are found in ./init.el
Emacs paths & variables
var | value | description |
---|---|---|
dc/emacs-chemacs | $HOME/.emacs.d/ | now you haz backup plan |
dc/emacs-d | $HOME/.emacs.g/ | well this is confusing |
dc/emacs-cache | $HOME/.cache/emacs/ | |
dc/emacs-dw | $HOME/.emacs.g/dw | added to load-path |
dc/emacs-modules | $HOME/.emacs.g/modules | added to load-path |
Org paths & variables
var | value | description |
---|---|---|
org-directory | $ORG_DIRECTORY | |
org-roam-directory | $ORG_DIRECTORY/roam/ | |
org-roam-db-location | may exhibit problems with syncthing |
Other files
var | value | description |
---|---|---|
For a more complete list of .emacs.d
file paths, see these lines in
emacscollective/no-littering.
Dependencies are loaded from guix first by a manifest and straight dependencies are loaded on top.
Update with the script below.
- If the profile doesn’t exist, setting
INSTALL_EMACS
will run activate it - If debugging is needed, set
DEBUG_EMACS
and a new guix profile will be activated. Set the variable again when updating to update the debugging profile. - Other supporting scripts like a systemd service or launcher scripts need to be
updated to respond to
DEBUG_EMACS
as expected. - The repo needs to be cloned to the installation location first. The supporting
scripts expect everything to be in
~/.emacs.g
# hmmm +- works, but ensure DEBUG_EMACS is unset
emacs_profile="emacs-g${DEBUG_EMACS+-debug}"
#default_target=".emacs.g${DEBUG_EMACS+.debug}"
default_target=".emacs.g"
target="${INIT_EMACS:-$HOME/$default_target}"
emacs_manifest="emacs-g.scm"
new_manifest="$emacs_profile.scm"
guix_manifests=$HOME/.config/guix/manifests
guix_channel=$HOME/.dotfiles
cp "$target/$emacs_manifest" "$guix_manifests/$new_manifest"
if [ -d "$GUIX_EXTRA/$emacs_profile" ]; then
update-profiles $emacs_profile
else
activate-profiles $emacs_profile
fi
Moving ~/.emacs.g
to a new location may require blowing away straight with rm
-rf ~/.emacs.g/straight
and reloading emacs to reinstall everything.
Instead of doing it like a caveman, you can also run straight-prune-build
and
straight-rebuild-all
from a fresh emacs session. I miss Doom Emacs already.
If you want to use the font packages from Guix, you’ll need to ensure that the
font directories in ~/.guix-extra-profiles
is made available in fontconfig.
This package ensures that most of your emacs-generated files like cache, history,
etc end up inside ~/.emacs.g/etc
or ~/.emacs.g/var
This is tangled in my dotfiles configured
if ps -e | grep emacs >> /dev/null; then
emacsclient --eval "(if (boundp 'pomm-current-mode-line-string) pomm-current-mode-line-string \"\") " | xargs echo -e
fi
[module/pomm]
type = custom/script
exec = /home/pavel/bin/polybar/pomm.sh
interval = 1
This package needs to be loaded by straight in order for the font to be installed properly. When it’s not, dired won’t function.
Run M-x all-the-icons-install-fonts
Launch emacs with script
export GUIX_SOURCE=$_ECTO/guix/guix
export EMACS_SOURCE=$_ECTO/emacs/emacs/src
# either set DEBUG_EMACS=1 (unset completely to avoid)
# or pass full path with -p
emacs_profile_name="emacs-g${DEBUG_EMACS+-debug}"
emacs_profile=$GUIX_EXTRA/$emacs_profile_name/$emacs_profile_name
search_paths=0
while getopts :Zp OPT; do
case $OPT in
Z|+Z)
search_paths=1
;;
p|+p)
emacs_profile="$OPTARG"
;;
--)
break
;;
*)
echo "usage: `basename $0` [+-p ARG} [--] ARGS..."
echo "-p profile/link"
exit 2
esac
done
shift `expr $OPTIND - 1`
OPTIND=1
if [ 0 -lt "$search_paths" ]; then
guix shell -E "^EMAIL$" \
-E 'EMACS_SOURCE' \
-E 'GUIX_SOURCE' \
-p $emacs_profile \
--search-paths
else
guix shell -E "^EMAIL$" \
-E 'EMACS_SOURCE' \
-E 'GUIX_SOURCE' \
-p $emacs_profile \
-- emacs "$@"
fi
Launch emacs client with script. It really needs to be the same profile (it will probably try to connect anyways)
# either set DEBUG_EMACS=1 (unset completely to avoid)
# or pass full path with -p
emacs_profile_name="emacs-g${DEBUG_EMACS+-debug}"
emacs_profile=$GUIX_EXTRA/$emacs_profile_name/$emacs_profile_name
search_paths=0
while getopts :Zp OPT; do
case $OPT in
Z|+Z)
search_paths=1
;;
p|+p)
emacs_profile="$OPTARG"
;;
--)
break
;;
*)
echo "usage: `basename $0` [+-p ARG} [--] ARGS..."
echo "-p profile/link"
exit 2
esac
done
shift `expr $OPTIND - 1`
OPTIND=1
guix shell -E "^EMAIL$" \
-p $emacs_profile \
-- emacsclient -c "$@"
Shepherd handles service mgmt, but soon this will be specified in Guix Home.
For now, the service is spec’d by scheme in ~/.config/shepherd
GDB expects a raw binary or one with args. That means you can’t just use the
gmacs
script above, but you need a gdb launcher script. Watch this video in
slow-motion for a gdb setup with tmux.
Problems ensue:
Emacs loaded in 30.39 seconds with 27 garbage collections. [yas] Prepared just-in-time loading of snippets successfully.
And running the profile uses have of my 32 CPU threads. Wow. I’m not even sure… (and the light came on)
There’s at least one big problem here: Can the emacs-g-debug
profile run from
the same init.el
? This depends on how compiling emacs package “link” to their
other dependencies. So of course, the answer is ¯\_(ツ)_/¯
or more precisely:
Over here on the x-axis we have … and on the y-axis we have ‘find out.’
I still haven’t really found out yet. I’m pretty sure they link by symbol name,
which is why autoload
and declare-function
do what they do, but I skipped
that part of Emacs 202 way back in 2014.
The straight packages will be built from whatever profile loads them. The Guix
emacs-*
packages handle byte-compiling, whereas straight will build its code
on top of the environment it gets, until it’s asked to rebuild everything. These
builds are actually isolated from one another or, at least they refer to the
outputs of whatever’s in their guix dependency tree – this tree does not depend
on emacs, only on the emacs-build-system process, see also Emacs Packages. The
Guix profile does some management of the dependency tree for a profile’s set of
dependencies.
Yeh… probably don’t check your email if both the emacs-g
and emacs-g-debug
are active and both think they own all the files.
TL;DR; for a better teleological overview on workflow why & how for…
- org-agenda
- see Organize Your Life In Plain Text or Rainer König’s Youtube
- org-roam zettelkasten
- see Vidianos-Giannitsis/Dotfiles/emacs/.emacs.d/libs/Zettelkasten.org
I have 5 priorities configured.
I attempt to capture as close to the context as possible, which is usually the project. I’ve imported some of the Doom Emacs capture templates.
This will be initially set to dc/org-roam-n-dailies
, which defaults
to 5. This clears everything out.
From there, the todo.org
for projects can be appended.
This is initially set as:
(setq-default org-refile-targets `((nil :maxlevel . 3) (org-agenda-files :maxlevel . 2) (org-default-notes-file :maxlevel . 2)) org-outline-path-complete-in-steps nil org-refile-use-outline-path 'file)
There should be an Inbox in each todo.org
file, along with some top-level
categories. For agenda files, two levels of headings are available in the
completing-read
.
Other variants of org-refile
commands can be created/used to allow for more
control when needed.
For an overview from an experienced org-agenda user, see Organize Your Life In Plain Text. It’s pretty much the definitive guide on the subject. There are also these videos from Rainer König, which are by far the best videos for explaining the “why” behind using org-agenda’s features in addition to the how. And it’s the why that’s very difficult to figure out on your own without being able to simply immitate someone else’s patterns.
There are features of org-agenda which if you don’t use, then you’re not really using org-agenda – in which case you’re likely generating large volumes of text to manage. Ask any writer or editor: writing is easy, editing takes forever.
That said, org-mode itself is already too large to learn quickly, especially if you’re attempting to use org-babel or other features like that. So you have to focus on categories of features and think a ton about your own process. Org Agenda and Org Roam and are, for now, very personal information management systems. They are much more personal than other similar PIMS.
There’s some magic to using for GTD, which isn’t necessarily obvious.
in plain english: the size/scope of your agile “stories” along with the number of subitems in a TODO list. The decisions a project manager makes can have multiplicative effects on how their team interacts with the system.
This is your own system, but how you decide to structure tasks in the future
will determine how valuable some features will be or how “stickable” your habits
will be. The org-clock
features are a good example of something that will be
extremely valuable if you can structure your tasks properly. The smaller a
parent task, the more limited its time-tracking history.
If you don’t configure this properly, emacs may sputter out when dealing with too many headlines. It will be tough for you to quickly navigate the chaos.
This is critical for org-agenda and org-roam.
- You should approach the design of the schema like a search optimizaton specialist thinks about a site’s map & content or like a webapp developer thinks about desigining a site’s URL’s to be future proof, discoverable and meaningful.
- You should be designing a relatively future-proof system (at least one that is find-and-replaceable) where you think of both files and headlines as being URL’s.
You have files, you have headlines. Your files can have properties, but so can headlines. What’s the difference between an org file and a headline? It’s almost arbitrary. You should not think as though there are clear file-like boundaries between things in your org files: all the files can be thought of as headlines and all headlines can be thought of as files.
Notice how the IEEE refs for web domains, web URLs and the DOM tree basically create a similar space – and you should think of these as not existing in separate spaces, but in separate dimensions of a shared space. In practice, however, it’s impractical and, really, just overstimulating to do so. There are many exceptions. But it’s useful to understand:
Now your problem is a quite a bit more like deciding what URL’s should be on a website and what your tags should be if some small combination of them were to make your content more discoverable (where it markdown) and more functional if it is org. Since org is a PIMS (and since it’s your PIMS), you at least don’t have the “change management” problem. This makes it a good means of experimenting with different systems.
However, the more content you make, the more you’d have to edit – this should be considered whether your are making changes to your system or whether you are not making changes.
Your decisions in maintaining consistency in content synergize with the emacs tools you use to query or interact with the data. This kind of thinking is (or should be) called “ontological thinking” … but that term is a bit ambiguous,
This ambiguity may be why people in the West are so fucked up in the head. The smarter people among them who didn’t make it far enough in philosophy may not properly dillienate the “study of being” from the term’s usage in categorizing the metaphysical into [hopefully] mutually exclusive sets of nameable categories – e.g. the four elements from alchemy. And this is the source of almost every problem in conceptualization or epistemology: trees eventually must become graphs or networks to adequately describe things. When a system of categorization can maintain its partitioned categories, then trees can always neatly branch into completely separate things.
A different schism regarding conceptualization (of a different nature) occurs in Math where one begins to need Category Cheory instead of relying on Set Theory as a comprehensive foundation.
So think back to when people actually browsed the internet, instead of Facebook. People had personal blogs and they typically need two features to help make their content discoverable: categories and features. The categories and subcategories are the tree-like system of mutually exclusive groups mentioned above. The tags feature are a many-to-many system of classifying content to make it more discoverable. But, for the old-school blogger – what should be a category and what should be a tag? It’s unclear. Maybe tags should also be categories? Or maybe you should only use tags. Fortunately, every website implicitly uses a system almost identical to that of sub/categories: the URL/URI. Every branch point in the categories corresponds to a foreslash in the URL.
Problem solved (or sidestepped) – categories are an unnecessary abstraction. The best part? You don’t have to rack your brain on some O(N^N) ontological problem – that’s just a generous estimation on the complexity.
Doom is a great way to explore features. The codebase is a fantastic showcase of
emacs-lisp
metaprogramming and Emacs config ideas. I don’t use evil-mode
,
which isn’t much of a problem in Doom, but it’s still great. Basically it came
down to whether Guix is more important to me than Doom Emacs.
In Doom Emacs, mixxing Guix and Straight dependencies is a recipe for serious problems – mostly where native comp encounters duplicate dependencies. See this r/guix post for a description of issues with guile..
But there are benefits to pulling deps from guix:
- For one, on foreign distro’s, your
GUILE_LOAD_PATH
will be simple to set & control. This will be managed by the guix profile. - On foreign distro’s, without
emacs-guix
and other guix dependencies, then getting Guile configured properly while having access to the correct guix binary. You may encounter stability issues down the road. If you runguix pull
using the incorrect binary – i.e. you load your emacs profile everywhere so you can start it with systemd – then you’ll eventually pull updates to the wrong guix. - But if you mix both straight & guix packages in emacs, you’ll invariably have
overlapping dependency trees. If you use native comp, then you’ll need to
recompile everything if you update your Emacs binary or build deps. But, for
me,
doom clean
wasn’t working to this end. The reddit post contains more information. - Not having
emacs-guix
is a major impediment to a noob. I’m not a fan of GUI’s generally, but they are a great way to survey the functionality to seed your initial sparse knowledge graph. It can help you ask questions and priortize issues. - Not having
geiser
configured to interoperate at all withemacs-guix
or Guile Scheme kept me a noob for way too long.
Don’t take my word for it. I’m not sure on the correct answer for Guix System and Guix on foreign distro’s. I’m still figuring this out. I will update this description with new information and correct opinions.
The main benefits to mixxing guix + setup.el + straight
- Most of your packages are getting some vetting. The dependencies are ideally
deterministic and you can visualize them with
guix graph
.
Critically, it seems that either straight
or setup.el + straight
can
determine whether dependencies exist locally … AFAIK.
- So if Guix is providing an Emacs package, then
setup
won’t tell straight to load it – I havesetup.el
configured to only load from straight if:straight t
is set. - Regardless, wouldn’t it be useful if
straight
decided it didn’t need to pull dependencies or compile? And it should be trivial to detect requireable modules/namespaces. So it probably does because that would be the correct answer to handle as many configuration scenarios asstraight.el
may encounter.
The dependencies are spec’d out and reproducible packages can be supplied. You
can generate a guix graph
of the dependency graph! If it’s not enough that
Guix packages offer inheritance, tools like guix import
and guix update
are
available.
The flexibility and low maintainence overhead for personal packages makes
maintaining local channels dead simple. I tried RPM and didn’t quite make it to
the mock tools. It was fine, but it wasn’t ideal. I didn’t know what ideal was
until I saw Guix. No other distributions or package managers offer guix home
– they will never have anything like it because they lack the efficiency. There
is no purpose to a poor imitation of guix home
, since it’s still as
complicated as the domain but bundling the packages and services in RPM/Deb and
SystemD require about 10x the effort as similar tasks in Guix. Sadly, it takes a
long time to develop the chops to get to guix home
.
You may need to grok about 2,500 pages of content to get there if you don’t know Scheme … but that’s knowledge you can find in one place, thanks to the GNU documentation. The documentation is good, but there’s a bit of a bootstrapping problem if you don’t have a mentor. If you don’t care about scheme, then you’ll need to study about 250-500 pages, but it’s easy reading.
The scheme is hard. It’s too hard for most people. That’s fine. The difficulty barriers led ArchLinux to be the success that it became. Guix is actually easier, you just don’t realize it.
And why guix system? Because I’ve never learned about Linux this fast. When I wanted a RamFS only image of PXE booting, in one night, I went from:
- A poor understanding of Grub and bootloaders
- To grokking the basics of syslinux and pxelinux
- To understanding u-boot by reading Guix bootloader configs.
- To seeing configs for multiboot after reading
- To How do I adjust the post-boot mounting process init/mount disks to load all filesystems into RamFS by mapping/remapping over initramfs/squashfs?
- To Can Guix load via PXE/TFTP to pull a SquashFS image from HTTPS instead of NFS? So that I can tell if gd macbook pro 2011 has RAM problems or HD problems? Or so I can do something with Dells that don’t have disks?
And no, I can’t answer these questions fully. Guix has some SquashFS functionality, but the bootloader code needs to be modified. Still, you can’t really get around the TFTP limitation of ~100MB. There was a ton of googling there, more gentoo forums/wiki than archwiki… But when I need to confirm the logic of how builds/packages/systems are put together in various scenarios, nothing helps me understand the design of this better than Guix.
So, yeh, I’d like to have a consistent experience with emacs-guix
and
geiser
. And I’d like guix-devel-mode
to work.
I’ve been pushing forward where I could, trying to minimize moving parts. I
hope I haven’t pre-emptively obselesced some future guix-home
configuration
for Emacs. I think I’ve already obviated any simple means of building Emacs as a
set of Guix Home packages/services…
Guix Home elsewhere? Definitely, but I need a realistic migration path. For Emacs, I am also hesitant on trans-lisp configuration DSL’s outside of simple home services – but I need more experience with emacs-lisp before that could be a reasonable problem to deal with. Separating concerns in emacs configs while being able to quickly edit the config is too much for now. The benefits and drawbacks to the process and potentiallys are probably similar to Literate dotfiles – they can provide a standard experience or make projects like ESS/Scimacs/Doom more consistent or replicable.
Here I was also skeptical of how Guix itself would handle edge cases for system config – the immutability, the need to write packages for small things, the service dependencies, the lack of SystemD, lack of nonfree software by default, etc.
However, these turn out to be great limitations:
- immutability: I don’t have to care really. I just reinstall. Eventually, I may
use
guix time-machine
or be concerned with the specifics of reproducibility. - packages for small things: I should’ve been doing this for a decade or longer.
- services for small things: … ditto.
- on SystemD: now I appreciate/understand SystemD a bit more and the kind of tools/commands that services or SystemD components utilize.
- on lack of nonfree software in the ISO: this is complicated. If my Macbook Pro
2011 didn’t run the ISO, I may have assumed Guix was broken. But now I
understand, what non-free software runs on my hardware and where it is. I’m a
pragmatist, so while I prefer FOSS, but usually end up running a lot of
non-free software. But I am a lot more capable of knowing and deciding now.
So, my perspective/depth on this would be limited or misleading.
Without boundaries, the free energy in a particle simulation disperses quickly – i.e. some limitations can be essential to shape your creativity.