Emacs: Difference between revisions

Pigs (talk | contribs)
Configuration: provide a clearer list of possible ways to configure emacs
DHCP (talk | contribs)
fix formatting and consistency
 
(2 intermediate revisions by 2 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:
{{Commands|
<syntaxhighlight lang=console>
<nowiki>
$ nix-shell -p emacs
$ nix-shell -p emacs
</nowiki>
</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=
<nowiki>
environment.systemPackages = [
environment.systemPackages = [
   pkgs.emacs
   pkgs.emacs
];
];
</nowiki>
}}
}}


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|<nowiki>
{{file|home.nix|nix|3=
home.packages = [
home.packages = [
   pkgs.emacs
   pkgs.emacs
];
];
</nowiki>
}}
}}


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|<nowiki>
{{file|/etc/nixos/configuration.nix|nix|3=
services.emacs = {
services.emacs = {
  enable = true;
  enable = true;
  defaultEditor = true;
  defaultEditor = true;
};
};
</nowiki>
}}
}}


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|<nowiki>
{{file|home.nix|nix|3=
programs.emacs = {
programs.emacs = {
   enable = true;
   enable = true;
   package = pkgs.emacs; # replace with pkgs.emacs-gtk if desired
   package = pkgs.emacs; # replace with pkgs.emacs-gtk if desired
   extraPackages = epkgs: [
   extraPackages = epkgs: [
     epkgs.nix-mode
     epkgs.nix-mode
Line 84: Line 79:
   '';
   '';
};
};
</nowiki>
}}
}}


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|<nowiki>
{{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;
};
};
</nowiki>
}}
}}


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:<syntaxhighlight lang="nix">
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.
 
 
 
 
</syntaxhighlight>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|<nowiki>
{{file|/etc/nixos/configuration.nix|nix|3=
  nixpkgs.config.packageOverrides = pkgs: rec {
nixpkgs.config.packageOverrides = pkgs: rec {
    myEmacs = pkgs.emacs.pkgs.withPackages (epkgs: with epkgs; [
  myEmacs = pkgs.emacs.pkgs.withPackages (epkgs: with epkgs; [
      org
    org
      nixmode
    nixmode
      ... # list all your desired emacsPackages here
    ... # list all your desired emacsPackages here
    ]);
  ]);
  };
};
</nowiki>}}
}}


You may then reference it twice:
You may then reference it twice:


{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{{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
# if you want it per-user instead of system-wide use 'users.users.<name>.packages = with pkgs; [' instead
  environment.systemPackages = with pkgs; [
environment.systemPackages = with pkgs; [
    myEmacs
  myEmacs
  ];
];


  ## enabling emacsclient and making all the packages available
# enabling emacsclient and making all the packages available
  services.emacs = {
services.emacs = {
    enable = true;
  enable = true;
    package = pkgs.myEmacs;
  package = pkgs.myEmacs;
  };
};
</nowiki>}}
}}


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>:
<syntaxhighlight lang="nix">
{{file|/etc/nixos/configuration.nix|nix|3=
{
environment.systemPackages = [
  environment.systemPackages = [
  (pkgs.emacsWithPackagesFromUsePackage {
    (pkgs.emacsWithPackagesFromUsePackage {
    package = pkgs.emacsGit;  # replace with pkgs.emacsPgtk, or another version if desired.
      package = pkgs.emacsGit;  # replace with pkgs.emacsPgtk, or another version if desired.
    config = path/to/your/config.el;
      config = path/to/your/config.el;
    # config = path/to/your/config.org; # Org-Babel configs also supported
      # config = path/to/your/config.org; # Org-Babel configs also supported


      # Optionally provide extra packages not in the configuration file.
    # Optionally provide extra packages not in the configuration file.
      extraEmacsPackages = epkgs: [
    extraEmacsPackages = epkgs: [
        epkgs.use-package
      epkgs.use-package
      ];
    ];


      # Optionally override derivations.
    # Optionally override derivations.
      override = epkgs: epkgs // {
    override = epkgs: epkgs // {
        somePackage = epkgs.melpaPackages.somePackage.overrideAttrs(old: {
      somePackage = epkgs.melpaPackages.somePackage.overrideAttrs(old: {
          # Apply fixes here
        # Apply fixes here
        });
      });
      };
    };
    })
  })
  ];
];
}
}}
</syntaxhighlight>


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|<nowiki>
{{file|lambda-line.nix|nix|3=
{
{
   melpaBuild,
   melpaBuild,
Line 238: Line 226:
   ];
   ];
}
}
</nowiki>}}
}}


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|<nowiki>
{{file|configuration.nix|nix|3=
{
environment.systemPackages = [
  environment.systemPackages = [
  (pkgs.emacsWithPackagesFromUsePackage {
    (pkgs.emacsWithPackagesFromUsePackage {
    ...
      ...
    override = epkgs: epkgs // {
      override = epkgs: epkgs // {
      lambda-line = callPackage ./lambda-line.nix {
        lambda-line = callPackage ./lambda-line.nix {
        inherit (pkgs) fetchFromGitHub;
          inherit (pkgs) fetchFromGitHub;
        inherit (epkgs) melpaBuild all-the-icons;
          inherit (epkgs) melpaBuild all-the-icons;
        };
       };
       };
     })
     };
  ];
  })
}
];
</nowiki>}}
}}


