Skip to content

Commit f4aa1e9

Browse files
committed
Merge branch 'develop'
2 parents 5133373 + af5db6e commit f4aa1e9

File tree

4 files changed

+104
-71
lines changed

4 files changed

+104
-71
lines changed

modules/terminal/impl/terminal.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ Terminal::Impl::Impl(event::Loop *wp_loop)
5050
"Welcome to cpp-tbox terminal.\r\n";
5151

5252
root_token_ = nodes_.alloc(new DirNode("this is root node"));
53+
54+
registerBuildinCmds();
5355
}
5456

5557
Terminal::Impl::~Impl()
@@ -69,6 +71,19 @@ Terminal::Impl::~Impl()
6971
nodes_.clear();
7072
}
7173

74+
void Terminal::Impl::registerBuildinCmds()
75+
{
76+
using namespace std::placeholders;
77+
buildin_cmd_map_["cd"] = std::bind(&Terminal::Impl::executeCdCmd, this, _1, _2);
78+
buildin_cmd_map_["ls"] = std::bind(&Terminal::Impl::executeLsCmd, this, _1, _2);
79+
buildin_cmd_map_["tree"] = std::bind(&Terminal::Impl::executeTreeCmd, this, _1, _2);
80+
buildin_cmd_map_["exit"] = std::bind(&Terminal::Impl::executeExitCmd, this, _1, _2);
81+
buildin_cmd_map_["quit"] = std::bind(&Terminal::Impl::executeExitCmd, this, _1, _2);
82+
buildin_cmd_map_["help"] = std::bind(&Terminal::Impl::executeHelpCmd, this, _1, _2);
83+
buildin_cmd_map_["pwd"] = std::bind(&Terminal::Impl::executePwdCmd, this, _1, _2);
84+
buildin_cmd_map_["history"] = std::bind(&Terminal::Impl::executeHistoryCmd, this, _1, _2);
85+
}
86+
7287
SessionToken Terminal::Impl::newSession(Connection *wp_conn)
7388
{
7489
auto s = session_ctx_pool_.alloc();

modules/terminal/impl/terminal.h

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#ifndef TBOX_TELNETD_TERMINAL_IMPL_H_20220128
2121
#define TBOX_TELNETD_TERMINAL_IMPL_H_20220128
2222

23+
#include <map>
24+
2325
#include <tbox/base/cabinet.hpp>
2426
#include <tbox/base/object_pool.hpp>
2527
#include <tbox/event/forward.h>
@@ -62,6 +64,10 @@ class Terminal::Impl {
6264
void setWelcomeText(const std::string &text) { welcome_text_ = text; }
6365

6466
protected:
67+
using BuildinCmdMap = std::map<std::string, std::function<bool(SessionContext*, const Args &)>>;
68+
69+
void registerBuildinCmds();
70+
6571
void onChar(SessionContext *s, char ch);
6672
void onEnterKey(SessionContext *s);
6773
void onBackspaceKey(SessionContext *s);
@@ -80,22 +86,23 @@ class Terminal::Impl {
8086
bool execute(SessionContext *s);
8187
bool executeCmd(SessionContext *s, const std::string &cmdline);
8288

83-
void executeCdCmd(SessionContext *s, const Args &args);
84-
void executeHelpCmd(SessionContext *s, const Args &args);
85-
void executeLsCmd(SessionContext *s, const Args &args);
86-
void executeHistoryCmd(SessionContext *s, const Args &args);
87-
void executeExitCmd(SessionContext *s, const Args &args);
88-
void executeTreeCmd(SessionContext *s, const Args &args);
89-
void executePwdCmd(SessionContext *s, const Args &args);
89+
bool executeCdCmd(SessionContext *s, const Args &args);
90+
bool executeHelpCmd(SessionContext *s, const Args &args);
91+
bool executeLsCmd(SessionContext *s, const Args &args);
92+
bool executeHistoryCmd(SessionContext *s, const Args &args);
93+
bool executeExitCmd(SessionContext *s, const Args &args);
94+
bool executeTreeCmd(SessionContext *s, const Args &args);
95+
bool executePwdCmd(SessionContext *s, const Args &args);
9096
bool executeRunHistoryCmd(SessionContext *s, const Args &args);
91-
void executeUserCmd(SessionContext *s, const Args &args);
97+
bool executeUserCmd(SessionContext *s, const Args &args);
9298

9399
bool findNode(const std::string &path_str, Path &node_path) const;
94100
//! 从指定会话的当前路径寻找path_str对像的结点;如果不指定,则从根目录寻找
95101
NodeToken findNode(const std::string &path_str, SessionContext *s) const;
96102

97103
private:
98104
event::Loop *wp_loop_ = nullptr;
105+
BuildinCmdMap buildin_cmd_map_;
99106

100107
ObjectPool<SessionContext> session_ctx_pool_{1};
101108
cabinet::Cabinet<SessionContext> sessions_;

modules/terminal/impl/terminal_commands.cpp

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -64,31 +64,18 @@ bool Terminal::Impl::executeCmd(SessionContext *s, const std::string &cmdline)
6464
return true;
6565
}
6666

67-
const auto &cmd = args[0];
68-
if (cmd == "ls") {
69-
executeLsCmd(s, args);
70-
} else if (cmd == "pwd") {
71-
executePwdCmd(s, args);
72-
} else if (cmd == "cd") {
73-
executeCdCmd(s, args);
74-
} else if (cmd == "help") {
75-
executeHelpCmd(s, args);
76-
} else if (cmd == "history") {
77-
executeHistoryCmd(s, args);
78-
return false; //! 查看历史命令不要再存历史
79-
} else if (cmd == "exit" || cmd == "quit") {
80-
executeExitCmd(s, args);
81-
} else if (cmd == "tree") {
82-
executeTreeCmd(s, args);
67+
auto &cmd = args[0];
68+
auto iter = buildin_cmd_map_.find(cmd);
69+
if (iter != buildin_cmd_map_.end()) {
70+
return iter->second(s, args);
8371
} else if (cmd[0] == '!') {
8472
return executeRunHistoryCmd(s, args);
8573
} else {
86-
executeUserCmd(s, args);
74+
return executeUserCmd(s, args);
8775
}
88-
return true;
8976
}
9077

91-
void Terminal::Impl::executeCdCmd(SessionContext *s, const Args &args)
78+
bool Terminal::Impl::executeCdCmd(SessionContext *s, const Args &args)
9279
{
9380
string path_str = "/";
9481
if (args.size() >= 2)
@@ -113,13 +100,14 @@ void Terminal::Impl::executeCdCmd(SessionContext *s, const Args &args)
113100
}
114101

115102
s->wp_conn->send(s->token, oss.str());
103+
return true;
116104
}
117105

118-
void Terminal::Impl::executeHelpCmd(SessionContext *s, const Args &args)
106+
bool Terminal::Impl::executeHelpCmd(SessionContext *s, const Args &args)
119107
{
120108
if (args.size() < 2) {
121109
printHelp(s);
122-
return;
110+
return true;
123111
}
124112

125113
ostringstream oss;
@@ -140,9 +128,10 @@ void Terminal::Impl::executeHelpCmd(SessionContext *s, const Args &args)
140128
}
141129

142130
s->wp_conn->send(s->token, oss.str());
131+
return true;
143132
}
144133

