Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
a7a5872
chore: run `treefmt`
michalrus Feb 24, 2026
8c5ecda
chore: add a Haskell section to `.gitignore`
michalrus Feb 24, 2026
0628b3d
chore: use a patch for exposing `cardano-submit-api`
michalrus Feb 24, 2026
b03a11c
chore: apply Nix linters
michalrus Feb 24, 2026
ac5e889
feat: add a draft of a devshell for running incremental `cabal build …
michalrus Feb 24, 2026
551d238
chore: use a Python script for editing `cabal.project`, it's less fra…
michalrus Feb 24, 2026
982cbdb
chore: add a few more formatters
michalrus Feb 24, 2026
732a1d3
chore: remove unnecessary comments
michalrus Feb 24, 2026
84c051d
chore: add `inputs.devshell`
michalrus Feb 24, 2026
7a3de21
feat: add a working `numtide/devshell`
michalrus Feb 25, 2026
46f520d
feat: expose Haskell tools in the new devshell menu
michalrus Feb 25, 2026
a36a99f
feat: add `direnv`
michalrus Feb 25, 2026
c6cdd40
Merge branch 'main' into feat/devshell-proper
michalrus Feb 25, 2026
9c939a9
fix: the devshell build for 10.6.2
michalrus Feb 25, 2026
2c28fe3
chore: remove the suggestion to manually run `cabal update` on entry
michalrus Feb 25, 2026
8883264
fix: make directory entry quicker by 260 ms
michalrus Feb 25, 2026
2e31573
chore: make intent explicit with file redirections in shell startup s…
michalrus Feb 25, 2026
ad8c0ec
fix: only modify `cabal.project` when it's needed (keep mtime more st…
michalrus Feb 25, 2026
e0d1928
chore: make `nixlint` pass
michalrus Feb 25, 2026
8049e57
fix(lsp): use `makeRelativeToProject` with `embedFile` to fix a HLS i…
michalrus Mar 18, 2026
9fd64cb
chore: add a `README.md` section about LSP and `direnv`
michalrus Mar 18, 2026
67e0bb4
fix(punctation): use Unicode
michalrus Mar 18, 2026
3ebc43c
fix(vscode): don’t try to use `haskell-language-server-wrapper`
michalrus Mar 18, 2026
29966da
fix(lsp): expose a no-op `haskell-language-server-wrapper`
michalrus Mar 18, 2026
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
3 changes: 3 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
use flake

source_env_if_exists .envrc.local
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,14 @@
# Nix
result
result-*

# Haskell / Cabal
dist-newstyle/
/cabal.project
/cabal.project.*
/.cabal/
.ghc.environment.*

# direnv
.direnv/
.envrc.local
49 changes: 47 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Available commands:
```
❯ testgen-hs generate -g1 -n1 ApplyTxErr_Conway
```

```json
{
"seed": 1731690796,
Expand Down Expand Up @@ -266,11 +267,55 @@ And then easily reproduce it by providing the same seed that was found:

```
❯ ( echo 8182068182028200a0
echo 81820681820481581cc0231342a5c66b25d652a7116559d02cbe9515ef890fd698de38d456
echo 81820681820481581cc0231342a5c66b25d652a7116559d02cbe9515ef890fd698de38d456
) | testgen-hs deserialize-stream
```

``` json
```json
{"cbor":"8182068182028200a0","haskellRepr":"ApplyTxError (ConwayCertsFailure (WithdrawalsNotInRewardsCERTS (fromList [])) :| [])","json":{"contents":{"contents":{"contents":{"era":"ShelleyBasedEraConway","error":["ConwayCertsFailure (WithdrawalsNotInRewardsCERTS (fromList []))"],"kind":"ShelleyTxValidationError"},"tag":"TxValidationErrorInCardanoMode"},"tag":"TxCmdTxSubmitValidationError"},"tag":"TxSubmitFail"},"typeTag":"ApplyTxError (ConwayEra StandardCrypto)"}
{"cbor":"81820681820481581cc0231342a5c66b25d652a7116559d02cbe9515ef890fd698de38d456","haskellRepr":"ApplyTxError (ConwayWdrlNotDelegatedToDRep (KeyHash {unKeyHash = \"c0231342a5c66b25d652a7116559d02cbe9515ef890fd698de38d456\"} :| []) :| [])","json":{"contents":{"contents":{"contents":{"era":"ShelleyBasedEraConway","error":["ConwayWdrlNotDelegatedToDRep (KeyHash {unKeyHash = \"c0231342a5c66b25d652a7116559d02cbe9515ef890fd698de38d456\"} :| [])"],"kind":"ShelleyTxValidationError"},"tag":"TxValidationErrorInCardanoMode"},"tag":"TxCmdTxSubmitValidationError"},"tag":"TxSubmitFail"},"typeTag":"ApplyTxError (ConwayEra StandardCrypto)"}
```

## Development – HLS setup

This project provides a Nix devshell with GHC and HLS. To get full IDE
support you need [`direnv`](https://direnv.net/) with
[`nix-direnv`](https://github.com/nix-community/nix-direnv) so that the
`.envrc` is picked up automatically. See their official documentation for
installation instructions.

The instructions below use VS Code as an example, but any editor with LSP and
`direnv` support (Neovim, Emacs, etc.) works the same way. The devshell puts
both `haskell-language-server` and `haskell-language-server-wrapper` on
`PATH`, so most editors should pick up HLS automatically.

### VS Code example

1. Install the extensions **Haskell** (`haskell.haskell`) and **direnv**
(`mkhl.direnv`).

2. Tell the Haskell extension to use the HLS provided by the devshell
instead of managing its own. Add this to your VS Code settings:

```json
{ "haskell.manageHLS": "PATH" }
```

Optionally, enable semantic highlighting (richer colours for types,
type variables, etc.):

```json
{ "haskell.plugin.semanticTokens.globalOn": true }
```

3. Allow direnv for this project and restart HLS:

```
direnv allow
```

Then in VS Code: `Ctrl+Shift+P` → _Haskell: Restart Haskell LSP Server_.

> **Note:** The first HLS session takes roughly 10 minutes while `hie-bios`
> builds all dependencies via `cabal v2-repl`. Subsequent loads use the
> cache at `~/.cache/hie-bios/`.
21 changes: 21 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 38 additions & 23 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,26 @@
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
flake-parts.url = "github:hercules-ci/flake-parts";
treefmt-nix.url = "github:numtide/treefmt-nix";
treefmt-nix.inputs.nixpkgs.follows = "nixpkgs";
flake-compat.url = "github:input-output-hk/flake-compat";
flake-compat.flake = false;
cardano-node.url = "github:IntersectMBO/cardano-node/10.6.2";
cardano-node.flake = false; # otherwise, +2k dependencies we don’t really use
nix-bundle-exe.url = "github:3noch/nix-bundle-exe";
nix-bundle-exe.flake = false;
treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
flake-compat = {
url = "github:input-output-hk/flake-compat";
flake = false;
};
devshell = {
url = "github:numtide/devshell";
inputs.nixpkgs.follows = "nixpkgs";
};
cardano-node = {
url = "github:IntersectMBO/cardano-node/10.6.2";
flake = false; # otherwise, +2k dependencies we don’t really use
};
nix-bundle-exe = {
url = "github:3noch/nix-bundle-exe";
flake = false;
};
};

outputs = inputs: let
Expand All @@ -18,6 +30,7 @@
inputs.flake-parts.lib.mkFlake {inherit inputs;} ({config, ...}: {
imports = [
inputs.treefmt-nix.flakeModule
inputs.devshell.flakeModule
];

flake.internal =
Expand All @@ -29,29 +42,31 @@
);

systems = ["x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin"];
perSystem = {
config,
system,
pkgs,
...
}: {
packages = let
internal = inputs.self.internal.${system};
in
perSystem = {system, ...}: let
internal = inputs.self.internal.${system};
in {
packages =
{
default = internal.defaultPackage;
}
// (lib.optionalAttrs (system == "x86_64-linux") {
default-x86_64-windows = inputs.self.internal.x86_64-windows.defaultPackage;
});

devshells.default = internal.devShell.new;

treefmt = {pkgs, ...}: {
projectRootFile = "flake.nix";
programs.alejandra.enable = true; # Nix
programs.ormolu.enable = true; # Haskell
programs.cabal-fmt.enable = true;
programs.shfmt.enable = true;
programs.yamlfmt.enable = pkgs.system != "x86_64-darwin"; # a treefmt-nix+yamlfmt bug on Intel Macs
programs = {
alejandra.enable = true; # Nix
ormolu.enable = true; # Haskell
cabal-fmt.enable = true;
prettier.enable = true; # Markdown, JSON, …
shfmt.enable = true;
ruff-check.enable = true; # Python
ruff-format.enable = true; # Python
yamlfmt.enable = pkgs.system != "x86_64-darwin"; # a treefmt-nix+yamlfmt bug on Intel Macs
};
};
};

Expand All @@ -60,7 +75,7 @@
testgen-hs = lib.genAttrs (config.systems ++ ["x86_64-windows"]) (
targetSystem: inputs.self.internal.${targetSystem}.hydraPackage
);
inherit (inputs.self) checks;
inherit (inputs.self) checks devShells;
};
in
allJobs
Expand Down
Loading
Loading