diff --git a/aql2/src/prompt/ReadlinePromptCompletion.cpp b/aql2/src/prompt/ReadlinePromptCompletion.cpp index 40d88fc1a697da44d6dcd7b5a7ea7df23da6db75..fea1012721292141b4843c56264ec764e82723e6 100644 --- a/aql2/src/prompt/ReadlinePromptCompletion.cpp +++ b/aql2/src/prompt/ReadlinePromptCompletion.cpp @@ -31,6 +31,23 @@ bool ReadlinePromptCompletion::startswith ( const std::string & subject, const s return subject.substr ( 0, prefix.size ( ) ) == prefix; } +std::set < std::string > ReadlinePromptCompletion::getGroups ( const std::string & qualified_name ) { + std::set < std::string > res; + + unsigned template_level = 0; + for ( size_t i = 0; i < qualified_name.size ( ); i++ ) { + if ( qualified_name [ i ] == '<' ) + template_level ++; + else if ( qualified_name [ i ] == '>' ) + template_level --; + + else if ( template_level == 0 && i > 0 && qualified_name [ i - 1 ] == ':' && qualified_name [ i ] == ':' ) + res.insert ( qualified_name.substr ( 0, i + 1 ) ); + } + + return res; +} + std::set < std::string > ReadlinePromptCompletion::filter_completions ( const std::set < std::string > & choices, const char *text ) { std::pair < std::set < std::string > :: const_iterator, std::set < std::string > :: const_iterator > range; const std::string prefix = text; @@ -49,9 +66,12 @@ ReadlinePromptCompletion::CompletionContext ReadlinePromptCompletion::context ( if ( start == 0 ) return CompletionContext::COMMAND; - if ( startswith ( line, "introspect" ) && start == 11 ) { + if ( startswith ( line, "introspect" ) && start == 11 ) return CompletionContext::COMMAND_INTROSPECT; - } + + else if ( startswith ( line, "set" ) && start == 4 ) + return CompletionContext::SET; + else if ( startswith ( line, "introspect overloads" ) && start == 21 ) return CompletionContext::ALGORITHM; @@ -61,10 +81,14 @@ ReadlinePromptCompletion::CompletionContext ReadlinePromptCompletion::context ( else if ( startswith ( line, "introspect bindings" ) && start == 20 ) return CompletionContext::BINDING; + else if ( startswith ( line, "introspect algorithms" ) && start == 22 ) + return CompletionContext::ALGORITHM_GROUP; + + else if ( startswith ( line, "introspect datatypes" ) && start == 21 ) + return CompletionContext::DATATYPE_GROUP; + /* TODO - else if ( startswith ( line, "introspect algorithms" ) && start == 21 ) else if ( startswith ( line, "introspect casts" ) && start == 17 ) - else if ( startswith ( line, "introspect datatypes" ) && start == 20 ) */ if ( end - start > 0 && text [ 0 ] == '$' ) @@ -100,6 +124,10 @@ char ** ReadlinePromptCompletion::readline_completion ( const char *text, int st switch ( context ( text, start, end ) ) { case CompletionContext::ALGORITHM: return rl_completion_matches ( text, complete_algorithm ); + case CompletionContext::ALGORITHM_GROUP: + return rl_completion_matches ( text, complete_algorithm_group ); + case CompletionContext::DATATYPE_GROUP: + return rl_completion_matches ( text, complete_datatype_group ); case CompletionContext::COMMAND: return rl_completion_matches ( text, complete_command ); case CompletionContext::COMMAND_INTROSPECT: @@ -112,6 +140,8 @@ char ** ReadlinePromptCompletion::readline_completion ( const char *text, int st return rl_completion_matches ( text, complete_filepath ); case CompletionContext::FILEPATH_OR_VARIABLE: return rl_completion_matches ( text, complete_filepath_or_variable ); + case CompletionContext::SET: + return rl_completion_matches ( text, complete_set ); default: return nullptr; } diff --git a/aql2/src/prompt/ReadlinePromptCompletion.h b/aql2/src/prompt/ReadlinePromptCompletion.h index b325f5c9bc0028a79c97706268123b02d772483f..31e92768f279288179969b81f441c6c9356b41dc 100644 --- a/aql2/src/prompt/ReadlinePromptCompletion.h +++ b/aql2/src/prompt/ReadlinePromptCompletion.h @@ -16,24 +16,63 @@ #include <alib/string> #include <registry/Registry.h> +#include <registry/XmlRegistry.h> #include <environment/Environment.h> #include <prompt/Prompt.h> class ReadlinePromptCompletion { - static std::set < std::string > fetchAlgorithms ( const char *text ) { + static std::set < std::string > fetchAlgorithmsFullyQualifiedName ( const char *text ) { + std::set < std::string > fullyQualifiedNames; + + for ( const std::pair < std::string, std::vector < std::string > > & algo : abstraction::Registry::listAlgorithms ( ) ) { + fullyQualifiedNames.insert ( algo.first ); + } + + return filter_completions ( fullyQualifiedNames, text ); + } + + static std::set < std::string > fetchAlgorithmsLastSegmentName ( const char *text ) { + std::map < std::string, unsigned > collisions; + + for ( const std::pair < std::string, std::vector < std::string > > & algo : abstraction::Registry::listAlgorithms ( ) ) { + size_t pos = algo.first.find_last_of ( ':' ); + if ( pos != std::string::npos ) + collisions [ algo.first.substr ( pos + 1 ) ] += 1; + } + + std::set < std::string > res; + for ( const std::pair < const std::string, unsigned > & kv : collisions ) + if ( kv.second == 1 ) + res.insert ( kv.first ); + + return filter_completions ( res, text ); + } + + static std::set < std::string > fetchAlgorithmGroups ( const char *text ) { + std::set < std::string > res; + + for ( const std::pair < std::string, std::vector < std::string > > & algo : abstraction::Registry::listAlgorithms ( ) ) { + std::set < std::string > groups = getGroups ( algo.first ); + res.insert ( groups.begin ( ), groups.end ( ) ); + } + + return filter_completions ( res, text ); + } + + static std::set < std::string > fetchDatatypeGroups ( const char *text ) { std::set < std::string > res; - const ext::set < ext::pair < std::string, ext::vector < std::string > > >& algos = abstraction::Registry::listAlgorithms ( ); - for ( const std::pair < std::string, std::vector < std::string > > & algo : algos ) { - res.insert ( algo.first ); + for ( const std::string & dtt : abstraction::XmlRegistry::listDataTypes ( ) ) { + std::set < std::string > groups = getGroups ( dtt ); + res.insert ( groups.begin ( ), groups.end ( ) ); } return filter_completions ( res, text ); } static std::set < std::string > fetchCommands ( const char *text ) { - return filter_completions ( { "execute", "introspect", "quit", "help" }, text ); + return filter_completions ( { "execute", "introspect", "quit", "help", "set" }, text ); } static std::set < std::string > fetchCommandsIntrospect ( const char *text ) { @@ -48,6 +87,10 @@ class ReadlinePromptCompletion { return filter_completions ( addPrefix ( Prompt::getPrompt ( ).getEnvironment ( ).getVariableNames ( ), "$" ), text ); } + static std::set < std::string > fetchSet ( const char *text ) { + return filter_completions ( { "verbose", "measure", "optimizeXml", "seed" }, text ); + } + static std::set < std::string > fetchFilepath ( const char *text ) { std::set < std::string > res; char *str; @@ -66,12 +109,17 @@ public: COMMAND_INTROSPECT, ALGORITHM, + ALGORITHM_GROUP, + + DATATYPE_GROUP, FILEPATH, FILEPATH_OR_VARIABLE, VARIABLE, BINDING, + + SET, }; static char** readline_completion ( const char *text, int start, int end ); @@ -80,6 +128,7 @@ public: private: static std::set < std::string > addPrefix ( const std::set < std::string > & collection, const std::string & prefix ); static bool startswith ( const std::string & subject, const std::string & prefix ); + static std::set < std::string > getGroups ( const std::string & qualified_name ); static std::set < std::string > filter_completions ( const std::set < std::string > & choices, const char *text ); /** @@ -127,7 +176,15 @@ private: * @return malloc-allocated string or NULL if no more strings can be generated. */ static char * complete_algorithm ( const char *text, int state ) { - return completion_generator ( text, state, fetchAlgorithms ); + return completion_generator ( text, state, fetchAlgorithmsFullyQualifiedName, fetchAlgorithmsLastSegmentName ); + } + + static char * complete_algorithm_group ( const char *text, int state ) { + return completion_generator ( text, state, fetchAlgorithmGroups ); + } + + static char * complete_datatype_group ( const char *text, int state ) { + return completion_generator ( text, state, fetchDatatypeGroups ); } static char * complete_command ( const char *text, int state ) { @@ -154,6 +211,10 @@ private: return completion_generator ( text, state, fetchFilepath, fetchVariables ); } + static char * complete_set ( const char *text, int state ) { + return completion_generator ( text, state, fetchSet ); + } + }; #endif /* _READLINE_PROMPT_COMPLETION_H */