Skip to content

Commit

Permalink
Implement internal command execution
Browse files Browse the repository at this point in the history
The code now supports the execution of internal commands. It removes the previously standalone `dot_command` mechanism, transforming it into part of the broader command execution process. Additionally, it introduces a new `search` function in the dictionary that finds commands matching a given name.
  • Loading branch information
Barsik-sus committed Mar 25, 2024
1 parent 788897a commit 55b0788
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 40 deletions.
4 changes: 1 addition & 3 deletions module/move/wca/src/ca/aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub( crate ) mod private
ProgramParser,
Command,
grammar::command::private::CommandFormer,
help::{ HelpGeneratorFn, HelpGeneratorArgs, HelpVariants, dot_command },
help::{ HelpGeneratorFn, HelpGeneratorArgs, HelpVariants },
};

use std::collections::HashSet;
Expand Down Expand Up @@ -255,8 +255,6 @@ pub( crate ) mod private
}
}

dot_command( &help_generator, &mut ca.dictionary );

ca
}

Expand Down
81 changes: 79 additions & 2 deletions module/move/wca/src/ca/executor/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ pub( crate ) mod private
use crate::*;

use wtools::error::Result;
use error_tools::return_err;
use ca::help::private::{ HelpGeneratorArgs, LevelOfDetail, generate_help_content };

// aaa : for Bohdan : how is it useful? where is it used?
// aaa : `ExecutorType` has been removed
Expand Down Expand Up @@ -58,8 +60,15 @@ pub( crate ) mod private
/// Returns a Result indicating success or failure. If successful, returns `Ok(())`, otherwise returns an error.
pub fn command( &self, dictionary : &Dictionary, command : VerifiedCommand ) -> Result< () >
{
let routine = dictionary.command( &command.phrase ).unwrap().routine.clone();
_exec_command( command, routine, self.context.clone() )
if command.internal_command
{
_exec_internal_command( dictionary, command )
}
else
{
let routine = dictionary.command( &command.phrase ).unwrap().routine.clone();
_exec_command( command, routine, self.context.clone() )
}
}

// aaa : for Bohdan : probably redundant
Expand All @@ -74,6 +83,74 @@ pub( crate ) mod private
Routine::WithContext( routine ) => routine( ( Args( command.subjects ), Props( command.properties ) ), ctx ),
}
}

fn _exec_internal_command( dictionary : &Dictionary, command : VerifiedCommand ) -> Result< () >
{
match command.phrase.as_str()
{
"." =>
{
let generator_args = HelpGeneratorArgs::former()
.command_prefix( "." )
.form();

let content = generate_help_content( dictionary, generator_args );
println!( "{content}" );
}
".?" =>
{
let generator_args = HelpGeneratorArgs::former()
.description_detailing( LevelOfDetail::Simple )
.subject_detailing( LevelOfDetail::Simple )
.property_detailing( LevelOfDetail::Simple )
.form();

let content = generate_help_content( dictionary, generator_args );
println!( "{content}" );
}
name if name.ends_with( '.' ) =>
{
let name = name.strip_suffix( '.' ).unwrap();
let commands = dictionary.search( name.strip_prefix( '.' ).unwrap_or( name ) );
if commands.is_empty()
{
return_err!( "Not found command that starts with `.{}`.", name );
}
let generator_args = HelpGeneratorArgs::former()
.command_prefix( "." )
.for_commands( commands )
.form();

let content = generate_help_content( dictionary, generator_args );
println!( "{content}" );
}
name if name.ends_with( ".?" ) =>
{
let name = name.strip_suffix( ".?" ).unwrap();
let command = dictionary.command( &name.strip_prefix( '.' ).unwrap_or( name ).to_string() );
if let Some( command ) = command
{
let generator_args = HelpGeneratorArgs::former()
.for_commands([ command ])
.description_detailing( LevelOfDetail::Detailed )
.subject_detailing( LevelOfDetail::Simple )
.property_detailing( LevelOfDetail::Simple )
.with_footer( true )
.form();

let content = generate_help_content( dictionary, generator_args );
println!( "{content}" );
}
else
{
return_err!( "Not found command that starts with `.{}`.", name );
}
}
unexpected => return_err!( "Encountered an unrecognized internal command: `.{}`.", unexpected ),
}

Ok( () )
}
}