145-
void Terminal::Impl::executeLsCmd(SessionContext *s, const Args &args)
134+
bool Terminal::Impl::executeLsCmd(SessionContext *s, const Args &args)
146135
{
147136
string path_str = ".";
148137
if (args.size() >= 2)
@@ -171,7 +160,6 @@ void Terminal::Impl::executeLsCmd(SessionContext *s, const Args &args)
171160
oss << '/';
172161
oss << "\r\n";
173162
}
174-
oss << "\r\n";
175163
} else {
176164
oss << path_str << " is function" << ".\r\n";
177165
}
@@ -180,19 +168,21 @@ void Terminal::Impl::executeLsCmd(SessionContext *s, const Args &args)
180168
}
181169

182170
s->wp_conn->send(s->token, oss.str());
171+
return true;
183172
}
184173

185-
void Terminal::Impl::executeHistoryCmd(SessionContext *s, const Args &)
174+
bool Terminal::Impl::executeHistoryCmd(SessionContext *s, const Args &)
186175
{
187176
ostringstream oss;
188177
for (size_t i = 0; i < s->history.size(); ++i) {
189178
const auto &cmd = s->history.at(i);
190179
oss << setw(2) << i << " " << cmd << "\r\n";
191180
}
192181
s->wp_conn->send(s->token, oss.str());
182+
return false;
193183
}
194184

