Public Access
Tab used to complete a command's first word only. It now follows the help text word by word: `lora st` gives `lora status`, `gnss track ` lists `start stop`. The words are read from the help text as written, so a new command completes with no table to keep; the Shell's own words are added in the same notation. `*` and `?` in the last part of a path, for ls, du, rm, cp and mv, from the Shell and both consoles. The command runs once for each name matched, lined up and run by the main loop as each finishes; `cancel` empties the line-up. 64 matches at most, refused whole past that. In the Shell, rm with a pattern asks once, with the count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
66 lines
3.0 KiB
C++
66 lines
3.0 KiB
C++
#pragma once
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <deque>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
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<std::string>& 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<std::string> 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 <argument>, [option] or "...":
|
|
// lora rx on|off | lora preset <name> 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<std::string>& 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<std::string>& names, std::vector<std::string>& matches);
|
|
|
|
} // namespace roro
|