fix: update flake and refactor
This commit is contained in:
parent
25eadea4b7
commit
88b6816133
5 changed files with 246 additions and 29 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
@ -0,0 +1 @@
|
|||
use flake
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1 +1,3 @@
|
|||
target
|
||||
.direnv
|
||||
result
|
||||
|
|
135
flake.lock
Normal file
135
flake.lock
Normal file
|
@ -0,0 +1,135 @@
|
|||
{
|
||||
"nodes": {
|
||||
"crane": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1707685877,
|
||||
"narHash": "sha256-XoXRS+5whotelr1rHiZle5t5hDg9kpguS5yk8c8qzOc=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "2c653e4478476a52c6aa3ac0495e4dea7449ea0e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"fenix": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs",
|
||||
"rust-analyzer-src": "rust-analyzer-src"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1707891749,
|
||||
"narHash": "sha256-SeikNYElHgv8uVMbiA9/pU3Cce7ssIsiM8CnEiwd1Nc=",
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"rev": "3115aab064ef38cccd792c45429af8df43d6d277",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1705309234,
|
||||
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1707689078,
|
||||
"narHash": "sha256-UUGmRa84ZJHpGZ1WZEBEUOzaPOWG8LZ0yPg1pdDF/yM=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "f9d39fb9aff0efee4a3d5f4a6d7c17701d38a1d8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1707877513,
|
||||
"narHash": "sha256-sp0w2apswd3wv0sAEF7StOGHkns3XUQaO5erhWFZWXk=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "89653a03e0915e4a872788d10680e7eec92f8600",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"crane": "crane",
|
||||
"fenix": "fenix",
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
}
|
||||
},
|
||||
"rust-analyzer-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1707849817,
|
||||
"narHash": "sha256-If6T0MDErp3/z7DBlpG4bV46IPP+7BWSlgTI88cmbw0=",
|
||||
"owner": "rust-lang",
|
||||
"repo": "rust-analyzer",
|
||||
"rev": "a02a219773629686bd8ff123ca1aa995fa50d976",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "rust-lang",
|
||||
"ref": "nightly",
|
||||
"repo": "rust-analyzer",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
76
flake.nix
Normal file
76
flake.nix
Normal file
|
@ -0,0 +1,76 @@
|
|||
{
|
||||
description = "Build a cargo project";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||
|
||||
crane = {
|
||||
url = "github:ipetkov/crane";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
fenix = {
|
||||
url = "github:nix-community/fenix";
|
||||
};
|
||||
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs = inputs: with inputs;
|
||||
flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
};
|
||||
|
||||
inherit (pkgs) lib;
|
||||
|
||||
craneLib = crane.lib.${system}.overrideToolchain fenix.packages.${system}.complete.toolchain;
|
||||
src = craneLib.path ./.;
|
||||
|
||||
# Common arguments can be set here to avoid repeating them later
|
||||
commonArgs = {
|
||||
inherit src;
|
||||
|
||||
buildInputs = [
|
||||
# Add additional build inputs here
|
||||
] ++ lib.optionals pkgs.stdenv.isDarwin [
|
||||
# Additional darwin specific inputs can be set here
|
||||
pkgs.libiconv
|
||||
];
|
||||
|
||||
# Additional environment variables can be set directly
|
||||
# MY_CUSTOM_VAR = "some value";
|
||||
};
|
||||
|
||||
# Build *just* the cargo dependencies, so we can reuse
|
||||
# all of that work (e.g. via cachix) when running in CI
|
||||
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
|
||||
|
||||
# Build the actual crate itself, reusing the dependency
|
||||
# artifacts from above.
|
||||
my-crate = craneLib.buildPackage (commonArgs // {
|
||||
inherit cargoArtifacts;
|
||||
});
|
||||
in
|
||||
{
|
||||
packages = {
|
||||
default = my-crate;
|
||||
};
|
||||
|
||||
apps.default = flake-utils.lib.mkApp {
|
||||
drv = my-crate;
|
||||
};
|
||||
|
||||
devShells.default = pkgs.mkShell {
|
||||
# Extra inputs can be added here
|
||||
nativeBuildInputs = with pkgs; [
|
||||
cargo
|
||||
fenix.packages.${system}.complete.toolchain
|
||||
rustfmt
|
||||
] ++ lib.optionals pkgs.stdenv.isDarwin [
|
||||
libiconv
|
||||
];
|
||||
};
|
||||
});
|
||||
}
|
61
src/lib.rs
61
src/lib.rs
|
@ -1,56 +1,59 @@
|
|||
#![feature(box_patterns)]
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, ItemFn};
|
||||
use proc_macro2::{Ident, Span};
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, ItemFn, PatType, Receiver};
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn clap_main(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let mut f = parse_macro_input!(item as ItemFn);
|
||||
|
||||
// Make sure we actually have a function we can handle
|
||||
let item_type = f
|
||||
.sig
|
||||
.inputs
|
||||
.first()
|
||||
.expect("Need exactly one argument to the function");
|
||||
|
||||
let renamed_main = Ident::new("clap_rewritten_main", Span::call_site());
|
||||
|
||||
|
||||
// Rename the current main function so we can replace it
|
||||
let renamed_main = Ident::new("clap_main_fn", Span::call_site());
|
||||
f.sig.ident = renamed_main.clone();
|
||||
|
||||
let ty = match item_type {
|
||||
syn::FnArg::Receiver(recv) => match *recv.ty.clone() {
|
||||
syn::Type::Path(ty) => ty.path.clone(),
|
||||
_ => panic!("unexpected type"),
|
||||
},
|
||||
|
||||
syn::FnArg::Typed(typed) => match *typed.ty.clone() {
|
||||
syn::Type::Path(ty) => ty.path.clone(),
|
||||
_ => panic!("Unexpected type"),
|
||||
},
|
||||
let clap_options_type = match item_type {
|
||||
// Match named types since those are the only ones that
|
||||
// would have implemented Parser
|
||||
syn::FnArg::Receiver(Receiver { ty, .. }) | syn::FnArg::Typed(PatType { ty, .. }) => {
|
||||
match ty.as_ref() {
|
||||
syn::Type::Path(ty) => ty.path.clone(),
|
||||
_ => panic!("Expected a path type"),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let main_return_type = f.sig.output.clone();
|
||||
|
||||
quote! {
|
||||
// Paste the renamed main function here
|
||||
#f
|
||||
|
||||
pub fn main() {
|
||||
// Set the type so the return value of main gets forwarded
|
||||
pub fn main() -> #main_return_type {
|
||||
use clap::Parser;
|
||||
use std::io::Write;
|
||||
let args = match #ty::try_parse() {
|
||||
Ok(args) => args,
|
||||
Err(e) => {
|
||||
writeln!(&mut std::io::stderr(), "{e}").expect("Could not write to stderr!");
|
||||
std::process::exit(-1);
|
||||
},
|
||||
|
||||
// Handle the error on the type here and only continue
|
||||
// if we actually parsed the options. If the user wanted
|
||||
// to handle the errors manually they wouldn't be using this
|
||||
let args = Ok(match #clap_options_type::try_parse()) else {
|
||||
writeln!(&mut std::io::stderr(), "{e}").expect("Could not write to stderr!");
|
||||
// directly exit (we don't care about what possible types main might return
|
||||
// since we are erroring out before it even gets called
|
||||
std::process::exit(-1);
|
||||
};
|
||||
|
||||
match #renamed_main(args) {
|
||||
Ok(()) => {},
|
||||
Err(e) => {
|
||||
writeln!(&mut std::io::stderr(), "{e}").expect("Could not write to stderr!");
|
||||
std::process::exit(-1);
|
||||
},
|
||||
}
|
||||
// Call the decorated main function
|
||||
#renamed_main(args)
|
||||
}
|
||||
}
|
||||
.into()
|
||||
|
|
Loading…
Reference in a new issue