Skip to content

Commit 6abcee0

Browse files
author
Daniele Pallastrelli
committed
merge with master
2 parents 5e35fa7 + f8bdac4 commit 6abcee0

14 files changed

Lines changed: 419 additions & 68 deletions

File tree

.github/workflows/ccpp.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: C/C++ CI of Cli
2+
3+
on: [push,pull_request]
4+
5+
jobs:
6+
build:
7+
8+
runs-on: ubuntu-latest
9+
10+
steps:
11+
- uses: actions/checkout@v2
12+
- name: setup dependencies
13+
run: |
14+
sudo apt-get -y update
15+
sudo apt-get -y install libboost-all-dev
16+
- name: run cmake
17+
run: |
18+
mkdir build
19+
cd build
20+
cmake .. -DCLI_BuildTests=ON -DCLI_BuildExamples=ON
21+
- name: make
22+
run: |
23+
cd /home/runner/work/cli/cli/build
24+
make all
25+
- name: run tests
26+
run: |
27+
cd /home/runner/work/cli/cli/build/test
28+
./test_suite

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ Current Version: 1.1.1-dirty
66

77
- Consecutive identical commands are not stored in the history (issue #55)
88
- History persistence (issue #39)
9-
9+
- Change message in case of wrong command
10+
- Handle CTRL-D (EOF) on linux
11+
- Handle CTRL-D, CTRL-Z and CTRL-C on windows
12+
- Fix Backspace from remote terminal (issue #52)
13+
- Escaping and sentence support with quote and double quote
14+
- Fix duplicate autocompletion (issue #67)
15+
1016
## [1.1.1] - 2019-09-16
1117

1218
- Specify binding IP address in CliTelnetServer (issue #44)

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ A cross-platform header only C++14 library for interactive command line interfac
66

77
![demo_telnet_session](https://user-images.githubusercontent.com/5451767/51046612-d1dadc00-15c6-11e9-83c2-beadb3593348.gif)
88

9+
![C/C++ CI of Cli](https://github.com/daniele77/cli/workflows/C/C++%20CI%20of%20Cli/badge.svg)
10+
911
## Features
1012

1113
* Header only
@@ -93,6 +95,29 @@ Set the environment variable BOOST. Then, from a visual studio console, use the
9395
Set the environment variable BOOST. Then, open the file
9496
`cli/examples/examples.sln`
9597

98+
## CLI usage
99+
100+
The cli interpreter can manage correctly sentences using quote (') and double quote (").
101+
Any character (spaces too) comprises between quotes or double quotes are considered as a single parameter of a command.
102+
The characters ' and " can be used inside a command parameter by escaping them with a backslash.
103+
104+
Some example:
105+
106+
cli> echo "this is a single parameter"
107+
this is a single parameter
108+
cli> echo 'this too is a single parameter'
109+
this too is a single parameter
110+
cli> echo "you can use 'single quotes' inside double quoted parameters"
111+
you can use 'single quotes' inside double quoted parameters
112+
cli> echo 'you can use "double quotes" inside single quoted parameters'
113+
you can use "double quotes" inside single quoted parameters
114+
cli> echo "you can escape \"quotes\" inside a parameter"
115+
you can escape "quotes" inside a parameter
116+
cli> echo 'you can escape \'single quotes\' inside a parameter'
117+
you can escape 'single quotes' inside a parameter
118+
cli> echo "you can also show backslash \\ ... "
119+
you can also show backslash \ ...
120+
96121
## License
97122

98123
Distributed under the Boost Software License, Version 1.0.

examples/complete.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,20 @@ int main()
7171
},
7272
"Print the file descriptor specified",
7373
{"file_descriptor"} );
74+
rootMenu -> Insert(
75+
"echo", {"string to echo"},
76+
[](std::ostream& out, const string& arg)
77+
{
78+
out << arg << "\n";
79+
},
80+
"Print the string passed as parameter" );
81+
rootMenu -> Insert(
82+
"echo", {"first string to echo", "second string to echo"},
83+
[](std::ostream& out, const string& arg1, const string& arg2)
84+
{
85+
out << arg1 << ' ' << arg2 << "\n";
86+
},
87+
"Print the strings passed as parameter" );
7488
rootMenu -> Insert(
7589
"reverse", {"string_to_revert"},
7690
[](std::ostream& out, const string& arg)

include/cli/cli.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <vector>
3636
#include <memory>
3737
#include <functional>
38+
#include <algorithm>
3839
#include <cctype> // std::isspace
3940
#include <type_traits>
4041
#include <boost/lexical_cast.hpp>
@@ -44,7 +45,7 @@
4445
#include "historystorage.h"
4546
#include "localhistorystorage.h"
4647

47-
#define CLI_DEPRECATED_API
48+
// #define CLI_DEPRECATED_API
4849

4950
namespace cli
5051
{
@@ -224,7 +225,7 @@ namespace cli
224225
{
225226
public:
226227
CliSession(Cli& _cli, std::ostream& _out, std::size_t historySize = 100);
227-
~CliSession() { cli.UnRegister(out); }
228+
virtual ~CliSession() { cli.UnRegister(out); }
228229

229230
// disable value semantics
230231
CliSession(const CliSession&) = delete;
@@ -804,8 +805,8 @@ namespace cli
804805
VariadicFunctionCommand(
805806
const std::string& _name,
806807
F fun,
807-
const std::string& desc = "unknown command",
808-
const std::vector<std::string>& parDesc = {}
808+
const std::string& desc,
809+
const std::vector<std::string>& parDesc
809810
)
810811
: Command(_name), func(std::move(fun)), description(desc), parameterDesc(parDesc)
811812
{
@@ -898,7 +899,7 @@ namespace cli
898899
if (!found) found = current -> ScanCmds(std::move(strs), *this); // last use of strs
899900

900901
if (!found) // error msg if not found
901-
out << "Command unknown: " << cmd << "\n";
902+
out << "wrong command: " << cmd << "\n";
902903

903904
return;
904905
}
@@ -926,6 +927,12 @@ namespace cli
926927
auto v1 = globalScopeMenu->GetCompletions(currentLine);
927928
auto v3 = current->GetCompletions(currentLine);
928929
v1.insert(v1.end(), std::make_move_iterator(v3.begin()), std::make_move_iterator(v3.end()));
930+
931+
// removes duplicates (std::unique requires a sorted container)
932+
std::sort(v1.begin(), v1.end());
933+
auto ip = std::unique(v1.begin(), v1.end());
934+
v1.resize(std::distance(v1.begin(), ip));
935+
929936
return v1;
930937
}
931938

include/cli/inputdevice.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
namespace cli
3838
{
3939

40-
enum class KeyType { ascii, up, down, left, right, backspace, canc, home, end, ret, ignored };
40+
enum class KeyType { ascii, up, down, left, right, backspace, canc, home, end, ret, eof, ignored };
4141

4242
class InputDevice
4343
{

include/cli/inputhandler.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ class InputHandler
6666
{
6767
break;
6868
}
69+
case Symbol::eof:
70+
{
71+
session.Exit();
72+
break;
73+
}
6974
case Symbol::command:
7075
{
7176
session.Feed(s.second);

include/cli/linuxkeyboard.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ class LinuxKeyboard : public InputDevice
8080
int ch = getchar();
8181
switch( ch )
8282
{
83+
case EOF:
84+
case 4: // EOT
85+
return std::make_pair(KeyType::eof,' ');
86+
break;
8387
case 127: return std::make_pair(KeyType::backspace,' '); break;
8488
case 10: return std::make_pair(KeyType::ret,' '); break;
8589
case 27: // symbol

include/cli/remotecli.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,12 @@ class CliTelnetSession : public InputDevice, public TelnetSession, public CliSes
465465
case Step::_1:
466466
switch( c )
467467
{
468-
case 127: Notify(std::make_pair(KeyType::backspace,' ')); break;
468+
case EOF:
469+
case 4: // EOT
470+
Notify(std::make_pair(KeyType::eof,' ')); break;
471+
case 8: // Backspace
472+
case 127: // Backspace or Delete
473+
Notify(std::make_pair(KeyType::backspace, ' ')); break;
469474
//case 10: Notify(std::make_pair(KeyType::ret,' ')); break;
470475
case 27: step = Step::_2; break; // symbol
471476
case 13: step = Step::wait_0; break; // wait for 0 (ENTER key)
@@ -494,13 +499,13 @@ class CliTelnetSession : public InputDevice, public TelnetSession, public CliSes
494499
case Step::_3: // got 27 and 91
495500
switch( c )
496501
{
497-
case 51: step = Step::_4; break; // not arrow keys
498502
case 65: step = Step::_1; Notify(std::make_pair(KeyType::up,' ')); break;
499503
case 66: step = Step::_1; Notify(std::make_pair(KeyType::down,' ')); break;
500504
case 68: step = Step::_1; Notify(std::make_pair(KeyType::left,' ')); break;
501505
case 67: step = Step::_1; Notify(std::make_pair(KeyType::right,' ')); break;
502506
case 70: step = Step::_1; Notify(std::make_pair(KeyType::end,' ')); break;
503507
case 72: step = Step::_1; Notify(std::make_pair(KeyType::home,' ')); break;
508+
default: step = Step::_4; break; // not arrow keys
504509
}
505510
break;
506511

0 commit comments

Comments
 (0)