#| file: modules/home-manager/zed/default.nix
{
pkgs,
lib,
config,
...
}:
let
cfg = config.mjm.zed;
in
{
options.mjm.zed = {
enable = lib.mkOption {
type = lib.types.bool;
default = config.mjm.desktop.enable;
};
};
config = lib.mkIf cfg.enable {
<<config>>
};
_class = "homeManager";
}Zed is the text editor I'm using most of the time these days. While they are bigger on AI stuff than I'd generally prefer, it's still a pretty solid editor with those things disabled. Unless I'm stuck in the terminal or doing a really quick change of something, I'm probably working in Zed.
programs.zed-editor.enable = true;
programs.zed-editor.mutableUserSettings = false;
programs.zed-editor.userSettings = {
<<user-settings>>
};While it's a bit inconvenient to not be able to alter settings in the UI, I prefer to not have it be possible for my configs to get out of sync between machines, so my user settings for Zed are immutable.
programs.zed-editor.extraPackages = lib.attrValues {
inherit (pkgs)
rustup
gcc
nixd
nixfmt
gopls
;
};
programs.zed-editor.extensions = [
"dracula"
"grafana-alloy"
"ini"
"kdl"
"nix"
"scheme"
"toml"
];I preinstall several extensions for things I need to use regularly, and also add some packages to Zed's environment to support them. The packages don't need to include every single tool that a project might need, just ones that should always be available.
#| id: user-settings disable_ai = true; toolbar.agent_review = false;
I'm not interested in using any of the AI features in Zed, so I disable those.
#| id: user-settings
auto_update = false;
telemetry = {
diagnostics = false;
metrics = false;
};This is disabling things that phone home. Auto updates aren't needed because the version is tracked by Nixpkgs.
#| id: user-settings
theme = {
mode = "system";
light = "Dracula Light (Alucard";
dark = "Dracula";
};
ui_font_size = 14;
ui_font_family = "Ubuntu Sans";
buffer_font_size = 13;
buffer_font_family = "PragmataPro Liga";
buffer_line_height = "standard";
colorize_brackets = true;
preferred_line_length = 92;These are settings that affect the appearance of Zed, both in the chrome and the editor. I use the Dracula theme like I do with many other things.
#| id: user-settings vim_mode = true; helix_mode = true;
Zed has a Helix mode built-in, which is why I can deal with using it. It's not a perfect recreation, but it's good enough. The Helix mode is implemented on top of the Vim mode, so that must be enabled too.
#| id: user-settings autosave = "on_focus_change"; format_on_save = "on";
I like to have my editors save aggressively, and also automatically format files when they are saved.
#| id: user-settings toolbar.code_actions = true; diagnostics.inline.enabled = true; inlay_hints.enabled = true; code_lens = "on"; show_signature_help_after_edits = true; auto_signature_help = true;
These are editor features that I want enabled that are not by default.
#| id: user-settings git.inline_blame.enabled = false; title_bar.show_sign_in = false; title_bar.show_branch_status_icon = false; title_bar.show_branch_name = false; title_bar.show_worktree_name = false; collaboration_panel.button = false; terminal.button = false;
These are editor features that are enabled by default but that I don't want to use or have shown. Inline blame for Git is too noisy for my taste. The Git information in the title bar is not generally useful for me since I use Jujutsu. I never want to sign in to Zed, so having the button for that in the title bar is annoying. And I don't use the collaboration features or the built-in terminal, so I'd rather not have those buttons shown.
#| id: user-settings cli_default_open_behavior = "existing_window"; load_direnv = "shell_hook";
By default, I want the CLI command for Zed to open things in the existing window for the workspace the file belongs to.
I rely on direnv for most projects to set up the environment with the right tools in a Nix shell. This often includes LSPs and compilers/interpreters. Zed can load the direnv environment itself, so that the right tools are available even when you don't launch Zed from a CLI with that environment already set up.
#| id: user-settings
lsp.rust-analyzer.initialization_options = {
assist.preferSelf = true;
cargo.targetDir = true;
check.command = "clippy";
};I have a little bit of custom config for rust-analyzer. "assist.preferSelf" makes it use "Self" instead of the actual type name for completions where appropriate. "cargo.targetDir" makes rust-analyzer use its own target directory instead of sharing the default with normal cargo commands, which is important to avoid the editor needing to wait on a build happening outside the editor or vice versa. Usually this makes things more responsive, even if it means some duplicated work. And finally, I set the check command to clippy, as I want clippy warnings/errors to show up in the editor.
#| id: user-settings languages.Nix.language_servers = [ "nixd" "!nil" ];
For Nix, I use nixd as the language server. Zed defaults to using nil, so I need to add nixd to the list and remove nil.
xdg.configFile."zed/snippets/gemini.json".source =
let
json = pkgs.formats.json { };
in
{
"Code block" = {
prefix = "cc";
body = [
"``` {.\${1:nix}$2}"
"$0"
"```"
];
description = "Code block";
};
}
|> json.generate "gemini-snippets.json";The home-manager module for Zed doesn't include an option for snippets, but it's not hard to generate the necessary JSON file and link it into place. I have one snippet for Gemini files, which is used to generate the code blocks for literate programming.
text/gemini;lang=en-USThis content has been proxied by September (UNKNO).