From f43ca02e9b7368a8da58c03d2f1166794c099abf Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Thu, 20 Jul 2017 14:33:08 +0200 Subject: [PATCH] attempt to use readline --- .gitlab-ci.yml | 2 +- aql2/makefile.conf | 2 +- aql2/src/aql.cpp | 22 ++++++++----- aql2/src/prompt/Prompt.cpp | 65 ++++++++++++++++++++++++++++++++++++++ aql2/src/prompt/Prompt.h | 35 ++++++++++++++++++++ 5 files changed, 116 insertions(+), 10 deletions(-) create mode 100644 aql2/src/prompt/Prompt.cpp create mode 100644 aql2/src/prompt/Prompt.h diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e6af150cbf..c53d6f5ad1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,7 +14,7 @@ before_script: esac - export JOBS=$(grep -c processor /proc/cpuinfo) - apk add --no-cache build-base bash libexecinfo-dev - cppunit-dev libxml2-dev tclap-dev $EXTRA_PKGS + cppunit-dev libxml2-dev tclap-dev readline-dev $EXTRA_PKGS - case "$CI_BUILD_NAME" in *-clang) ln -s /usr/lib/llvm4/lib/LLVMgold.so /usr/lib/LLVMgold.so;; *) ;; diff --git a/aql2/makefile.conf b/aql2/makefile.conf index 4556c5f00d..29eb6afc94 100644 --- a/aql2/makefile.conf +++ b/aql2/makefile.conf @@ -1,4 +1,4 @@ EXECUTABLE:=aql2 LINK_PATHS=../alib2cli/ ../alib2elgo/ ../alib2algo/ ../alib2raw/ ../alib2str/ ../alib2data/ ../alib2common/ ../alib2std/ -LINK_LIBRARIES=alib2cli alib2elgo alib2algo alib2raw alib2str alib2data alib2common alib2std xml2 +LINK_LIBRARIES=alib2cli alib2elgo alib2algo alib2raw alib2str alib2data alib2common alib2std xml2 readline INCLUDE_PATHS=\$$(SOURCES_BASE_DIR)/../../alib2cli/src/ \$$(SOURCES_BASE_DIR)/../../alib2data/src/ \$$(SOURCES_BASE_DIR)/../../alib2common/src/ \$$(SOURCES_BASE_DIR)/../../alib2std/src/ /usr/include/libxml2/ diff --git a/aql2/src/aql.cpp b/aql2/src/aql.cpp index e899dc4506..cdfe7d1dec 100644 --- a/aql2/src/aql.cpp +++ b/aql2/src/aql.cpp @@ -1,11 +1,10 @@ /* * aql.cpp * - * Created on: 26. 3. 2014 + * Created on: 1. 7. 2017 * Author: Jan Travnicek */ -#include <measure> #include <istream> #include <iostream> @@ -27,11 +26,13 @@ std::istream& operator>> ( std::istream & in, std::pair < T, U > & value ) { return in; } +#include <string> + +#include <measure> #include <tclap/CmdLine.h> #include <global/GlobalData.h> -#include <lexer/Lexer.h> -#include <parser/Parser.h> +#include "prompt/Prompt.h" namespace TCLAP { @@ -50,7 +51,7 @@ int main ( int argc, char * argv[] ) { TCLAP::CmdLine cmd ( "Algorithms query language binary", ' ', "0.01" ); - TCLAP::ValueArg < std::string > query ( "q", "query", "Query index", true, "", "query" ); + TCLAP::ValueArg < std::string > query ( "q", "query", "Query index", false, "", "query" ); cmd.add ( query ); TCLAP::SwitchArg measure ( "m", "measure", "Measure times", false ); @@ -79,15 +80,20 @@ int main ( int argc, char * argv[] ) { environment.set ( param.first, param.second ); } - cli::Parser parser ( cli::Lexer ( query.getValue ( ) ) ); - parser.execute ( )->translateAndEval ( nullptr, environment ); + Prompt p ( std::move ( environment ) ); + + int result = 0; + if ( query.isSet ( ) ) + result = p.execute_line ( query.getValue ( ) ); + else + result = p.run ( ); measurements::end ( ); if ( measure.getValue ( ) ) std::cmeasure << measurements::results ( ) << std::endl; - return 0; + return result; } catch ( const exception::CommonException & exception ) { alib::XmlDataFactory::toStdout ( exception ); return 1; diff --git a/aql2/src/prompt/Prompt.cpp b/aql2/src/prompt/Prompt.cpp new file mode 100644 index 0000000000..8d98c9c6ae --- /dev/null +++ b/aql2/src/prompt/Prompt.cpp @@ -0,0 +1,65 @@ +/* + * Prompt.cpp + * + * Created on: 20. 7. 2017 + * Author: Jan Travnicek + */ + +#include "Prompt.h" + +#include <cstdlib> +#include <cctype> +#include <cstring> + +#include <readline/readline.h> +#include <readline/history.h> + +#include <lexer/Lexer.h> +#include <parser/Parser.h> + +char * Prompt::stripwhite ( char * begin ) { + while ( isspace ( * begin ) ) + ++ begin; + + char * end = begin + strlen ( begin ) - 1; + while ( end >= begin && isspace ( * end ) ) + -- end; + + if ( end >= begin ) + * ++ end = '\0'; + + return begin; +} + +Prompt::Prompt ( cli::Environment environment ) : m_prefix ( "> " ), m_active ( true ), m_exec_result ( 0 ), m_environment ( std::move ( environment ) ) { +} + +int Prompt::run ( ) { + while ( m_active ) { + char * line = readline ( m_prefix.c_str ( ) ); + + if ( ! line ) + continue; + + char * s = stripwhite ( line ); + + if ( * s ) { + add_history ( s ); + execute_line ( std::string ( s ) ); + } + + free ( line ); + } + return m_exec_result; +} + +int Prompt::execute_line ( std::string line ) { + if ( line == "quit" ) { + m_active = false; + m_exec_result = 0; + } else { + cli::Parser parser = cli::Parser ( cli::Lexer ( line ) ); + parser.execute ( )->translateAndEval ( nullptr, m_environment ); + } + return m_exec_result; +} diff --git a/aql2/src/prompt/Prompt.h b/aql2/src/prompt/Prompt.h new file mode 100644 index 0000000000..db0341300c --- /dev/null +++ b/aql2/src/prompt/Prompt.h @@ -0,0 +1,35 @@ +/* + * Prompt.h + * + * Created on: 20. 3. 2017 + * Author: Jan Travnicek + */ + +#ifndef _AQL_PROMPT_H_ +#define _AQL_PROMPT_H_ + +#include <string> +#include <parser/Parser.h> + +class Prompt { + Prompt ( const Prompt & ) = delete; + Prompt ( Prompt && ) = delete; + Prompt & operator = ( const Prompt & ) = delete; + Prompt & operator = ( Prompt && ) = delete; + + std::string m_prefix; + bool m_active; + int m_exec_result; + + cli::Environment m_environment; + + char * stripwhite ( char * begin ); + +public: + Prompt ( cli::Environment environment ); + + int run ( ); + int execute_line ( std::string line ); +}; + +#endif /* _AQL_PROMPT_H_ */ -- GitLab