daniele77 / cli Goto Github PK
View Code? Open in Web Editor NEWA library for interactive command line interfaces in modern C++
License: Boost Software License 1.0
A library for interactive command line interfaces in modern C++
License: Boost Software License 1.0
When you have many results of autocompletion that have the same prefix, pressing the tab key should autocomplete with the whole common prefix.
E.g.,
commands: hello, hello_everybody available
When you digit "hel" and press the tab key, the cli should autocomplete with "hello" (the common prefix)
Arrow and tab keys should work also from a telnet session
Using tab key should autocomplete the input
The library currently supports only arguments of type:
std::vector<std::string>
However, I see two big improvements:
int
variable that can only assume the values: {-1000, 0, 1000}
or a std::string
that can only assume the values: {"red", "green", "blue"}
).See also #157
Gist:
My particular use-case requires using a custom event dispatcher that selects on file descriptors. I spent a lot of time trying to make that happen with boost::asio::io_service
, and concluded that it can't be done (correct me if I'm wrong).
So I'm proposing something different. Allow passing a custom wrapper type instead of boost::asio::io_service
to the CliLocalTerminalSession and other objects. This can be done via a template argument defaulting to io_service
, or it can be done by expecting a virtual interface that can be pre-implemented for io_service
in a helper header.
I can pick this up myself as well when I get time, if there are no objections to the direction.
Basically what I would like to do in my custom wrapper interface / type is: I would make a pipe file descriptor dirty before actually calling Post
on the io_service. In my main thread, the dispatcher would be calling select
on the other end of the pipe (another file descriptor). It would then call poll
on the io_service
.
Boost Version: 1.70.0
OS: Debian GNU/Linux 9 (stretch) 64-bit / Gnome Version 3.22.2
Error Message:
/home/adem/LibSrc/cli/include/cli/remotecli.h:446:28: error: ‘boost::asio::ip::tcp::socket {aka class boost::asio::basic_stream_socket<boost::asio::ip::tcp>}’ has no member named ‘get_io_service’
InputDevice(socket.get_io_service()),
^~~~~~~~~~~~~~
examples/CMakeFiles/complete.dir/build.make:62: recipe for target 'examples/CMakeFiles/complete.dir/complete.cpp.o' failed
Take advantage of unique_ptr and move.
Remove cxx0x.h header file.
Hide implementation in a folder and namespace "detail"
It looks like backspace may not be properly handled (at least on Windows with the Windows telnet client). With a debugger I can see '\b'
in the strings that are matched to commands or arguments. Backspace is properly echoed though. Might be an issue with the telnet client and its configuration.
If the same command name is used with different arity, the autocompletion (tab) shows the command duplicated.
How hard would it be to extend it to allow completion also for arguments?
Let's say, for example, I have an command, that can only be called in the following way to be valid:
set_state RUNNING
, set_state WAITING
and set_state TERMINATED
.
I want to have completion of set_state R
to set_state RUNNING
in this case.
In Linux (and with putty as a telnet client on windows), some keyboard keys don't work (àèéùò"£).
In windows, the arrows in the numeric pad don't work.
Linked to this problem, is the backspace that after non-English keys misbehave.
In particular (x = doesn't work):
nocolor color
special char backspace special char backspace
win local
win telnet client
win putty client X
linux locale X X
linux telnet X X
Please note that the problem with non-English keys is only in the local echo of the characters because the cli engine receive the correct input string instead.
Putty on windows should be configured as following:
terminal -> Local echo: "Force off"
terminal -> Local line editing: "Force off"
The class CliFileSession does not check for invalid streams passed as argument (for input and output).
Should add the check.
Restore the possibility to feed the cli directly with user strings (without the special key handling) and check that AsyncInput class is still working.
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.
Hi @daniele77.
Do you believe it would be easy to add authentication to the library?. I know the scope of such a feature can be huge (for instance, supporting multiple authentication mechanisms, supporting multiple users, supporting different set of commands based on permissions and so on), but we could start with a simple scope, something easy like storing a local credentials file (like htpasswd).
My main concern is that right now any APP using the telnet server is open to the public, and the only way to restrict access is protecting it with networking workarounds like firewall rules. What do you think?
Thanks,
(and any other non-posix OS) Due to this line
https://github.com/daniele77/cli/blob/master/cli/cliasyncsession.h#L90
Could possibly give a diagnostic?
#if _WIN32
#error "Currently not supported. #issue"
#endif
//or
#if !__has_include(<unistd.h>)
#error "Currently not supported. #issue"
#endif
Of the compilers on Godbolt that support C++14 but not __has_include are gcc 4.9.0 and 4.9.1
Edit: 🤦♂️ just realised that Boost has several macros to be able to test for this...
Currently, every library message printed to the user (eg help, errors, ...) is in english.
It would be nice to let the user to (optionally) specify those strings at library initialization.
Hello. I really like your library, thanks for it. I'm confident it will get better as more functionalities are added.
I am actually using it on an new project, but I am facing the following issue: I need to bind the telnet server to a single address for security reasons. I was checking the source code, but I think that currently it cann't be controlled when creating a CliTelnetServer instance. It seems to listen in all available interfaces by default, am I right?
https://github.com/daniele77/cli/blob/master/include/cli/server.h#L126
If that's the case, can we add a constructor that will allow the developer to specify the IP address he wants the server to listen to? I am willing to help with this PR.
Thanks.
It's useful adding and removing commands and submenus during the working session. For example, when loading/unloading a plugin at run-time we should be able to add/remove the related cli commands.
To implement this, maybe we should get rid of std::unique_ptr for commands and menus. We need to return an handle when adding commands/submenus, to remove them at a later time.
Actually it's not so clear when the exit actions (cli, session, server) are called.
Consider to differentiate the prompt, the output and the input with colors.
Colors should be optional and customizable, possibly using a policy (template)
Nice work! How much would be needed to remove the boost dependency?
Memorize in a circular queue the commands with valid syntax.
Add an optional command to show the history.
Hello. I would like to ask if there is a way to avoid storing the same command over and over on history. If it is not possible right now, can you please provide some hint on the relevant classes/functions to modify to make it work? I will be willing to add it and send a PR. Thanks.
Hi.
Keys tab, up, down, left, right, backspace, home, end do not work in examples (asyncsession.cpp, simplesession.cpp).
I delete telnet session from complete.cpp, but the program ended immediately.
When you register a callback for a command, you get an output stream to provide output on the terminal you gave the command.
It would be useful to provide a "global" output stream (e.g., on the Cli class) to output "broadcast" messages on all the sessions (including remotes one).
Be careful that the global output can be asyncronous, and this could interfere with colors and autocompletion.
It could be useful if the same command name can have a different number of parameters / different parameter types.
e.g.,
show
show interfaces
show interface 42
Running the server on either Windows or Linux, I can't make the server echo the commands (or the autocompletion). Is this something that is not impelemented yet? A quick grep on the codebase finds a void TelnetSession::Echo( char c )
that is commented.
Pressing arrow up / arrow down on the local sessione should navigate the history
Hello.
I am facing issues with autocompletion. I noticed it works as expected when using a telnet session, but I tested all the other ones (local, file, async) and everytime I try to autocomplete, only the tab is printed as any other character, and the cli gets messed up.
I thought I was doing something wrong, but I tested the examples (generated following the README.md instructions) and experienced the same behavior. I also tested both latest master and v1.1.0 tags.
I am testing using Ubuntu 18.04. Boost version is 1.68. I observe the same behavior in regular terminal as inside vscode terminal. I this a bug, or I am doing something wrong?
Thanks in advance
Given the sequence of (valid) commands:
Using the arrow up key we get the history:
And that's ok. From here, if we use the arrow down key we get:
instead of the right sequence:
Using putty terminal with the following settings:
terminal -> Local echo: "Force off"
terminal -> Local line editing: "Force off"
after enabling terminal color (e.g., with the command color
in the complete example
), some characters ('ò', 'à', 'è', 'é', 'ù', '£') are not echoed correctly on the screen.
Instead, backspace key does not work correctly when the characters 'ò', 'à', 'è', 'é', 'ù', '£' are echoed correctly: the backspace keeps erasing characters even after the start of the prompt...
icli
Hi,
i am running a gateway fw as a service on an 'bionic-armhf' machine (ubuntu 18.04 TLS).
this service acts as the cli server (like in the 'complete' example).
when trying to telnet, it stuck and takes forever to respond.
when running the gateway fw from bash (not as a service), the telnet works just fine.
any idea?
i might have some clue:
when running the complete example as a service, the cpu usage is ~98%.
when running it from bash, the cpu usage is ~1%.
Currently, you cannot use strings with spaces as parameters to commands. It would be useful to use the symbol " to optionally delimitate a string argument.
Of course, it should be provided an escape mechanism also.
Consider to provide one header file that contains the others.
It could be useful to have two header file: one for the local session and one for the telnet server (or one for the core and the other for the asio part)
Is it possible to get some context related to the session in the function defined for the menu? One example would be a menu command to enable / disable debug output but only on that session - it wouldn't affect all sessions connected.
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
Steps to reproduce
examples/pluginmanager
cli> pluginmanager: include/cli/history.h:99: std::string cli::detail::History::Next(): Assertion `current < buffer.size()' failed.
Aborted
Add the keyboard management for windows, to make work history and autocompletion.
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.
When you have a menu structure like this:
main
submenu
cmd1
cmd2
and you're in the main
menu, the TAB
key should autocomplete with:
submenu
submenu cmd1
submenu cmd2
When you have the colors on and you edit a line by deleting a character, the part of the string following the edit becomes not colored.
This happens both with CANC and BACKSPACE keys.
Entering a line of the kind:
<menu> <cmd>
Should be the same as
<menu>
<cmd>
Would be great to use this library with cmake/vcpkg
Make AsyncCli working both on linux (with boost async file descriptor) and on windows (spawning a std::thread).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.