Skip to content

Commit

Permalink
Merge pull request #1325 from SRetip/alpha
Browse files Browse the repository at this point in the history
READY : Allow to save nature order in commands & props
  • Loading branch information
Wandalen authored May 29, 2024
2 parents f0d3981 + 22f9eac commit 4f18593
Show file tree
Hide file tree
Showing 9 changed files with 336 additions and 102 deletions.
11 changes: 6 additions & 5 deletions module/move/wca/examples/wca_trivial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! A trivial example.
//!

use wca::{ CommandsAggregator, Type, VerifiedCommand };
use wca::{ CommandsAggregator, Order, Type, VerifiedCommand };

fn f1( o : VerifiedCommand )
{
Expand All @@ -19,16 +19,17 @@ fn exit()
fn main()
{
let ca = CommandsAggregator::former()
.command( "exit" )
.hint( "just exit" )
.routine( || exit() )
.end()
.command( "echo" )
.hint( "prints all subjects and properties" )
.subject().hint( "Subject" ).kind( Type::String ).optional( true ).end()
.property( "property" ).hint( "simple property" ).kind( Type::String ).optional( true ).end()
.routine( f1 )
.end()
.command( "exit" )
.hint( "just exit" )
.routine( || exit() )
.end()
.order( Order::Lexicography )
.perform()
;

Expand Down
20 changes: 17 additions & 3 deletions module/move/wca/src/ca/aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ pub( crate ) mod private
for_lib::*,
};
use wtools::Itertools;

/// Order of commands and properties.
#[ derive( Debug, Default, Clone, Copy, Eq, PartialOrd, PartialEq ) ]
pub enum Order
{
/// Natures order.
#[ default ]
Nature,
/// Lexicography order.
Lexicography,
}

/// Validation errors that can occur in application.
#[ derive( Error, Debug ) ]
Expand Down Expand Up @@ -100,7 +111,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 >, order : Order ) ]
#[ mutator( custom = true ) ]
// #[ debug ]
pub struct CommandsAggregator
Expand All @@ -127,19 +138,20 @@ pub( crate ) mod private
{
let ca = storage;
let dictionary = ca.dictionary.get_or_insert_with( Dictionary::default );
dictionary.order = ca.order.unwrap_or_default();

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 ]) );

if help_variants.contains( &HelpVariants::All )
{
HelpVariants::All.generate( &help_generator, dictionary );
HelpVariants::All.generate( &help_generator, dictionary, ca.order.unwrap_or_default() );
}
else
{
for help in help_variants.iter().sorted()
{
help.generate( &help_generator, dictionary );
help.generate( &help_generator, dictionary, ca.order.unwrap_or_default() );
}
}
}
Expand All @@ -158,6 +170,7 @@ pub( crate ) mod private
where
IntoName : Into< String >,
{
let name = name.into();
let on_end = | command : CommandFormerStorage, super_former : Option< Self > | -> Self
{
let mut super_former = super_former.unwrap();
Expand Down Expand Up @@ -279,4 +292,5 @@ crate::mod_interface!
exposed use CommandsAggregatorFormer;
exposed use Error;
exposed use ValidationError;
exposed use Order;
}
25 changes: 12 additions & 13 deletions module/move/wca/src/ca/formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub( crate ) mod private

use crate::*;
use wtools::Itertools;
use ca::aggregator::private::Order;

/// -
#[ derive( Debug, Clone, PartialEq ) ]
Expand All @@ -12,18 +13,18 @@ pub( crate ) mod private
Another,
}

