A library for interactive command line interfaces in modern C++

Related tags

CLI cli
Overview

C/C++ CI of Cli

cli

A cross-platform header only C++14 library for interactive command line interfaces (Cisco style)

demo_local_session

demo_telnet_session

C/C++ CI of Cli

Features

  • Header only
  • Cross-platform (linux and windows)
  • Menus and submenus
  • Remote sessions (telnet)
  • Persistent history (navigation with arrow keys)
  • Autocompletion (with TAB key)
  • Async interface
  • Colors

How to get CLI library

Dependencies

The library depends on asio (either the standalone version or the boost version) only to provide telnet server. Therefore, the library has no dependencies if you don't need remote sessions.

Installation

The library is header-only: it consists entirely of header files containing templates and inline functions, and require no separately-compiled library binaries or special treatment when linking.

Extract the archive wherever you want.

Now you must only remember to specify the cli (and optionally asio or boost) paths when compiling your source code.

If you fancy it, a Cmake script is provided. To install you can use:

mkdir build && cd build
cmake ..
sudo make install

and, if you want to specify the installation path:

mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX:PATH=<cli_install_location>
make install

Compilation of the examples

You can find some examples in the directory "examples". Each .cpp file corresponds to an executable. You can compile each example by including cli (and optionally asio/boost header files) and linking pthread on linux (and optionally boost system).

To compile the examples using cmake, use:

mkdir build
cd build
cmake .. -DCLI_BuildExamples=ON
# or: cmake .. -DCLI_BuildExamples=ON -DBOOST_INCLUDEDIR=<boost_include_directory>
make all
# or: cmake --build .

In the same directory you can also find:

  • a GNU make file (Makefile)
  • a Windows nmake file (makefile.win)
  • a Visual Studio solution

You can specify boost library path in the following ways:

GNU Make

make CXXFLAGS="-isystem <boost_include>" LDFLAGS="-L<boost_lib>"

example:

make CXXFLAGS="-isystem /opt/boost_1_66_0/install/x86/include" LDFLAGS="-L/opt/boost_1_66_0/install/x86/lib"

(if you want to use clang instead of gcc, you can set the variable CXX=clang++)

Windows nmake

Optionally set the environment variable ASIO or BOOST to provide the library path. Then, from a visual studio console, start nmake passing one of the makefile.*.win files.

E.g., from a visual studio console, use one of the following commands:

# only compile examples that do not require asio
nmake /f makefile.noasio.win
# compile examples using boost asio
set BOOST=<path of boost libraries>
nmake /f makefile.boostasio.win
# compile examples using standalone asio
set ASIO=<path of asio library>
nmake /f makefile.standaloneasio.win

Visual Studio solution

Set the environment variable BOOST. Then, open the file cli/examples/examples.sln

CLI usage

