Skip to content

Commit

Permalink
READY: (wca): qqq (#1492)
Browse files Browse the repository at this point in the history
* wip

* wip

* wip

* done
  • Loading branch information
Barsik-sus authored Dec 4, 2024
1 parent 8fdf362 commit 39907f7
Show file tree
Hide file tree
Showing 38 changed files with 423 additions and 648 deletions.
12 changes: 6 additions & 6 deletions module/move/wca/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ harness = false
[dependencies]

## internal
error_tools = { workspace = true, features = [ "default" ] }
strs_tools = { workspace = true, features = [ "default" ] }
mod_interface = { workspace = true, features = [ "default" ] }
iter_tools = { workspace = true, features = [ "default" ] }
former = { workspace = true, features = [ "default" ] }
# xxx : qqq : optimize set of features
error_tools = { workspace = true, features = [ "enabled", "error_typed", "error_untyped" ] }
mod_interface = { workspace = true, features = [ "enabled" ] }
iter_tools = { workspace = true, features = [ "enabled" ] }
former = { workspace = true, features = [ "enabled", "derive_former" ] }
# xxx : aaa : optimize set of features
# aaa : done.

## external
log = "0.4"
Expand Down
4 changes: 2 additions & 2 deletions module/move/wca/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ The tool to make CLI ( commands user interface ). It is able to aggregate extern
```rust
#[ cfg( not( feature = "no_std" ) ) ]
{
use wca::{ VerifiedCommand, Context, Type };
use wca::{ VerifiedCommand, Type };

fn main()
{
Expand All @@ -37,7 +37,7 @@ The tool to make CLI ( commands user interface ). It is able to aggregate extern
.end()
.perform();

let args = std::env::args().skip( 1 ).collect::< Vec< String > >();
let args: Vec< String > = std::env::args().skip( 1 ).collect();
ca.perform( args ).unwrap();

}
Expand Down
43 changes: 43 additions & 0 deletions module/move/wca/examples/wca_custom_error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//!
//! # Handling Errors with CommandsAggregator
//!
//! This module provides an example of how to use `wca::CommandsAggregator` to manage error handling in a command-line interface. The `CommandsAggregator` offers a fluent interface for defining commands and associating them with various error types, making it straightforward to handle and present errors in a structured way.
//!
//! ## Purpose
//!
//! The primary goal of this example is to showcase how `CommandsAggregator` facilitates error handling, whether errors are simple strings, custom typed errors, untyped errors, or errors with additional context. This approach ensures that error management is both consistent and extensible.
//!
#[ derive( Debug, error_tools::typed::Error )]
enum CustomError
{
#[ error( "this is typed error" ) ]
TheError,
}

fn main() -> error_tools::error::untyped::Result< () >
{
let ca = wca::CommandsAggregator::former()
.command( "error.string" )
.hint( "Returns error as a string" )
.routine( || { Err( "this is string error" ) } )
.end()
.command( "error.typed" )
.hint( "Returns error as a custom error" )
.routine( || { Err( CustomError::TheError ) } )
.end()
.command( "error.untyped" )
.hint( "Returns error as untyped error" )
.routine( || { Err( error_tools::error::untyped::format_err!( "this is untyped error" ) ) } )
.end()
.command( "error.with_context" )
.hint( "Returns error as untyped error with context" )
.routine( || { Err( error_tools::error::untyped::format_err!( "this is untyped error" ).context( "with context" ) ) } )
.end()
.perform();

let args: Vec< String > = std::env::args().skip( 1 ).collect();
() = ca.perform( args )?;

Ok( () )
}
9 changes: 5 additions & 4 deletions module/move/wca/examples/wca_fluent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
//!

use wca::{ Context, Handler, Type, VerifiedCommand };
use wca::{ executor::{ Context, Handler }, Type, VerifiedCommand };
use std::sync::{ Arc, Mutex };

fn main()
fn main() -> error_tools::error::untyped::Result< () >
{

let ca = wca::CommandsAggregator::former()
Expand Down Expand Up @@ -45,7 +45,8 @@ fn main()
.end()
.perform();

let args = std::env::args().skip( 1 ).collect::< Vec< String > >();
ca.perform( args ).unwrap();
let args: Vec< String > = std::env::args().skip( 1 ).collect();
ca.perform( args )?;

Ok( () )
}
13 changes: 5 additions & 8 deletions module/move/wca/examples/wca_suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
use wca::{ CommandsAggregator, Type, VerifiedCommand };

fn main()
fn main() -> error_tools::error::untyped::Result< () >
{

let ca = CommandsAggregator::former()
Expand All @@ -34,14 +34,11 @@ fn main()
{
println!( "= Args\n{:?}\n\n= Properties\n{:?}\n", o.args, o.props );
})
.end()
.end()
.perform();

let args = std::env::args().skip( 1 ).collect::< Vec< String > >();
match ca.perform( args.join( " " ) )
{
Ok( _ ) => {}
Err( err ) => println!( "{err}" ),
};
let args: Vec< String > = std::env::args().skip( 1 ).collect();
ca.perform( args.join( " " ) )?;

Ok( () )
}
10 changes: 6 additions & 4 deletions module/move/wca/examples/wca_trivial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fn exit()
std::process::exit( 0 )
}

fn main()
fn main() -> error_tools::error::untyped::Result< () >
{
let ca = CommandsAggregator::former()
.command( "exit" )
Expand All @@ -33,7 +33,7 @@ fn main()
.perform()
;

// aaa : qqq2 : for Bohdan : that should work
// aaa : aaa2 : for Bohdan : that should work
// let ca = wca::CommandsAggregator::former()
// .command( "echo" )
// .hint( "prints all subjects and properties" )
Expand All @@ -50,6 +50,8 @@ fn main()
// ca.execute( input ).unwrap();
//aaa: works

let input = std::env::args().skip( 1 ).collect::< Vec< String > >();
ca.perform( input ).unwrap();
let input: Vec< String > = std::env::args().skip( 1 ).collect();
ca.perform( input )?;

Ok( () )
}
35 changes: 18 additions & 17 deletions module/move/wca/src/ca/aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ mod private
use crate::*;
use ca::
{
Verifier,
Executor,
grammar::command::
{
Expand All @@ -14,15 +13,17 @@ mod private
},
help::{ HelpGeneratorFn, HelpGeneratorOptions, HelpVariants },
};
use verifier::{ Verifier, VerificationError, VerifiedCommand };
use parser::{ Program, Parser, ParserError };
use grammar::Dictionary;
use executor::Context;

// qqq : group uses
use std::collections::HashSet;
use std::fmt;
use std::
{
fmt,
collections::HashSet
};
use former::StoragePreform;
// use wtools::
// {
// };
// use wtools::thiserror;
use error::
{
// Result,
Expand Down Expand Up @@ -54,11 +55,11 @@ mod private
/// source of the program
input : String,
/// original error
error : wError,
error : ParserError,
},
/// This variant represents errors that occur during grammar conversion.
#[ error( "Can not identify a command.\nDetails: {0}" ) ]
Verifier( wError ),
Verifier( VerificationError ),
/// This variant is used to represent errors that occur during executor conversion.
#[ error( "Can not find a routine for a command.\nDetails: {0}" ) ]
ExecutorConverter( wError ),
Expand All @@ -70,14 +71,14 @@ mod private
{
/// This variant is used to represent validation errors.
/// It carries a `ValidationError` payload that provides additional information about the error.
#[ error( "Validation error. {0}" ) ]
#[ error( "Validation error\n{0}" ) ]
Validation( ValidationError ),
/// This variant represents execution errors.
#[ error( "Execution failed. {0:?}" ) ]
#[ error( "Execution failed\n{0:?}" ) ]
Execution( wError ),
}

// xxx : qqq : qqq2 : for Bohdan : one level is obviously redundant
// xxx : aaa : aaa2 : for Bohdan : one level is obviously redundant
// Program< Namespace< ExecutableCommand_ > > -> Program< ExecutableCommand_ >
// aaa : done. The concept of `Namespace` has been removed
struct CommandsAggregatorCallback( Box< dyn Fn( &str, &Program< VerifiedCommand > ) > );
Expand Down Expand Up @@ -283,7 +284,7 @@ mod private
callback.0( &program.join( " " ), &grammar_program )
}

self.executor.program( &self.dictionary, grammar_program ).map_err( | e | Error::Execution( e ) )
self.executor.program( &self.dictionary, grammar_program ).map_err( | e | Error::Execution( e.into() ) )
}
}
}
Expand All @@ -293,8 +294,8 @@ mod private
crate::mod_interface!
{
exposed use CommandsAggregator;
exposed use CommandsAggregatorFormer;
exposed use Error;
exposed use ValidationError;
orphan use CommandsAggregatorFormer;
orphan use Error;
orphan use ValidationError;
exposed use Order;
}
6 changes: 3 additions & 3 deletions module/move/wca/src/ca/executor/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ mod private
/// # Examples:
///
/// ```
/// # use wca::{ Routine, Handler, Context, Value, Args, Props, VerifiedCommand };
/// # use wca::{ executor::{ Routine, Handler, Args, Props, Context }, Value, VerifiedCommand };
/// # use std::sync::{ Arc, Mutex };
/// let routine = Routine::from( Handler::from
/// (
Expand All @@ -33,7 +33,7 @@ mod private
/// }
/// assert_eq!( 1, *ctx.get::< Mutex< i32 > >().unwrap().lock().unwrap() );
/// ```
// qqq : ?
// xxx clarification is needed qqq : поточнити
#[ derive( Debug, Clone ) ]
pub struct Context
{
Expand Down Expand Up @@ -91,5 +91,5 @@ mod private

crate::mod_interface!
{
exposed use Context;
orphan use Context;
}
51 changes: 38 additions & 13 deletions module/move/wca/src/ca/executor/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,23 @@ mod private
{
use crate::*;

// use wtools::error::Result;
// use error::return_err;
use ca::help::{ HelpGeneratorOptions, generate_help_content, LevelOfDetail };
use verifier::VerifiedCommand;
use parser::Program;
use grammar::Dictionary;
use executor::{ Routine, Context };

// aaa : for Bohdan : how is it useful? where is it used?
// aaa : `ExecutorType` has been removed

#[ derive( Debug, error::typed::Error ) ]
pub enum CommandError
{
#[ error( "Internal command: `.{}` failed with: {}", command.phrase, error ) ]
Internal { command: VerifiedCommand, error: InternalCommandError },
#[ error( "Command: `.{}` failed with: {}", command.phrase, error ) ]
User { command: VerifiedCommand, error: error::untyped::Error },
}

/// Executor that is responsible for executing the program's commands.
/// It uses the given `Context` to store and retrieve values during runtime.
Expand Down Expand Up @@ -36,9 +46,10 @@ mod private
///
/// A `Result` with `Ok( () )` if the execution was successful, or an `Err` containing an error message if an error occurred.
///
// qqq : use typed error
// aaa : use typed error
// aaa : done
pub fn program( &self, dictionary : &Dictionary, program : Program< VerifiedCommand > )
-> error::untyped::Result< () >
-> Result< (), CommandError >
{
for command in program.commands
{
Expand All @@ -60,18 +71,21 @@ mod private
/// # Returns
///
/// Returns a Result indicating success or failure. If successful, returns `Ok(())`, otherwise returns an error.
// qqq : use typed error
// aaa : use typed error
// aaa : done
pub fn command( &self, dictionary : &Dictionary, command : VerifiedCommand )
-> error::untyped::Result< () >
-> Result< (), CommandError >
{
if command.internal_command
{
_exec_internal_command( dictionary, command )
_exec_internal_command( dictionary, command.clone() )
.map_err( | error | CommandError::Internal { command, error } )
}
else
{
let routine = dictionary.command( &command.phrase ).unwrap().routine.clone();
_exec_command( command, routine, self.context.clone() )
_exec_command( command.clone(), routine, self.context.clone() )
.map_err( | error | CommandError::User { command, error } )
}
}

Expand All @@ -80,6 +94,7 @@ mod private
}

// qqq : use typed error
// aaa : should it be typed? it is user command with unknown error type
fn _exec_command( command : VerifiedCommand, routine : Routine, ctx : Context )
-> error::untyped::Result< () >
{
Expand All @@ -90,9 +105,19 @@ mod private
}
}

// qqq : use typed error
#[ derive( Debug, error::typed::Error ) ]
pub enum InternalCommandError
{
#[ error( "Encountered an unrecognized internal command: `.{user_input}`." ) ]
UnknownInternalCommand { user_input: String },
#[ error( "Not found command that starts with `.{user_input}`." ) ]
CommandNotFound { user_input: String },
}

// aaa : use typed error
// aaa : done
fn _exec_internal_command( dictionary : &Dictionary, command : VerifiedCommand )
-> error::untyped::Result< () >
-> Result< (), InternalCommandError >
{
match command.phrase.as_str()
{
Expand Down Expand Up @@ -122,7 +147,7 @@ mod private
let commands = dictionary.search( name.strip_prefix( '.' ).unwrap_or( name ) );
if commands.is_empty()
{
error::untyped::return_err!( "Not found command that starts with `.{}`.", name );
return Err( InternalCommandError::CommandNotFound { user_input : name.into() } );
}
let generator_args = HelpGeneratorOptions::former()
.command_prefix( "." )
Expand Down Expand Up @@ -151,10 +176,10 @@ mod private
}
else
{
error::untyped::return_err!( "Not found command that starts with `.{}`.", name );
return Err( InternalCommandError::CommandNotFound { user_input : name.into() } );
}
}
unexpected => error::untyped::return_err!( "Encountered an unrecognized internal command: `.{}`.", unexpected ),
unexpected => return Err( InternalCommandError::UnknownInternalCommand { user_input: unexpected.into() }),
}

Ok( () )
Expand Down
Loading

0 comments on commit 39907f7

Please sign in to comment.