- /*
-
- Part of the TERMINAL MODULE
-
- Copyright (C) 2020 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
-
- */
-
- #pragma once
-
- #include <Arduino.h>
-
- #include "terminal_parsing.h"
-
- #include <forward_list>
- #include <functional>
- #include <vector>
-
- namespace terminal {
-
- struct Terminal;
-
- // We need to be able to pass arbitrary Args structure into the command function
- // Like Embedis implementation, we only pass things that we actually use instead of complete obj instance
- struct CommandContext {
- std::vector<String> argv;
- size_t argc;
- Print& output;
- };
-
- class Terminal {
- public:
- enum class Result {
- Error, // Genric error condition
- Command, // We successfully parsed the line and executed the callback specified via addCommand
- CommandNotFound, // ... similar to the above, but command was never added via addCommand
- BufferOverflow, // Command line processing failed, no \r\n / \n before buffer was filled
- Pending, // We got something in the buffer, but can't yet do anything with it
- NoInput // We got nothing in the buffer and stream read() returns -1
- };
-
- using CommandFunc = void(*)(const CommandContext&);
- using ProcessFunc = bool(*)(Result);
-
- using Names = std::vector<const __FlashStringHelper*>;
- using Command = std::pair<const __FlashStringHelper*, CommandFunc>;
- using Commands = std::forward_list<Command>;
-
- // stream - see `stream` description below
- // buffer_size - set internal limit for the total command line length
- Terminal(Stream& stream, size_t buffer_size = 128) :
- _stream(stream),
- _buffer_size(buffer_size)
- {
- _buffer.reserve(buffer_size);
- }
-
- static void addCommand(const __FlashStringHelper* name, CommandFunc func);
- static size_t commands();
- static Names names();
-
- // Try to process a single line (until either `\r\n` or just `\n`)
- Result processLine();
-
- // Calls processLine() repeatedly.
- // Blocks until the stream no longer has any data available.
- // `process_f` will return each individual processLine() Result,
- // and we can either stop (false) or continue (true) the function.
- void process(ProcessFunc = defaultProcessFunc);
-
- private:
-
- static bool defaultProcessFunc(Result);
-
- // general input / output stream:
- // - stream.read() should return user input
- // - stream.write() can be called from the command callback
- // - stream.write() can be called by us to show error messages
- Stream& _stream;
-
- // input stream is buffered until it can be parsed
- // in case parsing did not happen and we filled the buffer up to it's size,
- // the error will be returned and the buffer parsing will start from the beginning
- std::vector<char> _buffer;
- const size_t _buffer_size;
-
- static Commands _commands;
- };
-
- } // namespace terminal
|