or manual package management like so:
or manual package management like so:


{{file|configuration.nix|nix|<nowiki>
{{file|configuration.nix|nix|3=
{
environment.systemPackages = with pkgs; [
  environment.systemPackages = with pkgs;
  ...
    [ ...
  ((emacsPackagesFor emacs-pgtk).emacsWithPackages (epkgs: [
      ((emacsPackagesFor emacs-pgtk).emacsWithPackages (epkgs: [  
    epkgs.vterm
          epkgs.vterm  
    (callPackage ./lambda-line.nix {
          (callPackage ./lambda-line.nix {
      inherit (pkgs) fetchFromGitHub;
            inherit (pkgs) fetchFromGitHub;
      inherit (epkgs) melpaBuild all-the-icons;
            inherit (epkgs) melpaBuild all-the-icons;
    })
          };)  
  ]))
      ]))
  ...
      ...
];
    ];
}}
}</nowiki>}}


==== 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|<nowiki>
{{file|default.nix|nix|3=
{ melpaBuild
{
, lib
  melpaBuild,
, fetchFromGitHub
  lib,
...
  fetchFromGitHub
  ...
}:
}:


Line 306: Line 292:
   };
   };
}
}
</nowiki>}}
}}


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.
{{Commands|
<syntaxhighlight lang=console>
<nowiki>
$ 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> ])"
</nowiki>
</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|<nowiki>
{{file|configuration.nix|nix|3=
{
nixpkgs.overlays = [
  nixpkgs.overlays = [
  (import (builtins.fetchGit {
    (import (builtins.fetchGit {
    url = "https://github.com/nix-community/emacs-overlay.git";
      url = "https://github.com/nix-community/emacs-overlay.git";
    ref = "master";
      ref = "master";
    rev = "bfc8f6edcb7bcf3cf24e4a7199b3f6fed96aaecf"; # change the revision
      rev = "bfc8f6edcb7bcf3cf24e4a7199b3f6fed96aaecf"; # change the revision
  }))
    }))
];
  ];
}}
}
</nowiki>}}


===== Darwin (macOS) =====
===== Darwin (macOS) =====
Line 364: Line 348:
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
pkgs.emacsPgtk.overrideAttrs (old: {
pkgs.emacsPgtk.overrideAttrs (old: {
      patches =
  patches = (old.patches or [ ]) ++ [
        (old.patches or [])
    # Fix OS window role (needed for window managers like yabai)
        ++ [
    (fetchpatch {
          # Fix OS window role (needed for window managers like yabai)
      url = "https://raw.githubusercontent.com/d12frosted/homebrew-emacs-plus/master/patches/emacs-28/fix-window-role.patch";
          (fetchpatch {
      sha256 = "0c41rgpi19vr9ai740g09lka3nkjk48ppqyqdnncjrkfgvm2710z";
            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 {
          # Enable rounded window with no decoration
      url = "https://raw.githubusercontent.com/d12frosted/homebrew-emacs-plus/master/patches/emacs-29/round-undecorated-frame.patch";
          (fetchpatch {
      sha256 = "111i0r3ahs0f52z15aaa3chlq7ardqnzpwp8r57kfsmnmg6c2nhf";
            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 {
          # Make Emacs aware of OS-level light/dark mode
      url = "https://raw.githubusercontent.com/d12frosted/homebrew-emacs-plus/master/patches/emacs-28/system-appearance.patch";
          (fetchpatch {
      sha256 = "14ndp2fqqc95s70fwhpxq58y8qqj4gzvvffp77snm2xk76c1bvnn";
            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 406: 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|<nowiki>
{{file|configuration.nix|nix|3=
{
environment.systemPackages = with pkgs; [
  environment.systemPackages = with pkgs; [
  (aspellWithDicts (dicts: with dicts; [ en en-computers en-science es ]))
    (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]
A list of official dictionaries for aspell can be found on [https://ftp.gnu.org/gnu/aspell/dict/0index.html  Aspell Website]