nixd v2.9.0: Intelligent Refactoring
Welcome to nixd 2.9.0! This release features an extensive suite of Code Actions contributed by @takeokunn, greatly enhancing flexibility when working with Nix expressions. We have also optimized documentation support and performance details.
๐ Highlights
๐ ๏ธ Powerful Code Refactoring (Code Actions)
Nix can sometimes feel verbose. This update introduces a series of "one-click refactors" to keep your code clean:
AttrSet Restructuring
- Flatten & Pack: Quickly convert between nested sets and dotted paths (#757, #758).
{ foo = { bar = 1; }; } # <-> { foo.bar = 1; }
- The "Pack" Series: Added Pack One, Shallow Pack All, and Recursive Pack All to easily reorganize complex attribute definitions (#759).
- Pack One: Transforms a single dotted binding into a nested set.
{ foo.bar = 1; }โ{ foo = { bar = 1; }; }
- Shallow Pack All: When siblings share a prefix, packs the first level but preserves remaining dots.
{ foo.bar.x = 1; foo.baz = 2; }โ{ foo = { bar.x = 1; baz = 2; }; }
- Recursive Pack All: Fully nests all sibling bindings recursively.
{ foo.bar.x = 1; foo.baz = 2; }โ{ foo = { bar = { x = 1; }; baz = 2; }; }
- Pack One: Transforms a single dotted binding into a nested set.
Syntax Transformations
- Inherit Conversion: Convert explicit bindings to
inheritsyntax, or expand them back (#770, #773).# Pattern: Simple variable assignment { foo = foo; bar = bar; } -> { inherit foo bar; } # Pattern: Select from source { x = lib.x; y = lib.y; } -> { inherit (lib) x y; }
- Eliminate
with: Provides actions to refactorwithstatements into saferlet/inheritbindings (#768).# Before with lib; optionalString true "yes" # After let inherit (lib) optionalString; in optionalString true "yes"
- Strings & Quotes: Support for adding/removing quotes from attribute names (#756) and string literal syntax conversion (#775).
Developer Productivity
- JSON to Nix: Convert selected JSON snippets to Nix format instantly (#763).
{"foo": 1, "bar": true, "nested": {"key": "value"}}
# โ
{
foo = 1;
bar = true;
nested = {
key = "value";
};
}- Extract to File: Extract a selected expression and refactor it into a standalone file (#767).
Before:
{ pkgs }: { buildInputs = [ pkgs.foo pkgs.bar ]; }After extraction:
- New file (buildInputs.nix):
{ pkgs }:
[ pkgs.foo pkgs.bar ]
- Original file:
{ pkgs }: { buildInputs = import ./buildInputs.nix { inherit pkgs; }; }
- Auto-complete Formals: For undefined variables, use a Code Action to add them to function formals (#777).
| Before | After |
|---|---|
{x}: y
| {x, y}: y
|
{ }: y
| { y }: y
|
{ ... }: y
| { y, ... }: y
|
{x, ...}: y
| {x, y, ...}: y
|
- Quick Cleanup: Automatically remove unused
letbindings (#779).
| Before | After |
|---|---|
let x = 1; in 2
| let in 2
|
let x = 1; y = 2; in y
| let y = 2; in y
|
let x = 1; y = 2; in 3
| let y = 2; in 3 (each gets separate action)
|
๐ Documentation & Interaction
- Noogle Integration: Unsure how to use a
libfunction? You can now open noogle.dev documentation directly via a Code Action (#764).
lib.optionalStringโ Openshttps://noogle.dev/f/lib/optionalStringlib.strings.optionalStringโ Openshttps://noogle.dev/f/lib/strings/optionalString
- Enhanced Hover: Hovering now supports expression selection and provides more detailed documentation (#745). These descriptions are pulled directly from RFC 0145 ยท Doc-comments within nixpkgs.
๐ Fixes & Improvements
- Formatting Optimization: Saving is only triggered if the formatter actually modifies the code, reducing unnecessary pop-ups (#771) - by @cubewhy.
- Semantic Fixes: Fixed incorrect diagnostics when using
inherit (builtins)insideletblocks (#782). nixd now correctly handles these inletblocks while ignoring them in standard attrsets. - Stability: Added regression tests for Hover functionality (#781).
๐ค Community
- A special welcome to our new contributor @cubewhy!
- Congratulations to @takeokunn for becoming the Code Owner for the Code Actions module in
nixd.
Full Changelog: v2.8.2...v2.9.0
