Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

READY : Allow to save nature order in commands & props #1325

Merged
merged 11 commits into from
May 29, 2024
25 changes: 19 additions & 6 deletions module/move/wca/src/ca/aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ pub( crate ) mod private
/// ```
#[ derive( Debug ) ]
#[ derive( former::Former ) ]
#[ storage_fields( help_generator : HelpGeneratorFn, help_variants : HashSet< HelpVariants > ) ]
#[ storage_fields( help_generator : HelpGeneratorFn, help_variants : HashSet< HelpVariants >, with_nature_sort : bool, order : Option< Vec< String > > ) ]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use enum instead of bool, can't we?

#[ mutator( custom = true ) ]
// #[ debug ]
pub struct CommandsAggregator
Expand All @@ -117,7 +117,7 @@ pub( crate ) mod private

#[ former( default = Verifier ) ]
verifier : Verifier,

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

callback_fn : Option< CommandsAggregatorCallback >,
}

Expand All @@ -130,16 +130,25 @@ pub( crate ) mod private

let help_generator = std::mem::take( &mut ca.help_generator ).unwrap_or_default();
let help_variants = std::mem::take( &mut ca.help_variants ).unwrap_or_else( || HashSet::from([ HelpVariants::All ]) );


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

let order = if ca.with_nature_sort.unwrap_or_default()
{
std::mem::take( &mut ca.order )
}
else
{
None
};

if help_variants.contains( &HelpVariants::All )
{
HelpVariants::All.generate( &help_generator, dictionary );
HelpVariants::All.generate( &help_generator, dictionary, order.clone() );
}
else
{
for help in help_variants.iter().sorted()
{
help.generate( &help_generator, dictionary );
help.generate( &help_generator, dictionary, order.clone() );
}
}
}
Expand All @@ -154,10 +163,14 @@ pub( crate ) mod private
/// # Arguments
///
/// * `name` - The name of the command.
pub fn command< IntoName >( self, name : IntoName ) -> CommandAsSubformer< Self, impl CommandAsSubformerEnd< Self > >
pub fn command< IntoName >( mut self, name : IntoName ) -> CommandAsSubformer< Self, impl CommandAsSubformerEnd< Self > >
where
IntoName : Into< String >,
{
let name = name.into();
let mut order = self.storage.order.unwrap_or_default();
order.push( name.clone() );
self.storage.order = Some( order );
let on_end = | command : CommandFormerStorage, super_former : Option< Self > | -> Self
{
let mut super_former = super_former.unwrap();
Expand Down
7 changes: 6 additions & 1 deletion module/move/wca/src/ca/grammar/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ pub( crate ) mod private

#[ derive( Debug, Clone, PartialEq, Eq ) ]
#[ derive( Former ) ]
// #[ debug ]
pub struct Command
{
/// Command common hint.
Expand All @@ -100,6 +99,8 @@ pub( crate ) mod private
pub subjects : Vec< ValueDescription >,
/// Hints and types for command options.
pub properties : HashMap< String, ValueDescription >,
///
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you write concise documentation

pub properties_order : Vec< String >,
/// Map of aliases.
// Aliased key -> Original key
pub properties_aliases : HashMap< String, String >,
Expand Down Expand Up @@ -200,6 +201,8 @@ pub( crate ) mod private
let mut super_former = super_former.unwrap();
let mut properties = super_former.storage.properties.unwrap_or_default();
let property = property.preform();
let mut order = super_former.storage.properties_order.unwrap_or_default();

let value = ValueDescription
{
hint : property.hint,
Expand All @@ -208,6 +211,7 @@ pub( crate ) mod private
};
debug_assert!( !properties.contains_key( &property.name ), "Property name `{}` is already used for `{:?}`", property.name, properties[ &property.name ] );
properties.insert( property.name.clone(), value );
order.push( property.name.clone() );

let mut aliases = super_former.storage.properties_aliases.unwrap_or_default();
debug_assert!( !aliases.contains_key( &property.name ), "Name `{}` is already used for `{}` as alias", property.name, aliases[ &property.name ] );
Expand All @@ -216,6 +220,7 @@ pub( crate ) mod private

super_former.storage.properties = Some( properties );
super_former.storage.properties_aliases = Some( aliases );
super_former.storage.properties_order = Some( order );

super_former
};
Expand Down
85 changes: 60 additions & 25 deletions module/move/wca/src/ca/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ pub( crate ) mod private
pub description_detailing : LevelOfDetail,
/// If enabled - shows complete description of subjects and properties
pub with_footer : bool,

order : Option< Vec< String > >,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you write concise documentation


// #[ former( default = true ) ]
with_nature_order : bool,
}

// qqq : for Barsik : make possible to change properties order
Expand Down Expand Up @@ -90,13 +95,21 @@ pub( crate ) mod private
LevelOfDetail::None => "".into(),
_ if command.subjects.is_empty() => "".into(),
LevelOfDetail::Simple => "< properties >".into(),
LevelOfDetail::Detailed if o.with_nature_order => command.properties_order.iter().map( | n | format!( "< {n}:{}{:?} >", if command.properties.get(n).unwrap().optional { "?" } else { "" }, command.properties.get(n).unwrap().kind ) ).collect::< Vec< _ > >().join( " " ),
LevelOfDetail::Detailed => command.properties.iter().map( |( n, v )| format!( "< {n}:{}{:?} >", if v.optional { "?" } else { "" }, v.kind ) ).collect::< Vec< _ > >().join( " " ),
};

