Emacs: Difference between revisions
m →System setup: make it clear the distinction between installing system wide vs home manager |
fix formatting and consistency |
||
| (3 intermediate revisions by 3 users 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 51: | Line 47: | ||
== Configuration == | == Configuration == | ||
==== | ==== NixOS System Configuration ==== | ||
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|3= | ||
services.emacs = { | services.emacs = { | ||
enable = true; | enable = true; | ||
defaultEditor = true; | |||
}; | }; | ||
}} | |||
Use <code>emacsclient</code> to connect to the daemon. For a full list of module configuration options, see {{nixos:option|services.emacs}}. | |||
==== Home Manager ==== | |||
[[Home Manager]] provides a larger set of user-specific configuration options for Emacs. | |||
A minimal configuration that installs Emacs alongside <code>nix-mode</code> and <code>nixfmt</code> packages: | |||
{{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: [ | |||
epkgs.nix-mode | |||
epkgs.nixfmt | |||
]; | |||
extraConfig = '' | extraConfig = '' | ||
(setq standard-indent 2) | (setq standard-indent 2) | ||
''; | ''; | ||
}; | }; | ||
</ | }} | ||
{{note| An alternative option to setting the config inside a Nix string, you can load the config file by <code>extraConfig <nowiki>=</nowiki> builtins.readFile ./emacs_config.el</code>.}} | |||
To search for Emacs plugins within the package set, see {{nixos:package|emacsPackages.*}}. A full list of Home Manager configuration module options can be found [https://home-manager-options.extranix.com/?query=programs.emacs here]. | |||
Home Manager also provides a configuration module for enabling the Emacs daemon: | |||
{{file|home.nix|nix|3= | |||
# Emacs is running as a daemon here, accesible via the "emacsclient" command | |||
services.emacs = { | |||
enable = true; | |||
defaultEditor = true; | |||
}; | |||
}} | |||
See [https://home-manager-options.extranix.com/?query=services.emacs the module options] for <code>services.emacs</code> configurations options. | |||
== Tips and Tricks == | == Tips and Tricks == | ||
| Line 84: | 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 103: | 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 165: | 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 194: | 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 214: | 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 255: | 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 282: | 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 321: | 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 340: | 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> | ||
==== Running xwidgets ==== | |||
Currently, the xwidgets feature is available for Emacs, but will have some issues with the PGTK build. Indeed, when create a webkit xwidget, the widget will initially show a blank page, for some seconds (usually 4/5 seconds), no matter whether you actually try to load a web page. | |||
A workaround to this is to way that delay, and then try to load the page. You can do so programmatically by waiting 5 seconds, or from within a webkit widget by waiting for 5 seconds, then pressing <code>g</code>, then <code>RET</code>. | |||
Otherwise, you can fix the issue by building Emacs with the following patch<syntaxhighlight lang="diff">--- a/src/xwidget.c | |||
+++ b/src/xwidget.c | |||
@@ -362,8 +362,12 @@ | |||
"download-started", | |||
G_CALLBACK (webkit_download_cb), xw); | |||
+#if !defined HAVE_PGTK | |||
+ /* when using pgtk, the about:blank workaround is not needed | |||
+ would in fact make the initial load fail. */ | |||
webkit_web_view_load_uri (WEBKIT_WEB_VIEW (xw->widget_osr), | |||
"about:blank"); | |||
+#endif | |||
/* webkitgtk uses GSubprocess which sets sigaction causing | |||
Emacs to not catch SIGCHLD with its usual handle setup in | |||
'catch_child_signal'. This resets the SIGCHLD sigaction. */</syntaxhighlight>Say you saved this file in <code>xwidget.patch</code>, then you can override emacs with<syntaxhighlight lang="nix">pkgs.emacs-pgtk.overrideAttrs (old: { | |||
patches = (old.patches or []) ++ [ ./xwidget.patch ]; | |||
}</syntaxhighlight>Beware, this will trigger a full Emacs compilation whenever you update it, because it will not match any cached binary. | |||
== Troubleshooting == | == Troubleshooting == | ||
| Line 382: | 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] | ||