195-
void Terminal::Impl::executeExitCmd(SessionContext *s, const Args &)
185+
bool Terminal::Impl::executeExitCmd(SessionContext *s, const Args &)
196186
{
197187
if (!(s->options & kQuietMode))
198188
s->wp_conn->send(s->token, "Bye!\r\n");
@@ -204,9 +194,11 @@ void Terminal::Impl::executeExitCmd(SessionContext *s, const Args &)
204194
},
205195
__func__
206196
);
197+
198+
return false;
207199
}
208200

209-
void Terminal::Impl::executeTreeCmd(SessionContext *s, const Args &args)
201+
bool Terminal::Impl::executeTreeCmd(SessionContext *s, const Args &args)
210202
{
211203
string path_str = ".";
212204
if (args.size() >= 2)
@@ -314,9 +306,10 @@ void Terminal::Impl::executeTreeCmd(SessionContext *s, const Args &args)
314306
}
315307

316308
s->wp_conn->send(s->token, oss.str());
309+
return true;
317310
}
318311

319-
void Terminal::Impl::executePwdCmd(SessionContext *s, const Args &)
312+
bool Terminal::Impl::executePwdCmd(SessionContext *s, const Args &)
320313
{
321314
ostringstream oss;
322315
oss << '/';
@@ -327,6 +320,7 @@ void Terminal::Impl::executePwdCmd(SessionContext *s, const Args &)
327320
}
328321
oss << "\r\n";
329322
s->wp_conn->send(s->token, oss.str());
323+
return true;
330324
}
331325

332326
bool Terminal::Impl::executeRunHistoryCmd(SessionContext *s, const Args &args)
@@ -337,7 +331,7 @@ bool Terminal::Impl::executeRunHistoryCmd(SessionContext *s, const Args &args)
337331
return execute(s);
338332
}
339333

340-
size_t index = 0;
334+
int index = 0;
341335

342336
if (util::StringTo(sub_cmd, index)) {
343337
bool is_index_valid = false;
@@ -366,7 +360,7 @@ bool Terminal::Impl::executeRunHistoryCmd(SessionContext *s, const Args &args)
366360
return false;
367361
}
368362

369-
void Terminal::Impl::executeUserCmd(SessionContext *s, const Args &args)
363+
bool Terminal::Impl::executeUserCmd(SessionContext *s, const Args &args)
370364
{
371365
ostringstream oss;
372366

@@ -391,6 +385,7 @@ void Terminal::Impl::executeUserCmd(SessionContext *s, const Args &args)
391385
}
392386

393387
s->wp_conn->send(s->token, oss.str());
388+
return true;
394389
}
395390

396391
}

modules/terminal/impl/terminal_key_events.cpp

