Skip to content

Latest commit

 

History

History
560 lines (431 loc) · 23.2 KB

crafted-emacs.org

File metadata and controls

560 lines (431 loc) · 23.2 KB

Crafted Emacs

Hacking one’s Emacs configuration is, for some, an ongoing endeavor. For others, it just needs to work. Other configuration packages attempt to be a complete, canned, working configuration, while Crafted attempts to provide the bare minimum to get you started. More like a framework than a complete solution, Crafted Emacs intends to provide a sensible place to start configuring your Emacs to your needs.

Defaults provided here were provided by a community of volunteers and ideally represent sane defaults from which to start. We expect you to have different opinions than ours and we expect you to implement those differences in your own configuration. Our intent is to provide something you might find useful to get your started on your own Emacs configuration journey.

Principles

This configuration and all associated modules intend to follow these principles:

  • Minimal, modular configuration
    • The core configuration only sets up Emacs to have a cleaner presentation with sensible defaults. It is up to the user to decide which modules to load and when to load them.
    • Modules should not depend on other modules as much as possible. When a module needs to integrate with other functionality in Emacs, the standard extensibility points of each package should be used. The implication is someone should be able to copy code from a module into their own configuration without using Crafted Emacs.
  • Prioritize built-in Emacs functionality

    Where possible, we will leverage built-in Emacs functionality instead of external packages.

    Some of the packages we prefer:

    • project.el for project management.
    • tab-bar-mode for organizing groups of buffers.
    • whitespace.el to cleanup whitespace, like tabs, newlines or additional space added to the end of lines.
    • pulse.el to flash the current line under certain conditions.
    • And others…

    This is not to take away from the amazing work package providers have contributed to the Emacs community. By prioritizing built-in features, we can highlight less known packages, have a more stable product, and reduce the amount of network load just to get started. Indeed, if you do not pull in any of the modules we provide, you may not even need a network (other than to clone the repo from GitHub).

  • Works well in the terminal

    Not everyone uses a windowing environment, and the terminal is popular for remote sessions as well as command line utilities. Working well in the terminal also enables the use of Emacs in Termux on Android!

  • Can be integrated with a Guix configuration

    GNU Guix is a functional package manager and GNU Linux distribution. This integration enables setting things like font sizes, themes, etc in a system-specific and repeatable way.

  • Works well with Chemacs2

    Having multiple configurations available allows for testing individual package combinations or configurations from others. Chemacs2 allows for having multiple configurations simultaneously and Crafted Emacs should work well in this environment also.

  • Helps you learn Emacs Lisp

    Instead of providing a higher-level configuration system out of the box like other Emacs configurations (like Doom or Spacemacs for example), we follow standard Emacs Lisp patterns so you can learn by reading the configuration. This means we don’t provide macro wrappers around packaging and configuration tools. No complex framework exists.

Why use it?

Why choose this configuration over Doom Emacs, Spacemacs, Prelude, or others?

The goal of this configuration is to make it easier to write your own Emacs configuration while using pre-made configuration parts maintained by the community. Instead of using a monolithic, all-encompassing approach, we strive to ensure that all parts of this configuration are optional or interchangeable.

You should even be able to use the configuration modules we provide with your own init.el file without using this base configuration repo!

Folder structure

There are two primary folders for working with Crafted Emacs:

  • `user-emacs-directory` (ie: `~/.config/emacs`) where Emacs, by default, searches for its configuration, packages, etc.
  • `crafted-config-path` (ie: `~/.config/crafted-emacs`, see below) where Crafted Emacs searches for everything except packages.

By default Crafted Emacs does not do much regarding those paths except for customizations as introduced below.

The `crafted-config-path` layout is designed following current common practices to help you keep configuration and runtime data separatedly (inside `etc/` and `var/` respectively).

Moreover, the crafted-defaults module sets several common default paths to sensible new defaults following such practices.

We do not, yet, provide a cache path here as that needs further thought (most OS expect caches in specific places).

Customization

To add your own customization to this configuration, create a configuration file in one of the following places:

  • ~/.crafted-emacs/
  • ~/.config/crafted-emacs/

In your configuration you can set any Emacs configuration variable, face attributes, themes, etc as you normally would.

If you prefer to explicitly control where your config.el and early-config.el are found for Crafted Emacs, you may provide a value for the CRAFTED_EMACS_HOME environment variable, either on the command line or in your shell configuration. This variable should only contain the path to the config.el files, for example:

CRAFTED_EMACS_HOME=~/my-crafted-emacs-config

Managing packages

How the crafted config file is found

