mirror of https://gitee.com/bigwinds/arangodb
added better readline support for control-C
This commit is contained in:
parent
29b03e854d
commit
3029891405
|
@ -1,6 +1,8 @@
|
|||
v2.7.0 (XXXX-XX-XX)
|
||||
-------------------
|
||||
|
||||
* added better control-C support in arangosh
|
||||
|
||||
* increased default value collection-specific `indexBuckets` value from 1 to 16
|
||||
|
||||
Collections created from 2.7 on will use the new default if not overriden on
|
||||
|
|
|
@ -711,6 +711,10 @@ void ArangoServer::buildApplicationServer () {
|
|||
// disable certain options in unittest or script mode
|
||||
OperationMode::server_operation_mode_e mode = OperationMode::determineMode(_applicationServer->programOptions());
|
||||
|
||||
if (mode == OperationMode::MODE_CONSOLE) {
|
||||
_applicationScheduler->disableControlCHandler();
|
||||
}
|
||||
|
||||
if (mode == OperationMode::MODE_SCRIPT || mode == OperationMode::MODE_UNITTESTS) {
|
||||
// testing disables authentication
|
||||
_disableAuthentication = true;
|
||||
|
|
|
@ -71,8 +71,8 @@ ConsoleThread::ConsoleThread (ApplicationServer* applicationServer,
|
|||
_vocbase(vocbase),
|
||||
_done(0),
|
||||
_userAborted(false) {
|
||||
allowAsynchronousCancelation();
|
||||
|
||||
allowAsynchronousCancelation();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -184,12 +184,6 @@ static vector<string> JsLint;
|
|||
|
||||
static uint64_t GcInterval = 10;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief console object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static triagens::V8LineEditor* Console = nullptr;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief voice mode
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1503,26 +1497,6 @@ static std::string BuildPrompt () {
|
|||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief signal handler for CTRL-C
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef _WIN32
|
||||
// TODO
|
||||
|
||||
#else
|
||||
|
||||
static void SignalHandler (int signal) {
|
||||
if (Console != nullptr) {
|
||||
Console->close();
|
||||
Console = nullptr;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
TRI_EXIT_FUNCTION(EXIT_SUCCESS, nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes the shell
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1531,25 +1505,8 @@ static void RunShell (v8::Isolate* isolate, v8::Handle<v8::Context> context, boo
|
|||
v8::Context::Scope contextScope(context);
|
||||
v8::Local<v8::String> name(TRI_V8_ASCII_STRING(TRI_V8_SHELL_COMMAND_NAME));
|
||||
|
||||
Console = new triagens::V8LineEditor(context, ".arangosh.history");
|
||||
Console->open(BaseClient.autoComplete());
|
||||
|
||||
// install signal handler for CTRL-C
|
||||
#ifdef _WIN32
|
||||
// TODO
|
||||
|
||||
#else
|
||||
struct sigaction sa;
|
||||
sa.sa_flags = 0;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_handler = &SignalHandler;
|
||||
|
||||
int res = sigaction(SIGINT, &sa, 0);
|
||||
|
||||
if (res != 0) {
|
||||
LOG_ERROR("unable to install signal handler");
|
||||
}
|
||||
#endif
|
||||
triagens::V8LineEditor console(context, ".arangosh.history");
|
||||
console.open(BaseClient.autoComplete());
|
||||
|
||||
uint64_t nrCommands = 0;
|
||||
|
||||
|
@ -1573,17 +1530,7 @@ static void RunShell (v8::Isolate* isolate, v8::Handle<v8::Context> context, boo
|
|||
string badPrompt;
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
// ........................................................................................
|
||||
// MacOS uses libedit, which does not support ignoring of non-printable characters in the prompt
|
||||
// using non-printable characters in the prompt will lead to wrong prompt lengths being calculated
|
||||
// we will therefore disable colorful prompts for MacOS.
|
||||
// ........................................................................................
|
||||
|
||||
goodPrompt = badPrompt = dynamicPrompt;
|
||||
|
||||
#elif _WIN32
|
||||
#if _WIN32
|
||||
|
||||
// ........................................................................................
|
||||
// Windows console is not coloured by escape sequences. So the method given below will not
|
||||
|
@ -1637,7 +1584,7 @@ static void RunShell (v8::Isolate* isolate, v8::Handle<v8::Context> context, boo
|
|||
}
|
||||
#endif
|
||||
|
||||
char* input = Console->prompt(promptError ? badPrompt.c_str() : goodPrompt.c_str());
|
||||
char* input = console.prompt(promptError ? badPrompt.c_str() : goodPrompt.c_str());
|
||||
|
||||
if (input == nullptr) {
|
||||
break;
|
||||
|
@ -1666,7 +1613,7 @@ static void RunShell (v8::Isolate* isolate, v8::Handle<v8::Context> context, boo
|
|||
}
|
||||
}
|
||||
|
||||
Console->addHistory(input);
|
||||
console.addHistory(input);
|
||||
|
||||
v8::TryCatch tryCatch;
|
||||
|
||||
|
@ -1712,10 +1659,6 @@ static void RunShell (v8::Isolate* isolate, v8::Handle<v8::Context> context, boo
|
|||
}
|
||||
#endif
|
||||
|
||||
Console->close();
|
||||
delete Console;
|
||||
Console = nullptr;
|
||||
|
||||
BaseClient.printLine("");
|
||||
|
||||
BaseClient.printByeBye();
|
||||
|
|
160
configure.ac
160
configure.ac
|
@ -206,7 +206,165 @@ dnl ----------------------------------------------------------------------------
|
|||
dnl READLINE
|
||||
dnl ----------------------------------------------------------------------------
|
||||
|
||||
m4_include([m4/external.readline])
|
||||
AC_MSG_NOTICE([--------------------------------------------------------------------------------])
|
||||
AC_MSG_NOTICE([CHECKING FOR READLINE])
|
||||
AC_MSG_NOTICE([--------------------------------------------------------------------------------])
|
||||
|
||||
AC_LANG(C)
|
||||
|
||||
AC_ARG_ENABLE(readline,
|
||||
AS_HELP_STRING([--enable-readline], [enable readline support (default: yes)]),
|
||||
tr_READLINE="$enableval",
|
||||
tr_READLINE="maybe"
|
||||
)
|
||||
|
||||
if test "x$tr_DARWIN" = xyes; then
|
||||
READLINE=/usr/local/opt/readline
|
||||
READLINE_CPPFLAGS="-I$READLINE/include"
|
||||
READLINE_LDFLAGS="-L$READLINE/lib"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(readline,
|
||||
AS_HELP_STRING([--with-readline=DIR], [where the readline library and includes are located]),
|
||||
[READLINE_CPPFLAGS="-I$withval/include"
|
||||
READLINE_LDFLAGS="-L$withval/lib"
|
||||
READLINE="$withval"]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(readline-lib,
|
||||
AS_HELP_STRING([--with-readline-lib=DIR], [where the readline library is located]),
|
||||
[READLINE_LDFLAGS="-L$withval"]
|
||||
)
|
||||
|
||||
dnl checks for the READLINE library
|
||||
|
||||
if test "x$READLINE_CPPFLAGS" != x; then
|
||||
TR_INCLUDE([READLINE_CPPFLAGS])
|
||||
fi
|
||||
|
||||
dnl save flags
|
||||
|
||||
SAVE_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $READLINE_CPPFLAGS"
|
||||
|
||||
SAVE_LDFLAGS="$LDFLAGS"
|
||||
LDFLAGS="$LDFLAGS $READLINE_LDFLAGS"
|
||||
|
||||
SAVE_LIBS="$LIBS"
|
||||
|
||||
dnl check for header and library
|
||||
|
||||
if test "x$tr_READLINE" = xyes -o "x$tr_READLINE" = xmaybe; then
|
||||
ch_READLINE="$tr_READLINE"
|
||||
|
||||
AC_CHECK_HEADERS(readline/readline.h, [tr_READLINE="yes"], [tr_READLINE="no"])
|
||||
|
||||
if test "x$tr_READLINE" = xyes; then
|
||||
AC_CHECK_LIB([readline], [readline], [READLINE_LIBS="-lreadline" tr_READLINE="yes"], [tr_READLINE="no"])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([READLINE support])
|
||||
|
||||
if test "x$tr_READLINE" != xyes; then
|
||||
AC_MSG_RESULT([not found])
|
||||
|
||||
if test "x$ch_READLINE" = xyes; then
|
||||
AC_MSG_ERROR([Please install readline support])
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT([readline])
|
||||
fi
|
||||
else
|
||||
AC_MSG_CHECKING([READLINE support])
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
|
||||
dnl grep readline version number
|
||||
|
||||
if test "x$tr_READLINE" = xyes; then
|
||||
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <readline/readline.h>
|
||||
|
||||
main () {
|
||||
#if defined(RL_VERSION_MAJOR) && defined(RL_VERSION_MINOR)
|
||||
long sdnhg36ed = RL_VERSION_MAJOR RL_VERSION_MINOR ;
|
||||
#else
|
||||
long sdnhg36ed = RL_READLINE_VERSION hex ;
|
||||
#endif
|
||||
}
|
||||
|
||||
_ACEOF
|
||||
|
||||
AC_MSG_CHECKING([READLINE version])
|
||||
eval "$ac_cpp conftest.$ac_ext" | fgrep "long sdnhg36ed" | awk '{print $4 "." $5}' > conftest.output
|
||||
READLINE_VERSION=`cat conftest.output`
|
||||
|
||||
if test -z "$READLINE_VERSION"; then
|
||||
AC_MSG_ERROR([Readline support is not working. Please re-install readline support])
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT([$READLINE_VERSION])
|
||||
rm -f conftest*
|
||||
|
||||
if test "x$tr_DARWIN" = xyes; then
|
||||
case "$READLINE_VERSION" in
|
||||
6.*|5.*)
|
||||
;;
|
||||
|
||||
*)
|
||||
AC_MSG_ERROR([Please install readline 6 from brew. If you have a non-standard brew location, use "--with-readline".])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl restore flags and set readline flags
|
||||
|
||||
LIBS="$SAVE_LIBS"
|
||||
LDFLAGS="$SAVE_LDFLAGS"
|
||||
CPPFLAGS="$SAVE_CPPFLAGS"
|
||||
|
||||
if test "x$tr_READLINE" = xyes; then
|
||||
CPPFLAGS="$CPPFLAGS -DHAVE_READLINE=1"
|
||||
READLINE_CPPFLAGS="${READLINE_CPPFLAGS} -DTRI_READLINE_VERSION='\"${READLINE_VERSION}\"'"
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(ENABLE_READLINE, test "x$tr_READLINE" = xyes)
|
||||
|
||||
if test "x$tr_READLINE" = xyes; then
|
||||
AC_DEFINE_UNQUOTED(TRI_HAVE_READLINE, 1, [true if readline is used])
|
||||
fi
|
||||
|
||||
dnl add substitutions
|
||||
|
||||
AC_SUBST(READLINE_VERSION)
|
||||
AC_SUBST(READLINE_CPPFLAGS)
|
||||
AC_SUBST(READLINE_LDFLAGS)
|
||||
AC_SUBST(READLINE_LIBS)
|
||||
|
||||
dnl informational output
|
||||
|
||||
if test "x$tr_READLINE" = xyes; then
|
||||
LIB_INFO="$LIB_INFO|READLINE VERSION: ${READLINE_VERSION}"
|
||||
|
||||
LIB_INFO="$LIB_INFO|READLINE_CPPFLAGS: ${READLINE_CPPFLAGS}"
|
||||
LIB_INFO="$LIB_INFO|READLINE_LDLIBS: ${READLINE_LDLIBS}"
|
||||
LIB_INFO="$LIB_INFO|READLINE_LIBS: ${READLINE_LIBS}"
|
||||
|
||||
elif test "x$tr_READLINE" = xlinenoise; then
|
||||
LIB_INFO="$LIB_INFO|LINENOISE VERSION: ${READLINE_VERSION}"
|
||||
|
||||
LIB_INFO="$LIB_INFO|LINENOISE_CPPFLAGS: ${READLINE_CPPFLAGS}"
|
||||
LIB_INFO="$LIB_INFO|LINENOISE_LDLIBS: ${READLINE_LDLIBS}"
|
||||
LIB_INFO="$LIB_INFO|LINENOISE_LIBS: ${READLINE_LIBS}"
|
||||
|
||||
else
|
||||
LIB_INFO="$LIB_INFO|READLINE VERSION: disabled"
|
||||
fi
|
||||
|
||||
LIB_INFO="$LIB_INFO|."
|
||||
|
||||
dnl ----------------------------------------------------------------------------
|
||||
dnl OPENSSL
|
||||
|
|
|
@ -104,20 +104,11 @@ if ENABLE_READLINE
|
|||
lib_libarango_a_SOURCES += \
|
||||
lib/Utilities/ReadlineShell.cpp
|
||||
|
||||
else
|
||||
if ENABLE_LINENOISE
|
||||
|
||||
lib_libarango_a_SOURCES += \
|
||||
lib/Utilities/LinenoiseShell.cpp \
|
||||
3rdParty/linenoise/linenoise.c \
|
||||
3rdParty/linenoise/utf8.c
|
||||
|
||||
else
|
||||
|
||||
lib_libarango_a_SOURCES += \
|
||||
lib/Utilities/DummyShell.cpp
|
||||
endif
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
### @brief library "libarango.a", client part
|
||||
|
|
|
@ -341,7 +341,8 @@ ApplicationScheduler::ApplicationScheduler (ApplicationServer* applicationServer
|
|||
_multiSchedulerAllowed(true),
|
||||
_nrSchedulerThreads(4),
|
||||
_backend(0),
|
||||
_descriptorMinimum(256) {
|
||||
_descriptorMinimum(256),
|
||||
_disableControlCHandler(false) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -416,6 +417,14 @@ void ApplicationScheduler::setProcessorAffinity (const vector<size_t>& cores) {
|
|||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief disables CTRL-C handling (because taken over by console input)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ApplicationScheduler::disableControlCHandler () {
|
||||
_disableControlCHandler = true;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- ApplicationFeature methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -557,9 +566,7 @@ void ApplicationScheduler::stop () {
|
|||
static size_t const MAX_TRIES = 10;
|
||||
|
||||
// remove all helper tasks
|
||||
for (vector<Task*>::iterator i = _tasks.begin(); i != _tasks.end(); ++i) {
|
||||
Task* task = *i;
|
||||
|
||||
for (auto& task : _tasks) {
|
||||
_scheduler->destroyTask(task);
|
||||
}
|
||||
|
||||
|
@ -610,7 +617,7 @@ void ApplicationScheduler::buildSchedulerReporter () {
|
|||
Task* reporter = new SchedulerReporterTask(_scheduler, _reportInterval);
|
||||
|
||||
_scheduler->registerTask(reporter);
|
||||
_tasks.push_back(reporter);
|
||||
_tasks.emplace_back(reporter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -623,23 +630,25 @@ void ApplicationScheduler::buildControlCHandler () {
|
|||
LOG_FATAL_AND_EXIT("no scheduler is known, cannot create control-c handler");
|
||||
}
|
||||
|
||||
if (! _disableControlCHandler) {
|
||||
// control C handler
|
||||
Task* controlC = new ControlCTask(_applicationServer);
|
||||
|
||||
_scheduler->registerTask(controlC);
|
||||
_tasks.push_back(controlC);
|
||||
_tasks.emplace_back(controlC);
|
||||
}
|
||||
|
||||
// hangup handler
|
||||
Task* hangup = new HangupTask();
|
||||
|
||||
_scheduler->registerTask(hangup);
|
||||
_tasks.push_back(hangup);
|
||||
_tasks.emplace_back(hangup);
|
||||
|
||||
// sigusr handler
|
||||
Task* sigusr = new Sigusr1Task(this);
|
||||
|
||||
_scheduler->registerTask(sigusr);
|
||||
_tasks.push_back(sigusr);
|
||||
_tasks.emplace_back(sigusr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -112,6 +112,12 @@ namespace triagens {
|
|||
|
||||
void setProcessorAffinity (const std::vector<size_t>& cores);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief disables CTRL-C handling (because taken over by console input)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void disableControlCHandler ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- ApplicationFeature methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -257,6 +263,12 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
uint32_t _descriptorMinimum;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief disables CTRL-C handling (because taken over by console input)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool _disableControlCHandler;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,10 +28,8 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "LineEditor.h"
|
||||
#include "ShellImplementation.h"
|
||||
#include "Completer.h"
|
||||
|
||||
#include "Basics/tri-strings.h"
|
||||
#include "Utilities/ShellImplementation.h"
|
||||
#include "Utilities/Completer.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace triagens;
|
||||
|
@ -50,7 +48,7 @@ using namespace triagens;
|
|||
|
||||
LineEditor::LineEditor (std::string const& history)
|
||||
: _history(history) {
|
||||
_shellImpl = 0;
|
||||
_shellImpl = nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -121,6 +119,14 @@ bool LineEditor::writeHistory () {
|
|||
return _shellImpl->writeHistory();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief send a signal to the shell implementation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void LineEditor::signal () {
|
||||
_shellImpl->signal();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief sort the alternatives results vector
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief line editor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace triagens {
|
||||
class ShellImplementation;
|
||||
|
||||
|
@ -48,9 +49,9 @@ namespace triagens {
|
|||
LineEditor(LineEditor const&);
|
||||
LineEditor& operator= (LineEditor const&);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public constants
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public constants
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
|
@ -60,9 +61,9 @@ namespace triagens {
|
|||
|
||||
static const int MAX_HISTORY_ENTRIES = 1000;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
|
@ -78,9 +79,9 @@ namespace triagens {
|
|||
|
||||
virtual ~LineEditor ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public methods
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
|
@ -123,19 +124,21 @@ namespace triagens {
|
|||
|
||||
bool writeHistory ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief send a signal to the shell implementation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void signal ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief sort the alternatives results vector
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void sortAlternatives (std::vector<std::string>&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- protected methods
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- protected methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -151,15 +154,16 @@ namespace triagens {
|
|||
|
||||
virtual void initializeShell () = 0;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- protected variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
protected:
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- protected variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
ShellImplementation * _shellImpl;
|
||||
ShellImplementation* _shellImpl;
|
||||
|
||||
std::string _history;
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -27,19 +27,13 @@
|
|||
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "ReadlineShell.h"
|
||||
#include "Basics/tri-strings.h"
|
||||
#include "Utilities/Completer.h"
|
||||
#include "Utilities/LineEditor.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
#include "Basics/tri-strings.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <v8.h>
|
||||
|
||||
using namespace std;
|
||||
|
@ -97,17 +91,76 @@ namespace {
|
|||
// --SECTION-- class ReadlineShell
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief callback function that readline calls periodically while waiting
|
||||
/// for input and being idle
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int ReadlineIdle () {
|
||||
auto instance = ReadlineShell::instance();
|
||||
|
||||
if (instance != nullptr &&
|
||||
instance->getLoopState() == 2) {
|
||||
rl_done = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief callback function that readline calls when the input is completed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void ReadlineInputCompleted (char* value) {
|
||||
// if we don't clear the prompt here, readline will display it instantly
|
||||
// the user pressed the return key. this is not desired because when we
|
||||
// wait for input afterwards, readline will display the prompt again
|
||||
rl_set_prompt("");
|
||||
|
||||
auto instance = ReadlineShell::instance();
|
||||
|
||||
if (instance == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (instance->getLoopState() == 2) {
|
||||
// CTRL-C received
|
||||
rl_done = 1;
|
||||
// replace current input with nothing
|
||||
rl_replace_line("", 0);
|
||||
|
||||
if (value != nullptr) {
|
||||
// avoid memleak
|
||||
TRI_SystemFree(value);
|
||||
}
|
||||
instance->setLastInput(nullptr);
|
||||
}
|
||||
else {
|
||||
instance->setLoopState(1);
|
||||
instance->setLastInput(value);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief (sole) instance of a ReadlineShell
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::atomic<ReadlineShell*> ReadlineShell::_instance(nullptr);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief constructs a new editor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ReadlineShell::ReadlineShell (std::string const& history,
|
||||
Completer* completer)
|
||||
: ShellImplementation(history, completer) {
|
||||
: ShellImplementation(history, completer),
|
||||
_loopState(0),
|
||||
_lastInput(nullptr),
|
||||
_lastInputWasEmpty(false) {
|
||||
|
||||
COMPLETER = completer;
|
||||
|
||||
|
@ -116,11 +169,19 @@ ReadlineShell::ReadlineShell (std::string const& history,
|
|||
rl_attempted_completion_function = AttemptedCompletion;
|
||||
rl_completer_word_break_characters = WordBreakCharacters;
|
||||
|
||||
#ifndef __APPLE__
|
||||
rl_catch_signals = 0;
|
||||
#endif
|
||||
// register ourselves
|
||||
TRI_ASSERT(_instance == nullptr);
|
||||
_instance = this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ReadlineShell::~ReadlineShell () {
|
||||
// unregister ourselves
|
||||
_instance = nullptr;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public methods
|
||||
|
@ -188,11 +249,6 @@ bool ReadlineShell::close () {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef __APPLE__
|
||||
// reset state of the terminal to what it was before readline()
|
||||
rl_cleanup_after_signal();
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -252,8 +308,46 @@ bool ReadlineShell::writeHistory () {
|
|||
return (write_history(historyPath().c_str()) == 0);
|
||||
}
|
||||
|
||||
char * ReadlineShell::getLine (char const * input) {
|
||||
return readline(input);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief read a line from the input
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* ReadlineShell::getLine (char const* prompt) {
|
||||
setLoopState(0);
|
||||
rl_event_hook = ReadlineIdle;
|
||||
rl_callback_handler_install(prompt, ReadlineInputCompleted);
|
||||
|
||||
int state;
|
||||
do {
|
||||
rl_callback_read_char();
|
||||
state = getLoopState();
|
||||
}
|
||||
while (state == 0);
|
||||
rl_callback_handler_remove();
|
||||
|
||||
if (state == 2) {
|
||||
if (_lastInputWasEmpty) {
|
||||
setLastInput(nullptr);
|
||||
}
|
||||
else {
|
||||
setLastInput(strdup(""));
|
||||
_lastInputWasEmpty = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_lastInputWasEmpty = false;
|
||||
}
|
||||
|
||||
return _lastInput;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief handle a signal
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ReadlineShell::signal () {
|
||||
// set the global state, so the readline input loop can react on it
|
||||
setLoopState(2);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -31,9 +31,8 @@
|
|||
#define ARANGODB_UTILITIES_READLINE_SHELL_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
|
||||
#include "ShellImplementation.h"
|
||||
#include "Completer.h"
|
||||
#include "Utilities/Completer.h"
|
||||
#include "Utilities/ShellImplementation.h"
|
||||
|
||||
namespace triagens {
|
||||
|
||||
|
@ -44,22 +43,29 @@ namespace triagens {
|
|||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// public constructor
|
||||
/// @brief constructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ReadlineShell (std::string const& history, Completer *);
|
||||
ReadlineShell (std::string const& history,
|
||||
Completer*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
~ReadlineShell ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief line editor open
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual bool open (bool autoComplete);
|
||||
bool open (bool autoComplete) override final;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief line editor shutdown
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual bool close ();
|
||||
bool close () override final;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the history file path
|
||||
|
@ -68,26 +74,94 @@ namespace triagens {
|
|||
/// the local file _historyFilename.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::string historyPath ();
|
||||
std::string historyPath () override final;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief add to history
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void addHistory (char const*);
|
||||
void addHistory (char const*) override final;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief save the history
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual bool writeHistory ();
|
||||
bool writeHistory () override final;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief todo!!
|
||||
/// @brief read a line from the input
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual char * getLine (char const *);
|
||||
char* getLine (char const*) override final;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief handle a signal
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void signal () override final;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the last input value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setLastInput (char* input) {
|
||||
_lastInput = input;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the current input loop state
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int getLoopState () const {
|
||||
return _loopState;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the current input loop state
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setLoopState (int state) {
|
||||
_loopState = state;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the currently active shell instance
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static ReadlineShell* instance () {
|
||||
return _instance.load();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief current state of input loop (may be affected by out-of-band signals)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::atomic<int> _loopState;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief last value entered by user. memory is allocated by readline
|
||||
/// and must be freed using TRI_SystemFree()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* _lastInput;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether or not the input from the previous invocation was a CTRL-C
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool _lastInputWasEmpty;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief system-wide instance of the ReadlineShell
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static std::atomic<ReadlineShell*> _instance;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -41,13 +41,11 @@
|
|||
#endif
|
||||
|
||||
using namespace triagens;
|
||||
using namespace std;
|
||||
|
||||
ShellImplementation* ShellImplFactory::buildShell (string const & history,
|
||||
ShellImplementation* ShellImplFactory::buildShell (std::string const& history,
|
||||
Completer* completer) {
|
||||
|
||||
#ifdef _WIN32
|
||||
//under windows the readline is not compilable
|
||||
// under Windows the readline is not compilable
|
||||
return new LinenoiseShell(history, completer);
|
||||
#elif defined TRI_HAVE_LINENOISE
|
||||
return new LinenoiseShell(history, completer);
|
||||
|
@ -57,7 +55,19 @@ ShellImplementation* ShellImplFactory::buildShell (string const & history,
|
|||
// last resort!
|
||||
return new DummyShell(history, completer);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ShellImplFactory::hasCtrlCHandler () {
|
||||
#ifdef _WIN32
|
||||
// under Windows the readline is not compilable
|
||||
return false;
|
||||
#elif defined TRI_HAVE_LINENOISE
|
||||
return false;
|
||||
#elif defined TRI_HAVE_READLINE
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -43,10 +43,16 @@ namespace triagens {
|
|||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check if line is complete
|
||||
/// @brief creates a shell
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ShellImplementation * buildShell (std::string const & history, Completer *);
|
||||
static ShellImplementation* buildShell (std::string const& history, Completer*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether or not the shell will have a CTRL-C handler
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool hasCtrlCHandler ();
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -147,6 +147,14 @@ char* ShellImplementation::prompt (char const* the_prompt) {
|
|||
return line;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief handle a signal
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ShellImplementation::signal () {
|
||||
// do nothing special
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -106,6 +106,12 @@ namespace triagens {
|
|||
|
||||
virtual char* getLine (const char*) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief handle a signal
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void signal ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- protected variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -28,16 +28,34 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "V8LineEditor.h"
|
||||
#include "Utilities/ShellImplFactory.h"
|
||||
|
||||
#include "Basics/tri-strings.h"
|
||||
#include "V8/v8-utils.h"
|
||||
|
||||
#include "Basics/logging.h"
|
||||
#include "Basics/StringUtils.h"
|
||||
#include "Basics/tri-strings.h"
|
||||
#include "Utilities/ShellImplFactory.h"
|
||||
#include "V8/v8-utils.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace triagens;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- helper functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief signal handler for CTRL-C
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WIN32
|
||||
static void SignalHandler (int signal) {
|
||||
// get the instance of the console
|
||||
auto instance = triagens::V8LineEditor::instance();
|
||||
|
||||
if (instance != nullptr) {
|
||||
instance->signal();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class V8Completer
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -306,6 +324,8 @@ void V8Completer::getAlternatives (char const * text,
|
|||
// --SECTION-- class V8LineEditor
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
std::atomic<V8LineEditor*> V8LineEditor::_instance(nullptr);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -314,8 +334,18 @@ void V8Completer::getAlternatives (char const * text,
|
|||
/// @brief constructs a new editor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
V8LineEditor::V8LineEditor (v8::Handle<v8::Context> context, std::string const& history)
|
||||
: LineEditor(history), _context(context), _completer(V8Completer()) {
|
||||
V8LineEditor::V8LineEditor (v8::Handle<v8::Context> context,
|
||||
std::string const& history)
|
||||
: LineEditor(history),
|
||||
_context(context),
|
||||
_completer(V8Completer()) {
|
||||
|
||||
// register global instance
|
||||
|
||||
TRI_ASSERT(_instance.load() == nullptr);
|
||||
_instance.store(this);
|
||||
|
||||
setupCtrlCHandler();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -323,7 +353,30 @@ V8LineEditor::V8LineEditor (v8::Handle<v8::Context> context, std::string const&
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
V8LineEditor::~V8LineEditor () {
|
||||
// nothing
|
||||
// unregister global instance
|
||||
TRI_ASSERT(_instance.load() != nullptr);
|
||||
_instance.store(nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief setup a signal handler for CTRL-C
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void V8LineEditor::setupCtrlCHandler () {
|
||||
#ifndef _WIN32
|
||||
if (ShellImplFactory::hasCtrlCHandler()) {
|
||||
struct sigaction sa;
|
||||
sa.sa_flags = 0;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_handler = &SignalHandler;
|
||||
|
||||
int res = sigaction(SIGINT, &sa, 0);
|
||||
|
||||
if (res != 0) {
|
||||
LOG_ERROR("unable to install signal handler");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -331,8 +384,7 @@ V8LineEditor::~V8LineEditor () {
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
void V8LineEditor::initializeShell () {
|
||||
ShellImplFactory factory;
|
||||
_shellImpl = factory.buildShell(_history, &_completer);
|
||||
_shellImpl = ShellImplFactory::buildShell(_history, &_completer);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -103,7 +103,8 @@ namespace triagens {
|
|||
/// @brief constructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
V8LineEditor (v8::Handle<v8::Context>, std::string const& history);
|
||||
V8LineEditor (v8::Handle<v8::Context>,
|
||||
std::string const& history);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destructor
|
||||
|
@ -111,6 +112,14 @@ namespace triagens {
|
|||
|
||||
~V8LineEditor ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the global instance of the editor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static V8LineEditor* instance () {
|
||||
return _instance.load();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- protected methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -123,6 +132,12 @@ namespace triagens {
|
|||
|
||||
void initializeShell () override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief setup a signal handler for CTRL-C
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void setupCtrlCHandler ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -135,7 +150,17 @@ namespace triagens {
|
|||
|
||||
v8::Handle<v8::Context> _context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the completer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
V8Completer _completer;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the active instance of the editor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static std::atomic<V8LineEditor*> _instance;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -37,161 +37,26 @@ AC_ARG_WITH(readline-lib,
|
|||
)
|
||||
|
||||
dnl ----------------------------------------------------------------------------
|
||||
dnl checks for the READLINE library
|
||||
dnl ----------------------------------------------------------------------------
|
||||
|
||||
if test "x$READLINE_CPPFLAGS" != x; then
|
||||
TR_INCLUDE([READLINE_CPPFLAGS])
|
||||
fi
|
||||
|
||||
dnl ----------------------------------------------------------------------------
|
||||
dnl save flags
|
||||
dnl ----------------------------------------------------------------------------
|
||||
|
||||
SAVE_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $READLINE_CPPFLAGS"
|
||||
|
||||
SAVE_LDFLAGS="$LDFLAGS"
|
||||
LDFLAGS="$LDFLAGS $READLINE_LDFLAGS"
|
||||
|
||||
SAVE_LIBS="$LIBS"
|
||||
|
||||
dnl ----------------------------------------------------------------------------
|
||||
dnl check for header and library
|
||||
dnl ----------------------------------------------------------------------------
|
||||
|
||||
if test "x$tr_READLINE" = xyes -o "x$tr_READLINE" = xmaybe; then
|
||||
ch_READLINE="$tr_READLINE"
|
||||
|
||||
AC_CHECK_HEADERS(readline/readline.h, [tr_READLINE="yes"], [tr_READLINE="no"])
|
||||
|
||||
if test "x$tr_READLINE" = xyes; then
|
||||
AC_CHECK_LIB([readline], [readline], [READLINE_LIBS="-lreadline" tr_READLINE="yes"], [tr_READLINE="no"])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([READLINE support])
|
||||
|
||||
if test "x$tr_READLINE" != xyes; then
|
||||
AC_MSG_RESULT([not found])
|
||||
|
||||
if test "x$ch_READLINE" = xyes; then
|
||||
AC_MSG_ERROR([Please install readline support])
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT([readline])
|
||||
fi
|
||||
|
||||
elif test "x$tr_READLINE" = xlinenoise; then
|
||||
READLINE_CPPFLAGS="-I${srcdir}/3rdParty/linenoise -DUSE_UTF8"
|
||||
|
||||
AC_MSG_CHECKING([READLINE support])
|
||||
AC_MSG_RESULT([linenoise])
|
||||
|
||||
else
|
||||
AC_MSG_CHECKING([READLINE support])
|
||||
AC_MSG_RESULT([disabled])
|
||||
|
||||
fi
|
||||
|
||||
dnl ----------------------------------------------------------------------------
|
||||
dnl grep readline version number
|
||||
dnl ----------------------------------------------------------------------------
|
||||
|
||||
if test "x$tr_READLINE" = xyes; then
|
||||
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <readline/readline.h>
|
||||
|
||||
main () {
|
||||
#if defined(RL_VERSION_MAJOR) && defined(RL_VERSION_MINOR)
|
||||
long sdnhg36ed = RL_VERSION_MAJOR RL_VERSION_MINOR ;
|
||||
#else
|
||||
long sdnhg36ed = RL_READLINE_VERSION hex ;
|
||||
#endif
|
||||
}
|
||||
|
||||
_ACEOF
|
||||
|
||||
AC_MSG_CHECKING([READLINE version])
|
||||
eval "$ac_cpp conftest.$ac_ext" | fgrep "long sdnhg36ed" | awk '{print $4 "." $5}' > conftest.output
|
||||
READLINE_VERSION=`cat conftest.output`
|
||||
|
||||
if test -z "$READLINE_VERSION"; then
|
||||
AC_MSG_ERROR([Readline support is not working. Please re-install readline support])
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT([$READLINE_VERSION])
|
||||
rm -f conftest*
|
||||
|
||||
elif test "x$tr_READLINE" = xlinenoise; then
|
||||
READLINE_VERSION="linenoise"
|
||||
|
||||
AC_MSG_CHECKING([READLINE version])
|
||||
AC_MSG_RESULT([$READLINE_VERSION])
|
||||
fi
|
||||
|
||||
dnl ----------------------------------------------------------------------------
|
||||
dnl restore flags
|
||||
dnl ----------------------------------------------------------------------------
|
||||
|
||||
LIBS="$SAVE_LIBS"
|
||||
LDFLAGS="$SAVE_LDFLAGS"
|
||||
CPPFLAGS="$SAVE_CPPFLAGS"
|
||||
|
||||
if test "x$tr_READLINE" = xyes; then
|
||||
CPPFLAGS="$CPPFLAGS -DHAVE_READLINE=1"
|
||||
READLINE_CPPFLAGS="${READLINE_CPPFLAGS} -DTRI_READLINE_VERSION='\"${READLINE_VERSION}\"'"
|
||||
|
||||
elif test "x$tr_READLINE" = xlinenoise; then
|
||||
READLINE_CPPFLAGS="${READLINE_CPPFLAGS} -DTRI_HAVE_LINENOISE -DTRI_READLINE_VERSION='\"${READLINE_VERSION}\"'"
|
||||
fi
|
||||
|
||||
dnl ----------------------------------------------------------------------------
|
||||
dnl add substitutions
|
||||
dnl ----------------------------------------------------------------------------
|
||||
|
||||
AM_CONDITIONAL(ENABLE_READLINE, test "x$tr_READLINE" = xyes)
|
||||
|
||||
if test "x$tr_READLINE" = xyes; then
|
||||
AC_DEFINE_UNQUOTED(TRI_HAVE_READLINE, 1, [true if readline is used])
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(ENABLE_LINENOISE, test "x$tr_READLINE" = xlinenoise)
|
||||
|
||||
if test "x$tr_READLINE" = xlinenoise; then
|
||||
AC_DEFINE_UNQUOTED(TRI_HAVE_LINENOISE, 1, [true if linenoise is used])
|
||||
fi
|
||||
|
||||
AC_SUBST(READLINE_VERSION)
|
||||
AC_SUBST(READLINE_CPPFLAGS)
|
||||
AC_SUBST(READLINE_LDFLAGS)
|
||||
AC_SUBST(READLINE_LIBS)
|
||||
|
||||
dnl ----------------------------------------------------------------------------
|
||||
dnl informational output
|
||||
dnl ----------------------------------------------------------------------------
|
||||
|
||||
if test "x$tr_READLINE" = xyes; then
|
||||
LIB_INFO="$LIB_INFO|READLINE VERSION: ${READLINE_VERSION}"
|
||||
|
||||
LIB_INFO="$LIB_INFO|READLINE_CPPFLAGS: ${READLINE_CPPFLAGS}"
|
||||
LIB_INFO="$LIB_INFO|READLINE_LDLIBS: ${READLINE_LDLIBS}"
|
||||
LIB_INFO="$LIB_INFO|READLINE_LIBS: ${READLINE_LIBS}"
|
||||
|
||||
elif test "x$tr_READLINE" = xlinenoise; then
|
||||
LIB_INFO="$LIB_INFO|LINENOISE VERSION: ${READLINE_VERSION}"
|
||||
|
||||
LIB_INFO="$LIB_INFO|LINENOISE_CPPFLAGS: ${READLINE_CPPFLAGS}"
|
||||
LIB_INFO="$LIB_INFO|LINENOISE_LDLIBS: ${READLINE_LDLIBS}"
|
||||
LIB_INFO="$LIB_INFO|LINENOISE_LIBS: ${READLINE_LIBS}"
|
||||
|
||||
else
|
||||
LIB_INFO="$LIB_INFO|READLINE VERSION: disabled"
|
||||
fi
|
||||
|
||||
LIB_INFO="$LIB_INFO|."
|
||||
|
||||
dnl ----------------------------------------------------------------------------
|
||||
dnl --SECTION-- END-OF-FILE
|
||||
dnl ----------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue