diff --git a/alib2cli/src/command/AlgorithmsIntrospectionCommand.h b/alib2cli/src/command/AlgorithmsIntrospectionCommand.h index 06401321c4155395a81ced8ac6ad69474a7df759..103c54256e2a1a43a01645e5a2770458c4580772 100644 --- a/alib2cli/src/command/AlgorithmsIntrospectionCommand.h +++ b/alib2cli/src/command/AlgorithmsIntrospectionCommand.h @@ -25,7 +25,7 @@ public: } } - Command::Result run ( Environment & environment ) const override { + CommandResult run ( Environment & environment ) const override { std::string param; if ( m_param != nullptr ) param = m_param->eval ( environment ); @@ -37,7 +37,7 @@ public: } else { throw exception::CommonException ( "Invalid Algorithm introspection param" ); } - return Command::Result::OK; + return CommandResult::OK; } }; diff --git a/alib2cli/src/command/BindingsIntrospectionCommand.h b/alib2cli/src/command/BindingsIntrospectionCommand.h index 7d7032b47e53444a3ff6775e4107292032efe68f..dec939334868be6ea66594322d1df96e6a31b0ff 100644 --- a/alib2cli/src/command/BindingsIntrospectionCommand.h +++ b/alib2cli/src/command/BindingsIntrospectionCommand.h @@ -13,7 +13,7 @@ public: BindingsIntrospectionCommand ( std::unique_ptr < cli::Arg > param ) : m_param ( std::move ( param ) ) { } - Command::Result run ( Environment & environment ) const override { + CommandResult run ( Environment & environment ) const override { std::string param; if ( m_param != nullptr ) param = m_param->eval ( environment ); @@ -24,7 +24,7 @@ public: else common::Streams::out << param << " " << environment.getBinding ( param ) << std::endl; - return Command::Result::OK; + return CommandResult::OK; } }; diff --git a/alib2cli/src/command/CastsIntrospectionCommand.h b/alib2cli/src/command/CastsIntrospectionCommand.h index 7b2b448d459039d785980446c4e317a5d78fd6ad..d824c5c357b716467331c0c90d30915e45954fb4 100644 --- a/alib2cli/src/command/CastsIntrospectionCommand.h +++ b/alib2cli/src/command/CastsIntrospectionCommand.h @@ -34,7 +34,7 @@ public: } } - Command::Result run ( Environment & environment ) const override { + CommandResult run ( Environment & environment ) const override { std::string param; if ( m_param != nullptr ) param = m_param->eval ( environment ); @@ -48,7 +48,7 @@ public: if ( ! m_from && ! m_to ) printCasts ( abstraction::Registry::listCasts ( ) ); - return Command::Result::OK; + return CommandResult::OK; } }; diff --git a/alib2cli/src/command/Command.h b/alib2cli/src/command/Command.h index d7daf36e579969a53c3b994ce4d25783314235a8..3bb6ec8d4d6380e86fd5ebe0d850cf102158f401 100644 --- a/alib2cli/src/command/Command.h +++ b/alib2cli/src/command/Command.h @@ -1,23 +1,16 @@ #ifndef _CLI_COMMAND_H_ #define _CLI_COMMAND_H_ +#include <command/CommandResult.h> #include <environment/Environment.h> namespace cli { class Command { public: - enum class Result { - OK, - QUIT, - EXCEPTION, - ERROR, - EOT - }; - virtual ~Command ( ) noexcept = default; - virtual Command::Result run ( Environment & environment ) const = 0; + virtual CommandResult run ( Environment & environment ) const = 0; }; } /* namespace cli */ diff --git a/alib2cli/src/command/CommandList.h b/alib2cli/src/command/CommandList.h index ecfb42f0f81b9ea29f69958fc1c49f57ee76c4e2..3babfa77ca5e993f576842239e6c8f5e2ccdb8e6 100644 --- a/alib2cli/src/command/CommandList.h +++ b/alib2cli/src/command/CommandList.h @@ -12,12 +12,12 @@ public: CommandList ( ext::vector < std::unique_ptr < Command > > commands ) : m_commands ( std::move ( commands ) ) { } - Command::Result run ( Environment & environment ) const override { + CommandResult run ( Environment & environment ) const override { if ( m_commands.empty ( ) ) throw std::invalid_argument ( "Command list can't be empty" ); - Command::Result res = Command::Result::OK; - for ( size_t i = 0; i < m_commands.size ( ) && res == Command::Result::OK; ++ i ) + CommandResult res = CommandResult::OK; + for ( size_t i = 0; i < m_commands.size ( ) && res == CommandResult::OK; ++ i ) res = m_commands [ i ]->run ( environment ); return res; diff --git a/alib2cli/src/command/CommandResult.h b/alib2cli/src/command/CommandResult.h new file mode 100644 index 0000000000000000000000000000000000000000..afa6d05bf89de1db20aa4b0b56678d7871a3ba51 --- /dev/null +++ b/alib2cli/src/command/CommandResult.h @@ -0,0 +1,16 @@ +#ifndef _CLI_COMMAND_RESULT_H_ +#define _CLI_COMMAND_RESULT_H_ + +namespace cli { + +enum class CommandResult { + OK, + QUIT, + EXCEPTION, + ERROR, + EOT +}; + +} /* namespace cli */ + +#endif /* _CLI_COMMAND_RESULT_H_ */ diff --git a/alib2cli/src/command/DataTypesIntrospectionCommand.h b/alib2cli/src/command/DataTypesIntrospectionCommand.h index f01d97c8eeb0516bca020b733fb91df3114ad33b..fecd4ab9e13f09c97072d1546046bb63de948dab 100644 --- a/alib2cli/src/command/DataTypesIntrospectionCommand.h +++ b/alib2cli/src/command/DataTypesIntrospectionCommand.h @@ -20,7 +20,7 @@ public: common::Streams::out << type << std::endl; } - Command::Result run ( Environment & environment ) const override { + CommandResult run ( Environment & environment ) const override { std::string param; if ( m_param != nullptr ) param = m_param->eval ( environment ); @@ -32,7 +32,7 @@ public: } else { throw exception::CommonException ( "Invalid DataType introspection param" ); } - return Command::Result::OK; + return CommandResult::OK; } }; diff --git a/alib2cli/src/command/EOTCommand.h b/alib2cli/src/command/EOTCommand.h index 16bf1952f77ba63383666990e42a97d45619255c..fb72fc2171578f7914874ed47f72645bd80464fb 100644 --- a/alib2cli/src/command/EOTCommand.h +++ b/alib2cli/src/command/EOTCommand.h @@ -13,8 +13,8 @@ class EOTCommand : public Command { public: EOTCommand ( ) { } - Command::Result run ( Environment & /* environment */ ) const override { - return Command::Result::EOT; + CommandResult run ( Environment & /* environment */ ) const override { + return CommandResult::EOT; } }; diff --git a/alib2cli/src/command/ExecuteCommand.h b/alib2cli/src/command/ExecuteCommand.h index bfc5523bf523535720b8244034dcb0eb2fb3ae35..41f84f46ba96b7b0ec8ce30a4f40a5a2ffdcec43 100644 --- a/alib2cli/src/command/ExecuteCommand.h +++ b/alib2cli/src/command/ExecuteCommand.h @@ -14,9 +14,9 @@ public: ExecuteCommand ( std::shared_ptr < StatementList > command ) : m_command ( std::move ( command ) ) { } - Command::Result run ( Environment & environment ) const override { + CommandResult run ( Environment & environment ) const override { m_command->translateAndEval ( nullptr, environment ); - return Command::Result::OK; + return CommandResult::OK; } }; diff --git a/alib2cli/src/command/HelpCommand.h b/alib2cli/src/command/HelpCommand.h index 3415c27967b6f264fa5f40f0287add105b1b0931..08ecc0493d7d08924b1d394f476b282b4fa9a58d 100644 --- a/alib2cli/src/command/HelpCommand.h +++ b/alib2cli/src/command/HelpCommand.h @@ -13,7 +13,7 @@ public: HelpCommand ( std::unique_ptr < cli::Arg > command ) : m_command ( std::move ( command ) ) { } - Command::Result run ( Environment & environment ) const override { + CommandResult run ( Environment & environment ) const override { std::string command; if ( m_command != nullptr ) command = m_command->eval ( environment ); @@ -73,7 +73,7 @@ public: } else { common::Streams::out << "The command " << command << " either does not exist or does not have a help entry." << std::endl; } - return Command::Result::OK; + return CommandResult::OK; } }; diff --git a/alib2cli/src/command/LoadCommand.h b/alib2cli/src/command/LoadCommand.h index 3dc3d79eb4cabf5328cccc42b85a4ce3228de447..7ec174ad94f2fabcb0476de48795698f14c14af6 100644 --- a/alib2cli/src/command/LoadCommand.h +++ b/alib2cli/src/command/LoadCommand.h @@ -15,9 +15,9 @@ public: LoadCommand ( std::string libraryName ) : m_libraryName ( std::move ( libraryName ) ) { } - Command::Result run ( Environment & ) const override { + CommandResult run ( Environment & ) const override { cli::LibraryLoader::load ( m_libraryName ); - return Command::Result::OK; + return CommandResult::OK; } }; diff --git a/alib2cli/src/command/OverloadsIntrospectionCommand.h b/alib2cli/src/command/OverloadsIntrospectionCommand.h index 0b47850641ae71c4a852f3a41399a12fc6841719..538489656d3a12c4312bf8208eebdd6aa8799443 100644 --- a/alib2cli/src/command/OverloadsIntrospectionCommand.h +++ b/alib2cli/src/command/OverloadsIntrospectionCommand.h @@ -14,7 +14,7 @@ public: OverloadsIntrospectionCommand ( std::unique_ptr < cli::Arg > param, ext::vector < std::unique_ptr < cli::Arg > > templateParams ) : m_param ( std::move ( param ) ), m_templateParams ( std::move ( templateParams ) ) { } - Command::Result run ( Environment & environment ) const override { + CommandResult run ( Environment & environment ) const override { std::string param = m_param->eval ( environment ); ext::vector < std::string > templateParams; for ( const std::unique_ptr < cli::Arg > & templateParam : m_templateParams ) @@ -72,7 +72,7 @@ public: first = true; } - return Command::Result::OK; + return CommandResult::OK; } }; diff --git a/alib2cli/src/command/QuitCommand.h b/alib2cli/src/command/QuitCommand.h index 1d5b5e3ae0c63391f1e6009921cf25135b51e1ed..f18374f108c431999dbbac70c453149246a8aa86 100644 --- a/alib2cli/src/command/QuitCommand.h +++ b/alib2cli/src/command/QuitCommand.h @@ -14,11 +14,11 @@ public: QuitCommand ( std::shared_ptr < Statement > command ) : m_command ( std::move ( command ) ) { } - Command::Result run ( Environment & environment ) const override { + CommandResult run ( Environment & environment ) const override { if ( m_command ) environment.setResult ( m_command->translateAndEval ( nullptr, environment ) ); - return Command::Result::QUIT; + return CommandResult::QUIT; } }; diff --git a/alib2cli/src/command/SetCommand.h b/alib2cli/src/command/SetCommand.h index 8fd93f8baf39c03fa63fd0bd976c12cacfc5b9af..bcdf4f6e19bc3e0cd7536f84af3cbf7f4e9cc3c8 100644 --- a/alib2cli/src/command/SetCommand.h +++ b/alib2cli/src/command/SetCommand.h @@ -16,7 +16,7 @@ public: SetCommand ( std::string param, std::string value ) : m_param ( std::move ( param ) ), m_value ( std::move ( value ) ) { } - Command::Result run ( Environment & ) const override { + CommandResult run ( Environment & ) const override { if ( m_param == "verbose" ) { common::GlobalData::verbose = ext::from_string < bool > ( m_value ); } else if ( m_param == "measure" ) { @@ -28,7 +28,7 @@ public: } else { common::Streams::out << "The set parameter " << m_param << " does not exist." << std::endl; } - return Command::Result::OK; + return CommandResult::OK; } }; diff --git a/alib2cli/src/command/UnloadCommand.h b/alib2cli/src/command/UnloadCommand.h index 78c5ea9eb19e8f2fcb1729b3f224a069c843c382..470cb629ec7b240313f64dca1d075b5e76b749a9 100644 --- a/alib2cli/src/command/UnloadCommand.h +++ b/alib2cli/src/command/UnloadCommand.h @@ -15,9 +15,9 @@ public: UnloadCommand ( std::string libraryName ) : m_libraryName ( std::move ( libraryName ) ) { } - Command::Result run ( Environment & ) const override { + CommandResult run ( Environment & ) const override { cli::LibraryLoader::unload ( m_libraryName ); - return Command::Result::OK; + return CommandResult::OK; } }; diff --git a/alib2cli/src/command/VariablesIntrospectionCommand.h b/alib2cli/src/command/VariablesIntrospectionCommand.h index 8c91b8b76aa86b21df78f4c452f6c4919ac27a3a..2059838b9b5f095305e9b2404df62534cffaceae 100644 --- a/alib2cli/src/command/VariablesIntrospectionCommand.h +++ b/alib2cli/src/command/VariablesIntrospectionCommand.h @@ -13,7 +13,7 @@ public: VariablesIntrospectionCommand ( std::unique_ptr < cli::Arg > param ) : m_param ( std::move ( param ) ) { } - Command::Result run ( Environment & environment ) const override { + CommandResult run ( Environment & environment ) const override { std::string param; if ( m_param != nullptr ) param = m_param->eval ( environment ); @@ -24,7 +24,7 @@ public: else common::Streams::out << param << " " << environment.getVariable ( param )->getType ( ) << std::endl; - return Command::Result::OK; + return CommandResult::OK; } }; diff --git a/alib2cli/src/environment/Environment.cpp b/alib2cli/src/environment/Environment.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d949536123c7d72fa70e87c199d875e7aff2507b --- /dev/null +++ b/alib2cli/src/environment/Environment.cpp @@ -0,0 +1,31 @@ +#include <environment/Environment.h> + +#include <lexer/Lexer.h> +#include <parser/Parser.h> + +#include <alib/exception> + +#include <global/GlobalData.h> + +namespace cli { + +cli::CommandResult Environment::execute ( std::shared_ptr < cli::LineInterface > lineInterface ) { + cli::CommandResult state = cli::CommandResult::OK; + + while ( state == cli::CommandResult::OK || state == cli::CommandResult::ERROR || state == cli::CommandResult::EXCEPTION ) + state = execute_line ( cli::CharSequence ( lineInterface ) ); + + return state; +} + +cli::CommandResult Environment::execute_line ( cli::CharSequence charSequence ) { + try { + cli::Parser parser = cli::Parser ( cli::Lexer ( std::move ( charSequence ) ) ); + return parser.parse ( )->run ( * this ); + } catch ( ... ) { + alib::ExceptionHandler::handle ( common::Streams::err ); + return cli::CommandResult::EXCEPTION; + } +} + +} /* namespace cli */ diff --git a/alib2cli/src/environment/Environment.h b/alib2cli/src/environment/Environment.h index 2d681ed3efc9edb56960cc0c47176419b6804a55..2e29d6f757fe448e5aa8e5eda9d52606542c3130 100644 --- a/alib2cli/src/environment/Environment.h +++ b/alib2cli/src/environment/Environment.h @@ -10,6 +10,8 @@ #include <exception/CommonException.h> #include <abstraction/ValueHolder.hpp> +#include <command/CommandResult.h> +#include <lexer/CharSequence.h> namespace cli { @@ -126,6 +128,10 @@ public: return 0; } } + + cli::CommandResult execute ( std::shared_ptr < cli::LineInterface > lineInterface ); + + cli::CommandResult execute_line ( cli::CharSequence charSequence ); }; } /* namespace cli */ diff --git a/alib2cli/src/lexer/CharSequence.cpp b/alib2cli/src/lexer/CharSequence.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f2c7ff84dc02896ad7586792f8fecd90cea9495e --- /dev/null +++ b/alib2cli/src/lexer/CharSequence.cpp @@ -0,0 +1,67 @@ +#include "CharSequence.h" + +#include <algorithm> + +namespace cli { + +void CharSequence::fetch ( bool readNextLine ) { + if ( ! readNextLine ) + return; + + std::string line; + for ( std::string tmpLine; m_lineInterface->readline ( tmpLine, linePtr == nullptr ); ) { + if ( std::all_of ( tmpLine.begin ( ), tmpLine.end ( ), isspace ) ) { + line += tmpLine; + line += '\n'; + continue; + } + + if ( ! tmpLine.empty ( ) && tmpLine.back ( ) == '\\' ) { + tmpLine.back ( ) = '\n'; + line += tmpLine; + } else { + line += tmpLine; + line += '\n'; + break; + } + } + + if ( line.empty ( ) ) + return; + + m_lines.push_back ( std::move ( line ) ); + + this->linePtr = m_lines.back ( ).c_str ( ); +} + +int CharSequence::getCharacter ( ) const { + if ( ! putbackBuffer.empty ( ) ) + return ( int ) putbackBuffer.back ( ); + else if ( linePtr == nullptr ) + return EOF; + else + return ( int ) * linePtr; +} + +void CharSequence::advance ( bool readNextLine ) { + if ( ! putbackBuffer.empty ( ) ) { + putbackBuffer.pop_back ( ); + } else if ( linePtr == nullptr ) { + fetch ( readNextLine ); + } else { + if ( * linePtr != '\0' ) + ++ linePtr; + if ( * linePtr == '\0' ) + fetch ( readNextLine ); + } +} + +std::string CharSequence::getLine ( ) const { + std::string res; + for ( const std::string & line : m_lines ) { + res += line; + } + return res; +} + +} /* namespace cli */ diff --git a/alib2cli/src/lexer/CharSequence.h b/alib2cli/src/lexer/CharSequence.h index c7d9a391e9fa675274f5c0cc0b3ac7c699e70b11..199da1ffae8d285eeb72b4a9b0ef0fd3b2be8513 100644 --- a/alib2cli/src/lexer/CharSequence.h +++ b/alib2cli/src/lexer/CharSequence.h @@ -3,88 +3,50 @@ #include <string> #include <vector> +#include <memory> -#include <readline/LineReader.h> +#include <readline/LineInterface.h> namespace cli { class CharSequence { - std::unique_ptr < LineReader > m_lineReader; + std::shared_ptr < LineInterface > m_lineInterface; std::string putbackBuffer; const char * linePtr = nullptr; std::vector < std::string > m_lines; - void fetch ( bool readNextLine ) { - if ( ! readNextLine ) { - return; - } - - std::string line; - for ( std::string tmpLine; m_lineReader->readline ( tmpLine ); ) { - if ( ! tmpLine.empty ( ) && tmpLine.back ( ) == '\\' ) { - tmpLine.back ( ) = '\n'; - line += tmpLine; - } else { - line += tmpLine; - line += '\n'; - break; - } - } - - if ( line.empty ( ) ) - return; - - m_lines.push_back ( std::move ( line ) ); - - this->linePtr = m_lines.back ( ).c_str ( ); - } + void fetch ( bool readNextLine ); + std::string getLine ( ) const; public: - template < class Reader > - CharSequence ( Reader && reader ) : m_lineReader ( new Reader ( std::move ( reader ) ) ) { + CharSequence ( std::shared_ptr < cli::LineInterface > reader ) : m_lineInterface ( std::move ( reader ) ) { } - int getCharacter ( ) const { - if ( ! putbackBuffer.empty ( ) ) - return ( int ) putbackBuffer.back ( ); - else if ( linePtr == nullptr ) - return EOF; - else - return ( int ) * linePtr; + template < class Interface > + CharSequence ( Interface && reader ) : m_lineInterface ( std::make_shared < Interface > ( std::forward < Interface > ( reader ) ) ) { } - void advance ( bool readNextLine ) { - if ( ! putbackBuffer.empty ( ) ) { - putbackBuffer.pop_back ( ); - } else if ( linePtr == nullptr ) { - fetch ( readNextLine ); - } else { - if ( * linePtr != '\0' ) - ++ linePtr; - if ( * linePtr == '\0' ) - fetch ( readNextLine ); - } - } + CharSequence ( CharSequence && ) = default; + + CharSequence ( const CharSequence & ) = delete; + + CharSequence & operator = ( CharSequence && ) = delete; + + CharSequence & operator = ( const CharSequence & ) = delete; - std::string getLine ( ) const { - std::string res; - for ( const std::string & line : m_lines ) { - res += line; - } - return res; + ~CharSequence ( ) { + if ( m_lineInterface ) + m_lineInterface->lineCallback ( getLine ( ) ); } + int getCharacter ( ) const; + + void advance ( bool readNextLine ); + void putback ( std::string string ) { putbackBuffer.insert ( putbackBuffer.end ( ), string.rbegin ( ), string.rend ( ) ); } - - void reset ( ) { - putbackBuffer.clear ( ); - linePtr = nullptr; - m_lines.clear ( ); - m_lineReader->reset ( ); - } }; } /* namespace cli */ diff --git a/alib2cli/src/lexer/Lexer.h b/alib2cli/src/lexer/Lexer.h index d123bb62365b1782154c12d736d4bbcdce611121..7706d343295a16c39b54c42e4b22f1562b7a1056 100644 --- a/alib2cli/src/lexer/Lexer.h +++ b/alib2cli/src/lexer/Lexer.h @@ -10,7 +10,7 @@ #include <exception/CommonException.h> #include "CharSequence.h" -#include <readline/StringLineReader.h> +#include <readline/StringLineInterface.h> namespace cli { @@ -23,7 +23,7 @@ public: }; private: - CharSequence & m_source; + CharSequence m_source; Hint m_hint; public: @@ -144,7 +144,7 @@ public: }; - explicit Lexer ( CharSequence & source ) : m_source ( source ), m_hint ( Hint::NONE ) { + explicit Lexer ( CharSequence source ) : m_source ( std::move ( source ) ), m_hint ( Hint::NONE ) { m_source.advance ( true ); } @@ -157,10 +157,6 @@ public: void setHint ( Hint hint ) { m_hint = hint; } - - std::string getLine ( ) const { - return m_source.getLine ( ); - } }; } /* namespace cli */ diff --git a/alib2cli/src/parser/Parser.h b/alib2cli/src/parser/Parser.h index d0f63a0cb7f8d904f80b3a6e1a92c4f3a4afa357..a581f1f7913497342434d803e163ba50f2b5e702 100644 --- a/alib2cli/src/parser/Parser.h +++ b/alib2cli/src/parser/Parser.h @@ -28,10 +28,6 @@ public: Parser ( cli::Lexer lexer ) : m_lexer ( std::move ( lexer ) ), m_current ( m_lexer.nextToken ( true ) ) { } - const cli::Lexer & getLexer ( ) const { - return m_lexer; - } - void setHint ( Lexer::Hint hint ) { m_lexer.setHint ( hint ); m_lexer.putback ( std::move ( m_current ) ); diff --git a/alib2cli/src/readline/IstreamLineReader.h b/alib2cli/src/readline/IstreamLineInterface.h similarity index 52% rename from alib2cli/src/readline/IstreamLineReader.h rename to alib2cli/src/readline/IstreamLineInterface.h index b65d94467eecf200aef3beea8a4ec050d89862d1..7064ab5bee499c55459621be28d09abcc3544e78 100644 --- a/alib2cli/src/readline/IstreamLineReader.h +++ b/alib2cli/src/readline/IstreamLineInterface.h @@ -1,16 +1,16 @@ /* - * IstreamLineReader.h + * IstreamLineInterface.h * * Created on: 20. 3. 2017 * Author: Jan Travnicek */ -#ifndef _ISTREAM_LINE_READER_H_ -#define _ISTREAM_LINE_READER_H_ +#ifndef _ISTREAM_LINE_INTERFACE_H_ +#define _ISTREAM_LINE_INTERFACE_H_ #include <string> -#include <readline/LineReader.h> +#include <readline/LineInterface.h> namespace cli { @@ -20,18 +20,18 @@ namespace cli { * \tparam Stream the type of the stream to read from. It can be either reference or value. */ template < class Stream > -class IstreamLineReader final : public cli::LineReader { +class IstreamLineInterface final : public cli::LineInterface { Stream m_is; - bool readline ( std::string & line ) override { + bool readline ( std::string & line, bool ) override { return ( bool ) std::getline ( m_is, line ); } public: - IstreamLineReader ( Stream ifs ) : m_is ( std::forward < Stream > ( ifs ) ) { + IstreamLineInterface ( Stream ifs ) : m_is ( std::forward < Stream > ( ifs ) ) { } }; } // namespace cli -#endif /* _ISTREAM_LINE_READER_H_ */ +#endif /* _ISTREAM_LINE_INTERFACE_H_ */ diff --git a/alib2cli/src/readline/LineInterface.h b/alib2cli/src/readline/LineInterface.h new file mode 100644 index 0000000000000000000000000000000000000000..e5134940bdec124f1e5928de14f06775f02a849c --- /dev/null +++ b/alib2cli/src/readline/LineInterface.h @@ -0,0 +1,41 @@ +/* + * LineInterface.h + * + * Created on: 20. 3. 2017 + * Author: Jan Travnicek + */ + +#ifndef _LINE_ITERFACE_H_ +#define _LINE_ITERFACE_H_ + +#include <string> + +namespace cli { + +/** + * Line reader serves as a base class for adaptors reding from various source. + */ +class LineInterface { +public: + virtual bool readline ( std::string & line, bool first ) = 0; + + virtual void lineCallback ( const std::string & ) const { + } + +public: + LineInterface ( ) = default; + + LineInterface ( LineInterface && ) noexcept = default; + + LineInterface ( const LineInterface & ) = delete; + + LineInterface & operator = ( LineInterface && ) noexcept = delete; + + LineInterface & operator = ( const LineInterface & ) = delete; + + virtual ~LineInterface ( ) noexcept = default; +}; + +} // namespace cli + +#endif /* _LINE_ITERFACE_H_ */ diff --git a/alib2cli/src/readline/LineReader.h b/alib2cli/src/readline/LineReader.h deleted file mode 100644 index 676a8765139d9e977139676c23c801d11c2b26bc..0000000000000000000000000000000000000000 --- a/alib2cli/src/readline/LineReader.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * LineReader.h - * - * Created on: 20. 3. 2017 - * Author: Jan Travnicek - */ - -#ifndef _LINE_READER_H_ -#define _LINE_READER_H_ - -#include <string> - -#include <readline/LineReader.h> - -namespace cli { - -/** - * Line reader serves as a base class for adaptors reding from various source. - */ -class LineReader { -public: - virtual bool readline ( std::string & line ) = 0; - - virtual void reset ( ) { - } - -public: - LineReader ( ) = default; - - LineReader ( LineReader && ) noexcept = default; - - LineReader ( const LineReader & ) = delete; - - LineReader & operator = ( LineReader && ) noexcept = delete; - - LineReader & operator = ( const LineReader & ) = delete; - - virtual ~LineReader ( ) noexcept = default; -}; - -} // namespace cli - -#endif /* _LINE_READER_H_ */ diff --git a/alib2cli/src/readline/StringLineInterface.h b/alib2cli/src/readline/StringLineInterface.h new file mode 100644 index 0000000000000000000000000000000000000000..c9a363e97eccab4dbe34078f3e31cc75fb51ee72 --- /dev/null +++ b/alib2cli/src/readline/StringLineInterface.h @@ -0,0 +1,35 @@ +/* + * StringLineInterface.h + * + * Created on: 20. 3. 2017 + * Author: Jan Travnicek + */ + +#ifndef _STRING_LINE_INTERFACE_H_ +#define _STRING_LINE_INTERFACE_H_ + +#include <string> + +#include <readline/LineInterface.h> + +namespace cli { + +class StringLineInterface final : public cli::LineInterface { + std::string m_string; + + bool readline ( std::string & line, bool ) override { + if ( m_string == "" ) + return false; + + line = std::exchange ( m_string, "" ); + return true; + } + +public: + StringLineInterface ( std::string string ) : m_string ( std::move ( string ) ) { + } +}; + +} // namespace cli + +#endif /* _STRING_LINE_INTERFACE_H_ */ diff --git a/alib2cli/src/readline/StringLineReader.h b/alib2cli/src/readline/StringLineReader.h deleted file mode 100644 index 1b632377c91cb788674f37d07700a74530efe220..0000000000000000000000000000000000000000 --- a/alib2cli/src/readline/StringLineReader.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * StringLineReader.h - * - * Created on: 20. 3. 2017 - * Author: Jan Travnicek - */ - -#ifndef _STRING_LINE_READER_H_ -#define _STRING_LINE_READER_H_ - -#include <string> - -#include <readline/LineReader.h> - -namespace cli { - -class StringLineReader final : public cli::LineReader { - std::string m_string; - - bool readline ( std::string & line ) override { - if ( m_string == "" ) - return false; - - line = std::exchange ( m_string, "" ); - return true; - } - -public: - StringLineReader ( std::string string ) : m_string ( std::move ( string ) ) { - } -}; - -} // namespace cli - -#endif /* _STRING_LINE_READER_H_ */ diff --git a/alib2cli/test-src/cli/CliTest.cpp b/alib2cli/test-src/cli/CliTest.cpp index 8b1bfc6d9bdac723520e3e6e2e53b78b6a6b36f9..2b7f4441cd218291e2fe711594284abd6ea271cb 100644 --- a/alib2cli/test-src/cli/CliTest.cpp +++ b/alib2cli/test-src/cli/CliTest.cpp @@ -10,8 +10,7 @@ #include <registration/AlgoRegistration.hpp> void testLine ( std::string line, cli::Environment & environment ) { - cli::CharSequence sequence { cli::StringLineReader ( line ) }; - cli::Parser ( cli::Lexer ( sequence ) ).parse ( )->run ( environment ); + cli::Parser ( cli::Lexer ( cli::CharSequence ( cli::StringLineInterface ( line ) ) ) ).parse ( )->run ( environment ); } class Foo { diff --git a/alib2integrationtest/test-src/testing/TimeoutAqlTest.cpp b/alib2integrationtest/test-src/testing/TimeoutAqlTest.cpp index dd487e298cc19da8a4edfaef1f3f2ce51b91e4e4..35ee0666e3d32f8f9d2760d6d2d39bb436c749db 100644 --- a/alib2integrationtest/test-src/testing/TimeoutAqlTest.cpp +++ b/alib2integrationtest/test-src/testing/TimeoutAqlTest.cpp @@ -56,12 +56,12 @@ int aqlTest ( int fd, const ext::vector < std::string > & queries, unsigned seed common::Streams::out = ss; common::Streams::err = ss; - cli::CharSequence sequence { cli::StringLineReader ( "set seed " + ext::to_string ( seed ) ) }; - cli::Parser ( cli::Lexer ( sequence ) ).parse ( ) -> run ( environment ); + cli::CharSequence sequence { cli::StringLineInterface ( "set seed " + ext::to_string ( seed ) ) }; + cli::Parser ( cli::Lexer ( std::move ( sequence ) ) ).parse ( ) -> run ( environment ); for ( const std::string & q : queries ) { - cli::CharSequence querySequence { cli::StringLineReader ( q ) }; - cli::Parser ( cli::Lexer ( querySequence ) ).parse ( ) -> run ( environment ); + cli::CharSequence querySequence { cli::StringLineInterface ( q ) }; + cli::Parser ( cli::Lexer ( std::move ( querySequence ) ) ).parse ( ) -> run ( environment ); if ( write ( fd, ss.str ( ).c_str ( ), ss.str ( ).length ( ) ) != ( ssize_t ) ss.str ( ).length ( ) ) throw std::runtime_error ( "TimeoutAqlTest: child output write() failure (child to parent communication)" ); diff --git a/aql2/src/aql.cpp b/aql2/src/aql.cpp index fd27edbfd4bc10211213968c0f42adfef5c96462..8006b1c9474221b3a5c2e4bb8ee754b433de12f0 100644 --- a/aql2/src/aql.cpp +++ b/aql2/src/aql.cpp @@ -38,10 +38,10 @@ std::istream& operator>> ( std::istream & in, std::pair < T, U > & value ) { #include <global/GlobalData.h> #include "prompt/Prompt.h" -#include "prompt/ReadlineLineReader.h" +#include "prompt/ReadlineLineInterface.h" -#include <readline/IstreamLineReader.h> -#include <readline/StringLineReader.h> +#include <readline/IstreamLineInterface.h> +#include <readline/StringLineInterface.h> namespace TCLAP { @@ -55,7 +55,7 @@ struct ArgTraits < std::pair < T, U > > { class InteractiveVisitor : public TCLAP::Visitor { public: void visit ( ) override { - Prompt::getPrompt ( ).appendCharSequence ( ReadlineLineReader ( ), true ); + Prompt::getPrompt ( ).appendCharSequence ( ReadlineLineInterface ( true ) ); } }; @@ -72,7 +72,7 @@ public: if ( ! ifs.is_open ( ) ) throw exception::CommonException ( "File '" + m_arg->getValue ( ).back ( ) + "' not found." ); - Prompt::getPrompt ( ).appendCharSequence ( cli::IstreamLineReader < std::ifstream > ( std::move ( ifs ) ), false ); + Prompt::getPrompt ( ).appendCharSequence ( cli::IstreamLineInterface < std::ifstream > ( std::move ( ifs ) ) ); } }; @@ -84,7 +84,7 @@ public: } void visit ( ) override { - Prompt::getPrompt ( ).appendCharSequence ( cli::StringLineReader ( m_arg->getValue ( ).back ( ) ), false ); + Prompt::getPrompt ( ).appendCharSequence ( cli::StringLineInterface ( m_arg->getValue ( ).back ( ) ) ); } }; @@ -93,7 +93,10 @@ int main ( int argc, char * argv[] ) { exceptions.push_back ( exception.error ( ) ); } ); + ReadlinePromptHistory historyHandler ( std::string ( std::getenv ( "HOME" ) ) + "/.aql_history" ); + try { + common::GlobalData::argc = argc; common::GlobalData::argv = argv; @@ -141,10 +144,10 @@ int main ( int argc, char * argv[] ) { // if no -f, -c, or -i, go interactive. if ( ! queries.isSet ( ) && ! files.isSet ( ) && ! interactive.isSet ( ) ) { - Prompt::getPrompt ( ).appendCharSequence ( ReadlineLineReader ( ), true ); + Prompt::getPrompt ( ).appendCharSequence ( ReadlineLineInterface ( true ) ); } - cli::Command::Result res = Prompt::getPrompt ( ).run ( ); + cli::CommandResult res = Prompt::getPrompt ( ).run ( ); /* --------------------------------------------------------------------------------------------------------- */ @@ -155,9 +158,9 @@ int main ( int argc, char * argv[] ) { /* --------------------------------------------------------------------------------------------------------- */ - if ( res == cli::Command::Result::QUIT ) + if ( res == cli::CommandResult::QUIT ) return Prompt::getPrompt ( ).getEnvironment ( ).getResult ( ); - else if ( res == cli::Command::Result::EOT ) + else if ( res == cli::CommandResult::EOT ) return 0; else return 4; diff --git a/aql2/src/prompt/HistoryRegister.h b/aql2/src/prompt/HistoryRegister.h deleted file mode 100644 index 3864c0d06297adff9a8829f96fc0b41b6af31cd1..0000000000000000000000000000000000000000 --- a/aql2/src/prompt/HistoryRegister.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * HistoryRegister.h - * - * Created on: 20. 3. 2017 - * Author: Jan Travnicek - */ - -#ifndef _HISTORY_REGISTER_H_ -#define _HISTORY_REGISTER_H_ - -#include "ReadlinePromptHistory.h" - -#include <lexer/Lexer.h> - -class HistoryRegister { - const cli::Lexer & m_lexer; - bool m_allowHistory; - -public: - HistoryRegister ( const cli::Lexer & lexer, bool allowHistory ) : m_lexer ( lexer ), m_allowHistory ( allowHistory ) { - } - - ~HistoryRegister ( ) { - if ( m_allowHistory ) { - std::string line = m_lexer.getLine ( ); - ReadlinePromptHistory::addHistory ( ( std::string ) ext::trim ( line ) ); - } - } -}; - -#endif /* _HISTORY_REGISTER_H_ */ diff --git a/aql2/src/prompt/Prompt.cpp b/aql2/src/prompt/Prompt.cpp index 8d04b5a9d49f1d23b6441e885285f2eed2f74e93..926b13a4f139189f6c3c467a20de757ad671cd3c 100644 --- a/aql2/src/prompt/Prompt.cpp +++ b/aql2/src/prompt/Prompt.cpp @@ -6,62 +6,20 @@ */ #include "Prompt.h" -#include "ReadlinePromptCompletion.h" -#include "ReadlinePromptHistory.h" -#include <lexer/Lexer.h> -#include <parser/Parser.h> - -#include "HistoryRegister.h" - -#include <alib/exception> - -#include <global/GlobalData.h> - -Prompt::Prompt ( cli::Environment environment ) : m_history_file ( std::string ( std::getenv ( "HOME" ) ) + "/.aql_history" ), m_environment ( std::move ( environment ) ) { - ReadlinePromptHistory::readHistory ( m_history_file ); +Prompt::Prompt ( cli::Environment environment ) : m_environment ( std::move ( environment ) ) { } -Prompt::~Prompt ( ) { - ReadlinePromptHistory::writeHistory ( m_history_file ); -} - -void Prompt::appendCharSequence ( cli::CharSequence && charSequence, bool allowHistory ) { - m_charSequences.push_back ( std::make_pair ( std::move ( charSequence ), allowHistory ) ); -} +cli::CommandResult Prompt::run ( ) { + while ( ! m_lineInterfaces.empty ( ) ) { -void Prompt::prependCharSequence ( cli::CharSequence && charSequence, bool allowHistory ) { - m_charSequences.push_front ( std::make_pair ( std::move ( charSequence ), allowHistory ) ); -} + cli::CommandResult state = getEnvironment ( ).execute ( m_lineInterfaces.front ( ) ); -cli::Command::Result Prompt::run ( ) { - cli::Command::Result state = cli::Command::Result::OK; - - while ( ! m_charSequences.empty ( ) ) { - - while ( state == cli::Command::Result::OK || state == cli::Command::Result::ERROR || state == cli::Command::Result::EXCEPTION ) { - state = execute_line ( m_charSequences.front ( ).first, m_charSequences.front ( ).second ); - m_charSequences.front ( ).first.reset ( ); - } - - if ( state == cli::Command::Result::QUIT ) + if ( state == cli::CommandResult::QUIT ) return state; - state = cli::Command::Result::OK; - - m_charSequences.pop_front ( ); + m_lineInterfaces.pop_front ( ); } - return state; -} - -cli::Command::Result Prompt::execute_line ( cli::CharSequence & charSequence, bool allowHistory ) { - try { - cli::Parser parser = cli::Parser ( cli::Lexer ( charSequence ) ); - HistoryRegister historyRegister ( parser.getLexer ( ), allowHistory ); - return parser.parse ( )->run ( m_environment ); - } catch ( ... ) { - alib::ExceptionHandler::handle ( common::Streams::err ); - return cli::Command::Result::EXCEPTION; - } + return cli::CommandResult::OK; } diff --git a/aql2/src/prompt/Prompt.h b/aql2/src/prompt/Prompt.h index c3e28471c7c6332fbd7546f0111bfd42cde45082..3e709d8bf0641ea34a306c29fe7dc691585d8fcc 100644 --- a/aql2/src/prompt/Prompt.h +++ b/aql2/src/prompt/Prompt.h @@ -11,14 +11,11 @@ #include <string> #include <deque> -#include <command/Command.h> #include <environment/Environment.h> #include <lexer/CharSequence.h> class Prompt { - std::deque < std::pair < cli::CharSequence, bool > > m_charSequences; - - std::string m_history_file; + std::deque < std::shared_ptr < cli::LineInterface > > m_lineInterfaces; cli::Environment m_environment; @@ -33,28 +30,26 @@ public: Prompt & operator = ( Prompt && ) = delete; - ~Prompt ( ); - static Prompt & getPrompt ( ) { static Prompt instance { cli::Environment ( ) }; return instance; } - void appendCharSequence ( cli::CharSequence && charSequence, bool allowHistory ); - - void prependCharSequence ( cli::CharSequence && charSequence, bool allowHistory ); + template < class LineInterface > + void appendCharSequence ( LineInterface && lineInterface ) { + m_lineInterfaces.push_back ( std::make_shared < LineInterface > ( std::forward < LineInterface > ( lineInterface ) ) ); + } - cli::Command::Result run ( ); + template < class LineInterface > + void prependCharSequence ( LineInterface && lineInterface ) { + m_lineInterfaces.push_front ( std::make_shared < LineInterface > ( std::forward < LineInterface > ( lineInterface ) ) ); + } - cli::Command::Result execute_line ( cli::CharSequence & charSequence, bool allowHistory ); + cli::CommandResult run ( ); cli::Environment & getEnvironment ( ) { return m_environment; } - - const std::string & getHistoryFile ( ) const { - return m_history_file; - } }; #endif /* _AQL_PROMPT_H_ */ diff --git a/aql2/src/prompt/ReadlineLineInterface.h b/aql2/src/prompt/ReadlineLineInterface.h new file mode 100644 index 0000000000000000000000000000000000000000..bc4066d4b7b369e92ee3a27a3157ac5b866d23bb --- /dev/null +++ b/aql2/src/prompt/ReadlineLineInterface.h @@ -0,0 +1,43 @@ +/* + * ReadlineLineInterface.h + * + * Created on: 20. 3. 2017 + * Author: Jan Travnicek + */ + +#ifndef _READLINE_LINE_INTERFACE_H_ +#define _READLINE_LINE_INTERFACE_H_ + +#include <cctype> +#include <string> + +#include <readline/readline.h> + +#include "ReadlinePromptHistory.h" + +class ReadlineLineInterface final : public cli::LineInterface { + bool m_allowHistory; + + bool readline ( std::string & line, bool first ) override { + char * read = ::readline ( first ? "> ": "+ " ); + if ( read == nullptr ) { + std::cout << std::endl; + return false; + } + + line = read; + free ( read ); + + return true; + } + + void lineCallback ( const std::string & line ) const override { + if ( m_allowHistory ) + ReadlinePromptHistory::addHistory ( ( std::string ) ext::trim ( line ) ); + } +public: + ReadlineLineInterface ( bool allowHistory ) : m_allowHistory ( allowHistory ) { + } +}; + +#endif /* _READLINE_LINE_INTERFACE_H_ */ diff --git a/aql2/src/prompt/ReadlineLineReader.h b/aql2/src/prompt/ReadlineLineReader.h deleted file mode 100644 index 9359bf07118fb093c2ae1346fbc836631f07ee3c..0000000000000000000000000000000000000000 --- a/aql2/src/prompt/ReadlineLineReader.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * ReadlineLineReader.h - * - * Created on: 20. 3. 2017 - * Author: Jan Travnicek - */ - -#ifndef _READLINE_LINE_READER_H_ -#define _READLINE_LINE_READER_H_ - -#include <cctype> -#include <string> - -#include <readline/readline.h> - -class ReadlineLineReader final : public cli::LineReader { - bool first = true; - - bool readline ( std::string & line ) override { - char * read = ::readline ( first ? "> ": "+ " ); - if ( read == nullptr ) { - return false; - } - - line = read; - free ( read ); - - if ( ! std::all_of ( line.begin ( ), line.end ( ), isspace ) ) - first = false; - - return true; - } - - void reset ( ) override { - first = true; - } -}; - -#endif /* _READLINE_LINE_READER_H_ */ diff --git a/aql2/src/prompt/ReadlinePromptHistory.h b/aql2/src/prompt/ReadlinePromptHistory.h index fd7533488d8f5a5780a5a3b8e148e38bcd636bd1..e0a1db9fa7d8db6b6a998a0ee19e469758dfc948 100644 --- a/aql2/src/prompt/ReadlinePromptHistory.h +++ b/aql2/src/prompt/ReadlinePromptHistory.h @@ -8,9 +8,7 @@ #ifndef _READLINE_PROMPT_HISTORY_H #define _READLINE_PROMPT_HISTORY_H -#include <string.h> -#include <stdio.h> - +#include <cstring> #include <alib/string> #include <readline/history.h> @@ -77,7 +75,25 @@ class ReadlinePromptHistory { } } + std::string m_history_file; + public: + ReadlinePromptHistory ( std::string history_file ) : m_history_file ( std::move ( history_file ) ) { + ReadlinePromptHistory::readHistory ( m_history_file ); + } + + ReadlinePromptHistory ( const ReadlinePromptHistory & ) = delete; + + ReadlinePromptHistory ( ReadlinePromptHistory && ) = delete; + + ReadlinePromptHistory & operator = ( const ReadlinePromptHistory & ) = delete; + + ReadlinePromptHistory & operator = ( ReadlinePromptHistory && ) = delete; + + ~ ReadlinePromptHistory ( ) { + ReadlinePromptHistory::writeHistory ( m_history_file ); + } + static void readHistory ( const std::string & history_file ) { read_history ( history_file.c_str ( ) ); ReadlinePromptHistory::history_transform ( ReadlinePromptHistory::descape );