Emacs: Difference between revisions
imported>Tobias.bora No edit summary |
Phanirithvij (talk | contribs) m link to search.nixos.org |
||
(29 intermediate revisions by 17 users not shown) | |||
Line 1: | Line 1: | ||
[https://www.gnu.org/software/emacs/ Emacs] is a versatile and powerful software application, valued for its exceptional extensibility, allowing users to tailor the editor to their specific needs. It boasts an automatic self-documenting behavior, providing users with readily accessible information about functions, variables, and keybindings. The flexibility of Emacs enables it to adapt to various workflows and programming styles, while its syntax awareness enhances coding efficiency across multiple languages. Its extensive package repository surpasses many of its competitors, including [[Vim]] and its fork [[Neovim]], making it one of the most customizable and feature-rich editors available. | |||
For | For those seeking a more approachable entry point to the Emacs ecosystem, the [https://doomemacs.org Doom Emacs] project offers a framework with a beginner-friendly default configuration. Doom Emacs comes pre-configured with popular modules for features such as IDE-like functionality, note-taking, and time management. | ||
Emacs | |||
There is an official Matrix room for Nix/Emacs: [https://matrix.to/#/#emacs:nixos.org #emacs:nixos.org]. | |||
== Installation == | |||
==== Using nix-shell ==== | |||
<syntaxhighlight lang="bash" start="3"> | |||
nix-shell -p emacs | |||
</syntaxhighlight> | |||
==== Using Global Configuration ==== | |||
<syntaxhighlight lang="text"> | |||
environment.systemPackages = [ | |||
pkgs.emacs | |||
]; | |||
</syntaxhighlight>After modifying your configuration, apply the changes by running:<syntaxhighlight lang="bash"> | |||
sudo nixos-rebuild switch | |||
</syntaxhighlight> | |||
==== Using Home Configuration ==== | |||
<syntaxhighlight lang="text"> | |||
home.packages = [ | |||
pkgs.emacs | |||
]; | |||
</syntaxhighlight>After updating your configuration, apply the changes by running:<syntaxhighlight lang="bash"> | |||
home-manager switch | |||
</syntaxhighlight> | |||
== Configuration == | |||
{{Note|Currently, configuring Emacs is possible by using Home Manager. A workaround for a global configuration is highlighted in the advanced section.}} | |||
==== Basic ==== | |||
<syntaxhighlight lang="nix"> | |||
programs.emacs = { | |||
enable = true; | |||
defaultEditor = true; | |||
}; | |||
</syntaxhighlight> | |||
==== Advanced ==== | |||
<syntaxhighlight lang="nix"> | |||
# Global Configuration | |||
# Emacs is running as a daemon here, accesible via the "emacsclient" command | |||
services.emacs = { | |||
enable = true; | |||
package = pkgs.emacs; | |||
}; | |||
# Home Configuration | |||
programs.emacs = { | |||
enable = true; | |||
package = pkgs.emacs; # replace with pkgs.emacs-gtk if desired | |||
defaultEditor = true; | |||
extraConfig = '' | |||
(setq standard-indent 2) | |||
''; | |||
}; | |||
</syntaxhighlight> | |||
== Tips and Tricks == | |||
==== Location of Options ==== | |||
The home manager options are defined in the following [https://nix-community.github.io/home-manager/options.xhtml#opt-programs.emacs.enable Home Manager Options Manual]. | |||
The global options are listed here [https://search.nixos.org/options?channel=unstable&query=services.emacs services.emacs.*]. | |||
==== Installing Packages ==== | |||
{{tip|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 {{ic|(use-package)}}. Such a configuration file can be version controlled and used in all compatible operating systems.}} | {{tip|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 {{ic|(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|emacsPgtkNativeComp}} with the variant in use:<syntaxhighlight lang="nix"> | |||
environment.systemPackages = with pkgs; | |||
[ ... | |||
((emacsPackagesFor emacsPgtkNativeComp).emacsWithPackages ( | |||
epkgs: [ epkgs.vterm ] | |||
)) | |||
... | |||
]; | |||
# To make the packages available to emacsclient, one can do the following: | |||
services.emacs.package = with pkgs; ( | |||
(emacsPackagesFor emacsPgtkNativeComp).emacsWithPackages ( | |||
epkgs: [ epkgs.vterm ] | |||
) | |||
); | |||
# Some packages have characters like + that Nix considers a syntax error. | |||
# 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+". | |||
</syntaxhighlight> | |||
==== Tree-sitter ==== | |||
[[Emacs]] 29 [[emacswiki:Tree-sitter|supports Tree-sitter parsers]] when built with the <code>--with-tree-sitter</code> option. The <code>emacsPackages.treesit-grammars</code> fake package makes them accessible to Emacs when using <code>emacs29.pkgs.withPackages</code>:<ref>https://github.com/NixOS/nixpkgs/pull/230751</ref><syntaxhighlight lang="nix"> | |||
{ | |||
pkgs ? import <nixpkgs> { }, | |||
}: | |||
pkgs.emacs29.pkgs.withPackages (epkgs: [ | |||
(epkgs.treesit-grammars.with-grammars (grammars: [ grammars.tree-sitter-bash ])) | |||
]) | |||
</syntaxhighlight> | |||
When using Emacs with tree-sitter support, it's recommended to install both <code>epkgs.tree-sitter-langs</code> and <code>epkgs.treesit-grammars</code>. While <code>treesit-grammars</code> handles the registration of grammars with Emacs's native tree-sitter interface, the actual grammar files will come from <code>tree-sitter-langs</code>. <code>tree-sitter-langs</code> being a MELPA package means it receives regular updates when new grammar versions are released, whereas the grammars in the tree-sitter-grammars package may lag behind in nixpkgs. The combination ensures you get both up-to-date grammars and proper integration with Emacs's built-in tree-sitter support. | |||
<b>Bonus Tip:</b> | |||
<code>emacs.pkgs.pretty-sha-path</code> is quality of life improvement for nix, guix users. | |||
Allows toggling Guix / Nix store paths by replacing SHA-sequences with ellipsis, i.e.: | |||
<syntaxhighlight lang="bash"> | |||
/gnu/store/72f54nfp6g1hz873w8z3gfcah0h4nl9p-foo-0.1 → /gnu/store/…-foo-0.1 | |||
/nix/store/nh4n4yzb1bx7nss2rg342dz44g14m06x-bar-0.2 → /nix/store/…-bar-0.2 | |||
</syntaxhighlight> | |||
located at https://github.com/alezost/pretty-sha-path.el | |||
==== 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>: | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
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 | |||
}); | |||
}; | |||
}) | |||
]; | |||
} | |||
</syntaxhighlight> | |||
See the [https://github.com/nix-community/emacs-overlay#extra-library-functionality overlay README] for a full list of options. | |||
==== Adding packages from outside ELPA / MELPA ==== | |||
Some packages may require more sophisticated derivation, but the following is a good starting point for adding external packages: | |||
{{file|lambda-line.nix|nix|<nowiki> | |||
{ | |||
melpaBuild, | |||
fetchFromGitHub, | |||
all-the-icons, | |||
}: | |||
melpaBuild { | |||
pname = "lambda-line"; | |||
version = "0-unstable-2022-11-23"; | |||
src = fetchFromGitHub { | |||
owner = "Lambda-Emacs"; | |||
repo = "lambda-line"; | |||
rev = "22186321a7442f1bd3b121f739007bd809cb38f8"; | |||
hash = "sha256-2tOXMqpmd14ohzmrRoV5Urf0HlnRPV1EVHm/d8OBSGE="; | |||
}; | |||
# elisp dependencies | |||
packageRequires = [ | |||
all-the-icons | |||
]; | |||
} | |||
</nowiki>}} | |||
You can then use the new package with automatic package management like so: | |||
{{file|configuration.nix|nix|<nowiki> | |||
{ | |||
environment.systemPackages = [ | |||
(pkgs.emacsWithPackagesFromUsePackage { | |||
... | |||
override = epkgs: epkgs // { | |||
lambda-line = callPackage ./lambda-line.nix { | |||
inherit (pkgs) fetchFromGitHub; | |||
inherit (epkgs) melpaBuild all-the-icons; | |||
}; | |||
}; | |||
}) | |||
]; | |||
} | |||
</nowiki>}} | |||
or manual package management like so: | |||
{{file|configuration.nix|nix|<nowiki> | |||
{ | |||
environment.systemPackages = with pkgs; | |||
[ ... | |||
((emacsPackagesFor emacsPgtkNativeComp).emacsWithPackages (epkgs: [ | |||
epkgs.vterm | |||
(callPackage ./lambda-line.nix { | |||
inherit (pkgs) fetchFromGitHub; | |||
inherit (epkgs) melpaBuild all-the-icons; | |||
};) | |||
])) | |||
... | |||
]; | |||
}</nowiki>}} | |||
==== Packaging and testing emacs nixpkgs ==== | |||
Emacs packages can be defined and tested like other nixpkgs. | |||
They can be obtained from melpa, elpa or other sources such as github. | |||
{{file|default.nix|nix|<nowiki> | |||
{ melpaBuild | |||
, lib | |||
, fetchFromGitHub | |||
... | |||
}: | |||
melpaBuild { | |||
pname = "..."; | |||
version = "..."; | |||
src = fetchFromGitHub { | |||
owner = "..."; | |||
repo = "..."; | |||
rev = "..."; | |||
hash = "..."; | |||
}; | |||
packageRequires = [ ... ]; | |||
patches = [ ... ]; | |||
meta = { | |||
description = "..."; | |||
license = lib.licenses.gpl3Plus; | |||
}; | |||
} | |||
</nowiki>}} | |||
They are located at pkgs/applications/editors/emacs/elisp-packages/manual-packages/ and a new pkg must be added under pkgs/applications/editors/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. | |||
nix-shell -I nixpkgs=<path_to_nixpkgs_copy> -p "(emacsPackagesFor pkgs.emacs28).emacsWithPackages (epkgs: [ epkgs.<package> ])" | |||
==== Window Manager Integration ==== | |||
Out of the box, non-"Mac Port" versions of Emacs will not be picked up properly by window managers like [https://github.com/koekeishiya/yabai Yabai] because [https://github.com/koekeishiya/yabai/issues/86#issuecomment-507537023 Emacs does not set the correct macOS window role]. This can be fixed with a patch (e.g. the first patch in the example above). However, even with the patch, Yabai may not correctly pick up Emacs if you invoke the <code>emacs</code> binary directly from a shell. For Emacs to work properly with window managers you must invoke it by running the macOS app that is generated when you install Emacs with nix. You can setup an alias to do this like so (replace <code>pkgs.emacs</code> with the package you are using):<syntaxhighlight lang="nix"> | |||
programs.zsh = { | |||
enable = true; | |||
shellAliases = { | |||
emacs = "${pkgs.emacs}/Applications/Emacs.app/Contents/MacOS/Emacs"; | |||
}; | |||
}; | |||
</syntaxhighlight> | |||
==== Available Emacs Variants ==== | |||
{{warning| Certain issues are possible, when mixing different versions of Emacs, in particular a configuration file tailored towards emacs with native compilation, may misbehave on non-native compiling versions, unless only the emacs lisp code is shared between them.}} | {{warning| Certain issues are possible, when mixing different versions of Emacs, in particular a configuration file tailored towards emacs with native compilation, may misbehave on non-native compiling versions, unless only the emacs lisp code is shared between them.}} | ||
==== | ===== 1. Stable (nixpkgs) ===== | ||
Emacs is available in nixpkgs under the names <code>emacs</code> and <code>emacs-gtk</code>. | |||
[https://github.com/NixOS/nixpkgs/pull/189543 Since 2022-09], the package called <code>emacs</code> now installs the lucid toolkit instead of gtk. The reason is that emacs is less stable with gtk especially in daemon mode. However, the lucid flavor of emacs will not take into account the gtk theme (since it is not even gtk) and looks quite… ugly (see comparisons [https://emacs.stackexchange.com/questions/33065/on-linux-why-should-one-choose-lucid-over-gtk-gui-for-emacs here]). If you still prefer the gtk version of emacs, you can instead install <code>emacs-gtk</code> (before 2022-09 this package does not exist and emacs defaults to the gtk version). | |||
===== 2. Unstable (community overlay) ===== | |||
The [https://github.com/nix-community/emacs-overlay community overlay] provides nightly versions of the Emacs unstable branches, ELPA / MELPA packages, and [https://github.com/ch11ng/exwm EXWM] + its dependencies. '''To use these, first apply the overlay (instructions below), which will make the packages available in nixpkgs.''' Then you can follow the normal nixpkgs installation instructions (above), but use your package of choice from the overlay (e.g. <code>pkgs.emacsGit</code>) in place of <code>pkgs.emacs</code>. See the [https://github.com/nix-community/emacs-overlay#emacs-overlay README] for a complete list of packages provided, and their differences. | |||
===== | ===== With flakes ===== | ||
Using a system flake, one can specify the specific revision of the overlay as a flake input, for example: | |||
= | inputs.emacs-overlay.url = "github:nix-community/emacs-overlay/da2f552d133497abd434006e0cae996c0a282394"; | ||
= | This can then be used in the system configuration by using the {{ic|self}} argument: | ||
nixpkgs.overlays = [ (import self.inputs.emacs-overlay) ]; | |||
=== | ===== Without flakes ===== | ||
For installing one of the unstable branches of emacs, add the following lines to {{ic|/etc/nixos/configuration.nix}} | For installing one of the unstable branches of emacs, add the following lines to {{ic|/etc/nixos/configuration.nix}}: | ||
{{file|configuration.nix|nix|<nowiki> | {{file|configuration.nix|nix|<nowiki> | ||
{ | { | ||
nixpkgs.overlays = [ | nixpkgs.overlays = [ | ||
(import (builtins.fetchGit { | (import (builtins.fetchGit { | ||
Line 41: | Line 285: | ||
rev = "bfc8f6edcb7bcf3cf24e4a7199b3f6fed96aaecf"; # change the revision | rev = "bfc8f6edcb7bcf3cf24e4a7199b3f6fed96aaecf"; # change the revision | ||
})) | })) | ||
]; | ]; | ||
} | } | ||
</nowiki>}} | </nowiki>}} | ||
==== | ===== 3. Darwin (macOS) ===== | ||
Nixpkgs provides several of the "Mac Port" versions of Emacs, which have been patched to provide better integration with macOS (see the [https://nixos.org/manual/nixos/stable/index.html#module-services-emacs-releases NixOS manual entry for a full list of packages]). However, those packages typically track the stable releases of Emacs. | |||
If you would like to use the latest version of Emacs on Darwin, one option is to use a package like <code>emacsPgkt</code> from the community overlay (see above), and apply patches yourself via an override. For example, here is a derivation that applies the patches from the [https://github.com/d12frosted/homebrew-emacs-plus <code>emacs-plus</code> homebrew formula]: | |||
<syntaxhighlight lang="nix"> | |||
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> | |||
== | == Troubleshooting == | ||
==== Plasma taskbar grouping ==== | |||
To fix/workaround [[Plasma]] grouping emacs incorrectly (confusing emacs.desktop with emacsclient.desktop), perform the following: | |||
1. open emacs | |||
2. right click title bar | |||
3. More Actions > Configure Special Window Settings | |||
4. click Add Property > Desktop File Name | |||
5. set desktop file name to "/home/<USERNAME>/.nix-profile/share/applications/emacs.desktop" | |||
6. hit OK | |||
7. restart emacs if need | |||
all emacs instances should now be grouped together, allowing you to pin it and reliably switch to it with Super+<number> | |||
==== Spell checking ==== | |||
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|<nowiki> | |||
{ | |||
environment.systemPackages = with pkgs; [ | |||
(aspellWithDicts (dicts: with dicts; [ en en-computers en-science es])) | |||
]; | |||
} | |||
</nowiki>}} | |||
A list of official dictionaries for aspell can be found on [https://ftp.gnu.org/gnu/aspell/dict/0index.html Aspell Website] | |||
== References == | |||
[[Category:Applications]] | [[Category:Applications]] | ||
[[Category:CLI Applications]] | |||
[[Category:NixOS Manual]] | |||
[[Category:Text Editor]] |