ed(1) is the right tool (VI)
==================================

So, let's keep going from where we left it. We have put together a
TODO-list with ed(1):

 $ cat TODO.txt
 TODO LIST
 + phlog about ed(1)
 - put rubbish bins outside
 - buy some tea
 - make a tea
 * check postgrey hiccup
 + configure Unix V7 outpost
 + read Schismatrix

and we have learned a bunch of simple ed(1) commands so far. Indeed, a
lot of time has passed since we put that TODO-list together, and many
items have been addressed and can be marked as "done". In particular, I
have definitely phlogged (a bit) about ed(1), I have put the rubbish
outside (at least a couple of times since we started this series of
phlogs), and made myself many teas. We want our TODO-list to reflect
this progress:

 $ ed TODO.txt
 156
 /phlog/s/^+/*/
 3s/^-/*/
 /make/s/^-/*/
 1,$p
 TODO LIST
 * phlog about ed(1)
 * put rubbish bins outside
 - buy some tea
 * make a tea
 * check postgrey hiccup
 + configure Unix V7 outpost
 + read Schismatrix

OK, that's a bit better. I have marked all the "completed" tasks with a
"*", using different ways to address the corresponding lines. The main
issue is that I would like to keep all the outstanding tasks at the
beginning of the TODO list, for convenience. How to do that?  What we
would like to do is to "move" line 4 (- buy some tea) at the top of the
list, i.e., after the line with "TODO LIST". Easy:

 4m1
 1,$p
 TODO LIST
 - buy some tea
 * phlog about ed(1)
 * put rubbish bins outside
 * make a tea
 * check postgrey hiccup
 + configure Unix V7 outpost
 + read Schismatrix

Wow. That's it, but what's the magic? No magic involved, at all. If you
want to "move" a line somewhere else, you use the "m" command. The
command "m" can be preceded by an address, a range, or a regular
expression that specifies which lines you want to move, and is followed
by an address. It will put the lines specified before "m" right after
the address specified after "m". So

  4m1

means move line 4 after line 1. Which is exactly what "m" did. Now, it
would also make sense to put all the completed tasks at the end of
the file, since we don't have to work on them any more. Well, since
all the completed tasks are lines starting with "*", this is quite easy
to achieve:

 g/^\*/m$
 1,$p
 TODO LIST
 - buy some tea
 + configure Unix V7 outpost
 + read Schismatrix
 * phlog about ed(1)
 * put rubbish bins outside
 * make a tea
 * check postgrey hiccup

and was accomplished by telling ed(1) to take all (g) the lines that
start with "*" (/^\*/), and move them (m) after the last line ($). Note
that we had to "quote" the "*" character, since it is also used as a
wildcard in regular expressions, while we are referrin to a literal "*"
here.

Now what if we would like to copy a line instead of moving it? If you
thought that the "copy" command would be "c" then think again, because
we have already seen that "c" is the command to "change" an existing
line [1]. The command to copy lines is "t", for "transfer", and its
syntax is identical to that of "m". I just remembered that I need to buy
some tomatoes:

 /tea/t
 1,$p
 TODO LIST
 - buy some tea
 + configure Unix V7 outpost
 + read Schismatrix
 * phlog about ed(1)
 * put rubbish bins outside
 * make a tea
 * check postgrey hiccup
 - buy some tea

what happened here? I gave the command "/tea/t" which means "look for
the first line that matches 'tea' and copy it...WHERE?". Well, remember
that consistency in ed(1) is key: if an address is missing, then ed(1)
will assume you are referring to the "current line". In this case, the
current line when we typed the "t" command was the last line in the file
(since we had just given the "1,$p" command...). So "t" did the right
thing, and copied the matching line after the last line of the file. Now
we just replace "tea" with tomatoes:

  s/ea/omatoes/

and then move all the lines with outstanding items to the top of the
file:

  g/^-/m1
  1,$p
  TODO LIST
  - buy some tomatoes
  - buy some tea
  + configure Unix V7 outpost
  + read Schismatrix
  * phlog about ed(1)
  * put rubbish bins outside
  * make a tea
  * check postgrey hiccup

Quite simple, right? As usual, let's save our TODO-list, until next
time:

  w
  176
  q

-+-+-+-

[1] gopher://republic.circumlunar.space/0/~katolaz/phlog/20190830_ed_lists_2.txt