Emacs: Difference between revisions
Added a workaround for a bug that hasn't been fixed upstream yet, when using xwidgets and pgtk. |
fix formatting and consistency |
||
| (One intermediate revision by the same user not shown) | |||
| Line 20: | Line 20: | ||
To temporarily use Emacs in a shell environment without modifying your system configuration, you can run: | To temporarily use Emacs in a shell environment without modifying your system configuration, you can run: | ||
<syntaxhighlight lang=console> | |||
< | |||
$ nix-shell -p emacs | $ nix-shell -p emacs | ||
</ | </syntaxhighlight> | ||
This makes the Emacs editor available in your current shell. You can then launch Emacs by typing <code>emacs</code>. | This makes the Emacs editor available in your current shell. You can then launch Emacs by typing <code>emacs</code>. | ||
| Line 31: | Line 30: | ||
To install Emacs system-wide, making it available to all users, add the following to your configuration: | To install Emacs system-wide, making it available to all users, add the following to your configuration: | ||
{{file|/etc/nixos/configuration.nix|nix| | {{file|/etc/nixos/configuration.nix|nix|3= | ||
environment.systemPackages = [ | environment.systemPackages = [ | ||
pkgs.emacs | pkgs.emacs | ||
]; | ]; | ||
}} | }} | ||
Alternatively, Emacs can be installed specific to a user via [[Home Manager]]: | Alternatively, Emacs can be installed specific to a user via [[Home Manager]]: | ||
{{file|home.nix|nix| | {{file|home.nix|nix|3= | ||
home.packages = [ | home.packages = [ | ||
pkgs.emacs | pkgs.emacs | ||
]; | ]; | ||
}} | }} | ||
| Line 56: | Line 52: | ||
System wide configuration of Emacs is limited to only the [https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html Emacs daemon]. To enable Emacs daemon user services system-wide and set as default editor: | System wide configuration of Emacs is limited to only the [https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html Emacs daemon]. To enable Emacs daemon user services system-wide and set as default editor: | ||
{{file|/etc/nixos/configuration.nix|nix| | {{file|/etc/nixos/configuration.nix|nix|3= | ||
services.emacs = { | services.emacs = { | ||
enable = true; | |||
defaultEditor = true; | |||
}; | }; | ||
}} | }} | ||
| Line 72: | Line 67: | ||
A minimal configuration that installs Emacs alongside <code>nix-mode</code> and <code>nixfmt</code> packages: | A minimal configuration that installs Emacs alongside <code>nix-mode</code> and <code>nixfmt</code> packages: | ||
{{file|home.nix|nix| | {{file|home.nix|nix|3= | ||
programs.emacs = { | programs.emacs = { | ||
enable = true; | enable = true; | ||
package = pkgs.emacs; | package = pkgs.emacs; # replace with pkgs.emacs-gtk if desired | ||
extraPackages = epkgs: [ | extraPackages = epkgs: [ | ||
epkgs.nix-mode | epkgs.nix-mode | ||
| Line 84: | Line 79: | ||
''; | ''; | ||
}; | }; | ||
}} | }} | ||
| Line 93: | Line 87: | ||
Home Manager also provides a configuration module for enabling the Emacs daemon: | Home Manager also provides a configuration module for enabling the Emacs daemon: | ||
{{file|home.nix|nix| | {{file|home.nix|nix|3= | ||
# Emacs is running as a daemon here, accesible via the "emacsclient" command | # Emacs is running as a daemon here, accesible via the "emacsclient" command | ||
services.emacs = { | services.emacs = { | ||
| Line 99: | Line 93: | ||
defaultEditor = true; | defaultEditor = true; | ||
}; | }; | ||
}} | }} | ||
| Line 108: | Line 101: | ||
==== Installing Packages ==== | ==== Installing Packages ==== | ||
{{Note|Emacs, much like NixOS can rebuild and re-fetch all of its packages based on its initialization file alone, if one chooses to use an extension called "use-package". Such a configuration file can be version controlled and used in all compatible operating systems.}} | {{Note|Emacs, much like NixOS can rebuild and re-fetch all of its packages based on its initialization file alone, if one chooses to use an extension called "use-package". Such a configuration file can be version controlled and used in all compatible operating systems.}} | ||
One can mix and match whether Emacs packages are installed by Nix or Emacs. This can be particularly useful for Emacs packages that need to be built, such as vterm. One way to install Emacs packages through Nix is by the following, replacing {{ic|emacs-pgtk}} with the variant in use: | One can mix and match whether Emacs packages are installed by Nix or Emacs. This can be particularly useful for Emacs packages that need to be built, such as vterm. One way to install Emacs packages through Nix is by the following, replacing {{ic|emacs-pgtk}} with the variant in use: | ||
environment.systemPackages = with pkgs; | {{file|/etc/nixos/configuration.nix|nix|3= | ||
environment.systemPackages = with pkgs; [ | |||
... | |||
((emacsPackagesFor emacs-pgtk).emacsWithPackages ( | ((emacsPackagesFor emacs-pgtk).emacsWithPackages ( | ||
epkgs: [ epkgs.vterm ] | epkgs: [ epkgs.vterm ] | ||
| Line 127: | Line 121: | ||
# To fix this, write the package name in quotes and specify the package set, even if using with epkgs;. | # To fix this, write the package name in quotes and specify the package set, even if using with epkgs;. | ||
# For example, use epkgs."ido-completing-read+". | # For example, use epkgs."ido-completing-read+". | ||
}} | |||
Note that if the expression <code>(emacsPackagesFor emacs-pgtk)</code> is present, <code>emacs-pgtk</code> need not be listed separately in the list <code>environment.systemPackages</code>. Indeed, if one does that, <code>nixos-rebuild</code> will warn about link collisions when the configuration is rebuilt. | |||
====== Alternative way of installation to ensuring consistent package management for emacs and emacsclient ====== | ====== Alternative way of installation to ensuring consistent package management for emacs and emacsclient ====== | ||
If you plan to use the same packages for both emacs and emacsclient, you can define a custom emacs like this: | If you plan to use the same packages for both emacs and emacsclient, you can define a custom emacs like this: | ||
{{file|/etc/nixos/configuration.nix|nix| | {{file|/etc/nixos/configuration.nix|nix|3= | ||
nixpkgs.config.packageOverrides = pkgs: rec { | |||
myEmacs = pkgs.emacs.pkgs.withPackages (epkgs: with epkgs; [ | |||
org | |||
nixmode | |||
... # list all your desired emacsPackages here | |||
]); | |||
}; | |||
}} | |||
You may then reference it twice: | You may then reference it twice: | ||
{{file|/etc/nixos/configuration.nix|nix| | {{file|/etc/nixos/configuration.nix|nix|3= | ||
# if you want it per-user instead of system-wide use 'users.users.<name>.packages = with pkgs; [' instead | |||
environment.systemPackages = with pkgs; [ | |||
myEmacs | |||
]; | |||
# enabling emacsclient and making all the packages available | |||
services.emacs = { | |||
enable = true; | |||
package = pkgs.myEmacs; | |||
}; | |||
}} | |||
Using this approach, there is no need to keep two lists of emacsPackages in sync. | Using this approach, there is no need to keep two lists of emacsPackages in sync. | ||
| Line 189: | Line 179: | ||
==== Automatic Package Management ==== | ==== Automatic Package Management ==== | ||
If you use <code>use-package</code> or <code>leaf</code> in your configuration, the community overlay can manage your Emacs packages automatically by using <code>emacsWithPackagesFromUsePackage</code>. First, install the overlay (instructions above), then add the following to your <code>configuration.nix</code>: | If you use <code>use-package</code> or <code>leaf</code> in your configuration, the community overlay can manage your Emacs packages automatically by using <code>emacsWithPackagesFromUsePackage</code>. First, install the overlay (instructions above), then add the following to your <code>configuration.nix</code>: | ||
{{file|/etc/nixos/configuration.nix|nix|3= | |||
environment.systemPackages = [ | |||
(pkgs.emacsWithPackagesFromUsePackage { | |||
package = pkgs.emacsGit; # replace with pkgs.emacsPgtk, or another version if desired. | |||
config = path/to/your/config.el; | |||
# config = path/to/your/config.org; # Org-Babel configs also supported | |||
# Optionally provide extra packages not in the configuration file. | |||
extraEmacsPackages = epkgs: [ | |||
epkgs.use-package | |||
]; | |||
# Optionally override derivations. | |||
override = epkgs: epkgs // { | |||
somePackage = epkgs.melpaPackages.somePackage.overrideAttrs(old: { | |||
# Apply fixes here | |||
}); | |||
}; | |||
}) | |||
]; | |||
} | }} | ||
See the [https://github.com/nix-community/emacs-overlay#extra-library-functionality overlay README] for a full list of options. | See the [https://github.com/nix-community/emacs-overlay#extra-library-functionality overlay README] for a full list of options. | ||
| Line 218: | Line 206: | ||
Some packages may require more sophisticated derivation, but the following is a good starting point for adding external packages: | Some packages may require more sophisticated derivation, but the following is a good starting point for adding external packages: | ||
{{file|lambda-line.nix|nix| | {{file|lambda-line.nix|nix|3= | ||
{ | { | ||
melpaBuild, | melpaBuild, | ||
| Line 238: | Line 226: | ||
]; | ]; | ||
} | } | ||
}} | |||
You can then use the new package with automatic package management like so: | You can then use the new package with automatic package management like so: | ||
{{file|configuration.nix|nix| | {{file|configuration.nix|nix|3= | ||
environment.systemPackages = [ | |||
(pkgs.emacsWithPackagesFromUsePackage { | |||
... | |||
override = epkgs: epkgs // { | |||
lambda-line = callPackage ./lambda-line.nix { | |||
inherit (pkgs) fetchFromGitHub; | |||
inherit (epkgs) melpaBuild all-the-icons; | |||
}; | }; | ||
}) | }; | ||
}) | |||
]; | |||
}} | |||
or manual package management like so: | or manual package management like so: | ||
{{file|configuration.nix|nix| | {{file|configuration.nix|nix|3= | ||
environment.systemPackages = with pkgs; [ | |||
... | |||
((emacsPackagesFor emacs-pgtk).emacsWithPackages (epkgs: [ | |||
epkgs.vterm | |||
(callPackage ./lambda-line.nix { | |||
inherit (pkgs) fetchFromGitHub; | |||
inherit (epkgs) melpaBuild all-the-icons; | |||
}) | |||
])) | |||
... | |||
]; | |||
}} | |||
==== Packaging and testing Emacs nixpkgs ==== | ==== Packaging and testing Emacs nixpkgs ==== | ||
| Line 279: | Line 264: | ||
They can be obtained from melpa, elpa or other sources such as github. | They can be obtained from melpa, elpa or other sources such as github. | ||
{{file|default.nix|nix| | {{file|default.nix|nix|3= | ||
{ melpaBuild | { | ||
, | melpaBuild, | ||
lib, | |||
... | fetchFromGitHub | ||
... | |||
}: | }: | ||
| Line 306: | Line 292: | ||
}; | }; | ||
} | } | ||
}} | |||
They are located at <code>pkgs/applications/editors/emacs/elisp-packages/manual-packages/</code> [https://github.com/NixOS/nixpkgs/tree/master/pkgs/applications/editors/emacs/elisp-packages/manual-packages] and a new pkg must be added under <code>pkgs/applications/editors/elisp-packages/manual-packages.nix</code> [https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/emacs/elisp-packages/manual-packages.nix]. Once the nixpkg is ready, it can be tested using the following command. This inserts the nixpkg into the load-path of Emacs. | They are located at <code>pkgs/applications/editors/emacs/elisp-packages/manual-packages/</code> [https://github.com/NixOS/nixpkgs/tree/master/pkgs/applications/editors/emacs/elisp-packages/manual-packages] and a new pkg must be added under <code>pkgs/applications/editors/elisp-packages/manual-packages.nix</code> [https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/emacs/elisp-packages/manual-packages.nix]. Once the nixpkg is ready, it can be tested using the following command. This inserts the nixpkg into the load-path of Emacs. | ||
<syntaxhighlight lang=console> | |||
< | $ nix-shell -I nixpkgs=<path_to_nixpkgs_copy> -p \ | ||
$ nix-shell -I nixpkgs=<path_to_nixpkgs_copy> -p "(emacsPackagesFor pkgs.emacs28).emacsWithPackages (epkgs: [ epkgs.<package> ])" | "(emacsPackagesFor pkgs.emacs28).emacsWithPackages (epkgs: [ epkgs.<package> ])" | ||
</ | </syntaxhighlight> | ||
}} | }} | ||
| Line 345: | Line 331: | ||
====== Without flakes ====== | ====== Without flakes ====== | ||
For installing one of the unstable branches of Emacs, add the following lines to your configuration file: | For installing one of the unstable branches of Emacs, add the following lines to your configuration file: | ||
{{file|configuration.nix|nix| | {{file|configuration.nix|nix|3= | ||
nixpkgs.overlays = [ | |||
(import (builtins.fetchGit { | |||
url = "https://github.com/nix-community/emacs-overlay.git"; | |||
ref = "master"; | |||
rev = "bfc8f6edcb7bcf3cf24e4a7199b3f6fed96aaecf"; # change the revision | |||
})) | |||
]; | |||
}} | |||
===== Darwin (macOS) ===== | ===== Darwin (macOS) ===== | ||
| Line 364: | Line 348: | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
pkgs.emacsPgtk.overrideAttrs (old: { | pkgs.emacsPgtk.overrideAttrs (old: { | ||
patches = (old.patches or [ ]) ++ [ | |||
# Fix OS window role (needed for window managers like yabai) | |||
(fetchpatch { | |||
url = "https://raw.githubusercontent.com/d12frosted/homebrew-emacs-plus/master/patches/emacs-28/fix-window-role.patch"; | |||
sha256 = "0c41rgpi19vr9ai740g09lka3nkjk48ppqyqdnncjrkfgvm2710z"; | |||
}) | |||
# Enable rounded window with no decoration | |||
(fetchpatch { | |||
url = "https://raw.githubusercontent.com/d12frosted/homebrew-emacs-plus/master/patches/emacs-29/round-undecorated-frame.patch"; | |||
sha256 = "111i0r3ahs0f52z15aaa3chlq7ardqnzpwp8r57kfsmnmg6c2nhf"; | |||
}) | |||
# Make Emacs aware of OS-level light/dark mode | |||
(fetchpatch { | |||
url = "https://raw.githubusercontent.com/d12frosted/homebrew-emacs-plus/master/patches/emacs-28/system-appearance.patch"; | |||
sha256 = "14ndp2fqqc95s70fwhpxq58y8qqj4gzvvffp77snm2xk76c1bvnn"; | |||
}) | |||
]; | |||
}) | |||
</syntaxhighlight> | </syntaxhighlight> | ||
| Line 429: | Line 409: | ||
Because Emacs expects the dictionaries to be on the same directory as aspell, they won't be picked up. To fix it install the <code>aspellWithDicts</code> package, specifying the dictionaries you want to use: | Because Emacs expects the dictionaries to be on the same directory as aspell, they won't be picked up. To fix it install the <code>aspellWithDicts</code> package, specifying the dictionaries you want to use: | ||
{{file|configuration.nix|nix| | {{file|configuration.nix|nix|3= | ||
environment.systemPackages = with pkgs; [ | |||
(aspellWithDicts (dicts: with dicts; [ en en-computers en-science es ])) | |||
]; | |||
}} | |||
A list of official dictionaries for aspell can be found on [https://ftp.gnu.org/gnu/aspell/dict/0index.html Aspell Website] | A list of official dictionaries for aspell can be found on [https://ftp.gnu.org/gnu/aspell/dict/0index.html Aspell Website] | ||