diff --git a/README.md b/README.md index 893d7bc..0b94c95 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,11 @@ The home-manager module supports the same options, as well as: - `provideEmacs`: disable this to only provide a `doom-emacs` binary, not an `emacs` binary (that is: it switches from `emacsWithDoom` to `doomEmacs`). Use this if you want to install vanilla Emacs in parallel. + +- `extraPackages`: Specify extra Emacs packages from nixpkgs to be available to Doom Emacs. +Defaults to this function `epkgs: [ ]` (no extra packages). +For example to include Emacs package `treesit-grammars.with-all-grammars`: +`extraPackages = epkgs: [ epkgs.treesit-grammars.with-all-grammars ];`. ## Comparison to "normal" Doom Emacs @@ -309,6 +314,29 @@ Unstraightened uses `--init-directory`, as the doctor recommends. Safe to ignore, for the same reason as the previous warning. +### tree-sitter error on initialization with `file-error "Opening output file" "Read-only file system"` +The ABI loaded for some grammars from nixpkgs is too new (14) compared to what vanilla Doom Emacs receives (13). +This results in tree-sitter and some particular grammars to be incompatible. +This issue is currently confirmed to affect golang. + +See issue [#7](https://github.com/marienz/nix-doom-emacs-unstraightened/issues/7) for a more detailed explanation. + +Considering that Doom Emacs will likely use the Emacs 29+ built-in tree-sitter at some point at least as an opt-in +(see related [Doom Emacs issue](https://github.com/doomemacs/doomemacs/issues/7623)) +this particular issue for Unstraightened is unlikely to get solved. + +As a workaround the following is possible: +- Temporarily disable Doom Emacs from handling tree-sitter in `init.el`. +- Define your nix Emacs package to be compiled with native tree-sitter support. +- Use package [treesit-auto](https://github.com/renzmann/treesit-auto) (e.g. it to `packages.el`) +to gracefully include activation of tree-sitter specific modes of a programming language, +depending on if a particular grammer is installed or not. +- Include Emacs package `treesit-grammars.with-all-grammars` from nixpkgs, +e.g. use the home-manager option `extraPackages` like so: +`extraPackages = epkgs: [ epkgs.treesit-grammars.with-all-grammars ];`. + +As a result tree-sitter (built-in to Emacs) will be compatible with the current ABI for grammars included in nixpkgs. + ## Frequently Anticipated Questions ### How do I add more packages? @@ -318,8 +346,8 @@ Add `(package! foo)` to `packages.el`. Do not wrap emacsWithDoom in emacsWithPackages. See HACKING.md for why this will not work. -If this is not sufficient, file an issue. I can add a hook to add more packages -from Nix: I just don't want to add that hook unless someone has a use for it. +The home-manager option `extraPackages` is available to add extra Emacs packages from nixpkgs to Doom Emacs. +If this is not sufficient, please file an issue. ### How do I add packages not in Emacs overlay? diff --git a/checks.nix b/checks.nix index 36f32c2..e9d4b81 100644 --- a/checks.nix +++ b/checks.nix @@ -67,6 +67,10 @@ in { minimalEmacs = (makeDoomPackages (common // { doomDir = minimalDoomDir; })).emacsWithDoom; + minimalExtraPackages = mkDoom { + doomDir = minimalDoomDir; + extraPackages = epkgs: [ epkgs.vterm epkgs.treesit-grammars.with-all-grammars ]; + }; allModules = mkDoom { doomDir = allModsDoomDir; }; allModulesAndFlags = mkDoom { doomDir = allFlagsDoomDir; }; example = mkDoom { doomDir = ./doomdir; }; @@ -81,4 +85,6 @@ in { # Various tests of module combinations. unpinned-org = doomTest "external-org" { app = [ [ "rss" "+org" ] ]; } { }; + + extraPackages = doomTest "extraPackages" { config = [ "default" ]; } { extraPackages = epkgs: [ epkgs.vterm ]; }; } diff --git a/default.nix b/default.nix index e460f7e..95238f2 100644 --- a/default.nix +++ b/default.nix @@ -38,6 +38,8 @@ noProfileHack ? false, /* Use fetchTree instead of fetchGit for package fetches. */ experimentalFetchTree ? false, + /* Extra emacs packages from nixpkgs */ + extraPackages ? epkgs: [ ], callPackages, git, @@ -331,7 +333,7 @@ let # Step 3: Build an emacsWithPackages, pulling all packages from step 1 from # the set from step 2. emacsWithPackages = doomEmacsPackages.emacsWithPackages - (epkgs: (map (p: epkgs.${p}) (builtins.attrNames doomPackageSet))); + (epkgs: (map (p: epkgs.${p}) (builtins.attrNames doomPackageSet)) ++ (extraPackages epkgs)); # Step 4: build a DOOMDIR, Doom profile and profile loader using Emacs from # step 3 and packages.el from step 1. diff --git a/home-manager.nix b/home-manager.nix index a438366..1bf360f 100644 --- a/home-manager.nix +++ b/home-manager.nix @@ -17,7 +17,7 @@ let cfg = config.programs.doom-emacs; - inherit (lib) literalExpression mkEnableOption mkIf mkMerge mkOption types; + inherit (lib) literalExpression mkEnableOption mkIf mkMerge mkOption types hm; in { options = { programs.doom-emacs = { @@ -94,13 +94,40 @@ in { readOnly = true; description = "The final doom-emacs package"; }; + + extraPackages = mkOption { + default = self: [ ]; + type = hm.types.selectorFunction; + defaultText = "epkgs: [ ]"; + example = literalExpression + "epkgs: [ epkgs.treesit-grammars.with-all-grammars ]"; + description = '' + Extra Emacs packages from nixpkgs available to Doom Emacs, + unless that packages is handled by Doom Emacs. + + If Doom Emacs specifies a package, + then that specific package and version will be exactly as Doom specifies even if it's + included in 'extraPackages'. + + To use 'extraPackages' to override a specific package otherwise specified by Doom Emacs, + it is required that the Doom Emacs config use the following arguments for the package: + '(package! ... :built-in t)' + This allows nix to be used to apply patches to an Emacs package. + + Some Emacs packages from nixpkgs have additional side-effects specific to nix, + consider the Emacs Package 'treesit-grammars.with-all-grammars'. + It downloads all treesitter grammars defined in nixpkgs at build time and makes them + available on path for Emacs at runtime. + Doom cannot specify that package using the '(package! ...)' syntax. + ''; + }; }; }; config = mkIf cfg.enable (mkMerge [ (let doomPackages = doomFromPackages pkgs { - inherit (cfg) emacs doomDir doomLocalDir profileName noProfileHack; + inherit (cfg) emacs doomDir doomLocalDir profileName noProfileHack extraPackages; }; in { diff --git a/tests.el b/tests.el index 6f22de6..5686dfe 100644 --- a/tests.el +++ b/tests.el @@ -49,4 +49,7 @@ (write-region result nil out nil nil nil 'mustbenew)) (kill-emacs)) +(defun test-extraPackages () + (require 'vterm)) + (add-hook 'doom-after-init-hook 'test-doom)