Lines changed: 50 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ void Terminal::Impl::onDeleteKey(SessionContext *s)
122122
*/
123123
void Terminal::Impl::onTabKey(SessionContext *s)
124124
{
125+
//! 不带回显的终端不能支持补全功能
126+
if ((s->options & kEnableEcho) == 0)
127+
return;
128+
125129
//! 如果当前用户没有任何输入,则不进行补全
126130
if (s->curr_input.empty() || s->cursor_pos == 0)
127131
return;
@@ -194,69 +198,81 @@ void Terminal::Impl::onTabKey(SessionContext *s)
194198

195199
vector<string> matched_node_name_vec;
196200
if (auto dir_node = dynamic_cast<DirNode*>(base_node)) {
201+
//! 先获取目录下的所有结点
197202
vector<NodeInfo> children_info_vec;
198203
dir_node->children(children_info_vec);
199204

200-
//! 遍历dir_node下有所有子结点,找出匹配得上的,加入到matched_node_name_vec中
205+
//! 遍历所有子结点,找出匹配得上的,加入到matched_node_name_vec中
201206
for (const auto& child_info : children_info_vec) {
202-
if (util::string::IsStartWith(child_info.name, prefix))
203-
matched_node_name_vec.push_back(child_info.name);
207+
auto node_name = child_info.name;
208+
if (util::string::IsStartWith(node_name, prefix)) {
209+
Node* child_node = nodes_.at(child_info.token);
210+
if (child_node && child_node->type() == NodeType::kDir)
211+
node_name.push_back('/');
212+
matched_node_name_vec.push_back(node_name);
213+
}
214+
}
215+
216+
if (!prefix.empty()) {
217+
//! 检查是否与内建命令匹配,如何有,也加入到matched_node_name_vec中
218+
for (const auto & buildin_cmd : buildin_cmd_map_) {
219+
auto &cmd_name = buildin_cmd.first;
220+
if (util::string::IsStartWith(cmd_name, prefix))
221+
matched_node_name_vec.push_back(cmd_name);
222+
}
204223
}
205224
}
206225

207226
//! 如果没有找到匹配项,直接结束
208227
if (matched_node_name_vec.empty())
209228
return;
210229

211-
string completion; //! 补全内容
212-
213230
//! 如果只有一个匹配,直接补全
214231
if (matched_node_name_vec.size() == 1) {
215232
const auto &match_node_name = matched_node_name_vec.back();
216-
completion = match_node_name.substr(prefix.length()); //! 需要补全的字串
233+
auto completion = match_node_name.substr(prefix.length()); //! 需要补全的字串
217234

218235
//! 如果不需要补全,则结束
219236
if (completion.empty())
220237
return;
221238

222-
//! 检查是否为目录,如果是则添加/
223-
NodeToken child_token = findNode(dir_path + "/" + match_node_name, s);
224-
if (!child_token.isNull()) {
225-
Node* child_node = nodes_.at(child_token);
226-
if (child_node && child_node->type() == NodeType::kDir) {
227-
completion.push_back('/');
228-
}
229-
}
239+
s->curr_input.insert(s->cursor_pos, completion);
240+
s->cursor_pos += completion.length();
241+
242+
s->wp_conn->send(s->token, completion);
230243

231-
} else {
232-
//! 多个匹配,显示所有可能
233244
ostringstream oss;
234-
oss << "\r\n";
235-
for (const auto& match : matched_node_name_vec)
236-
oss << match << "\t";
237-
oss << "\r\n";
245+
oss << s->curr_input.substr(s->cursor_pos)
246+
<< string((s->curr_input.size() - s->cursor_pos), '\b');
247+
248+
auto refresh_str = oss.str();
249+
if (!refresh_str.empty())
250+
s->wp_conn->send(s->token, refresh_str);
251+
252+
} else {
253+
{
254+
//! 多个匹配,显示所有可能
255+
ostringstream oss;
256+
oss << "\r\n";
257+
for (const auto& match : matched_node_name_vec)
258+
oss << match << " ";
259+
oss << "\r\n";
238260

239-
if (s->options & kEnableEcho) {
240261
s->wp_conn->send(s->token, oss.str());
241-
printPrompt(s);
242-
s->wp_conn->send(s->token, s->curr_input);
243262
}
244263

245-
//! 找出最大共同字串,设置补全内容
246-
std::string common_prefix = util::string::ExtractCommonPrefix(matched_node_name_vec);
247-
completion = common_prefix.substr(prefix.length()); //! 需要补全的字串
248-
}
264+
printPrompt(s);
249265

250-
//! 如果需要补全,则进行补全
251-
if (!completion.empty()) {
252-
s->curr_input.insert(s->cursor_pos, completion);
253-
s->cursor_pos += completion.length();
266+
{
267+
//! 找出最大共同字串,补全内容
268+
auto common_prefix = util::string::ExtractCommonPrefix(matched_node_name_vec);
269+
auto completion = common_prefix.substr(prefix.length()); //! 需要补全的字串
254270

255-
if (s->options & kEnableEcho) {
256-
s->wp_conn->send(s->token, completion);
271+
s->curr_input.insert(s->cursor_pos, completion);
272+
s->cursor_pos += completion.length();
257273

258274
ostringstream oss;
259-
oss << s->curr_input.substr(s->cursor_pos)
275+
oss << s->curr_input
260276
<< string((s->curr_input.size() - s->cursor_pos), '\b');
261277

262278
auto refresh_str = oss.str();

0 commit comments

Comments
 (0)