The crafted config files (config.el and early-config.el) are found in the crafted-config-path. That path will match exactly one of the following scenarios, in the order specified:

  • Using Chemacs2 (See below for more on this)
    • The environment variable CRAFTED_EMACS_HOME is used if provided in the profile definition.
    • The profile directory is used when no environment variable is provided in the profile definition.
  • Use the value found in the CRAFTED_EMACS_HOME environment variable.
  • The environment variable XDG_CONFIG_HOME is present or the path $HOME/.config/crafted-emacs exists.
    • These normally resolve to the same file, so build the path from the XDG_CONFIG_HOME environment variable or the explicit path ~/.config/crafted-emacs
  • Use the HOME environment variable to make the path, which expands to $HOME/.crafted-emacs.

Once the crafted-config-path is determined, if it does not exist in the file system, it is created. However, just the path is created, the files config.el and early-config.el must be created by you.

Example Configuration:

(require 'crafted-defaults)
(require 'crafted-screencast)
(require 'crafted-ui)
(require 'crafted-editing)
(require 'crafted-evil)
(require 'crafted-completion)
(require 'crafted-windows)

;; Set further font and theme customizations
(custom-set-variables
 '(crafted-ui-default-font
   '(:font "JetBrains Mono" :weight light :height 185)))

(crafted-package-install-package 'doom-themes)
(load-theme 'doom-one t)

See the examples folder in the git-repo for more up to date and comprehensive examples.

The custom.el file

The custom.el file will hold the auto-generated code from the Emacs Customization UI.

Simplified overview of how Emacs Customization works

Customizable values are defined with the defcustom form, and can be customized using the Easy Customization UI. A complete discussion is out of scope for this document, instead see the Emacs Manual for more information.

There are several states a value can be in, for our purposes, we will only consider two of them: the default state and the changed state. These are not the “official” names but easily convey the concepts of the variable. If a value is in the default state, looking in the Customization UI, the state will be listed as STANDARD. Crafted Emacs takes the approach of using the customize-set-variable to update the values defined with defcustom. This will show the values as SET for current session only in the Customization UI. This is normal since the values are set each time Emacs starts. They are technically “SAVED” since they exist as emacs-lisp code, but since they are not in a custom-set-variables form the Customization UI only sees them as “SET for the current session only”.

A SAVED and set value means the Customization code has written the configuration to disk to be loaded again the next time Emacs starts. When Emacs saves the configuration from the Customization UI, it simply adds a couple of forms to the end of your initialization file (typically init.el), with comments warning about having more than one form with the same name (see example below).

Loading the custom.el file

This is important because if you, the user, wish to use the Customization UI to configure Emacs, the customizations will (by default) be written to the bottom of the init.el file in a form called custom-set-variables and custom-set-faces. These are loaded usually at the end of the init cycle (which is why they are listed at the bottom of the init.el file) and allows restoring values set by the Customization UI rather than through code.

This configuration sets the custom-file to exist in the crafted-config-path (see above) as a file known as custom.el. This file is not automatically loaded by Crafted Emacs configuration. You may, if you choose, load this file yourself with the following code in your config.el file.

(load "custom")

It is important to load this file last to make sure it overrides any values previously set while Emacs was starting.

If you are using something like the example provided above, you might have something that looks more like this:

(require 'crafted-defaults)
(require 'crafted-screencast)
(require 'crafted-ui)
(require 'crafted-editing)
(require 'crafted-evil)
(require 'crafted-completion)
(require 'crafted-windows)

(crafted-package-install-package 'doom-themes)
(load-theme 'doom-one t)

(load "custom")
;;; example-config.el ends here

And then in custom.el you would have something like the following which is auto-generated by Emacs:

(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(crafted-ui-default-font '(:font "JetBrains Mono" :weight light :height 185))
 '(crafted-ui-display-line-numbers t))
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 )

Not loading the custom.el file

You may choose not to load the custom.el file if you are writing your own configuration with Emacs-Lisp. Using customize-set-variable has the same effect as using the Customization UI, with the primary difference, the customization is not written later as if you had used the Customization UI. If you choose to follow this pattern, you will not need to load the custom.el file ever. Our example (see above) could imply the use of the Customization UI, as our example uses the custom-set-variables form to set a list of customizable values all at once. Here is the same example written differently.

(require 'crafted-defaults)
(require 'crafted-screencast)
(require 'crafted-ui)
(require 'crafted-editing)
(require 'crafted-evil)
(require 'crafted-completion)
(require 'crafted-windows)

(customize-set-variable 'crafted-ui-default-font
                        '(:font "JetBrains Mono" :weight light :height 185))
(customize-set-variable 'crafted-ui-display-line-numbers t)

(crafted-package-install-package 'doom-themes)
(load-theme 'doom-one t)

Caveat on the timing of loading custom.el

Even if you are using emacs-lisp to customize Emacs, you may still choose to load the custom.el file. Keep in mind, if you use customize-set-variable or setq to set the value for a defcustom option and then load the custom.el file which might have the same variable set with a different value, the last thing to set that value wins.

Here is an example, first a config.el snippet:

;; ... some customization before
(customize-set-variable 'display-line-numbers-type 'relative)
;; ... some more customization

(load "custom")

and the custom.el snippet

(custom-set-variables
 '(display-line-numbers-type t))

The value of the display-line-numbers-type will be t. Since the custom.el file is loaded last the first value of the display-line-numbers-type is overwritten. The fix is to make sure you set the value only once in your configuration with either customize-set-variable or with custom-set-variables either in your config.el or loaded from custom.el

Using it with Chemacs2

If you have the Chemacs2 configuration cloned to ~/.emacs.d or ~/.config/emacs, you can clone crafted-emacs anywhere you like and add an entry to it in your ~/.emacs-profiles.el file:

You can then put your early-config.el and config.el files in the sub-folder ~/path/to/crafted-emacs/crafted-emacs. So, for example if you installed Crafted Emacs to ~/.crafted-emacs, then your early-config.el and config.el files would be in the path ~/.crafted-emacs/crafted-emacs. This is the default path, but you can change the name to something else, see below for examples.

(("crafted" . ((user-emacs-directory . "~/path/to/crafted-emacs"))))

If you prefer to put your Crafted Emacs customizations elsewhere (for example in a folder called `config` or maybe `personal`), you can specify the CRAFTED_EMACS_HOME environment variable, for example like this:

(("crafted" . ((user-emacs-directory . "~/path/to/crafted-emacs")
                (env . (("CRAFTED_EMACS_HOME" . "~/path/to/crafted-emacs/personal"))))))

Or some place completely different:

(("crafted" . ((user-emacs-directory . "~/path/to/crafted-emacs")
                (env . (("CRAFTED_EMACS_HOME" . "~/crafted-config/personal"))))))

Then launch it with emacs --with-profile crafted!

Contributing

Follow the Elisp Style Guide when submitting pull requests.

This is a community-run modular Emacs configuration, for which we appreciate feedback in the form of issues and pull requests. Feel free to open an issue prior to opening a pull request if you’re not certain your idea is in the spirit of the Principles.

If you enjoy crafting your computing experience, join the SystemCrafters community!

Modules

Crafted Emacs includes a number of modules to further configure Emacs. These are intended to be stand-alone in the sense that no module requires the use of any other module.

The modules are written to support various themes: mini-buffer selection (completion), editing, ui, etc. To use these modules, simply require them in your config.el, or copy the relevant portions to your config.el and modify them to suit your needs.

In most cases, you can require the module, and then adjust the configuration for specific parts by overriding the settings provided by the module by additional code in your config.el.

While the intent here is to document each module as completely as reasonably possible, the best-practice is to simply read the code for the module of interest to understand it best.

Troubleshooting

Some tips when things don’t seem to work right.

A package (suddenly?) fails to work

This scenario happened frequently when upgading to Emacs 28. It also may occur in other scenarios as well. Usually, you will see some message indicating some symbol is void or some function or command does not exist. More often than not, the package maintainer is using a feature from another package which has not yet been released. The new feature is available in the development version of the package however.

Here are some example issues where things went wrong:

Here are some strategies:

  • Check the code on the package source control page (ie GitHub, GitLab or whatever), and make sure the missing code is present on the master branch.
  • Look at the code associated with the released version (you need to look at the most recent tag for this). If the code is missing there, ask the maintainer for a new release. Often, there are years between releases of Emacs packages, but that depends completely on the package maintainer. Some of them release more frequently, others only on request.

Once you have done the steps above, you can choose to take one of these actions in your configuration:

  • Option 1
    • Use M-x package-list-packages to display the list of packages.
    • Find the package in the list which doesn’t work for you, it will have either the installed or dependency status.
    • Press the enter key to get more details on the package an look near the bottom of the metadata, you should see a line with “Other Versions”. Choose the development version - it will have a version number that looks like a date and the text (melpa) next to it. Press enter on this version.
    • Following the step above will take you to the same package but from the MELPA repository, and you’ll see a button at the top labeled Install. Click this button.
    • Optionally you can go back to the list of packages, find previous installed version, press the letter ‘D’ and then the letter ‘X’ to uninstall that version.
    • Restart Emacs
  • Option 2
    • Edit your early-config.el file.
    • Near the bottom, add a line similar to this to pin the offending package to MELPA (make sure to replace package-name with the name of the actual package):
      (add-to-list 'package-pinned-packages (cons 'package-name "melpa"))
              
    • Use M-x package-list-packages to display the list of packages.
    • Find the package in the list, press the letter ‘D’ and the letter ‘X’ to uninstall that package.
    • Restart Emacs, the package should be installed from MELPA thus using the development version of the package instead of the released version.

Regardless, always feel free to open an issue here and we can help you out. Please be as complete as possible in your description of the problem. Include any stack traces Emacs provides (ie start Emacs with: emacs --debug-init), mention the version number of the package you are installing, and anything you might have tried but which didn’t work for you.

License

Copyright © 2022 System Crafters Community

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

MIT License