// ========================================================================= // @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) // ========================================================================= #include #include #include #include #include // ------------------------------------------------------------------------- TinyCon::CompletionConsole:: CompletionConsole( ) : Superclass( ) { } // ------------------------------------------------------------------------- TinyCon::CompletionConsole:: CompletionConsole( const std::string& prompt ) : Superclass( prompt ) { } // ------------------------------------------------------------------------- TinyCon::CompletionConsole:: ~CompletionConsole( ) { } // ------------------------------------------------------------------------- TinyCon::CompletionConsole:: TTrie* TinyCon::CompletionConsole:: addCommand( const std::string& cmd ) { return( this->m_CommandsTrie.insert( cmd ) ); } // ------------------------------------------------------------------------- TinyCon::CompletionConsole:: TTrie* TinyCon::CompletionConsole:: addCommand( const std::string& cmd, const std::string& opt ) { TTrie* t = this->m_CommandsTrie.find( cmd ).first; if( t == NULL ) t = this->m_CommandsTrie.insert( cmd ); TTrie* s = t->getExtension( ); if( s == NULL ) s = t->createExtension( ); s->insert( opt ); return( s ); } // ------------------------------------------------------------------------- TinyCon::CompletionConsole:: TTrie* TinyCon::CompletionConsole:: addCommand( const std::string& cmd, Trie* opt ) { TTrie* t = this->m_CommandsTrie.find( cmd ).first; if( t == NULL ) t = this->m_CommandsTrie.insert( cmd ); t->setExtension( opt ); return( opt ); } // ------------------------------------------------------------------------- int TinyCon::CompletionConsole:: trigger( const std::string& s ) { typedef boost::char_separator< char > _TSep; typedef boost::tokenizer< _TSep > _TTok; _TTok tok( s, _TSep( " " ) ); std::vector< std::string > tokens; for( _TTok::const_iterator tIt = tok.begin( ); tIt != tok.end( ); ++tIt ) tokens.push_back( *tIt ); if( tokens.size( ) > 0 ) return( this->trigger( tokens ) ); else return( 0 ); } // ------------------------------------------------------------------------- int TinyCon::CompletionConsole:: hotkeys( char c ) { typedef boost::char_separator< char > _TSep; typedef boost::tokenizer< _TSep > _TTok; if( c == Superclass::TAB ) { // Get current line and tokenize it std::string line; line.assign( this->m_Buffer.begin( ), this->m_Buffer.end( ) ); _TTok tok( line, _TSep( " " ) ); // Get current trie const TTrie* t = &( this->m_CommandsTrie ); _TTok::const_iterator tIt = tok.begin( ); bool ok = true; std::string prefix = ""; while( ok && tIt != tok.end( ) ) { if( t != NULL ) { std::pair< const TinyCon::Trie*, std::string > it = t->find( *tIt ); t = it.first; prefix = it.second; if( t != NULL ) { if( t->IsWord( ) ) { t = t->getExtension( ); prefix = ""; } else ok = false; } else ok = false; } // end if tIt++; } // end for // Analize current command if( t != NULL ) { std::vector< std::string > options; t->words( options ); if( options.size( ) == 1 ) { // Delete line from console for( int i = 0; i <= line.size( ) + this->m_Prompt.size( ); ++i ) std::cout << "\b \b"; // Update line line += options[ 0 ] + " "; } else if( options.size( ) > 1 ) { for( const std::string& o: options ) std::cout << std::endl << prefix << o; std::cout << std::endl; line += this->_prefix( options ); } // end if // Show line this->setBuffer( line ); std::cout << this->m_Prompt << line; } // end if return( 1 ); } else return( 0 ); } // ------------------------------------------------------------------------- std::string TinyCon::CompletionConsole:: _prefix( const std::vector< std::string >& v ) const { if( v.size( ) > 0 ) { std::string prefix = v[ 0 ]; for( unsigned long i = 1; i < v.size( ); ++i ) { const char* a = prefix.c_str( ); const char* b = v[ i ].c_str( ); std::size_t sa = prefix.size( ); std::size_t sb = v[ i ].size( ); ptrdiff_t d; if( sb < sa ) d = std::distance( b, std::mismatch( b, b + sb, a ).first ); else d = std::distance( a, std::mismatch( a, a + sa, b ).first ); prefix = v[ i ].substr( 0, std::size_t( d ) ); } // end for return( prefix ); } else return( "" ); } // eof - $RCSfile$