semf
shell.cpp
Go to the documentation of this file.
1
12#include <algorithm>
13#include <string>
14
15namespace semf::esh
16{
17Shell::Shell(UartHardware& uart, const Config& config)
18: m_config{config},
19 m_history(config.historyBuffer, config.numberOfEntries, config.lineBufferSize),
20 m_printer(uart),
21 m_tab(m_printer, m_commands, config.lineBuffer, config.lineBufferSize, config.prompt),
22 m_processor(m_commands, m_printer, config.lineBuffer, config.lineBufferSize, config.argvBuffer, config.argvBufferSize),
23 m_arrow(m_printer, m_count, config.echo)
24{
25 m_printer.error.connect(m_onErrorSlot);
26 m_arrow.up.connect(m_onArrowUpSlot);
27 m_arrow.down.connect(m_onArrowDownSlot);
28 m_arrow.error.connect(m_onErrorSlot);
29 m_tab.error.connect(m_onErrorSlot);
30 m_tab.done.connect(m_onTabDoneSlot);
31 m_processor.error.connect(m_onErrorSlot);
32}
33
35{
36 m_commands.pushBack(cmd);
37}
38
40{
41 m_printer.dataWritten.disconnect(m_restartShell);
42 m_printer.dataWritten.connect(m_readNextCharSlot);
43 m_printer.print(m_config.prompt);
44}
45
47{
48 m_processor.execLoadedCommand();
49}
50
51void Shell::onCharAvailable(char character)
52{
53 m_printer.dataAvailable.disconnect(m_onCharAvailableSlot);
54 switch (character)
55 {
56 case '\r':
57 case '\n':
58 m_config.lineBuffer[m_count] = 0;
59 m_history.insert(m_config.lineBuffer);
60 m_processor.done.connect(m_onExecutedSlot);
61 m_processor.loadCommand();
62 break;
63 case kDelete:
64 case '\b':
65 if (m_count == 0)
66 {
67 readNextCharacter();
68 return;
69 }
70 m_count--;
71 m_config.lineBuffer[m_count] = 0;
72
73 m_printer.dataWritten.connect(m_readNextCharSlot);
74 m_printer.print("\b \b", m_config.echo ? 1 : 3);
75
76 break;
77 case kEscape:
78 m_arrow.start();
79 break;
80 case '\t':
81 m_tab.start(m_count);
82 break;
83 default:
84 m_config.lineBuffer[m_count++] = character;
85 if (m_config.echo && character != kDelete && character != '\b')
86 {
87 m_printer.dataWritten.connect(m_readNextCharSlot);
88 m_printer.print(character, 1);
89 }
90 else
91 {
92 readNextCharacter();
93 }
94 break;
95 }
96}
97void Shell::onTabDone(size_t charCount)
98{
99 if (charCount != 0)
100 {
101 m_count = charCount;
102 }
103 readNextCharacter();
104}
105
106void Shell::onExecuted()
107{
108 m_processor.done.disconnect(m_onExecutedSlot);
109 m_printer.dataWritten.connect(m_restartShell);
110 std::fill(m_config.lineBuffer, m_config.lineBuffer + m_config.lineBufferSize, 0);
111 m_count = 0;
112 m_printer.print("\r\n");
113}
114
115void Shell::onArrowUp()
116{
117 m_history.handleArrowUp(m_config.lineBuffer);
118 updateStateAndPrint();
119}
120void Shell::onArrowDown()
121{
122 m_history.handleArrowDown(m_config.lineBuffer);
123 updateStateAndPrint();
124}
125
126void Shell::updateStateAndPrint()
127{
128 m_count = std::char_traits<char>::length(m_config.lineBuffer);
129 m_printer.dataWritten.connect(m_readNextCharSlot);
130 m_printer.print(m_config.lineBuffer);
131}
132
133void Shell::onError(Error error)
134{
135 if (error.classId() == Error::ClassID::ArrowControl && (error.errorCode() == static_cast<uint8_t>(ArrowControl::ErrorCode::OnSecondChar_UnexpectedChar) ||
136 error.errorCode() == static_cast<uint8_t>(ArrowControl::ErrorCode::OnThirdChar_UnexpectedChar)))
137 {
138 m_printer.dataAvailable.connect(m_onCharAvailableSlot);
139 m_printer.readCharacter();
140 }
141 else
142 {
143 this->error(error);
144 }
145}
146
147void Shell::readNextCharacter()
148{
149 m_printer.dataWritten.disconnect(m_readNextCharSlot);
150 m_printer.dataAvailable.connect(m_onCharAvailableSlot);
151 m_printer.readCharacter();
152}
153} // namespace semf::esh
Class for using UART hardware.
Definition: uarthardware.h:22
void start()
Starts the reading process.
Wrapper class for shell command. The user has to create object of this class for adding their functio...
Definition: command.h:28
void insert(std::string_view command)
Inserts a command.
Definition: history.cpp:25
void handleArrowUp(char commandBuffer[])
Performes a lookup based on an up-arrow key stroke.
Definition: history.cpp:37
void handleArrowDown(char commandBuffer[])
Performes a lookup based on an down-arrow key stroke.
Definition: history.cpp:52
void print(char character, size_t count)
Prints a single character count times.
Definition: printer.cpp:20
void readCharacter()
Triggers a read cyle for reading a single character.
Definition: printer.cpp:58
void loadCommand()
Load a command for execution according to the current command line.
Definition: processor.cpp:27
void execLoadedCommand()
Execute the currenty loaded command. Returns with no error if no command is loaded....
Definition: processor.cpp:56
void start()
Starts the reading process of the shell. The user should call this function once.
Definition: shell.cpp:39
void addCommand(Command &cmd)
Adds a command to the shell.
Definition: shell.cpp:34
void loop()
Performs the command execution.
Definition: shell.cpp:46
Shell(UartHardware &uart, const Config &config)
Constructor.
Definition: shell.cpp:17
void start(size_t charCount)
Starts the auto completion.
Definition: tabulator.cpp:24
Configuarion parameters of the shell.
Definition: shell.h:40
char *const lineBuffer
Definition: shell.h:42
const size_t lineBufferSize
Definition: shell.h:44
std::string_view prompt
Definition: shell.h:56