The cli interpreter can manage correctly sentences using quote (') and double quote ("). Any character (spaces too) comprises between quotes or double quotes are considered as a single parameter of a command. The characters ' and " can be used inside a command parameter by escaping them with a backslash.

Some example:

cli> echo "this is a single parameter"
this is a single parameter
cli> echo 'this too is a single parameter'
this too is a single parameter
cli> echo "you can use 'single quotes' inside double quoted parameters"
you can use 'single quotes' inside double quoted parameters
cli> echo 'you can use "double quotes" inside single quoted parameters'
you can use "double quotes" inside single quoted parameters
cli> echo "you can escape \"quotes\" inside a parameter"               
you can escape "quotes" inside a parameter
cli> echo 'you can escape \'single quotes\' inside a parameter'
you can escape 'single quotes' inside a parameter
cli> echo "you can also show backslash \\ ... "                
you can also show backslash \ ... 

License

Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Contact

Please report issues here: http://github.com/daniele77/cli/issues

and questions, feature requests, ideas, anything else here: http://github.com/daniele77/cli/discussions

You can always contact me via twitter at @DPallastrelli


Contributing (We Need Your Help!)

Any feedback from users and stakeholders, even simple questions about how things work or why they were done a certain way, carries value and can be used to improve the library.

Even if you just have questions, asking them in GitHub Discussions provides valuable information that can be used to improve the library - do not hesitate, no question is insignificant or unimportant!

If you or your company uses cli library, please consider becoming a sponsor to keep the project strong and dependable.

Issues
  • Initial support for Cmake

    Initial support for Cmake

    It may not be much but it is a start.

    I am mostly familiar with best practices consuming libraries but when it comes to creating them my knoledge could be improve.

    I will do some resaerch now but this is enoguh code so that others can take a look at it.

    Feedback is welcomed.

    #23 Is related

    opened by tete17 33
  • Support commands with variable number of arguments.

    Support commands with variable number of arguments.

    Using this we can now use lambdas that accept std::vector<std::string> in order to get the raw command into my lambda. This helps for situations when there's a few optional arguments that I need to have for my command.

    enhancement 
    opened by sakshamsharma 8
  • Bug instantiating Local terminal sessions in multiple threads

    Bug instantiating Local terminal sessions in multiple threads

    Discussed in https://github.com/daniele77/cli/discussions/131

    Originally posted by kalowery October 23, 2021 Hi - I'm using cli and really like it. It's going to save me huge amounts of time. I'm working on a tool that presents a cli on different threads at different times in a multi-threaded application. There's a segfault bug in linuxkeyboard.h when doing this. It has to do with the detached thread reading keyboard input (i.e. std::getchar) which is still alive after tearing down the session (it's blocking in getchar). The next time the user presses a key the detached thread returns from getchar (in Read()) but the reference to the scheduler is now invalid and the call to Post crashes with a segfault because the vtable is gone.

    I got it to quit crashing by having LinuxKeyboard check the "run" boolean member variable before calling notify. It still eats the first key stroke that would have gone to a new local session instance, which is annoying but it's better than crashing. I'm using the LoopScheduler and calling Stop() in my ExitAction. I'm open to the idea that I'm tearing things down improperly, but I really think it's an artifact of the detached thread being stuck in a blocking call to getchar() when the session is torn down.

    bug 
    opened by kalowery 6
  • Linker error when building examples using cmake in Visual Studio 2019

    Linker error when building examples using cmake in Visual Studio 2019

    Hey,

    I am trying to build the project in Visual Studio 2019, building it as a CMake project. I get the linker error:

    "fatal error LNK1104: cannot open file 'libboost_date_time-vc142-mt-gd-x64-1_70.lib'"

    I just dont understand where the dependancy on boosts date_time comes into play. Another curious thing is that it is only building complete.cpp and pluginmanager.cpp that fails. The exe files to filesession.cpp and simplelocalsession.cpp are building correctly without errors. Hope you could shed some light on this issue.

    If any other information is needed, please let me know

    help wanted 
    opened by chrisabr 6
  • Redesigned the function handle template for Menu::Add() to allow for arbitrary arguments

    Redesigned the function handle template for Menu::Add() to allow for arbitrary arguments

    The existing code had separate implementations of the FuncCmd wrapper that could handle 0 to 4 arguments passed from the command parser into the handler. This mechanism has been replaced with some relatively simple TMP based on a template parameter pack.

    You can now specify a command handler callable that takes any number of arguments. It's also easier to customize the display of help text for these arguments. The following pattern implemented before the menu items are instantiated will allow custom prompt text to be displayed even if the arguments are the same base type.

    namespace cli {
    	namespace argtypes {
    		struct device : public std::string {};
    		struct filename : public std::string {};
    	}
    	template <> struct TypeDesc<argtypes::device> { static const char* Name() { return "<device>"; } };
    	template <> struct TypeDesc<argtypes::filename> { static const char* Name() { return "<filename>"; } };
    }
    
    rootMenu->Add("do-something",
    	[service](std::ostream & out, cli::argtypes::device identifier){ performAction(identifier, "", out); });
    rootMenu->Add("do-something",
    	[service](std::ostream & out, cli::argtypes::device identifier, cli::argtypes::filename filename){ performAction(identifier, filename, out); },
    	"Perform the action on the device with the file");
    

    You'll get the following help text:

     - do-something <device>
     - do-something <device> <filename>
    	Perform the action on the device with the file
    

    The implementation relies on std::apply() as specified by C++17 so I've relicensed a portion of my C++17 compatibility layer and included it for configurations where std::experimental::apply() isn't available.

    The reordering of the arguments in the command handler declaration, with the ostream parameter coming first is intentional. This is necessary to reduce ambiguity with the variadic arguments. If the description field is an empty string, an empty newline is not printed for that command. This makes it cleaner to specify overloads of command names that take slightly different arguments.

    opened by ghost 6
  • Replaced Boost.Asio with Asio (much smaller library)

    Replaced Boost.Asio with Asio (much smaller library)

    This was much easier than I expected. I basically just messed with the namespaces to rearrange things to depend on Asio instead of Boost. I had to change boost::system::error_code to std::error_code in a few places, but that's consistent with the other differences of Boost-less Asio. More info on that: https://think-async.com/Asio/AsioAndBoostAsio.html

    I wasn't able to get tests working immediately because I had some issues with my local Boost library. I did try the Windows examples, though, and they all worked!

    opened by connorjak 5
  • Examples fail to build with Boost 1.74

    Examples fail to build with Boost 1.74

    It looks like v1.2.0 is not compatible with ASIO that comes with Boost 1.74, or is there any flags that should be set when configuring ?

    In file included from /home/debionne/dev/boost/boost_1_74_0/boost/asio/executor.hpp:342,
                     from /home/debionne/dev/boost/boost_1_74_0/boost/asio.hpp:86,
                     from /home/debionne/dev/cli/include/cli/detail/newboostasio.h:33,
                     from /home/debionne/dev/cli/include/cli/detail/boostasio.h:43,
                     from /home/debionne/dev/cli/include/cli/cliasyncsession.h:34,
                     from /home/debionne/dev/cli/examples/asyncsession.cpp:30:
    /home/debionne/dev/boost/boost_1_74_0/boost/asio/impl/executor.hpp: In instantiation of ‘void boost::asio::executor::impl<...> >’ has no member named ‘on_work_started’
         executor_.on_work_started();
         ~~~~~~~~~~^~~~~~~~~~~~~~~
    
    bug help wanted 
    opened by sdebionne 5
  • Persistent history

    Persistent history

    It would be useful to (optionally) make persistent the cli history.

    The local session and each remote session should maintain its own history. But how to identify remote sessions? According to the client IP address? Or more simply by providing one history for the local session and just one for all the remote sessions? In this case, what happens when more than one client is connected simultaneously?

    Maybe we could start by providing persistent history just for the local session.

    enhancement 
    opened by daniele77 5
  • vcpkg does not have telnet server include files

    vcpkg does not have telnet server include files

    First off, thanks for the library.

    Looking at Github and what's installed as part of vcpkg shows that telnet server support is not included in vcpkg. May request for updated package with telnet support?

    suspended 
    opened by tukotech 4
  • Default input handler without specifying a command

    Default input handler without specifying a command

    Like the switch grammar, how about register a default handler for input? For example: just input three integers after the prompt, and then call the Add command by default.

    cli> 1 2 3 6 cli>

    It would be nice when a single command is massively used.

    BTW, cli now supports Insert a command name of std::string(""), but it seems this command would never be called.

    opened by EFS86340 4
  • Better character escaping / sentence support.

    Better character escaping / sentence support.

    I was tempted to use std::quoted, but it doesn't handle single quoted strings like shells do.

    Also, this particular form of escaping allows accepting json strings as input easily (because now we can do things like: '{"a": "b"}').

    opened by sakshamsharma 4
  • Backspace is not working in MobaXterm

    Backspace is not working in MobaXterm

    In putty the backspace int value is 127 but in MobaXterm (https://mobaxterm.mobatek.net/) the value is 8. Hence, the cli apps are not usable in MobaXterm.

    bug 
    opened by paulsubrata55 5
  • Differentiate features in vcpkg

    Differentiate features in vcpkg

    It looks like using Asio standalone instead of boost/asio has been mentioned but not conversed about; that would be a drop-in replacement for all the networking features from what I was able to see in the code. Asio has a TINY compile time compared to full boost.

    Another option for vcpkg users is to segment the remote cli features into a module, so you could vcpkg install cli or cli[with_remote].

    Originally posted by @connorjak in https://github.com/daniele77/cli/issues/41#issuecomment-703419813

    opened by daniele77 0
  • Add starting conanfile.py for conan packaging

    Add starting conanfile.py for conan packaging

    As mentioned in #113 I believe it would be useful to add conan support. I've added a conanfile.py recipe file in this commit. For the moment it is tied specifically to the 1.2.1 release and pulls the files from the tar.gz based on the tag.

    In order to use it in a conan enabled environment (like the docker image conanio/gcc10) run the command: conan create cli @/ to create a conan package which can be uploaded. Some notes about what is here:

    • The default usage attempts to build the examples and run the tests.
    • When the examples are built they are included in the package so while a header only library usually has one version this could have multiple. When the examples are not include it does go to a header only package id.
    • There is an option for whether or not you want to use boost. Currently this controls only if the examples are included the package because it seems the current examples build does not handle not having boost to only build the items that do not depend on it. Using the conan create command you can include changing the option like this: -o use_boost=False
    • The conan package changes how Boost unit tests are used in the case where Boost has only static libraries.

    I've tested this on the docker image noted above as well as a cross compile in docker image conanio/gcc6-armv7hf. When cross compiling the CONAN_RUN_TESTS env should be set since tests can run.

    Please let me know what you think.

    opened by rob-baily 0
  • Add support for packaging using conan

    Add support for packaging using conan

    Have been working with conan as a package manager and I like it! I think it would be useful to have this in Conan Center under https://conan.io/center/. To do this there is information at https://github.com/conan-io/conan-center-index/blob/master/docs/how_to_add_packages.md which is the repo where the recipe goes. I've created a simple recipe that works for me. I will create a pull request so it can be reviewed and I will cross reference with this for any discussion.

    enhancement help wanted 
    opened by rob-baily 8
  • Allow custom prompt for a menu

    Allow custom prompt for a menu

    The name you give in the menu construction is the command to change to the submenu but also the label for the prompt.

    It would be nice if you could have a different prompt though. Keep the command short so that it can be type easy and quick but give the the prompt a meaningful label providing more contextual info to the user.

    cf: Discussion #95

    //

    opened by grbba 0
Releases(v2.0.1)
  • v2.0.1(Apr 19, 2022)

    • Add a non-blocking exec method to schedulers (issue #127)
    • Add a Menu::Insert method working with free functions as handler
    • Cli::cout() returns a class derived from std::ostream
    • Fix address sanitizer issue with GenericAsioScheduler dtor
    • Fix teardown problem with linux (issue #132)
    • Fix teardown problem with windows
    • The prompt is no more shown after exit
    • Telnet server now works on MobaXTerm
    Source code(tar.gz)
    Source code(zip)
  • v2.0.0(Aug 25, 2021)

    • Remove boost dependency for local only sessions (issue #83)
    • Now you can use standalone asio library instead of boost asio for remote sessions (issue #41)
    • Fix missing echo after ctrl-v paste of command (issue #72)
    • Remove the symbol BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT (issue #89)
    • Fix unused parameters warning in release mode (issue #90)
    • Cli constructor revision (issue #75)
    • Special keys not recognized behaves like backspace in windows (issue #111)
    • Fix cmake install dependencies (issue #117)
    Source code(tar.gz)
    Source code(zip)
  • v1.2.1(Aug 27, 2020)

  • v1.2.0(Jun 27, 2020)

    • History persistence (issue #39)
    • Escaping and sentence support with quote and double quote
    • Remove boost dependency from cli.h: now, if you just use CliFileSession you don't need boost anymore
    • Support commands with a variable number of arguments through vector<string>
    • Handle CTRL-D (EOF) on linux
    • Handle CTRL-D, CTRL-Z and CTRL-C on windows
    • Consecutive identical commands are not stored in the history (issue #55)
    • Change message in case of wrong command
    • Fix Backspace from a remote terminal (issue #52)
    • Fix duplicate autocompletion (issue #67)
    • Add a namespace and folder "detail" (issue #17)
    Source code(tar.gz)
    Source code(zip)
  • v1.1.1(Sep 16, 2019)

    • Specify binding IP address in CliTelnetServer (issue #44)
    • Fix compilation with boost v. 1.70.0 (issue #40)
    • Fix assertion in History::Next() when buffer is empty (issue #47)
    • Fix compilation with older boost versions (< 1.66.0)
    • CMake generates cli.pc configuration file for pkg-config
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Apr 14, 2019)

    • Dynamically Remove/Disable/Enable commands and submenus (issue #15)
    • New variadic template method to add commands and menu (makes Add() deprecated)
    • Optionally delimitate string parameters by " (issue #38)
    • Explicitly set the names of parameters in help description
    • Unit tests
    • CMake support
    • Vcpkg support
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Feb 16, 2019)

    • Fix Clang 3.6 - 7.0 undefined reference bug
    • Fix infinite loop on EoF
    • Fix issue #27 (odd history behaviour): the history now works like in bash
    • Fix issue #28 (check for invalid stream in CliFileSession class)
    • Add doxygen basic configuration
    • Add session recordings in README file
    • Add CHANGELOG.md, CODE_OF_CONDUCT.md, CONTRIBUTING.md files
    Source code(tar.gz)
    Source code(zip)
Owner
Daniele Pallastrelli
Follow me on twitter at: @DPallastrelli
Daniele Pallastrelli
easy to use, powerful & expressive command line argument parsing for modern C++ / single header / usage & doc generation

clipp - command line interfaces for modern C++ Easy to use, powerful and expressive command line argument handling for C++11/14/17 contained in a sing

André Müller 872 May 11, 2022
A single header C++ library for parsing command line arguments and options with minimal amount of code

Quick Arg Parser Tired of unwieldy tools like getopt or argp? Quick Arg Parser is a single header C++ library for parsing command line arguments

null 44 Feb 21, 2022
null 76 Apr 18, 2022
C++ Library for pulling system and hardware information, without hitting the command line.

infoware C++ Library for pulling system and hardware information, without hitting the command line. Requirements No non-built-in ones by default. Some

The Phantom Derpstorm 278 May 13, 2022
A simple to use, composable, command line parser for C++ 11 and beyond

Clara v1.1.5 !! This repository is unmaintained. Go here for a fork that is somewhat maintained. !! A simple to use, composable, command line parser f

Catch Org 651 Apr 30, 2022
CLI11 is a command line parser for C++11 and beyond that provides a rich feature set with a simple and intuitive interface.

CLI11: Command line parser for C++11 What's new • Documentation • API Reference CLI11 is a command line parser for C++11 and beyond that provides a ri

null 2.1k May 10, 2022
Lightweight C++ command line option parser

Release versions Note that master is generally a work in progress, and you probably want to use a tagged release version. Version 3 breaking changes I

null 3.1k May 12, 2022
A simple to use, composable, command line parser for C++ 11 and beyond

Lyra A simple to use, composing, header only, command line arguments parser for C++ 11 and beyond. Obtain License Standards Stats Tests License Distri

Build Frameworks Group 337 May 8, 2022
CLIp is a clipboard emulator for a command line interface written in 100% standard C only. Pipe to it to copy, pipe from it to paste.

CLIp v2 About CLIp is a powerful yet easy to use and minimal clipboard manager for a command line environment, with no dependencies or bloat. Usage Sy

A.P. Jo. 12 Sep 18, 2021
pbr2gltf2 is a command line tool for converting PBR images to a glTF 2.0 material.

pbr2gltf2 is a command line tool for converting PBR images to a glTF 2.0 material. The tool is detecting depending on the filename, which PBR information is stored. It swizzles the images and does reassign the channels to a glTF 2.0 image. The tool stores the images plus a minimal, valid glTF 2.0 file containing the required material, textures and images.

UX3D GmbH 22 Jan 11, 2022
A command-line tool to display colorful distro information.

sjfetch A command-line tool to display colorful distro information.

Fikret Musk 6 Apr 6, 2022
LwSHELL is lightweight, platform independent, command line shell for embedded systems.

LwSHELL is lightweight, platform independent, command line shell for embedded systems. It targets communication with embedded systems from remote terminal to quickly send commands and the retrieve data from the device.

Tilen Majerle 47 May 6, 2022
Toybox: all-in-one Linux command line.

Toybox: all-in-one Linux command line.

Rob Landley 1.6k May 3, 2022
Simple command line tool that processes image files using the FidelityFX Super Resolution (FSR) or Contrast Adaptive Sharpening (CAS) shader systems.

Simple command line tool that processes image files using the FidelityFX Super Resolution (FSR) or Contrast Adaptive Sharpening (CAS) shader systems.

GPUOpen Effects 164 May 3, 2022
Command-line flag parsing in C

flag.h Inspired by Go's flag module: https://pkg.go.dev/flag WARNING! The design of the library is not finished and may be a subject to change. Quick

Tsoding 34 May 1, 2022
A command line tool with no external dependencies to print information about an X server instance.

xinfo A command line tool with no external dependencies to print information about an X server instance. Building and running To build the code in thi

Jean-Michel Gorius 6 Jan 13, 2022
Windows command line program for Spleeter, written in pure C, no need of Python.

SpleeterMsvcExe is a Windows command line program for Spleeter, which can be used directly. It is written in pure C language, using ffmpeg to read and write audio files, and using Tensorflow C API to make use of Spleeter models. No need to install Python environment, and it does not contain anything related to Python.

Wudi 146 May 4, 2022
Parse command line arguments by defining a struct

Parse command line arguments by defining a struct Quick Start #include <structopt/app.hpp> struct Options { // positional argument // e.g., .

Pranav 389 May 11, 2022
Rizin - UNIX-like reverse engineering framework and command-line toolset.

Rizin - UNIX-like reverse engineering framework and command-line toolset.

Rizin Organization 1.4k May 12, 2022