radian-software / radian

🍉 Dotfiles that marry elegance and practicality.
MIT License
490 stars 47 forks source link

New option: radian-disabled-packages #478

Closed haji-ali closed 2 years ago

haji-ali commented 3 years ago

Implemented ideas from #475.

As an example, here's the setting that causes Radian not to load any packages (Except for the mandatory straight, use-package, blackout, bind-key and el-patch).

(setq radian-disabled-packages
        '(straight-x no-littering org-plus-contrib org
                     which-key selectrum prescient selectrum-prescient windmove winner
                     transpose-frame buffer-move ibuffer saveplace projectile auth-source
                     newcomment whitespace outline delsel warnings undo-tree subword bookmark ctrlf
                     fileloop visual-regexp visual-regexp-steroids autorevert smartparens org
                     org-agenda apheleia abbrev yasnippet company pyvenv lsp-mode company
                     company-prescient company-lsp lsp dumb-jump eldoc flycheck lsp-ui lsp-mode
                     lsp-ui-doc lisp-mode apples-mode cc-mode clojure-mode cider cider-doc go-mode
                     lsp-ui haskell-mode haskell haskell-customize lsp-haskell lua-mode make-mode
                     markdown-mode protobuf-mode python lsp-python-ms robe ruby-electric rust-mode
                     geiser sh-script swift-mode auctex tex tex-buf latex font-latex vimrc-mode js
                     web-mode apheleia apache-mode crontab-mode dockerfile-mode gitconfig-mode
                     gitignore-mode json-mode pip-requirements pkgbuild-mode ssh-config-mode
                     terraform-mode toml-mode yaml-mode help helpful cus-edit elisp-mode find-func
                     macrostep bytecomp checkdoc package-lint org org-indent org-agenda org-clock
                     osx-trash dired dired-x term vc-hooks smerge-mode with-editor transient magit
                     magit-diff git-commit emacsql-sqlite forge forge-core git-gutter autorevert
                     apheleia git-gutter-fringe git-gutter compile rg browse-url bug-reference
                     git-link atomic-chrome sx esup restart-emacs which-key zerodark-theme
                     zerodark-theme git-gutter))

PS: This is not relevant to this pull request. But I find it strange that el-patch is loaded even when radian.el is compiled. Perhaps loading the package should be excluded from the compiled file? But then it would be automatically pruned which might be undesirable.

haji-ali commented 3 years ago

For me, (featurep 'el-patch) returns nil after init, unless el-patch was rebuilt by straight.el due to modifications to its source code. Remember, (straight-use-package 'el-patch) doesn't actually load el-patch: it only adds the package to load-path, so that it can be loaded if requested.

Ah yes, I didn't notice before, but el-patch was actually being automatically loaded because I was using it. Please disregard this comment.

hrehfeld commented 3 years ago

One minor comment:

If we disallow-list things, it's not possible to be achieve a state where you're safe against radian pulling in new unwanted features.

If we allow-list things, you can (setq radian-features '(my features))to get that behavior, but still easily achieve the current behavior by just removing unwanted things as in (setq radian-features (delq 'my-feature radian-features)).

Maybe even provide (defun radian-disable-feature (feature-sym)) (setq radian-features (delq feature-sym radian-features))? Or let it take a list...

raxod502 commented 3 years ago

Hey @haji-ali, sorry for the delay, I have returned to civilization.

disallow-list vs allow-list

I think this might be a case where we can eat our cake and have it too! We could have a variable radian-disabled-packages as present, but that list can start with :not, in which case it changes from a denylist to an allowlist. I've seen this pattern at least once before in Emacs package configuration, though I can't remember where off the top of my head.

Maybe even provide radian-disable-feature

Yeah, we could definitely do that!

haji-ali commented 3 years ago

@raxod502, I just forced pushed the suggestions. radian-disabled-packages can now start with :not as suggested.

I still need to figure out two things:

haji-ali commented 2 years ago

Another point for consideration. For some reason when compiling radian.el, I get error of the form cannot load package-X for disabled packages. I am not sure why disabled packages are being loaded during compilations but not during execution.

raxod502 commented 2 years ago

I apologize for the great delay here. I am going to take a look at this PR and see if I can't finish it up on my end.

raxod502 commented 2 years ago

