Skip to content

Commit

Permalink
Add readline support to fc::rpc::cli
Browse files Browse the repository at this point in the history
  • Loading branch information
theoreticalbts committed Apr 29, 2015
1 parent 35d4893 commit 80de098
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 5 deletions.
25 changes: 24 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ ELSE(WIN32)
ENDIF(NOT APPLE)
ENDIF(WIN32)



IF(NOT "$ENV{OPENSSL_ROOT_DIR}" STREQUAL "")
set(OPENSSL_ROOT_DIR $ENV{OPENSSL_ROOT_DIR} )
set(OPENSSL_INCLUDE_DIR ${OPENSSL_ROOT_DIR}/include)
Expand Down Expand Up @@ -123,6 +125,7 @@ set( fc_sources
src/interprocess/file_mapping.cpp
src/interprocess/mmap_struct.cpp
src/rpc/json_connection.cpp
src/rpc/cli.cpp
src/log/log_message.cpp
src/log/logger.cpp
src/log/appender.cpp
Expand Down Expand Up @@ -195,6 +198,25 @@ add_subdirectory( vendor/udt4 )

setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC DONT_INSTALL_LIBRARY )

# begin readline 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)
target_compile_definitions( fc PRIVATE _CRT_NONSTDC_NO_DEPRECATE )
endif(WIN32)
# end readline stuff

IF(WIN32)
target_compile_definitions(fc PUBLIC WIN32 NOMINMAX _WIN32_WINNT=0x0501 _CRT_SECURE_NO_WARNINGS
_SCL_SERCURE_NO_WARNINGS
Expand All @@ -221,6 +243,7 @@ target_include_directories(fc
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
${Boost_INCLUDE_DIR}
${OPENSSL_INCLUDE_DIR}
"${readline_includes}"

PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
#${CMAKE_CURRENT_SOURCE_DIR}/vendor/scrypt-jane
Expand All @@ -233,7 +256,7 @@ target_include_directories(fc
)

#target_link_libraries( fc PUBLIC easylzma_static scrypt udt ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library})
target_link_libraries( fc PUBLIC easylzma_static udt ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library})
target_link_libraries( fc PUBLIC easylzma_static udt ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${readline_libraries})

IF(NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY MATCHES "\\.(a|lib)$")
IF(WIN32)
Expand Down
47 changes: 47 additions & 0 deletions CMakeModules/FindReadline.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# - 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
)
18 changes: 14 additions & 4 deletions include/fc/rpc/cli.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <fc/rpc/api_connection.hpp>
#include <fc/thread/thread.hpp>

#include <iostream>

namespace fc { namespace rpc {

/**
Expand Down Expand Up @@ -48,16 +50,24 @@ namespace fc { namespace rpc {
{
_result_formatters[method] = formatter;
}

virtual void getline( const fc::string& prompt, fc::string& line );

private:
void run()
{
while( !fc::cin.eof() && !_run_complete.canceled() )
while( !_run_complete.canceled() )
{
try {
std::cout << ">>> ";
std::cout.flush();
std::string line;
fc::getline( fc::cin, line );
try
{
getline( ">>> ", line );
}
catch ( const fc::eof_exception& e )
{
break;
}
std::cout << line << "\n";
line += char(EOF);
fc::variants args = fc::json::variants_from_string(line);;
Expand Down
69 changes: 69 additions & 0 deletions src/rpc/cli.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@

#include <fc/rpc/cli.hpp>

#include <iostream>

#ifndef WIN32
#include <unistd.h>
#endif

#ifdef HAVE_READLINE
# include <readline/readline.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
#endif

namespace fc { namespace rpc {

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
#ifndef WIN32
if( isatty( fileno( stdin ) ) )
#else
// it's implied by
// https://msdn.microsoft.com/en-us/library/f4s0ddew.aspx
// that this is the proper way to do this on Windows, but I have
// no access to a Windows compiler and thus,
// no idea if this actually works
if( _isatty( _fileno( stdin ) ) )
#endif
{
char* line_read = nullptr;
std::cout.flush(); //readline doesn't use cin, so we must manually flush _out
line_read = readline(prompt.c_str());
if( line_read == nullptr )
FC_THROW_EXCEPTION( fc::eof_exception, "" );
if( *line_read )
add_history(line_read);
line = line_read;
free(line_read);
}
else
#endif
{
std::cout << prompt;
// sync_call( cin_thread, [&](){ std::getline( *input_stream, line ); }, "getline");
fc::getline( fc::cin, line );
return;
}
}

} }

0 comments on commit 80de098

Please sign in to comment.