diff --git a/Cargo.toml b/Cargo.toml index e1e5cb4..612de2d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,13 +24,13 @@ watch = ["dep:notify-debouncer-mini", "dep:ctrlc"] zip = ["shulkerbox/zip"] [dependencies] -clap = { version = "4.5.4", features = ["derive", "env", "deprecated"] } +clap = { version = "4.5.4", features = ["deprecated", "derive", "env"] } colored = "2.1.0" serde = { version = "1.0.197", features = ["derive"] } thiserror = "1.0.58" toml = "0.8.12" -shulkerscript = { git = "https://github.com/moritz-hoelting/shulkerscript-lang.git", features = ["shulkerbox"], default-features = false, rev = "a0a27cda96e1922b019b216961c39f7ef7991d22" } -shulkerbox = { git = "https://github.com/moritz-hoelting/shulkerbox.git", default-features = false, rev = "a2d20dab8ea97bbd873edafb23afaad34292457f" } +shulkerscript = { git = "https://github.com/moritz-hoelting/shulkerscript-lang.git", features = ["fs_access", "shulkerbox"], default-features = false, rev = "0cccee936e427d8ac2238956d2ef7b240d568e13" } +shulkerbox = { git = "https://github.com/moritz-hoelting/shulkerbox.git", default-features = false, rev = "aff342a64a94981af942223345b5a5f105212957" } git2 = { version = "0.19.0", default-features = false } path-absolutize = "3.1.1" dotenvy = "0.15.7" @@ -40,7 +40,7 @@ tracing = "0.1.40" tracing-subscriber = "0.3.18" # waiting for pull request to be merged inquire = { git = "https://github.com/moritz-hoelting/rust-inquire.git", branch = "main", package = "inquire" } -camino = "1.1.7" human-panic = "2.0.0" anyhow = "1.0.86" pathdiff = "0.2.1" +const_format = "0.2.32" diff --git a/src/cli.rs b/src/cli.rs index acc3602..e410e17 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -2,11 +2,18 @@ use crate::subcommands::{self, BuildArgs, CleanArgs, InitArgs}; use anyhow::Result; use clap::{Parser, Subcommand, ValueEnum}; +use const_format::formatcp; use tracing::Level; use tracing_subscriber::FmtSubscriber; +static VERSION: &str = formatcp!( + "v{cli_version}\nshulkerscript-lang v{lang_version}", + cli_version = env!("CARGO_PKG_VERSION"), + lang_version = shulkerscript::VERSION +); + #[derive(Debug, Clone, Parser)] -#[command(version, about, long_about = None)] +#[command(version, about, long_about = None, disable_version_flag = false, version = VERSION)] pub struct Args { #[command(subcommand)] cmd: Command, diff --git a/src/config.rs b/src/config.rs index db7ac86..9d0b484 100644 --- a/src/config.rs +++ b/src/config.rs @@ -20,7 +20,7 @@ pub struct PackConfig { impl PackConfig { pub const DEFAULT_NAME: &'static str = "shulkerscript-pack"; pub const DEFAULT_DESCRIPTION: &'static str = "A Minecraft datapack created with shulkerscript"; - pub const DEFAULT_PACK_FORMAT: u8 = 48; + pub const DEFAULT_PACK_FORMAT: u8 = shulkerbox::datapack::Datapack::LATEST_FORMAT; } impl Default for PackConfig { diff --git a/src/lib.rs b/src/lib.rs index add9d0f..4a91825 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,33 @@ +//! This crate is the cli app of the ShulkerScript language for creating Minecraft datapacks. +//! +//! # Installation +//! ```bash +//! cargo install shulkerscript-cli +//! ``` +//! +//! # Usage +//! An extended description of the commands can be found in the readme or by running `shulkerscript --help`. +//! +//! ### Initialize a new project +//! ```bash +//! shulkerscript init [OPTIONS] [PATH] +//! ``` +//! +//! ### Build a project +//! ```bash +//! shulkerscript build [OPTIONS] [PATH] +//! ``` +//! +//! ### Clean the output directory +//! ```bash +//! shulkerscript clean [OPTIONS] [PATH] +//! ``` +//! +//! ### Watch for changes +//! ```bash +//! shulkerscript watch [OPTIONS] [PATH] +//! ``` + pub mod cli; pub mod config; pub mod error; diff --git a/src/subcommands/build.rs b/src/subcommands/build.rs index 78f93bc..2028526 100644 --- a/src/subcommands/build.rs +++ b/src/subcommands/build.rs @@ -4,7 +4,7 @@ use shulkerbox::{ util::compile::CompileOptions, virtual_fs::{VFile, VFolder}, }; -use shulkerscript::base::FsProvider; +use shulkerscript::base::{FsProvider, PrintHandler}; use crate::{ config::ProjectConfig, @@ -76,6 +76,7 @@ pub fn build(args: &BuildArgs) -> Result<()> { )?; let datapack = shulkerscript::transpile( + &PrintHandler::new(), &FsProvider::default(), project_config.pack.pack_format, &script_paths, diff --git a/src/subcommands/lang_debug.rs b/src/subcommands/lang_debug.rs index 9f3584c..15930ea 100644 --- a/src/subcommands/lang_debug.rs +++ b/src/subcommands/lang_debug.rs @@ -1,7 +1,7 @@ use clap::ValueEnum; use anyhow::Result; -use shulkerscript::base::FsProvider; +use shulkerscript::base::{FsProvider, PrintHandler}; use std::path::PathBuf; use crate::{config::PackConfig, util}; @@ -33,7 +33,14 @@ pub fn lang_debug(args: &LangDebugArgs) -> Result<()> { let file_provider = FsProvider::default(); match args.dump { DumpState::Tokens => { - let tokens = shulkerscript::tokenize(&file_provider, &args.path)?; + let tokens = shulkerscript::tokenize( + &PrintHandler::new(), + &file_provider, + &args.path, + args.path.file_stem().map_or(String::from("main"), |s| { + s.to_string_lossy().into_owned().to_string() + }), + )?; if args.pretty { println!("{:#?}", tokens); } else { @@ -41,7 +48,14 @@ pub fn lang_debug(args: &LangDebugArgs) -> Result<()> { } } DumpState::Ast => { - let ast = shulkerscript::parse(&file_provider, &args.path)?; + let ast = shulkerscript::parse( + &PrintHandler::new(), + &file_provider, + &args.path, + args.path.file_stem().map_or(String::from("main"), |s| { + s.to_string_lossy().into_owned().to_string() + }), + )?; if args.pretty { println!("{:#?}", ast); } else { @@ -55,6 +69,7 @@ pub fn lang_debug(args: &LangDebugArgs) -> Result<()> { .join("src"), )?; let datapack = shulkerscript::transpile( + &PrintHandler::new(), &file_provider, PackConfig::DEFAULT_PACK_FORMAT, &program_paths, diff --git a/src/util.rs b/src/util.rs index 2d34c8c..62ceb16 100644 --- a/src/util.rs +++ b/src/util.rs @@ -5,8 +5,6 @@ use std::{ path::{Path, PathBuf}, }; -use camino::Utf8PathBuf; - use inquire::{autocompletion::Replacement, Autocomplete}; use path_absolutize::Absolutize; @@ -68,17 +66,20 @@ impl PathAutocomplete { if !self.cache.contains_key(parent) { tracing::trace!("Cache miss for \"{}\", reading dir", parent); - let parent_path = Utf8PathBuf::from(parent); + let parent_path = PathBuf::from(parent); if !parent_path.exists() || !parent_path.is_dir() { return Err("Path does not exist"); } let entries = parent_path - .read_dir_utf8() + .read_dir() .map_err(|_| "Could not read dir")? .filter_map(|entry| { - entry.ok().map(|entry| { - entry.file_name().to_string() + if entry.path().is_dir() { "/" } else { "" } + entry.ok().and_then(|entry| { + Some( + entry.file_name().into_string().ok()?.to_string() + + if entry.path().is_dir() { "/" } else { "" }, + ) }) }) .collect::>();