mirror of
https://github.com/xqtc161/meowlog.git
synced 2025-04-27 13:37:31 +02:00
Add flake; Shell completion; Refactor
This commit is contained in:
parent
8960c3b1df
commit
c26f70a52f
10 changed files with 37535 additions and 20 deletions
1748
Cargo.lock
generated
Normal file
1748
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -9,6 +9,8 @@ aes = "0.6.0"
|
|||
crc = "3.2.1"
|
||||
chrono = { version = "0.4.38", features = ["serde"] }
|
||||
clap = { version = "4.5.20", features = ["derive"] }
|
||||
clap_complete = "4.5.33"
|
||||
clap_complete_nushell = "4.5.4"
|
||||
color-eyre = "0.6.3"
|
||||
inquire = "0.7.5"
|
||||
lazy_static = "1.5.0"
|
||||
|
@ -20,4 +22,3 @@ toml = "0.8.19"
|
|||
uuid = { version = "1.10.0", features = ["serde", "v4"] }
|
||||
|
||||
[build-dependencies]
|
||||
clap_complete = "4.5.33"
|
||||
|
|
|
@ -11,8 +11,8 @@ use std::fmt::Formatter;
|
|||
use std::process::exit;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::config::INGESTIONS_FILE;
|
||||
use crate::substances::Substance;
|
||||
use crate::INGESTIONS_FILE;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
||||
pub struct Ingestion {
|
||||
|
@ -150,7 +150,7 @@ pub fn edit_ingestion() -> Result<(), std::io::Error> {
|
|||
{
|
||||
key.clone()
|
||||
} else {
|
||||
unreachable!()
|
||||
unsafe { std::hint::unreachable_unchecked() }
|
||||
}
|
||||
})
|
||||
.collect::<Vec<Uuid>>();
|
||||
|
@ -275,4 +275,3 @@ pub fn create_ingestions_file() -> Result<(), std::io::Error> {
|
|||
let hash_ser = bincode::serialize(&hash).unwrap();
|
||||
std::fs::write(INGESTIONS_FILE.to_string(), hash_ser)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::config::INGESTIONS_FILE;
|
||||
use crate::ingestions::{DoseUnit, Ingestion, IngestionMethod};
|
||||
use crate::substances::Substance;
|
||||
use crate::util::path_exists;
|
||||
use crate::INGESTIONS_FILE;
|
||||
use chrono::NaiveDateTime;
|
||||
use inquire;
|
||||
use std::{collections::HashMap, process::exit};
|
||||
|
@ -9,19 +9,19 @@ use strum::IntoEnumIterator;
|
|||
use uuid::Uuid;
|
||||
|
||||
pub fn ensure_ingestion_files() -> HashMap<Uuid, Ingestion> {
|
||||
let ingesstions_bytes_loaded_des: HashMap<Uuid, Ingestion>;
|
||||
let ingestions_bytes_loaded_des: HashMap<Uuid, Ingestion>;
|
||||
if path_exists(INGESTIONS_FILE.to_string()) {
|
||||
let substances_bytes_loaded =
|
||||
std::fs::read(INGESTIONS_FILE.to_string()).expect("Could not read ingestions file");
|
||||
ingesstions_bytes_loaded_des = bincode::deserialize(&substances_bytes_loaded).expect("Could not deserialize ingestions file. If you are tech-savvy try fixing it with a hex editor.");
|
||||
ingestions_bytes_loaded_des = bincode::deserialize(&substances_bytes_loaded).expect("Could not deserialize ingestions file. If you are tech-savvy try fixing it with a hex editor.");
|
||||
} else {
|
||||
std::fs::File::create(INGESTIONS_FILE.to_string()).unwrap();
|
||||
ingesstions_bytes_loaded_des = HashMap::new();
|
||||
ingestions_bytes_loaded_des = HashMap::new();
|
||||
let ingesstions_bytes_loaded_ser =
|
||||
bincode::serialize(&ingesstions_bytes_loaded_des).unwrap();
|
||||
bincode::serialize(&ingestions_bytes_loaded_des).unwrap();
|
||||
std::fs::write(INGESTIONS_FILE.to_string(), ingesstions_bytes_loaded_ser).unwrap();
|
||||
}
|
||||
ingesstions_bytes_loaded_des
|
||||
ingestions_bytes_loaded_des
|
||||
}
|
||||
|
||||
pub fn get_user_date(current: NaiveDateTime) -> chrono::NaiveDate {
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
use core::panic;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use config::{INGESTIONS_FILE, LOCAL_PATH, SUBSTANCES_FILE};
|
||||
use clap::{Command, Parser, Subcommand};
|
||||
use clap_complete::aot::{generate, Generator, Shell};
|
||||
use lazy_static::lazy_static;
|
||||
use std::io;
|
||||
|
||||
mod config;
|
||||
lazy_static! {
|
||||
pub static ref HOME: String = std::env::var("HOME").unwrap();
|
||||
pub static ref LOCAL_PATH: String = format!("{}/.local/share/meowlog", HOME.to_string());
|
||||
pub static ref SUBSTANCES_FILE: String =
|
||||
format!("{}/substances.bin", LOCAL_PATH.to_string()).to_string();
|
||||
pub static ref INGESTIONS_FILE: String =
|
||||
format!("{}/ingestions.bin", LOCAL_PATH.to_string()).to_string();
|
||||
}
|
||||
mod util;
|
||||
|
||||
mod ingestions;
|
||||
|
@ -47,13 +56,27 @@ enum Commands {
|
|||
|
||||
/// Remove substance
|
||||
RemoveSubstance,
|
||||
|
||||
/// Generate shell completions
|
||||
GenerateCompletions { shell: String },
|
||||
}
|
||||
|
||||
use clap::CommandFactory;
|
||||
use std::str::FromStr;
|
||||
fn build_cli_command() -> Command {
|
||||
Cli::command()
|
||||
}
|
||||
|
||||
fn print_completions<G: Generator>(gen: G, cmd: &mut Command) {
|
||||
generate(gen, cmd, cmd.get_name().to_string(), &mut io::stdout());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
ensure_files();
|
||||
|
||||
let cli = Cli::parse();
|
||||
|
||||
match &cli.command {
|
||||
match cli.command {
|
||||
Some(Commands::AddIngestion) => ingestions::add_ingestion(),
|
||||
Some(Commands::EditIngestion) => ingestions::edit_ingestion().unwrap(),
|
||||
Some(Commands::ListIngestions) => ingestions::list_ingestions().unwrap(),
|
||||
|
@ -62,6 +85,18 @@ fn main() {
|
|||
Some(Commands::EditSubstance) => substances::edit_substance().unwrap(),
|
||||
Some(Commands::ListSubstances) => substances::list_substances().unwrap(),
|
||||
Some(Commands::RemoveSubstance) => substances::remove_substance().unwrap(),
|
||||
Some(Commands::GenerateCompletions { shell }) => {
|
||||
let mut cmd = Cli::command();
|
||||
eprintln!("Generating completion file for {shell}...");
|
||||
if matches!(shell.as_str(), "nu" | "nushell") {
|
||||
print_completions(clap_complete_nushell::Nushell, &mut cmd);
|
||||
} else if let Ok(shell) = Shell::from_str(shell.as_str()) {
|
||||
print_completions(shell, &mut cmd);
|
||||
} else {
|
||||
return eprintln!("Shell not recognized!");
|
||||
};
|
||||
}
|
||||
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use uuid::Uuid;
|
|||
|
||||
use crate::substances::SubstanceClass;
|
||||
use crate::util::path_exists;
|
||||
use crate::{config::SUBSTANCES_FILE, substances::Substance};
|
||||
use crate::{substances::Substance, SUBSTANCES_FILE};
|
||||
|
||||
pub fn ensure_substance_file() -> HashMap<Uuid, Substance> {
|
||||
let substances_bytes_loaded_des: HashMap<Uuid, Substance>;
|
||||
|
|
|
@ -3,8 +3,8 @@ use std::collections::HashMap;
|
|||
use strum::IntoEnumIterator;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::config::SUBSTANCES_FILE;
|
||||
use crate::substance_util::{ensure_substance_file, get_substance_class, substances_to_vec};
|
||||
use crate::SUBSTANCES_FILE;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
||||
pub struct Substance {
|
||||
|
@ -81,7 +81,7 @@ pub fn remove_substance() -> Result<(), std::io::Error> {
|
|||
"Are you sure you want to remove '{}'? [y/N]",
|
||||
name
|
||||
))
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
if confirm {
|
||||
// Clone to avoid immutable borrow
|
||||
let sub_dec_clone = sub_dec.clone();
|
||||
|
@ -134,8 +134,8 @@ pub fn edit_substance() -> Result<(), std::io::Error> {
|
|||
format!("[{}] What do you want to edit?", substance_name).as_str(),
|
||||
SubstanceEditOptions::iter().collect::<Vec<_>>(),
|
||||
)
|
||||
.prompt()
|
||||
.unwrap();
|
||||
.prompt()
|
||||
.unwrap();
|
||||
match edit_select {
|
||||
SubstanceEditOptions::Name => {
|
||||
let name_updated = inquire::prompt_text("What should the new name be?").unwrap();
|
||||
|
@ -161,7 +161,7 @@ pub fn edit_substance() -> Result<(), std::io::Error> {
|
|||
"[{}] What should the new substance class be?",
|
||||
substance_name
|
||||
)
|
||||
.as_str(),
|
||||
.as_str(),
|
||||
class_variants,
|
||||
);
|
||||
let substance = Substance {
|
||||
|
|
35423
drugs.json
Normal file
35423
drugs.json
Normal file
File diff suppressed because it is too large
Load diff
116
flake.lock
generated
Normal file
116
flake.lock
generated
Normal file
|
@ -0,0 +1,116 @@
|
|||
{
|
||||
"nodes": {
|
||||
"advisory-db": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1728429239,
|
||||
"narHash": "sha256-k1KRRgmfKNhO9eU55FMkkzkneqAlwz5oLC5NSiEfGxs=",
|
||||
"owner": "rustsec",
|
||||
"repo": "advisory-db",
|
||||
"rev": "acb7ce45817b13dd34cb32540ff18be4e1f3ba09",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "rustsec",
|
||||
"repo": "advisory-db",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"crane": {
|
||||
"locked": {
|
||||
"lastModified": 1728776144,
|
||||
"narHash": "sha256-fROVjMcKRoGHofDm8dY3uDUtCMwUICh/KjBFQnuBzfg=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "f876e3d905b922502f031aeec1a84490122254b7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"fenix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"rust-analyzer-src": []
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1728887700,
|
||||
"narHash": "sha256-i+WCARuldFmXlNW6XlEYiL8UGMzjdg5lMQ9gpACQL/A=",
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"rev": "bcf74e45d5a818fe3aadf5cb3099189770e18579",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1726560853,
|
||||
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1728538411,
|
||||
"narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "b69de56fac8c2b6f8fd27f2eca01dcda8e0a4221",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"advisory-db": "advisory-db",
|
||||
"crane": "crane",
|
||||
"fenix": "fenix",
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"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
|
||||
}
|
193
flake.nix
Normal file
193
flake.nix
Normal file
|
@ -0,0 +1,193 @@
|
|||
{
|
||||
description = "Build a cargo workspace";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||
|
||||
crane.url = "github:ipetkov/crane";
|
||||
|
||||
fenix = {
|
||||
url = "github:nix-community/fenix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.rust-analyzer-src.follows = "";
|
||||
};
|
||||
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
|
||||
advisory-db = {
|
||||
url = "github:rustsec/advisory-db";
|
||||
flake = false;
|
||||
};
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, crane, fenix, flake-utils, advisory-db, ... }:
|
||||
flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
|
||||
inherit (pkgs) lib;
|
||||
|
||||
craneLib = crane.mkLib pkgs;
|
||||
src = craneLib.cleanCargoSource ./.;
|
||||
|
||||
# Common arguments can be set here to avoid repeating them later
|
||||
commonArgs = {
|
||||
inherit src;
|
||||
strictDeps = true;
|
||||
|
||||
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";
|
||||
};
|
||||
|
||||
craneLibLLvmTools = craneLib.overrideToolchain
|
||||
(fenix.packages.${system}.complete.withComponents [
|
||||
"cargo"
|
||||
"llvm-tools"
|
||||
"rustc"
|
||||
]);
|
||||
|
||||
# Build *just* the cargo dependencies (of the entire workspace),
|
||||
# so we can reuse all of that work (e.g. via cachix) when running in CI
|
||||
# It is *highly* recommended to use something like cargo-hakari to avoid
|
||||
# cache misses when building individual top-level-crates
|
||||
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
|
||||
|
||||
individualCrateArgs = commonArgs // {
|
||||
inherit cargoArtifacts;
|
||||
inherit (craneLib.crateNameFromCargoToml { inherit src; }) version;
|
||||
# NB: we disable tests since we'll run them all via cargo-nextest
|
||||
doCheck = false;
|
||||
};
|
||||
|
||||
fileSetForCrate = crate: lib.fileset.toSource {
|
||||
root = ./.;
|
||||
fileset = lib.fileset.unions [
|
||||
./Cargo.toml
|
||||
./Cargo.lock
|
||||
crate
|
||||
];
|
||||
};
|
||||
|
||||
# Build the top-level crates of the workspace as individual derivations.
|
||||
# This allows consumers to only depend on (and build) only what they need.
|
||||
# Though it is possible to build the entire workspace as a single derivation,
|
||||
# so this is left up to you on how to organize things
|
||||
meowlog-cli = craneLib.buildPackage (individualCrateArgs // {
|
||||
pname = "meowlog";
|
||||
cargoExtraArgs = "-p meowlog";
|
||||
src = fileSetForCrate ./.;
|
||||
});
|
||||
meowlog-server = craneLib.buildPackage (individualCrateArgs // {
|
||||
pname = "meowlog-server";
|
||||
cargoExtraArgs = "-p meowlog-server";
|
||||
src = fileSetForCrate ./.;
|
||||
});
|
||||
in
|
||||
{
|
||||
checks = {
|
||||
# Build the crates as part of `nix flake check` for convenience
|
||||
inherit meowlog-cli meowlog-server;
|
||||
|
||||
# Run clippy (and deny all warnings) on the workspace source,
|
||||
# again, reusing the dependency artifacts from above.
|
||||
#
|
||||
# Note that this is done as a separate derivation so that
|
||||
# we can block the CI if there are issues here, but not
|
||||
# prevent downstream consumers from building our crate by itself.
|
||||
my-workspace-clippy = craneLib.cargoClippy (commonArgs // {
|
||||
inherit cargoArtifacts;
|
||||
cargoClippyExtraArgs = "--all-targets -- --deny warnings";
|
||||
});
|
||||
|
||||
my-workspace-doc = craneLib.cargoDoc (commonArgs // {
|
||||
inherit cargoArtifacts;
|
||||
});
|
||||
|
||||
# Check formatting
|
||||
my-workspace-fmt = craneLib.cargoFmt {
|
||||
inherit src;
|
||||
};
|
||||
|
||||
my-workspace-toml-fmt = craneLib.taploFmt {
|
||||
src = pkgs.lib.sources.sourceFilesBySuffices src [ ".toml" ];
|
||||
# taplo arguments can be further customized below as needed
|
||||
# taploExtraArgs = "--config ./taplo.toml";
|
||||
};
|
||||
|
||||
# Audit dependencies
|
||||
my-workspace-audit = craneLib.cargoAudit {
|
||||
inherit src advisory-db;
|
||||
};
|
||||
|
||||
# Audit licenses
|
||||
my-workspace-deny = craneLib.cargoDeny {
|
||||
inherit src;
|
||||
};
|
||||
|
||||
# Run tests with cargo-nextest
|
||||
# Consider setting `doCheck = false` on other crate derivations
|
||||
# if you do not want the tests to run twice
|
||||
my-workspace-nextest = craneLib.cargoNextest (commonArgs // {
|
||||
inherit cargoArtifacts;
|
||||
partitions = 1;
|
||||
partitionType = "count";
|
||||
});
|
||||
|
||||
# Ensure that cargo-hakari is up to date
|
||||
my-workspace-hakari = craneLib.mkCargoDerivation {
|
||||
inherit src;
|
||||
pname = "my-workspace-hakari";
|
||||
cargoArtifacts = null;
|
||||
doInstallCargoArtifacts = false;
|
||||
|
||||
buildPhaseCargoCommand = ''
|
||||
cargo hakari generate --diff # workspace-hack Cargo.toml is up-to-date
|
||||
cargo hakari manage-deps --dry-run # all workspace crates depend on workspace-hack
|
||||
cargo hakari verify
|
||||
'';
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.cargo-hakari
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
packages = {
|
||||
inherit meowlog-cli meowlog-server;
|
||||
} // lib.optionalAttrs (!pkgs.stdenv.isDarwin) {
|
||||
my-workspace-llvm-coverage = craneLibLLvmTools.cargoLlvmCov (commonArgs // {
|
||||
inherit cargoArtifacts;
|
||||
});
|
||||
};
|
||||
|
||||
apps = rec {
|
||||
meowlog = flake-utils.lib.mkApp {
|
||||
drv = meowlog-cli;
|
||||
};
|
||||
meowlog-server = flake-utils.lib.mkApp {
|
||||
drv = meowlog-server;
|
||||
};
|
||||
default = meowlog;
|
||||
};
|
||||
|
||||
devShells.default = craneLib.devShell {
|
||||
# Inherit inputs from checks.
|
||||
checks = self.checks.${system};
|
||||
|
||||
# Additional dev-shell environment variables can be set directly
|
||||
# MY_CUSTOM_DEVELOPMENT_VAR = "something else";
|
||||
|
||||
# Extra inputs can be added here; cargo and rustc are provided by default.
|
||||
packages = [
|
||||
pkgs.cargo-hakari
|
||||
];
|
||||
};
|
||||
});
|
||||
}
|
Loading…
Add table
Reference in a new issue