Verified that (setq radian-disabled-packages '(magit magit-diff forge)) successfully appears to disable Magit configuration at runtime. However, I do see lots of byte-compilation errors. Will investigate.

``` make -sC "$(git rev-parse --show-toplevel)" lint Cannot load magit: (file-missing "Cannot open load file" "No such file or directory" "magit") radian.el:4466:9: Warning: assignment to free variable ‘magit-no-message’ radian.el:4522:13: Warning: reference to free variable ‘magit-credential-cache-daemon-socket’ radian.el:4480:33: Warning: reference to free variable ‘magit-credential-cache-daemon-process’ radian.el:4483:13: Warning: assignment to free variable ‘magit-credential-cache-daemon-process’ radian.el:4522:50: Warning: assignment to free variable ‘magit-credential-cache-daemon-socket’ radian.el:4527:9: Warning: assignment to free variable ‘magit-save-repository-buffers’ Cannot load magit-diff: (file-missing "Cannot open load file" "No such file or directory" "magit-diff") Cannot load git-commit: (file-missing "Cannot open load file" "No such file or directory" "git-commit") radian.el:4565:9: Warning: assignment to free variable ‘git-commit-summary-max-length’ Cannot load emacsql-sqlite: (file-missing "Cannot open load file" "No such file or directory" "emacsql-sqlite") Cannot load forge: (file-missing "Cannot open load file" "No such file or directory" "forge") Cannot load forge-core: (file-missing "Cannot open load file" "No such file or directory" "forge-core") radian.el:4616:32: Warning: reference to free variable ‘emacsql-sqlite-executable’ radian.el:4837:58: Warning: the function ‘magit-mode’ is not known to be defined. radian.el:4610:15: Warning: the function ‘forge-dispatch’ is not known to be defined. radian.el:4617:8: Warning: the function ‘emacsql-sqlite-compile’ is not known to be defined. radian.el:4601:21: Warning: the function ‘forge-get-repository’ is not known to be defined. radian.el:4584:21: Warning: the function ‘emacsql-sqlite-ensure-binary’ is not known to be defined. radian.el:4545:15: Warning: the function ‘magit-diff-visit-file--setup’ is not known to be defined. radian.el:4507:21: Warning: the function ‘magit-maybe-start-credential-cache-daemon’ is not known to be defined. radian.el:4498:41: Warning: the function ‘magit-git-executable’ is not known to be defined. radian.el:4460:25: Warning: the function ‘el-patch-require-magit’ is not known to be defined. make: *** [Makefile:25: compile] Error 1 ```
raxod502 commented 2 years ago

Ah, so the issue here is basically that since the package is not loaded, Emacs cannot verify that any of the functions in the package configuration are defined, hence warnings get thrown.

The answer to why the packages are getting loaded is pretty simple---that's a default behavior of use-package, it tries to load the package at byte-compile time for exactly this reason (to avoid byte-compilation warnings and possible wrong macroexpansion in some rare edge cases). Even though the use-package form is nested inside an if branch that isn't touched at runtime, Emacs does not know that at byte-compilation time (and with the current design, radian-disabled-packages could actually be determined at runtime).

I'm not sure what would be the right thing to do here. Will think on it.

raxod502 commented 2 years ago

One option would be to load all packages during byte-compilation, ignoring radian-disabled-packages. However, this has some undesirable side effects, including:

The fundamental issue here is that radian-disabled-packages is customizable at runtime, but we need to know whether a package is disabled at compile time. The most appropriate solution seems to me to be to force radian-disabled-packages to be customizable only statically at the beginning of init. This should be possible. I will investigate.

raxod502 commented 2 years ago

I came up with a workaround. We can sidestep the problem by observing that while we cannot byte-compile a package's configuration without having that package loaded, this does not make the configuration invalid. Therefore, if the package is not available at byte-compile time, we can simply refrain from byte-compiling the configuration, and leave it unchanged. I implemented a wrapper macro that does the necessary feature detection, and this appears to fully resolve the problem described above without introducing any new constraints on configuration.

However, disabling one package may still introduce byte-compilation warnings in other packages' configuration. For example, disabling Magit as described above leads to a warning here, which is completely legitimate and expected from a correctness standpoint, but not good from a user standpoint: https://github.com/raxod502/radian/blob/9f7891c52cac04e49b95c4ce93d3bc18bef9ab0b/emacs/radian.el#L4849-L4854

Some thought will be needed to figure out how to handle these cross-package configuration dependencies in general, or if there is a good way to do so.

raxod502 commented 2 years ago

This should be straightforward to address on a package-by-package basis. I have pushed a commit which corrects the issue with disabling Magit. I tested disabling Org and it appears to work fine. With that, I think this feature looks basically correct. @haji-ali, would you be able to see if it works in your setup and for all the desired packages?

haji-ali commented 2 years ago

@raxod502, thanks for these fixes and the nice approach to fixing the compilation!

I just had time to try out this feature, sorry for the delay. I noticed the following problems;

raxod502 commented 2 years ago

Alrighty, I think all those issues should now be fixed. Thoughts?

raxod502 commented 2 years ago

Ugh, they renamed functions again between Emacs versions---have to add a switch between abort-minibuffers and whatever it used to be called. Will tackle that at some point, if you don't get to it first.

haji-ali commented 2 years ago

Great! Just tested and everything works as expected. A couple of thoughts/changes:

raxod502 commented 2 years ago

LGTM! Thanks!