pub fn md_generator( grammar : &Dictionary ) -> String
pub fn md_generator( grammar : &Dictionary, order: Order ) -> String
{
let text = grammar.commands
.iter()
.sorted_by_key( |( name, _ )| *name )
let text = grammar.commands()
.into_iter()
.map( |( name, cmd )|
{
let subjects = cmd.subjects.iter().fold( String::new(), | _, _ | format!( " `[argument]`" ) );
let properties = if cmd.properties.is_empty() { " " } else { " `[properties]` " };
format!
(
"[.{name}{subjects}{properties}](#{}{}{})",
"[.{}{subjects}{properties}](#{}{}{})",
name,
name.replace( '.', "" ),
if cmd.subjects.is_empty() { "" } else { "-argument" },
if cmd.properties.is_empty() { "" } else { "-properties" },
Expand All @@ -36,16 +37,15 @@ pub( crate ) mod private

let list_of_commands = format!( "## Commands\n\n{}", text );

let about_each_command = grammar.commands
.iter()
.sorted_by_key( |( name, _ )| *name )
let about_each_command = grammar.commands()
.into_iter()
.map( |( name, cmd )|
{
let subjects = cmd.subjects.iter().fold( String::new(), | _, _ | format!( " `[Subject]`" ) );
let properties = if cmd.properties.is_empty() { " " } else { " `[properties]` " };
let hint = if cmd.hint.is_empty() { &cmd.long_hint } else { &cmd.hint };

let heading = format!( "## .{name}{subjects}{properties}\n__{}__\n", hint );
let heading = format!( "## .{}{subjects}{properties}\n__{}__\n", name, hint );

let hint = if cmd.long_hint.is_empty() { &cmd.hint } else { &cmd.long_hint };
let full_subjects = cmd
Expand All @@ -59,13 +59,12 @@ pub( crate ) mod private
)
.join( "\n" );
let full_properties = cmd
.properties
.iter()
.sorted_by_key( |( name, _ )| *name )
.properties( order )
.into_iter()
.map
(
|( name, value )|
format!( "\n- {}{name} - {} `[{:?}]`", if value.optional { "`< optional >` " } else { "" }, value.hint, value.kind )
format!( "\n- {}{} - {} `[{:?}]`", if value.optional { "`< optional >` " } else { "" }, value.hint, name, value.kind )
)
.join( "\n" );
// aaa : for Bohdan : toooooo log lines. 130 is max
Expand Down
36 changes: 29 additions & 7 deletions module/move/wca/src/ca/grammar/command.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
pub( crate ) mod private
{
use crate::*;

use { Handler, Routine, Type };

use std::collections::HashMap;

use std::collections::{ BTreeMap, HashMap };
use former::{ Former, StoragePreform };
use wtools::Itertools;

/// A description of a Value in a command. Used to specify the expected type and provide a hint for the Value.
///
Expand Down Expand Up @@ -87,7 +86,6 @@ pub( crate ) mod private

#[ derive( Debug, Clone, PartialEq, Eq ) ]
#[ derive( Former ) ]
// #[ debug ]
pub struct Command
{
/// Command common hint.
Expand All @@ -100,7 +98,10 @@ pub( crate ) mod private
#[ subform_entry( setter = true ) ]
pub subjects : Vec< ValueDescription >,
/// Hints and types for command options.
pub properties : HashMap< String, ValueDescription >,
pub properties : BTreeMap< CommandName, ValueDescription >,
/// Last inserted property id.
#[ scalar( setter = false ) ]
last_id : usize,
/// Map of aliases.
// Aliased key -> Original key
pub properties_aliases : HashMap< String, String >,
Expand All @@ -112,6 +113,24 @@ pub( crate ) mod private
#[ former( default = Routine::from( Handler::from( || { panic!( "No routine available: A handler function for the command is missing" ) } ) ) ) ]
pub routine : Routine,
}

impl Command
{
pub( crate ) fn properties( &self, order : Order ) -> Vec< ( &String, &ValueDescription ) >
{
match order
{
Order::Nature =>
{
self.properties.iter().map( | ( key, value ) | ( &key.name, value ) ).collect()
}
Order::Lexicography =>
{
self.properties.iter().map( | ( key, value ) | ( &key.name, value ) ).sorted_by_key( | ( k, _ ) | *k ).collect()
}
}
}
}

impl< Definition > CommandFormer< Definition >
where
Expand Down Expand Up @@ -201,14 +220,17 @@ 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 value = ValueDescription
{
hint : property.hint,
kind : property.kind,
optional : property.optional,
};
debug_assert!( !properties.contains_key( &property.name ), "Property name `{}` is already used for `{:?}`", property.name, properties[ &property.name ] );
properties.insert( property.name.clone(), value );
super_former.storage.last_id = Some( super_former.storage.last_id.unwrap_or_default() + 1 );
let name = CommandName { id : super_former.storage.last_id.unwrap(), name : property.name.clone() };
properties.insert( name, value );

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 Down
92 changes: 82 additions & 10 deletions module/move/wca/src/ca/grammar/dictionary.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
pub( crate ) mod private
{
use crate::*;

use { Command };
use std::collections::HashMap;
use former::Former;
use wtools::Itertools;
use std::cmp::Ordering;
use std::collections::BTreeMap;

// qqq : `Former` does not handle this situation well

Expand All @@ -14,14 +14,66 @@ pub( crate ) mod private
// #[ derive( Debug, Former ) ]
// pub struct Dictionary( HashMap< String, Command > );

/// Command name with id.
#[ derive( Debug, Default, Clone, Eq ) ]
pub struct CommandName
{
/// id of command.
pub( crate ) id : usize,
/// Name of command.
pub name : String,
}

impl std::borrow::Borrow< String > for CommandName
{
fn borrow( &self ) -> &String
{
&self.name
}
}

impl Ord for CommandName
{
fn cmp( &self, other : &Self ) -> Ordering
{
if self.name == other.name
{
Ordering::Equal
}
else
{
self.id.cmp( &other.id )
}
}
}

impl PartialEq< Self > for CommandName
{
fn eq( &self, other : &Self ) -> bool
{
self.name.eq( &other.name )
}
}

impl PartialOrd for CommandName
{
fn partial_cmp( &self, other : &Self ) -> Option< Ordering >
{
self.id.partial_cmp( &other.id )
}
}

/// A collection of commands.
///
/// This structure holds a hashmap of commands where each command is mapped to its name.
/// This structure holds a btreemap of commands where each command is mapped to its name.
#[ derive( Debug, Default, Former, Clone ) ]
pub struct Dictionary
{
#[ scalar( setter = false, hint = false ) ]
pub( crate ) commands : HashMap< String, Command >,
pub( crate ) commands : BTreeMap< CommandName, Command >,
#[ scalar( setter = false, hint = false ) ]
dictionary_last_id : usize,
pub( crate ) order : Order,
}

// qqq : IDK how to integrate it into the `CommandsAggregatorFormer`
Expand All @@ -31,7 +83,9 @@ pub( crate ) mod private
pub fn command( mut self, command : Command ) -> Self
{
let mut commands = self.storage.commands.unwrap_or_default();
commands.extend([( command.phrase.clone(), command )]);
self.storage.dictionary_last_id = Some( self.storage.dictionary_last_id.unwrap_or_default() + 1 );
let name = CommandName { id : self.storage.dictionary_last_id.unwrap(), name : command.phrase.clone() };
commands.insert( name, command );
self.storage.commands = Some( commands );

self
Expand All @@ -47,7 +101,9 @@ pub( crate ) mod private
/// * `command` - The command to be registered.
pub fn register( &mut self, command : Command ) -> Option< Command >
{
self.commands.insert( command.phrase.clone(), command )
self.dictionary_last_id += 1;
let name = CommandName { id : self.dictionary_last_id, name : command.phrase.clone() };
self.commands.insert( name, command )
}

/// Retrieves the command with the specified `name` from the `commands` hashmap.
Expand All @@ -62,10 +118,9 @@ pub( crate ) mod private
/// Returns `None` if no command with the specified `name` is found.
pub fn command< Name >( &self, name : &Name ) -> Option< &Command >
where
String : std::borrow::Borrow< Name >,
Name : std::hash::Hash + Eq,
Name : std::hash::Hash + Eq + Ord + ToString,
{
self.commands.get( name )
self.commands.iter().find( | ( k, _ ) | k.name == name.to_string() ).map( | ( _, v ) | v )
}

/// Find commands that match a given name part.
Expand All @@ -86,6 +141,22 @@ pub( crate ) mod private
{
self.commands.values().filter( | command | command.phrase.starts_with( name_part.as_ref() ) ).collect()
}

/// asd
pub fn commands( &self ) -> Vec< ( &String, &Command ) >
{
match self.order
{
Order::Nature =>
{
self.commands.iter().map( | ( key, value ) | ( &key.name, value ) ).collect()
}
Order::Lexicography =>
{
self.commands.iter().map( | ( key, value ) | ( &key.name, value ) ).sorted_by_key( | ( key, _ ) | *key ).collect()
}
}
}
}
}

Expand All @@ -94,4 +165,5 @@ pub( crate ) mod private
crate::mod_interface!
{
exposed use Dictionary;
exposed use CommandName;
}
Loading

0 comments on commit 4f18593

Please sign in to comment.