//
Expand Down
19 changes: 19 additions & 0 deletions module/move/wca/src/ca/grammar/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,25 @@ pub( crate ) mod private
{
self.commands.get( name )
}

/// Find commands that match a given name part.
///
/// This function accepts a `name_part` parameter which is of generic type `NamePart`.
/// The `NamePart` type must implement the `AsRef<str>` trait.
///
/// # Arguments
///
/// * `name_part` - The name part to match against command phrases.
///
/// # Returns
///
/// A vector of references to `Command` that match the given `name_part`.
pub fn search< NamePart >( &self, name_part : NamePart ) -> Vec< &Command >
where
NamePart : AsRef< str >,
{
self.commands.values().filter( | command | command.phrase.starts_with( name_part.as_ref() ) ).collect()
}
}
}

Expand Down
40 changes: 7 additions & 33 deletions module/move/wca/src/ca/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,6 @@ pub( crate ) mod private

// qqq : for Bohdan : it should transparent mechanist which patch list of commands, not a stand-alone mechanism

/// Generate `dot` command
pub fn dot_command( generator : &HelpGeneratorFn, dictionary : &mut Dictionary )
{
let generator = generator.clone();
let grammar = dictionary.clone();
let routine = move | props : Props |
{
let prefix : String = props.get_owned( "command_prefix" ).unwrap();

let generator_args = HelpGeneratorArgs::former()
.command_prefix( prefix )
.form();

println!( "{}", generator.exec( &grammar, generator_args ) );
};

let cmd = Command::former()
.hint( "prints all available commands" )
.phrase( "" )
.property( "command_prefix" ).kind( Type::String ).end()
.routine( routine )
.form();

dictionary.register( cmd );
}

#[ derive( Debug, Default, Copy, Clone, PartialEq, Eq ) ]
pub enum LevelOfDetail
{
Expand All @@ -56,8 +30,8 @@ pub( crate ) mod private
/// Prefix that will be shown before command name
#[ default( String::new() ) ]
pub command_prefix : String,
/// Show help for the specified command
pub for_command : Option< &'a Command >,
/// Show help for the specified commands
pub for_commands : Vec< &'a Command >,
/// Reresents how much information to display for the subjects
///
/// - `None` - nothing
Expand All @@ -81,7 +55,7 @@ pub( crate ) mod private
}

// qqq : for Barsik : make possible to change properties order
fn generate_help_content( dictionary : &Dictionary, args : HelpGeneratorArgs< '_ > ) -> String
pub fn generate_help_content( dictionary : &Dictionary, args : HelpGeneratorArgs< '_ > ) -> String
{
let for_single_command = | command : &Command |
{
Expand Down Expand Up @@ -133,9 +107,10 @@ pub( crate ) mod private
if footer.is_empty() { "" } else { "\n" },
)
};
if let Some( command ) = args.for_command
if args.for_commands.len() == 1 || !args.for_commands.is_empty() && !args.with_footer
{
for_single_command( command )
args.for_commands.into_iter().map( | command | for_single_command( command ) )
.join( "\n" )
}
else
{
Expand Down Expand Up @@ -270,7 +245,7 @@ pub( crate ) mod private
let cmd = grammar.commands.get( &command ).ok_or_else( || anyhow!( "Can not found help for command `{command}`" ) )?;

let args = HelpGeneratorArgs::former()
.for_command( cmd )
.for_commands([ cmd ])
.description_detailing( LevelOfDetail::Detailed )
.subject_detailing( LevelOfDetail::Simple )
.property_detailing( LevelOfDetail::Simple )
Expand Down Expand Up @@ -417,6 +392,5 @@ crate::mod_interface!
{
protected use HelpGeneratorFn;
protected use HelpGeneratorArgs;
protected use dot_command;
prelude use HelpVariants;
}
2 changes: 0 additions & 2 deletions module/move/wca/src/ca/parser/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ pub( crate ) mod private
},
wtools
};
use std::collections::HashMap;
use wtools::{ error:: Result, err };
use nom::
{
Expand Down Expand Up @@ -75,7 +74,6 @@ pub( crate ) mod private
Command
{
name : command_prefix.to_string(),
properties : HashMap::from_iter([ ( "command_prefix".to_string(), command_prefix.to_string() ) ]),
..Default::default()
}
)
Expand Down

0 comments on commit 55b0788

Please sign in to comment.