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