STinC++ rewrites the programs in Software Tools in Pascal using C++
The i
command sets dot
, the current line, to the most recent line entered. The p
command prints lines, defaulting to dot
. Therefore an i
followed by a p
should echo back the last thing you typed.
void editor::process(std::istream& in, std::ostream& out) {
while(in.peek() != eof) {
auto line = stiX::getline(in);
if (line == "=")
out << buffer_.dot() << "\n";
else if (line == "i")
do_insert(in, buffer_);
else if (line == "p")
do_print(out, buffer_);
else
out << "?\n";
}
}
void do_print(std::ostream& out, edit_buffer& buffer) {
auto index = buffer.dot();
if (index == 0)
out << "?";
else
out << buffer[index-1];
out << "\n";
}
I don’t often use the word easy when talking about software, but let’s not kid ourselves here. This is easy stuff.
Fact is, pretty much all of the edit
commands are going to be similarly straightforward - append, delete, change, write to file, read to file - they’re all just going to be a few lines of code each.
This is especially true so long as I carry on ignoring the real meat of the task. The complexity in edit
comes not from the commands, but from the line addressing.
Line numbers are formed by the following components:
n a decimal number
. the current line ("dot")
$ the last line
/pattern/ a forward context search
\pattern\ a backward context search
Components may be combined with + or - , as in, for example
.+1 sum of . and 1
$-5 five lines before $
Line numbers are separated by commas or semicolons; a semicolon sets the current line to the most recent line number preceding. |
The global prefixes cause repeated execution of a command, one for each line that matches (g ) or does not match (x ) a specified text pattern:
(1,$) g/pattern/command
(1,$) x/pattern/command
|
There’s a lot going on there. Line numbers can be given as a start and end pair, a single value, or omitted entirely. There are special characters, simple arithmetic, and line numbers can also be combined with search patterns.
Extending, say, p
to support a pair of lines is going to be straightforward. I imagine the code will be something along the lines of
void do_print(std::ostream& out, size_t from, size_t to, edit_buffer& buffer) {
auto index = buffer.dot();
if (to == 0) {
out << "?\n";
return;
}
for(auto i = from; i != to; ++i)
out << buffer[index-1] << '\n';
}
Getting hold of from
and to
in the first place, though, is a nice little parsing problem. That’s where I’m off to next.