--- /dev/null
+// =========================================================================
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// =========================================================================
+
+#include <iostream>
+#include <iterator>
+#include <sstream>
+#include <boost/tokenizer.hpp>
+#include <TinyCon/CompletionConsole.h>
+
+// -------------------------------------------------------------------------
+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$