Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Individual Features #1

Merged
merged 12 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 56 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,57 @@
[![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://nixos.zulipchat.com/#narrow/stream/413950-nix)

# just-flake
Convenient way to use [`just`](https://just.systems/) in your Nix devShells

Use [`just`](https://just.systems/) in your Nix devShells with re-usable and share-able targets.

> [!WARNING]
> Module options API is subject to change.


## Usage

In your `flake.nix`:

```nix
# In flake-parts' perSystem
{
just-flake.features = {
treefmt.enable = true;
rust.enable = true;
convco.enable = true;
hello = {
enable = true;
justfile = ''
hello:
echo Hello World
'';
};
};
}
```

In your `justfile`:

```just
# See flake.nix (just-flake)
import 'just-flake.just'

# Display the list of recipes
default:
@just --list
```

Then, add `config.just-flake.outputs.devShell` to the `inputsFrom` of your devShell.

Resulting devShell banner:

```
🍎🍎 Run 'just <recipe>' to get started
Available recipes:
changelog # Generate CHANGELOG.md using recent commits
default # Display the list of recipes
fmt # Auto-format the source tree using treefmt
hello
test # Run and watch 'cargo test'
w # Compile and watch the project
```
70 changes: 61 additions & 9 deletions flake-module.nix
Original file line number Diff line number Diff line change
@@ -1,12 +1,64 @@
{
perSystem = { pkgs, ... }: {
devShells.just = pkgs.mkShell {
packages = [ pkgs.just ];
shellHook = ''
echo
echo "🍎🍎 Run 'just <recipe>' to get started"
just
'';
};
perSystem = { config, pkgs, lib, ... }: {
options =
let
inherit (lib) types;
in
{
just-flake = lib.mkOption {
default = { };
type = types.submoduleWith {
specialArgs = { inherit pkgs; };
modules = [{
imports = [
./nix/features.nix
];

options = {
commonFileName = lib.mkOption {
type = lib.types.str;
default = "just-flake.just";
description = ''
The name of the common justfile generated by this module.
'';
};

outputs.devShell = lib.mkOption {
type = lib.types.package;
readOnly = true;
description = ''
The output devShell to include in `inputsFrom`.
'';
};
};
}];
};
};
};
config =
let
cfg = config.just-flake;
in
{
just-flake.outputs.devShell =
let
commonJustfile = pkgs.writeTextFile {
name = "justfile";
text =
lib.concatStringsSep "\n"
(lib.mapAttrsToList (name: feature: feature.outputs.justfile) cfg.features);
};
in
pkgs.mkShell {
packages = [ pkgs.just ];
shellHook = ''
ln -sf ${builtins.toString commonJustfile} ./${cfg.commonFileName}

echo
echo "🍎🍎 Run 'just <recipe>' to get started"
just --list
'';
};
};
};
}
32 changes: 32 additions & 0 deletions nix/feature.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{ config, name, lib, pkgs, ... }:

{
options = {
enable = lib.mkEnableOption "Enable this feature";
justfile = lib.mkOption {
type = lib.types.either lib.types.str lib.types.path;
description = ''
The justfile representing this feature.
'';
apply = x:
if builtins.isPath x then x else
pkgs.writeTextFile {
name = "${name}.just";
text = x;
};
};
outputs.justfile = lib.mkOption {
type = lib.types.str;
readOnly = true;
description = ''
The justfile code for importing this feature's justfile.

See https://just.systems/man/en/chapter_53.html
'';
default =
if config.enable
then "import '${builtins.toString config.justfile}'"
else "";
};
};
}
61 changes: 61 additions & 0 deletions nix/features.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# This largely inspired by the use of freeformType in
# https://github.com/cachix/git-hooks.nix/blob/master/modules/hooks.nix
{ pkgs, lib, ... }:

let
inherit (lib) types;
featureMod = {
imports = [ ./feature.nix ];
config._module.args = { inherit pkgs; };
};
featureType = types.submodule featureMod;
in
{
imports = [{
options.features = lib.mkOption {
type = types.submoduleWith {
modules = [{ freeformType = types.attrsOf featureType; }];
specialArgs = { inherit pkgs; };
};
default = { };
};
}];

# NOTE: At somepoint, we may want to add `settings` options to some of these features.
options.features = {
convco = lib.mkOption {
description = "Add the 'changelog' target calling convco";
type = types.submodule { imports = [ featureMod ]; };
};
rust = lib.mkOption {
description = "Add 'w' and 'test' targets for running cargo";
type = types.submodule { imports = [ featureMod ]; };
};
treefmt = lib.mkOption {
description = "Add the 'fmt' target to format source tree using treefmt";
type = types.submodule { imports = [ featureMod ]; };
};
};

config.features = lib.mapAttrs (_: lib.mapAttrs (_: lib.mkDefault)) {
convco.justfile = ''
# Generate CHANGELOG.md using recent commits
changelog:
convco changelog -p ""
'';
rust.justfile = ''
# Compile and watch the project
w:
cargo watch

# Run and watch 'cargo test'
test:
cargo watch -s "cargo test"
'';
treefmt.justfile = ''
# Auto-format the source tree using treefmt
fmt:
treefmt
'';
};
}