From abb4b9b0ab94cf904f784eb3eb92dc70ea016228 Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 20 Feb 2018 15:18:47 -0500 Subject: [PATCH] Added editline as submodule --- .gitmodules | 3 + CMakeLists.txt | 25 ++++---- CMakeModules/FindEditline.cmake | 50 +++++++++++++++ CMakeModules/FindReadline.cmake | 49 --------------- src/rpc/cli.cpp | 106 +++++++++++++++++--------------- vendor/editline | 1 + 6 files changed, 124 insertions(+), 110 deletions(-) create mode 100644 CMakeModules/FindEditline.cmake delete mode 100644 CMakeModules/FindReadline.cmake create mode 160000 vendor/editline diff --git a/.gitmodules b/.gitmodules index 0c2a833..7abf7dd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "vendor/websocketpp"] path = vendor/websocketpp url = https://github.com/zaphoyd/websocketpp.git +[submodule "vendor/editline"] + path = vendor/editline + url = https://github.com/troglobit/editline.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f7787d..3766b1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -251,24 +251,25 @@ add_subdirectory( vendor/websocketpp EXCLUDE_FROM_ALL ) setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC ) install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include ) -# begin readline stuff -find_package(Curses) -find_package(Readline) +# begin editline stuff +#find_package(Curses) +set(EDITLINE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline" ) +find_package(Editline) file(GLOB HEADERS "include/bts/cli/*.hpp") -if (READLINE_FOUND) - target_compile_definitions (fc PRIVATE HAVE_READLINE) - set(readline_libraries ${Readline_LIBRARY}) - if (CURSES_FOUND) - list(APPEND readline_libraries ${CURSES_LIBRARY}) - endif() - set(readline_includes ${Readline_INCLUDE_DIR}) +if (EDITLINE_FOUND) + target_compile_definitions (fc PRIVATE HAVE_EDITLINE) + set(editline_libraries ${Editline_LIBRARY}) + #if (CURSES_FOUND) + # list(APPEND editline_libraries ${CURSES_LIBRARY}) + #endif() + set(editline_includes ${Editline_INCLUDE_DIR}) endif() if(WIN32) target_compile_definitions( fc PRIVATE _CRT_NONSTDC_NO_DEPRECATE ) endif(WIN32) -# end readline stuff +# end editline stuff if( NOT CPP_STANDARD ) set( CPP_STANDARD, "-std=c++11" ) @@ -362,7 +363,7 @@ target_include_directories(fc ${OPENSSL_INCLUDE_DIR} "vendor/diff-match-patch-cpp-stl" ${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp - "${readline_includes}" + "${editline_includes}" PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/vendor/boost_1.51/include diff --git a/CMakeModules/FindEditline.cmake b/CMakeModules/FindEditline.cmake new file mode 100644 index 0000000..3508fe1 --- /dev/null +++ b/CMakeModules/FindEditline.cmake @@ -0,0 +1,50 @@ +# - Try to find editline include dirs and libraries +# +# Usage of this module as follows: +# +# find_package(Editline) +# +# Variables used by this module, they can change the default behaviour and need +# to be set before calling find_package: +# +# Editline_ROOT_DIR Set this variable to the root installation of +# editline if the module has problems finding the +# proper installation path. +# +# Variables defined by this module: +# +# EDITLINE_FOUND System has editline, include and lib dirs found +# Editline_INCLUDE_DIR The editline include directories. +# Editline_LIBRARY The editline library. + +find_path(Editline_ROOT_DIR + NAMES include/editline.h + HINTS ${EDITLINE_DIR} +) + +find_path(Editline_INCLUDE_DIR + NAMES editline.h + HINTS ${Editline_ROOT_DIR}/include +) + +find_library(Editline_LIBRARY + NAMES libeditline.a + HINTS ${Editline_ROOT_DIR}/src/.libs +) + +if(Editline_INCLUDE_DIR AND Editline_LIBRARY) + set(EDITLINE_FOUND TRUE) +else(Editline_INCLUDE_DIR AND Editline_LIBRARY) + FIND_LIBRARY(Editline_LIBRARY NAMES editline) + include(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(Editline DEFAULT_MSG Editline_INCLUDE_DIR Editline_LIBRARY ) + MARK_AS_ADVANCED(Editline_INCLUDE_DIR Editline_LIBRARY) +endif(Editline_INCLUDE_DIR AND Editline_LIBRARY) + +mark_as_advanced( + Editline_ROOT_DIR + Editline_INCLUDE_DIR + Editline_LIBRARY +) + +MESSAGE( STATUS "Found Editline: ${Editline_LIBRARY}" ) diff --git a/CMakeModules/FindReadline.cmake b/CMakeModules/FindReadline.cmake deleted file mode 100644 index f1d0d74..0000000 --- a/CMakeModules/FindReadline.cmake +++ /dev/null @@ -1,49 +0,0 @@ -# - Try to find readline include dirs and libraries -# -# Usage of this module as follows: -# -# find_package(Readline) -# -# Variables used by this module, they can change the default behaviour and need -# to be set before calling find_package: -# -# Readline_ROOT_DIR Set this variable to the root installation of -# readline if the module has problems finding the -# proper installation path. -# -# Variables defined by this module: -# -# READLINE_FOUND System has readline, include and lib dirs found -# Readline_INCLUDE_DIR The readline include directories. -# Readline_LIBRARY The readline library. - -find_path(Readline_ROOT_DIR - NAMES include/readline/readline.h -) - -find_path(Readline_INCLUDE_DIR - NAMES readline/readline.h - HINTS ${Readline_ROOT_DIR}/include -) - -find_library(Readline_LIBRARY - NAMES readline - HINTS ${Readline_ROOT_DIR}/lib -) - -if(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY) - set(READLINE_FOUND TRUE) -else(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY) - FIND_LIBRARY(Readline_LIBRARY NAMES readline) - include(FindPackageHandleStandardArgs) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(Readline DEFAULT_MSG Readline_INCLUDE_DIR Readline_LIBRARY ) - MARK_AS_ADVANCED(Readline_INCLUDE_DIR Readline_LIBRARY) -endif(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY) - -mark_as_advanced( - Readline_ROOT_DIR - Readline_INCLUDE_DIR - Readline_LIBRARY -) - -MESSAGE( STATUS "Found Readline: ${Readline_LIBRARY}" ) diff --git a/src/rpc/cli.cpp b/src/rpc/cli.cpp index d3070fb..487e444 100644 --- a/src/rpc/cli.cpp +++ b/src/rpc/cli.cpp @@ -7,22 +7,8 @@ #include #endif -#ifdef HAVE_READLINE -# include -# include -// I don't know exactly what version of readline we need. I know the 4.2 version that ships on some macs is -// missing some functions we require. We're developing against 6.3, but probably anything in the 6.x -// series is fine -# if RL_VERSION_MAJOR < 6 -# ifdef _MSC_VER -# pragma message("You have an old version of readline installed that might not support some of the features we need") -# pragma message("Readline support will not be compiled in") -# else -# warning "You have an old version of readline installed that might not support some of the features we need" -# warning "Readline support will not be compiled in" -# endif -# undef HAVE_READLINE -# endif +#ifdef HAVE_EDITLINE +# include "editline.h" # ifdef WIN32 # include # endif @@ -134,53 +120,73 @@ char * dupstr (const char* s) { return (r); } -char* my_generator(const char* text, int state) +/**** + * @brief loop through list of commands, attempting to find a match + * @param token what the user typed + * @param match + * @returns the full name of the command or NULL if no matches found + */ +static char *my_rl_complete(char *token, int *match) { - static int list_index, len; - const char *name; + int matchlen = 0; + int count = 0; + const char* method_name; - if (!state) { - list_index = 0; - len = strlen (text); - } + auto& cmd = cli_commands(); + for (auto it = cmd.begin(); it != cmd.end(); it++) { + int partlen = strlen (token); /* Part of token */ - auto& cmd = cli_commands(); + if (!strncmp ((*it).c_str(), token, partlen)) { + method_name = (*it).c_str(); + matchlen = partlen; + count ++; + } + } - while( list_index < cmd.size() ) - { - name = cmd[list_index].c_str(); - list_index++; + if (count == 1) { + *match = 1; + return strdup (method_name + matchlen); + } - if (strncmp (name, text, len) == 0) - return (dupstr(name)); - } - - /* If no names matched, then return NULL. */ - return ((char *)NULL); + return NULL; } - -static char** cli_completion( const char * text , int start, int end) +/*** + * @brief return an array of matching commands + * @param token the incoming text + * @param av the resultant array of possible matches + * @returns the number of matches + */ +static int cli_completion(char *token, char ***av) { - char **matches; - matches = (char **)NULL; + int num, total = 0; + char **copy; -#ifdef HAVE_READLINE - if (start == 0) - matches = rl_completion_matches ((char*)text, &my_generator); - else - rl_bind_key('\t',rl_abort); -#endif + auto& cmd = cli_commands(); + num = cmd.size(); - return (matches); + copy = (char **) malloc (num * sizeof(char *)); + for (auto it = cmd.begin(); it != cmd.end(); ++it) { + if (!strncmp ((*it).c_str(), token, strlen (token))) { + copy[total] = strdup ( (*it).c_str() ); + total ++; + } + } + *av = copy; + + return total; } - +/*** + * @brief Read input from the user + * @param prompt the prompt to display + * @param line what the user typed + */ void cli::getline( const fc::string& prompt, fc::string& line) { // getting file descriptor for C++ streams is near impossible // so we just assume it's the same as the C stream... -#ifdef HAVE_READLINE +#ifdef HAVE_EDITLINE #ifndef WIN32 if( isatty( fileno( stdin ) ) ) #else @@ -192,7 +198,9 @@ void cli::getline( const fc::string& prompt, fc::string& line) if( _isatty( _fileno( stdin ) ) ) #endif { - rl_attempted_completion_function = cli_completion; + //rl_attempted_completion_function = cli_completion; + rl_set_complete_func(my_rl_complete); + rl_set_list_possib_func(cli_completion); static fc::thread getline_thread("getline"); getline_thread.async( [&](){ @@ -201,7 +209,7 @@ void cli::getline( const fc::string& prompt, fc::string& line) line_read = readline(prompt.c_str()); if( line_read == nullptr ) FC_THROW_EXCEPTION( fc::eof_exception, "" ); - rl_bind_key( '\t', rl_complete ); + //el_bind_key( '\t', rl_complete ); if( *line_read ) add_history(line_read); line = line_read; diff --git a/vendor/editline b/vendor/editline new file mode 160000 index 0000000..5be965d --- /dev/null +++ b/vendor/editline @@ -0,0 +1 @@ +Subproject commit 5be965deec0527b48b393b7aca9cb2a76aec2a99