let footer = if o.with_footer
{
let full_subjects = command.subjects.iter().map( | subj | format!( "- {} [{}{:?}]", subj.hint, if subj.optional { "?" } else { "" }, subj.kind ) ).join( "\n\t" );
let full_properties = format_table( command.properties.iter().sorted_by_key( |( name, _ )| *name ).map( |( name, value )| [ name.clone(), format!( "- {} [{}{:?}]", value.hint, if value.optional { "?" } else { "" }, value.kind ) ] ) ).unwrap().replace( '\n', "\n\t" );
let full_properties = if o.with_nature_order
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let full_properties = if o.with_nature_order
let full_properties = if o.with_nature_order

{
format_table( command.properties_order.iter().map( | name | [ name.clone(), format!( "- {} [{}{:?}]", command.properties.get( name ).unwrap().hint, if command.properties.get( name ).unwrap().optional { "?" } else { "" }, command.properties.get( name ).unwrap().kind ) ] ) ).unwrap().replace( '\n', "\n\t" )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can avoid duplication here, can't we?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you fmt this?

}
else
{
format_table( command.properties.iter().sorted_by_key( |( name, _ )| *name ).map( |( name, value )| [ name.clone(), format!( "- {} [{}{:?}]", value.hint, if value.optional { "?" } else { "" }, value.kind ) ] ) ).unwrap().replace( '\n', "\n\t" )
};
format!
(
"{}{}",
Expand Down Expand Up @@ -130,14 +143,25 @@ pub( crate ) mod private
}
else
{
let rows = dictionary.commands
.iter()
.sorted_by_key( |( name, _ )| *name )
.map( |( _, cmd )| cmd )
.map( for_single_command )
.map( | row | [ row.name, row.args, row.hint ] );

format_table( rows ).unwrap()
if let Some(order) = o.order
{
let rows = order
.iter()
.map( | k | dictionary.commands.get( k ).unwrap() )
.map( for_single_command )
.map( | row | [ row.name, row.args, row.hint ] );
format_table( rows ).unwrap()
}
else
{
let rows = dictionary.commands
.iter()
.sorted_by_key( |( name, _ )| *name )
.map( |( _, cmd )| cmd )
.map( for_single_command )
.map( | row | [ row.name, row.args, row.hint ] );
format_table( rows ).unwrap()
}
}
}

Expand All @@ -158,25 +182,27 @@ pub( crate ) mod private
impl HelpVariants
{
/// Generates help commands
pub fn generate( &self, helper : &HelpGeneratorFn, dictionary : &mut Dictionary )
pub fn generate( &self, helper : &HelpGeneratorFn, dictionary : &mut Dictionary, order : Option< Vec< String > > )
{
// debug_assert!( dictionary.commands.len() == order.as_ref().map( | o | o.len() ).unwrap_or( dictionary.commands.len() ) );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove redundant comments, please

// dictionary.commands.keys().for_each( | k | assert!( order.as_ref().map( | a | a.contains( &k ) ).unwrap_or( true ) ) );
match self
{
HelpVariants::All =>
{
self.general_help( helper, dictionary );
self.subject_command_help( helper, dictionary );
self.general_help( helper, dictionary, order.clone() );
self.subject_command_help( helper, dictionary, order );
// self.dot_command_help( helper, dictionary );
},
HelpVariants::General => self.general_help( helper, dictionary ),
HelpVariants::SubjectCommand => self.subject_command_help( helper, dictionary ),
HelpVariants::General => self.general_help( helper, dictionary, order ),
HelpVariants::SubjectCommand => self.subject_command_help( helper, dictionary, order ),
_ => unimplemented!()
// HelpVariants::DotCommand => self.dot_command_help( helper, dictionary ),
}
}

// .help
fn general_help( &self, helper : &HelpGeneratorFn, dictionary : &mut Dictionary )
fn general_help( &self, helper : &HelpGeneratorFn, dictionary : &mut Dictionary, order : Option< Vec< String > > )
{
let phrase = "help".to_string();

Expand Down Expand Up @@ -205,18 +231,23 @@ pub( crate ) mod private
}
else
{
let mut options = HelpGeneratorOptions::former()
.command_prefix( "." )
.description_detailing( LevelOfDetail::Simple )
.subject_detailing( LevelOfDetail::Simple )
.property_detailing( LevelOfDetail::Simple )
.with_nature_order( order.is_some() );
if let Some(order) = order.as_ref()
{
options = options.order( order.clone() );
}
println!
(
"Help command\n\n{text}",
text = generator.exec
(
&grammar,
HelpGeneratorOptions::former()
.command_prefix( "." )
.description_detailing( LevelOfDetail::Simple )
.subject_detailing( LevelOfDetail::Simple )
.property_detailing( LevelOfDetail::Simple )
.form()
options.form()
)
);
}
Expand All @@ -240,7 +271,7 @@ pub( crate ) mod private
}

// .help command_name
fn subject_command_help( &self, helper : &HelpGeneratorFn, dictionary : &mut Dictionary )
fn subject_command_help( &self, helper : &HelpGeneratorFn, dictionary : &mut Dictionary, order : Option< Vec< String > > )
{
let phrase = "help".to_string();

Expand All @@ -260,15 +291,19 @@ pub( crate ) mod private
let command = o.args.get_owned::< String >( 0 ).unwrap();
let cmd = grammar.commands.get( &command ).ok_or_else( || anyhow!( "Can not found help for command `{command}`" ) )?;

let args = HelpGeneratorOptions::former()
let mut args = HelpGeneratorOptions::former()
.command_prefix( "." )
.for_commands([ cmd ])
.description_detailing( LevelOfDetail::Detailed )
.subject_detailing( LevelOfDetail::Simple )
.property_detailing( LevelOfDetail::Simple )
.with_footer( true )
.form();
let text = generator.exec( &grammar, args );
.with_nature_order( order.is_some() );
if let Some(order) = order.as_ref()
{
args = args.order( order.clone() );
}
let text = generator.exec( &grammar, args.form() );

println!( "Help command\n\n{text}" );
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
fn main()
{
use wca::{ Type, VerifiedCommand };

let ca = wca::CommandsAggregator::former()
.command( "c" )
.hint( "c" )
.property( "c-property" ).kind( Type::String ).optional( true ).end()
.property( "b-property" ).kind( Type::String ).optional( true ).end()
.property( "a-property" ).kind( Type::String ).optional( true ).end()
.routine( | o : VerifiedCommand | { println!("c") } )
.end()
.command( "b" )
.hint( "b" )
.property( "b-property" ).kind( Type::String ).optional( true ).end()
.routine( | o : VerifiedCommand | { println!("b") } )
.end()
.command( "a" )
.hint( "a" )
.property( "a-property" ).kind( Type::String ).optional( true ).end()
.routine( | o : VerifiedCommand | { println!("a") } )
.end()
.with_nature_sort( false )
.perform();

let args = std::env::args().skip( 1 ).collect::< Vec< String > >();
ca.perform( args ).unwrap();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
fn main()
{
use wca::{ Type, VerifiedCommand };

let ca = wca::CommandsAggregator::former()
.command( "c" )
.hint( "c" )
.property( "c-property" ).kind( Type::String ).optional( true ).end()
.property( "b-property" ).kind( Type::String ).optional( true ).end()
.property( "a-property" ).kind( Type::String ).optional( true ).end()
.routine( | o : VerifiedCommand | { println!("c") } )
.end()
.command( "b" )
.hint( "b" )
.property( "b-property" ).kind( Type::String ).optional( true ).end()
.routine( | o : VerifiedCommand | { println!("b") } )
.end()
.command( "a" )
.hint( "a" )
.property( "a-property" ).kind( Type::String ).optional( true ).end()
.routine( | o : VerifiedCommand | { println!("a") } )
.end()
.with_nature_sort( true )
.perform();

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