diff --git a/CMakeLists.txt b/CMakeLists.txt index 409ef786e46e62b32648e7eb7287cdb7f1df0a13..1a12a95474c292b447960e40d63b8beb98b18eed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,9 @@ set (CMAKE_CXX_FLAGS "-std=c++11 -Wno-return-type -Wall -Wextra -Wnon-virtual-dt find_package (GnuTLS 3.1 REQUIRED) find_package (Msgpack 1.1 REQUIRED) +if (OPENDHT_TOOLS) + find_package (Readline 6 REQUIRED) +endif () list (APPEND opendht_SOURCES src/infohash.cpp diff --git a/cmake/FindReadline.cmake b/cmake/FindReadline.cmake new file mode 100644 index 0000000000000000000000000000000000000000..6807812f4d3383149af590ee8f3971e4d3f3ee2d --- /dev/null +++ b/cmake/FindReadline.cmake @@ -0,0 +1,48 @@ +# - Try to find readline, a library for easy editing of command lines. +# Variables used by this module: +# READLINE_ROOT_DIR - Readline root directory +# Variables defined by this module: +# READLINE_FOUND - system has Readline +# READLINE_INCLUDE_DIR - the Readline include directory (cached) +# READLINE_INCLUDE_DIRS - the Readline include directories +# (identical to READLINE_INCLUDE_DIR) +# READLINE_LIBRARY - the Readline library (cached) +# READLINE_LIBRARIES - the Readline library plus the libraries it +# depends on + +# Copyright (C) 2009 +# ASTRON (Netherlands Institute for Radio Astronomy) +# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +# +# This program is free software; you can redistribute it and/or modify +# modify it under the terms of the GNU General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. +# +# $Id: FindReadline.cmake 15228 2010-03-16 09:27:26Z loose $ + +if(NOT READLINE_FOUND) + + find_path(READLINE_INCLUDE_DIR readline/readline.h + HINTS ${READLINE_ROOT_DIR} PATH_SUFFIXES include) + find_library(READLINE_LIBRARY readline + HINTS ${READLINE_ROOT_DIR} PATH_SUFFIXES lib) + find_library(NCURSES_LIBRARY ncurses) # readline depends on libncurses + mark_as_advanced(READLINE_INCLUDE_DIR READLINE_LIBRARY NCURSES_LIBRARY) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(Readline DEFAULT_MSG + READLINE_LIBRARY NCURSES_LIBRARY READLINE_INCLUDE_DIR) + + set(READLINE_INCLUDE_DIRS ${READLINE_INCLUDE_DIR}) + set(READLINE_LIBRARIES ${READLINE_LIBRARY} ${NCURSES_LIBRARY}) + +endif(NOT READLINE_FOUND) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index f299d2123f619b0fa23514c811740335adc23b28..2db4ef3670806eef2db931089ea3aace27f1faa3 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -3,9 +3,9 @@ add_executable (dhtnode dhtnode.cpp tools_common.h) add_executable (dhtscanner dhtscanner.cpp tools_common.h) add_executable (dhtchat dhtchat.cpp tools_common.h) -target_link_libraries (dhtnode LINK_PUBLIC opendht gnutls) -target_link_libraries (dhtscanner LINK_PUBLIC opendht gnutls) -target_link_libraries (dhtchat LINK_PUBLIC opendht gnutls) +target_link_libraries (dhtnode LINK_PUBLIC opendht gnutls readline) +target_link_libraries (dhtscanner LINK_PUBLIC opendht gnutls readline) +target_link_libraries (dhtchat LINK_PUBLIC opendht gnutls readline) if (NOT DEFINED CMAKE_INSTALL_BINDIR) set(CMAKE_INSTALL_BINDIR bin) diff --git a/tools/dhtchat.cpp b/tools/dhtchat.cpp index 831f4b4686d49a405707c15b22829cbd55f11f0f..c610b546560d60440855874a4084c190c7b0e580 100644 --- a/tools/dhtchat.cpp +++ b/tools/dhtchat.cpp @@ -72,18 +72,20 @@ main(int argc, char **argv) InfoHash room; const InfoHash myid = dht.getId(); + // using the GNU History API + using_history(); + while (true) { - std::cout << (connected ? ">> " : "> "); - std::string line; - std::getline(std::cin, line); - static constexpr dht::InfoHash INVALID_ID {}; - - if (std::cin.eof()) + // using the GNU Readline API + std::string line = readLine(connected ? PROMPT : "> "); + if (!line.empty() && line[0] == '\0') break; if (line.empty()) continue; + static constexpr dht::InfoHash INVALID_ID {}; + std::istringstream iss(line); std::string op, idstr; iss >> op; diff --git a/tools/dhtnode.cpp b/tools/dhtnode.cpp index f9fc37ee0132450e7621cdc4cbcf4305b1bb8fe1..3dae0d3732292b0b86313a125badf57b52419f50 100644 --- a/tools/dhtnode.cpp +++ b/tools/dhtnode.cpp @@ -114,16 +114,21 @@ main(int argc, char **argv) print_node_info(dht, params); std::cout << " (type 'h' or 'help' for a list of possible commands)" << std::endl << std::endl; + // using the GNU History API + using_history(); + while (true) { - std::cout << ">> "; - std::string line; - std::getline(std::cin, line); + // using the GNU Readline API + std::string line = readLine(); + if (!line.empty() && line[0] == '\0') + break; + std::istringstream iss(line); std::string op, idstr, value; iss >> op >> idstr; - if (std::cin.eof() || op == "x" || op == "q" || op == "exit" || op == "quit") { + if (op == "x" || op == "q" || op == "exit" || op == "quit") { break; } else if (op == "h" || op == "help") { print_help(); diff --git a/tools/tools_common.h b/tools/tools_common.h index 4c7af5e213652a64c3844ac8f5376809b790be56..c1aebb090a71f79744d42833fa1a656cf1c91d2a 100644 --- a/tools/tools_common.h +++ b/tools/tools_common.h @@ -39,6 +39,8 @@ #include <opendht.h> #include <getopt.h> +#include <readline/readline.h> +#include <readline/history.h> /** * Terminal colors for logging @@ -202,3 +204,15 @@ parseArgs(int argc, char **argv) { } return params; } + +static const constexpr char* PROMPT = ">> "; + +std::string +readLine(const char* prefix = PROMPT) +{ + const char* line_read = readline(prefix); + if (line_read && *line_read) + add_history(line_read); + + return line_read ? std::string(line_read) : std::string("\0", 1); +}