add editline changes
This commit is contained in:
parent
fb27454cdf
commit
e33cd275aa
5 changed files with 158 additions and 124 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -1,3 +1,6 @@
|
||||||
[submodule "vendor/secp256k1-zkp"]
|
[submodule "vendor/secp256k1-zkp"]
|
||||||
path = vendor/secp256k1-zkp
|
path = vendor/secp256k1-zkp
|
||||||
url = https://github.com/bitshares/secp256k1-zkp.git
|
url = https://github.com/bitshares/secp256k1-zkp.git
|
||||||
|
[submodule "vendor/editline"]
|
||||||
|
path = vendor/editline
|
||||||
|
url = https://github.com/troglobit/editline.git
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,54 @@ else ( MSVC )
|
||||||
endif ( MSVC )
|
endif ( MSVC )
|
||||||
# End configure secp256k1-zkp
|
# End configure secp256k1-zkp
|
||||||
|
|
||||||
|
# Configure editline
|
||||||
|
if ( MSVC )
|
||||||
|
# autoconf won't work here, hard code the defines
|
||||||
|
set( EDITLINE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline" )
|
||||||
|
|
||||||
|
file( GLOB EDITLINE_SOURCES "${EDITLINE_DIR}/src/editline.c" )
|
||||||
|
add_library( editline ${EDITLINE_SOURCES} )
|
||||||
|
|
||||||
|
target_include_directories( editline PRIVATE "${EDITLINE_DIR}" PUBLIC "${EDITLINE_DIR}/include" )
|
||||||
|
|
||||||
|
set_target_properties( editline PROPERTIES COMPILE_DEFINITIONS LINKER_LANGUAGE C )
|
||||||
|
else ( MSVC )
|
||||||
|
include(ExternalProject)
|
||||||
|
if ( MINGW )
|
||||||
|
ExternalProject_Add( project_editline
|
||||||
|
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline
|
||||||
|
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline
|
||||||
|
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/editline --host=x86_64-w64-mingw32
|
||||||
|
BUILD_COMMAND make
|
||||||
|
INSTALL_COMMAND true
|
||||||
|
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline/src/project_editline-build/.libs/libeditline.a
|
||||||
|
)
|
||||||
|
else ( MINGW )
|
||||||
|
ExternalProject_Add( project_editline
|
||||||
|
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline
|
||||||
|
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline
|
||||||
|
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/editline
|
||||||
|
BUILD_COMMAND make
|
||||||
|
INSTALL_COMMAND true
|
||||||
|
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline/src/project_editline-build/.libs/libeditline.a
|
||||||
|
)
|
||||||
|
endif ( MINGW )
|
||||||
|
ExternalProject_Add_Step(project_editline autogen
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline
|
||||||
|
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/autogen.sh
|
||||||
|
DEPENDERS configure
|
||||||
|
)
|
||||||
|
|
||||||
|
ExternalProject_Get_Property(project_editline binary_dir)
|
||||||
|
|
||||||
|
add_library(editline STATIC IMPORTED)
|
||||||
|
set_property(TARGET editline PROPERTY IMPORTED_LOCATION ${binary_dir}/src/.libs/libeditline${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||||
|
set_property(TARGET editline PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/include)
|
||||||
|
add_dependencies(editline project_editline)
|
||||||
|
install( FILES ${binary_dir}/src/.libs/libeditline${CMAKE_STATIC_LIBRARY_SUFFIX} DESTINATION lib/cryptonomex )
|
||||||
|
endif ( MSVC )
|
||||||
|
# End configure editline
|
||||||
|
|
||||||
IF( WIN32 )
|
IF( WIN32 )
|
||||||
MESSAGE(STATUS "Configuring fc to build on Win32")
|
MESSAGE(STATUS "Configuring fc to build on Win32")
|
||||||
|
|
||||||
|
|
@ -258,27 +306,17 @@ add_subdirectory( vendor/websocketpp EXCLUDE_FROM_ALL )
|
||||||
setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC )
|
setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC )
|
||||||
install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include )
|
install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include )
|
||||||
|
|
||||||
# begin readline stuff
|
# begin editline stuff
|
||||||
find_package(Curses)
|
|
||||||
find_package(Readline)
|
|
||||||
|
|
||||||
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})
|
|
||||||
endif()
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_compile_definitions( fc PRIVATE _CRT_NONSTDC_NO_DEPRECATE )
|
target_compile_definitions( fc PRIVATE _CRT_NONSTDC_NO_DEPRECATE )
|
||||||
|
else(WIN32)
|
||||||
|
target_compile_definitions( fc PRIVATE HAVE_EDITLINE )
|
||||||
|
set( editline_libraries editline )
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
# end readline stuff
|
# end editline stuff
|
||||||
|
|
||||||
if( NOT CPP_STANDARD )
|
if( NOT CPP_STANDARD )
|
||||||
set( CPP_STANDARD, "-std=c++11" )
|
set( CPP_STANDARD "-std=c++11" )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
|
|
@ -360,7 +398,6 @@ target_include_directories(fc
|
||||||
${OPENSSL_INCLUDE_DIR}
|
${OPENSSL_INCLUDE_DIR}
|
||||||
"vendor/diff-match-patch-cpp-stl"
|
"vendor/diff-match-patch-cpp-stl"
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp
|
${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp
|
||||||
"${readline_includes}"
|
|
||||||
|
|
||||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp
|
${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp
|
||||||
|
|
@ -370,7 +407,7 @@ target_include_directories(fc
|
||||||
IF(NOT WIN32)
|
IF(NOT WIN32)
|
||||||
set(LINK_USR_LOCAL_LIB -L/usr/local/lib)
|
set(LINK_USR_LOCAL_LIB -L/usr/local/lib)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${readline_libraries} ${ECC_LIB} )
|
target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${editline_libraries} ${ECC_LIB} )
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
set_source_files_properties( src/network/http/websocket.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
|
set_source_files_properties( src/network/http/websocket.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
|
||||||
|
|
@ -495,3 +532,4 @@ ADD_CUSTOM_COMMAND(TARGET fc POST_BUILD ${POST_BUILD_STEP_COMMANDS}
|
||||||
)
|
)
|
||||||
|
|
||||||
MESSAGE(STATUS "Finished fc module configuration...")
|
MESSAGE(STATUS "Finished fc module configuration...")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,47 +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
|
|
||||||
)
|
|
||||||
157
src/rpc/cli.cpp
157
src/rpc/cli.cpp
|
|
@ -7,22 +7,8 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_READLINE
|
#ifdef HAVE_EDITLINE
|
||||||
# include <readline/readline.h>
|
# include "editline.h"
|
||||||
# include <readline/history.h>
|
|
||||||
// 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 WIN32
|
# ifdef WIN32
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
# endif
|
# endif
|
||||||
|
|
@ -131,61 +117,107 @@ void cli::run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char * dupstr (const char* s) {
|
/****
|
||||||
char *r;
|
* @brief loop through list of commands, attempting to find a match
|
||||||
|
* @param token what the user typed
|
||||||
r = (char*) malloc ((strlen (s) + 1));
|
* @param match sets to 1 if only 1 match was found
|
||||||
strcpy (r, s);
|
* @returns the remaining letters of the name of the command or NULL if 1 match not found
|
||||||
return (r);
|
*/
|
||||||
}
|
static char *my_rl_complete(char *token, int *match)
|
||||||
|
|
||||||
char* my_generator(const char* text, int state)
|
|
||||||
{
|
{
|
||||||
static int list_index, len;
|
|
||||||
const char *name;
|
|
||||||
|
|
||||||
if (!state) {
|
const auto& cmds = cli_commands();
|
||||||
list_index = 0;
|
const size_t partlen = strlen (token); /* Part of token */
|
||||||
len = strlen (text);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& cmd = cli_commands();
|
std::vector<std::reference_wrapper<const std::string>> matched_cmds;
|
||||||
|
for( const std::string& it : cmds )
|
||||||
while( list_index < cmd.size() )
|
|
||||||
{
|
{
|
||||||
name = cmd[list_index].c_str();
|
if( it.compare(0, partlen, token) == 0 )
|
||||||
list_index++;
|
{
|
||||||
|
matched_cmds.push_back( it );
|
||||||
if (strncmp (name, text, len) == 0)
|
}
|
||||||
return (dupstr(name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If no names matched, then return NULL. */
|
if( matched_cmds.size() == 0 )
|
||||||
return ((char *)NULL);
|
return NULL;
|
||||||
|
|
||||||
|
const std::string& first_matched_cmd = matched_cmds[0];
|
||||||
|
if( matched_cmds.size() == 1 )
|
||||||
|
{
|
||||||
|
*match = 1;
|
||||||
|
std::string matched_cmd = first_matched_cmd + " ";
|
||||||
|
return strdup( matched_cmd.c_str() + partlen );
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t first_cmd_len = first_matched_cmd.size();
|
||||||
|
size_t matched_len = partlen;
|
||||||
|
for( ; matched_len < first_cmd_len; ++matched_len )
|
||||||
|
{
|
||||||
|
char next_char = first_matched_cmd[matched_len];
|
||||||
|
bool end = false;
|
||||||
|
for( const std::string& s : matched_cmds )
|
||||||
|
{
|
||||||
|
if( s.size() <= matched_len || s[matched_len] != next_char )
|
||||||
|
{
|
||||||
|
end = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( end )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( matched_len == partlen )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
std::string matched_cmd_part = first_matched_cmd.substr( partlen, matched_len - partlen );
|
||||||
|
return strdup( matched_cmd_part.c_str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
static char** cli_completion( const char * text , int start, int end)
|
* @brief return an array of matching commands
|
||||||
|
* @param token the incoming text
|
||||||
|
* @param array the resultant array of possible matches
|
||||||
|
* @returns the number of matches
|
||||||
|
*/
|
||||||
|
static int cli_completion(char *token, char ***array)
|
||||||
{
|
{
|
||||||
char **matches;
|
auto& cmd = cli_commands();
|
||||||
matches = (char **)NULL;
|
int num_commands = cmd.size();
|
||||||
|
|
||||||
#ifdef HAVE_READLINE
|
char **copy = (char **) malloc (num_commands * sizeof(char *));
|
||||||
if (start == 0)
|
if (copy == NULL)
|
||||||
matches = rl_completion_matches ((char*)text, &my_generator);
|
{
|
||||||
else
|
// possible out of memory
|
||||||
rl_bind_key('\t',rl_abort);
|
return 0;
|
||||||
#endif
|
}
|
||||||
|
int total_matches = 0;
|
||||||
|
|
||||||
return (matches);
|
int partlen = strlen(token);
|
||||||
|
|
||||||
|
for (const std::string& it : cmd)
|
||||||
|
{
|
||||||
|
if ( it.compare(0, partlen, token) == 0)
|
||||||
|
{
|
||||||
|
copy[total_matches] = strdup ( it.c_str() );
|
||||||
|
++total_matches;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*array = copy;
|
||||||
|
|
||||||
|
return total_matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* @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)
|
void cli::getline( const fc::string& prompt, fc::string& line)
|
||||||
{
|
{
|
||||||
// getting file descriptor for C++ streams is near impossible
|
// getting file descriptor for C++ streams is near impossible
|
||||||
// so we just assume it's the same as the C stream...
|
// so we just assume it's the same as the C stream...
|
||||||
#ifdef HAVE_READLINE
|
#ifdef HAVE_EDITLINE
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
if( isatty( fileno( stdin ) ) )
|
if( isatty( fileno( stdin ) ) )
|
||||||
#else
|
#else
|
||||||
|
|
@ -197,8 +229,8 @@ void cli::getline( const fc::string& prompt, fc::string& line)
|
||||||
if( _isatty( _fileno( stdin ) ) )
|
if( _isatty( _fileno( stdin ) ) )
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
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");
|
static fc::thread getline_thread("getline");
|
||||||
getline_thread.async( [&](){
|
getline_thread.async( [&](){
|
||||||
char* line_read = nullptr;
|
char* line_read = nullptr;
|
||||||
|
|
@ -206,10 +238,17 @@ void cli::getline( const fc::string& prompt, fc::string& line)
|
||||||
line_read = readline(prompt.c_str());
|
line_read = readline(prompt.c_str());
|
||||||
if( line_read == nullptr )
|
if( line_read == nullptr )
|
||||||
FC_THROW_EXCEPTION( fc::eof_exception, "" );
|
FC_THROW_EXCEPTION( fc::eof_exception, "" );
|
||||||
rl_bind_key( '\t', rl_complete );
|
|
||||||
if( *line_read )
|
|
||||||
add_history(line_read);
|
|
||||||
line = line_read;
|
line = line_read;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (*line_read)
|
||||||
|
add_history(line_read);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
free(line_read);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
free(line_read);
|
free(line_read);
|
||||||
}).wait();
|
}).wait();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
vendor/editline
vendored
Submodule
1
vendor/editline
vendored
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 62bba782585c6c18d7a2b27beeb60a45db9abb43
|
||||||
Loading…
Reference in a new issue