#pragma once #include #include #include #include #include namespace roro { // What the Shell App shows (issue #67): the lines it was given, with the oldest dropped past a size. // Which lines it is given is the console's business: by default, only what is printed for the // Shell's own commands (Console::Origin). class ShellLog { public: static constexpr size_t kMaxBytes = 4096; // Bytes as the console printed them: lines may arrive in pieces. The line with the free heap // every ten seconds is never kept: it would push everything else off a ten-line screen. void feed(const char* data, size_t len); // A line the Shell adds itself. void add(const std::string& line); const std::deque& lines() const { return lines_; } void clear(); uint32_t revision() const { return revision_; } // changes when the lines do private: void push(const std::string& line); std::deque lines_; std::string partial_; size_t bytes_ = 0; uint32_t revision_ = 0; }; // Tab on a command (issue #67): every word of it, read from the firmware's `help` text each time it // is asked, so nothing is kept in memory for it. A line of that text is commands, three spaces, then // what they do; commands are separated by " | ", a word like on|off is either of them, and a command // stops being words at its first , [option] or "...": // lora rx on|off | lora preset the radio // gives "lora rx on", "lora rx off" and "lora preset". An App's name starts with a capital. // // The line with its last word completed as far as the commands that fit agree; a word completed // whole gets a space after it. `matches` gets the candidates when there are several. Unchanged, with // no matches, when no command goes on that way: then it may be a path (below). std::string completeWords(const std::string& typed, const char* helpText, std::vector& matches); // Tab on a later word: a path on the SD card (issue #67). What is being completed, taken apart: // `rm -r /notes/sh` is head "rm -r ", folder "/notes/", prefix "sh". False when the cursor is still // on the first word, when the word is a switch (-r), or when it isn't a path and the command doesn't // take one. After a file command a path may be started without its slash: `cat no` is /no. struct PathToComplete { std::string head, folder, prefix; }; bool splitForPath(const std::string& typed, PathToComplete& out); // `names` are the folder's entries, a folder's with a slash at its end. The line with the path // completed as far as the entries that start with the prefix agree, whatever their case (the card // doesn't tell cases apart, so the name's own case is taken). A file completed whole gets a space // after it; a folder keeps its slash, to go on from. `matches` gets the candidates when there are // several. Unchanged when nothing matches. std::string completePath(const PathToComplete& what, const std::vector& names, std::vector& matches); } // namespace roro