Compare commits

..

1 commit

Author SHA1 Message Date
2960b6dfc4 feat: Implemented file hierarchy initialization
- Bump version to 0.5.1
- Added Config::save method
- cli: Added init command
2025-12-05 17:16:40 +03:00
5 changed files with 111 additions and 25 deletions

View file

@ -2,7 +2,7 @@
members = ["cli"] members = ["cli"]
[workspace.package] [workspace.package]
version = "0.5.0" version = "0.5.1"
edition = "2024" edition = "2024"
repository = "https://2ndbeam.ru/git/2ndbeam/squad-quest" repository = "https://2ndbeam.ru/git/2ndbeam/squad-quest"
license = "MIT" license = "MIT"

View file

@ -1,10 +1,4 @@
# Default config quests_path = "quests"
accounts_path = "accounts"
# Path to quests folder relative to config map = "map.toml"
quests_path = "./quests" verbose = true
# Path to accounts folder relative to config
accounts_path = "./accounts"
# Path to map .toml file relative to config
map = "./map.toml"

View file

@ -1,6 +1,6 @@
use std::path::PathBuf; use std::path::PathBuf;
use clap::{Parser,Subcommand}; use clap::{Args,Parser,Subcommand};
pub mod account; pub mod account;
pub mod map; pub mod map;
@ -23,6 +23,8 @@ pub struct Cli {
#[derive(Subcommand)] #[derive(Subcommand)]
pub enum Objects { pub enum Objects {
/// Initialize new SquadQuest in current working directory
Init(InitArgs),
/// Operations on the quests /// Operations on the quests
#[command(subcommand)] #[command(subcommand)]
Quest(quest::QuestCommands), Quest(quest::QuestCommands),
@ -34,3 +36,8 @@ pub enum Objects {
Map(map::MapCommands), Map(map::MapCommands),
} }
#[derive(Args)]
pub struct InitArgs {
#[arg(long,short)]
pub path: Option<PathBuf>,
}

View file

@ -1,4 +1,4 @@
use std::path::{Path, PathBuf}; use std::{fs::DirBuilder, path::{Path, PathBuf}};
use clap::Parser; use clap::Parser;
use squad_quest_cli::cli::{Cli,Objects,account::*,map::*,quest::*}; use squad_quest_cli::cli::{Cli,Objects,account::*,map::*,quest::*};
@ -25,19 +25,17 @@ fn do_and_log(result: Result<(),Error>, log: bool, ok_text: String) {
} }
} }
fn main() { fn load_config_silent(quiet: bool, path: PathBuf) -> Config {
let cli = Cli::parse(); match quiet {
false => Config::load(path.clone()),
let config = match cli.quiet {
false => Config::load(cli.config.clone()),
true => { true => {
match Config::try_load(cli.config.clone()) { match Config::try_load(path.clone()) {
Ok(mut config) => { Ok(mut config) => {
config.verbose = false; config.verbose = false;
config config
}, },
Err(_) => { Err(_) => {
let path = cli.config.clone().parent().unwrap_or(&Path::new(".")).to_owned(); let path = path.clone().parent().unwrap_or(&Path::new(".")).to_owned();
Config { Config {
verbose: false, verbose: false,
path, path,
@ -46,9 +44,61 @@ fn main() {
} }
} }
}, },
}; }
}
fn main() {
let cli = Cli::parse();
let config = load_config_silent(cli.quiet, cli.config.clone());
let map_save = |map: Map, map_path: PathBuf| { map.save(map_path.parent().unwrap_or(Path::new("")).to_owned()) };
match &cli.command { match &cli.command {
Objects::Init(args) => {
let path = match args.path.clone() {
Some(path) => path,
None => PathBuf::new(),
};
match DirBuilder::new().recursive(true).create(path.clone()) {
Ok(_) if !cli.quiet => println!("Created directory {:?}", path),
Err(error) => {
if !cli.quiet { eprintln!("Error: {error}"); }
return;
},
_ => {},
}
let config = Config {
path: path.clone(),
..Default::default()
};
do_and_log(config.save(path.clone()), !cli.quiet, format!("Created file {:?}/config.toml", path));
let mut config_path = path.clone();
config_path.push("config.toml");
let mut config = load_config_silent(true, config_path);
config.verbose = Config::default().verbose;
let map = Map::default();
let map_path = config.full_map_path();
do_and_log(map_save(map, map_path.clone()), !cli.quiet, format!("Created file {:?}/map.toml", map_path));
let quests_path = config.full_quests_path();
let accounts_path = config.full_accounts_path();
for path in [quests_path, accounts_path] {
match DirBuilder::new().recursive(true).create(path.clone()) {
Ok(_) if !cli.quiet => println!("Created directory {:?}", path),
Err(error) => {
if !cli.quiet { eprintln!("Error: {error}"); }
return;
},
_ => {},
}
}
},
Objects::Quest(commands) => { Objects::Quest(commands) => {
let mut quests = config.load_quests(); let mut quests = config.load_quests();
let mut path = config.full_quests_path(); let mut path = config.full_quests_path();
@ -289,7 +339,6 @@ fn main() {
} }
}; };
let map_save = |map: Map, map_path: PathBuf| { map.save(map_path.parent().unwrap_or(Path::new("")).to_owned()) };
match commands { match commands {
MapCommands::List => { MapCommands::List => {
for room in map.room { for room in map.room {

View file

@ -1,12 +1,12 @@
//! Configuration file that handles (de-)serializing other components //! Configuration file that handles (de-)serializing other components
use std::{fs::{self, DirEntry},path::{Path, PathBuf}}; use std::{fs::{self, DirEntry}, io::Write, path::{Path, PathBuf}};
use serde::Deserialize; use serde::{Deserialize, Serialize};
use crate::{SquadObject, account::Account, error::Error, quest::Quest}; use crate::{SquadObject, account::Account, error::Error, quest::Quest};
/// Struct for containing paths to other (de-)serializable things /// Struct for containing paths to other (de-)serializable things
#[derive(Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(default)] #[serde(default)]
pub struct Config { pub struct Config {
/// Path to config directory /// Path to config directory
@ -112,6 +112,42 @@ impl Config {
} }
} }
/// Serialize config into TOML.
/// Config will be saved as `path/config.toml`
///
/// # Examples
/// ```rust
/// use squad_quest::config::Config;
///
/// let path = "cfg".into();
///
/// let config = Config::default();
///
/// if let Err(error) = config.save(path) {
/// // handle error
/// }
/// ```
pub fn save(&self, path: PathBuf) -> Result<(), Error> {
let mut path = path;
path.push("config.toml");
let str = match toml::to_string_pretty(&self) {
Ok(string) => string,
Err(error) => return Err(Error::TomlSerializeError(error)),
};
let mut file = match fs::File::create(path) {
Ok(f) => f,
Err(error) => return Err(Error::IoError(error)),
};
if let Err(error) = file.write_all(str.as_bytes()) {
return Err(Error::IoError(error));
}
Ok(())
}
/// Deserialize config from TOML /// Deserialize config from TOML
/// ///
/// # Examples /// # Examples