Gopher root is [sdf.org] port = 70
SDF GOPHERSPACE (1186 ACTIVE users)/
[10-Mar-2020] undo Ctrl Z back to Sanity/
Journal - Doth He Protest Too Much?.
Journal - Build Your Own Damn Boat.
Script - Contextual Bookmarking with dmenu.
Journal - Numbed, Distracted and Infected.
Journal - Brexit.
Journal - Imposter.
Journal - Why we are so Confused.
Journal - Bullshit Detector.
Comment - Cancer Mice Central.
Quote - Cancer Mice Central.
Theory - Simulation Argument is a Tautology.
Journal - Disappearing Modes of Being.
Quote - On Diverse Monoculture.
Quote - Spectrum-y Dissidents.
Comment - Cancelled.
Journal - Techno-Animism.
Comment - Oligopoly of Academic Publishers.
Quote - Oligopoly of Academic Publishers.
Journal - Basics.
Theory - Alternative to Strauss-Howe Generations.
Journal - Who am I?.
Journal - The First Entry.
[10-Mar-2020] danielo danielo (el gopherspace)/
danielo.sdf.org <~h~>
sdf.org/
<< see line 1 >>
phlog/
2020/
Febrero/
.. /
<< see line 31 >>
2020-02-24.txt 2020-Feb-25 04:57 1.5 KB.
2020-02-25.txt 2020-Feb-26 06:41 1.4 KB.
2020-02-26.txt 2020-Feb-27 00:06 2.2 KB.
2020-02-27.txt 2020-Feb-27 23:36 1.0 KB.
Marzo/
.. /
<< see line 31 >>
2020-03-02.txt 2020-Mar-02 09:08 1.1 KB.
2020-03-04.txt 2020-Mar-04 23:34 1.7 KB.
2020-03-09.txt 2020-Mar-10 02:56 1.2 KB.
2019/
Enero/
.. /
<< see line 45 >>
2019-01-01.txt 2019-Jan-02 07:05 0.2 KB.
2019-01-04.txt 2019-Jan-05 00:01 0.3 KB.
2019-01-06.txt 2019-Jan-07 02:53 2.3 KB.
2019-01-06a.txt 2019-Jan-07 08:10 1.1 KB.
2019-01-07.txt 2019-Jan-08 02:51 0.6 KB.
2019-01-08.txt 2019-Jan-09 00:53 0.1 KB.
2019-01-09.txt 2019-Jan-10 06:02 0.1 KB.
2019-01-14.txt 2019-Jan-15 09:01 1.3 KB.
2019-01-29.txt 2019-Jan-30 01:52 1.7 KB.
Febrero/
.. /
<< see line 45 >>
2019-02-04.txt 2019-Feb-05 05:53 0.2 KB.
2019-02-10.txt 2019-Feb-11 08:30 2.1 KB.
2018/
Enero/
.. /
<< see line 63 >>
2018-01-05.txt 2018-Jan-06 04:05 2.5 KB.
2018-01-06.txt 2018-Jan-07 02:28 0.6 KB.
2018-01-09.txt 2018-Jan-10 08:39 1.3 KB.
2018-01-12.txt 2018-Jan-13 09:01 2.1 KB.
2018-01-14.txt 2018-Jan-15 08:36 0.4 KB.
2018-01-15.txt 2018-Jan-16 01:55 1.0 KB.
2018-01-16.txt 2018-Jan-17 02:05 0.8 KB.
2018-01-17.txt 2018-Jan-18 00:12 0.5 KB.
2018-01-18.txt 2018-Jan-19 04:44 1.2 KB.
2018-01-26.txt 2018-Jan-27 02:58 3.4 KB.
2018-01-27.txt 2018-Jan-28 00:37 4.2 KB.
2018-01-28.txt 2018-Jan-29 01:08 1.0 KB.
2018-01-30.txt 2018-Jan-31 00:49 2.0 KB.
2018-01-31.txt 2018-Feb-01 03:43 2.4 KB.
Febrero/
.. /
<< see line 63 >>
2018-02-03.txt 2018-Feb-25 11:17 5.6 KB.
2018-02-10.txt 2018-Feb-10 10:57 0.3 KB.
2018-02-11.txt 2018-Feb-11 09:40 1.2 KB.
2018-02-15.txt 2018-Feb-16 05:26 2.6 KB.
2018-02-19.txt 2018-Feb-20 01:38 1.3 KB.
2018-02-21.txt 2018-Feb-22 08:36 1.4 KB.
2018-02-22.txt 2018-Feb-23 02:37 1.5 KB.
2018-02-23.txt 2018-Feb-24 00:21 2.0 KB.
2018-02-24.txt 2018-Feb-25 07:21 2.0 KB.
2018-02-26.txt 2018-Feb-27 12:02 4.1 KB.
2018-02-28.txt 2018-Mar-01 02:05 1.0 KB.
Marzo/
.. /
<< see line 63 >>
2018-03-01.txt 2018-Mar-02 01:27 0.9 KB.
2018-03-05.txt 2018-Mar-06 09:53 0.3 KB.
2018-03-18.txt 2018-Mar-18 07:59 1.7 KB.
Mayo/
.. /
<< see line 63 >>
2018-05-06.txt 2018-Sep-20 23:49 0.1 KB.
Septiembre/
.. /
<< see line 63 >>
2018-09-20.txt 2018-Sep-21 02:04 1.9 KB.
2018-09-21.txt 2018-Sep-22 08:16 1.5 KB.
2018-09-28.txt 2018-Sep-29 03:30 0.8 KB.
Octubre/
.. /
<< see line 63 >>
2018-10-01.txt 2018-Oct-01 07:12 2.7 KB.
2018-10-01a.txt 2018-Oct-02 03:59 0.8 KB.
2018-10-02.txt 2018-Oct-03 07:22 2.6 KB.
2018-10-03.txt 2018-Oct-03 22:57 0.2 KB.
2018-10-04.txt 2018-Oct-05 00:18 1.3 KB.
2018-10-05.txt 2018-Oct-06 04:03 2.7 KB.
2018-10-06.txt 2018-Oct-06 22:32 0.5 KB.
2018-10-07.txt 2018-Oct-08 00:06 2.0 KB.
2018-10-08.txt 2018-Oct-09 05:32 3.9 KB.
2018-10-09.txt 2018-Oct-10 06:32 4.1 KB.
2018-10-09a.txt 2018-Oct-10 04:25 1.7 KB.
2018-10-10.txt 2018-Oct-12 06:28 2.3 KB.
2018-10-11.txt 2018-Oct-13 12:50 3.2 KB.
2018-10-12.txt 2018-Oct-14 08:11 3.8 KB.
2018-10-13.txt 2018-Oct-14 04:30 0.8 KB.
2018-10-14.txt 2018-Oct-16 03:58 0.4 KB.
2018-10-17.txt 2018-Oct-18 06:49 1.6 KB.
2018-10-18.txt 2018-Oct-19 05:36 0.7 KB.
2018-10-19.txt 2018-Oct-20 08:05 2.6 KB.
2018-10-20.txt 2018-Oct-21 07:07 2.0 KB.
2018-10-21.txt 2018-Oct-22 05:01 1.4 KB.
2018-10-22.txt 2018-Oct-23 07:48 3.5 KB.
2018-10-23.txt 2018-Oct-24 07:18 5.4 KB.
2018-10-24.txt 2018-Oct-25 07:40 2.1 KB.
2018-10-25.txt 2018-Oct-26 06:57 3.1 KB.
2018-10-26.txt 2018-Oct-27 08:49 1.1 KB.
2018-10-27.txt 2018-Oct-28 07:53 2.6 KB.
2018-10-30.txt 2018-Oct-31 06:14 3.7 KB.
2018-10-30a.txt 2018-Oct-31 02:17 2.8 KB.
2018-10-31.txt 2018-Nov-01 07:17 4.5 KB.
Noviembre/
.. /
<< see line 63 >>
2018-11-01.txt 2018-Nov-02 01:42 2.3 KB.
2018-11-03.txt 2018-Nov-04 07:08 1.0 KB.
2018-11-04.txt 2018-Nov-05 04:49 1.3 KB.
2018-11-05.txt 2018-Nov-06 00:50 3.0 KB.
2018-11-06.txt 2018-Nov-07 07:33 0.4 KB.
2018-11-08.txt 2018-Nov-09 04:31 1.6 KB.
2018-11-16.txt 2018-Nov-17 06:59 6.0 KB.
2018-11-20.txt 2018-Nov-21 07:25 3.9 KB.
2018-11-21.txt 2018-Nov-21 23:36 1.3 KB.
2018-11-22.txt 2018-Nov-23 02:18 2.8 KB.
2018-11-23.txt 2018-Nov-24 08:04 2.8 KB.
2018-11-24.txt 2018-Nov-25 07:53 2.1 KB.
2018-11-25.txt 2018-Nov-26 05:15 1.4 KB.
2018-11-25a.txt 2018-Nov-26 11:07 2.8 KB.
2018-11-26.txt 2018-Nov-27 01:33 1.5 KB.
2018-11-27.txt 2018-Nov-28 07:16 0.6 KB.
2018-11-29.txt 2018-Nov-30 08:34 2.0 KB.
2018-11-30.txt 2018-Dec-01 08:25 2.0 KB.
Diciembre/
.. /
<< see line 63 >>
2018-12-01.txt 2018-Dec-02 00:56 1.1 KB.
2018-12-08.txt 2018-Dec-09 04:46 2.3 KB.
2018-12-10.txt 2018-Dec-12 02:17 0.3 KB.
2018-12-13.txt 2018-Dec-14 01:20 2.6 KB.
2018-12-15.txt 2018-Dec-15 08:37 1.9 KB.
2018-12-16.txt 2018-Dec-16 05:25 2.2 KB.
2018-12-17.txt 2018-Dec-17 07:59 0.8 KB.
2018-12-18.txt 2018-Dec-19 06:51 2.9 KB.
2018-12-19.txt 2018-Dec-20 07:43 0.6 KB.
2018-12-20.txt 2018-Dec-21 07:01 0.1 KB.
2018-12-22.txt 2018-Dec-23 08:53 0.1 KB.
2018-12-26.txt 2018-Dec-27 01:22 0.9 KB.
2017/
Diciembre/
.. /
<< see line 180 >>
2017-12-07.txt 2017-Dec-09 05:44 2.1 KB.
2017-12-08.txt 2017-Dec-09 05:04 3.0 KB.
2017-12-09.txt 2017-Dec-10 05:36 3.7 KB.
2017-12-10.txt 2017-Dec-10 21:47 3.6 KB.
2017-12-11.txt 2017-Dec-12 03:58 3.0 KB.
2017-12-13.txt 2017-Dec-16 09:00 1.5 KB.
2017-12-14.txt 2017-Dec-15 00:04 1.7 KB.
2017-12-15.txt 2017-Dec-16 01:59 9.5 KB.
2017-12-16.txt 2017-Dec-17 06:17 3.5 KB.
2017-12-17.txt 2017-Dec-18 06:58 1.1 KB.
2017-12-18.txt 2017-Dec-19 03:31 3.3 KB.
2017-12-19.txt 2017-Dec-19 23:28 0.1 KB.
2017-12-20.txt 2017-Dec-21 02:10 1.6 KB.
2017-12-21.txt 2017-Dec-22 02:54 2.6 KB.
2017-12-22.txt 2017-Dec-23 05:48 0.7 KB.
2017-12-23.txt 2018-Oct-10 00:54 0.1 KB.
2017-12-24.txt 2018-Oct-10 00:54 0.2 KB.
2017-12-25.txt 2017-Dec-25 23:30 0.1 KB.
2017-12-26.txt 2017-Dec-26 21:18 0.8 KB.
2017-12-27.txt 2017-Dec-27 07:34 0.0 KB.
2017-12-28.txt 2017-Dec-29 06:41 0.0 KB.
2017-12-29.txt 2017-Dec-30 23:44 0.2 KB.
2017-12-30.txt 2017-Dec-31 00:23 2.7 KB.
2015/
Enero/
.. /
<< see line 207 >>
2015-01-03.txt 2015-Jan-04 03:52 0.5 KB.
2015-01-13.txt 2015-Jan-16 04:15 0.5 KB.
Septiembre/
.. /
<< see line 207 >>
2015-09-08.txt 2015-Sep-30 00:47 0.9 KB.
2015-09-09.txt 2015-Sep-09 22:40 0.8 KB.
2015-09-10.txt 2015-Sep-10 22:15 0.6 KB.
2015-09-11.txt 2015-Sep-11 22:05 0.2 KB.
2015-09-12.txt 2015-Sep-13 07:43 0.8 KB.
2015-09-13.txt 2015-Sep-14 13:06 0.3 KB.
2015-09-14.txt 2015-Sep-15 05:28 0.3 KB.
2015-09-25.txt 2015-Sep-26 04:26 2.1 KB.
2015-09-27.txt 2015-Sep-28 00:43 0.6 KB.
2015-09-28.txt 2015-Sep-28 05:12 1.1 KB.
2015-09-29.txt 2015-Sep-29 03:01 0.9 KB.
2015-09-30.txt 2015-Sep-29 22:08 1.1 KB.
Octubre/
.. /
<< see line 207 >>
2015-10-01.txt 2015-Oct-01 23:47 1.2 KB.
2015-10-02.txt 2015-Oct-03 00:20 2.7 KB.
2015-10-03.txt 2015-Oct-04 03:09 1.6 KB.
2015-10-04.txt 2015-Oct-05 03:37 0.2 KB.
2015-10-05.txt 2015-Oct-05 23:49 0.4 KB.
2015-10-06.txt 2015-Oct-06 21:47 1.1 KB.
2015-10-07.txt 2015-Oct-08 04:33 1.6 KB.
2015-10-08.txt 2015-Oct-09 01:49 0.4 KB.
2015-10-09.txt 2015-Oct-10 04:38 0.8 KB.
2015-10-10.txt 2015-Oct-11 05:30 0.8 KB.
2015-10-11.txt 2015-Oct-12 06:13 0.3 KB.
2015-10-12.txt 2015-Oct-13 01:00 1.0 KB.
2015-10-14.txt 2015-Oct-15 04:56 0.1 KB.
2015-10-17.txt 2015-Oct-18 02:58 0.1 KB.
2015-10-18.txt 2015-Oct-19 03:55 1.0 KB.
2015-10-19.txt 2015-Oct-20 01:55 0.6 KB.
2015-10-20.txt 2015-Oct-21 05:31 0.8 KB.
2015-10-22.txt 2015-Oct-22 12:38 0.6 KB.
2015-10-27.txt 2015-Oct-28 12:01 0.9 KB.
2015-10-30.txt 2015-Oct-31 07:05 0.8 KB.
2014/
Febrero/
.. /
<< see line 251 >>
2014-02-12.txt 2014-Feb-13 03:36 0.1 KB.
Mayo/
.. /
<< see line 251 >>
2014-05-14.txt 2014-May-15 05:40 0.6 KB.
Junio/
.. /
<< see line 251 >>
2014-06-05.txt 2014-Jun-06 02:09 0.4 KB.
2014-06-16.txt 2014-Jun-17 00:46 0.7 KB.
Septiembre/
.. /
<< see line 251 >>
2014-09-23.txt 2014-Sep-24 03:32 0.1 KB.
Octubre/
.. /
<< see line 251 >>
2014-10-15.txt 2014-Oct-19 04:48 0.2 KB.
2014-10-18.txt 2014-Oct-19 03:49 0.4 KB.
2014-10-19.txt 2014-Oct-19 04:58 1.0 KB.
2014-10-20.txt 2014-Oct-19 18:09 0.4 KB.
2014-10-21.txt 2014-Oct-20 06:58 0.3 KB.
2014-10-22.txt 2014-Oct-20 17:38 0.3 KB.
2014-10-23.txt 2014-Oct-21 05:18 0.6 KB.
2014-10-23a.txt 2014-Oct-23 20:51 0.3 KB.
2014-10-24.txt 2014-Oct-22 01:46 0.1 KB.
2014-10-25.txt 2014-Oct-23 01:53 0.3 KB.
2014-10-25a.txt 2014-Oct-26 04:38 0.9 KB.
2014-10-26.txt 2014-Oct-27 04:34 0.9 KB.
2014-10-27.txt 2014-Oct-28 01:00 0.3 KB.
2014-10-28.txt 2014-Oct-29 02:19 0.5 KB.
2014-10-29.txt 2014-Oct-30 01:49 0.4 KB.
2014-10-31.txt 2014-Nov-01 04:02 1.5 KB.
Noviembre/
.. /
<< see line 251 >>
2014-11-04.txt 2014-Nov-04 23:01 1.7 KB.
2014-11-06.txt 2014-Nov-06 19:47 1.5 KB.
2014-11-07.txt 2014-Nov-08 02:56 1.3 KB.
2014-11-10.txt 2014-Nov-11 03:32 1.0 KB.
2014-11-18.txt 2014-Nov-19 04:04 1.8 KB.
2014-11-21.txt 2014-Nov-22 04:13 1.1 KB.
2014-11-23.txt 2014-Nov-24 04:53 0.9 KB.
2014-11-28.txt 2014-Nov-29 03:53 1.3 KB.
Diciembre/
.. /
<< see line 251 >>
2014-12-01.txt 2014-Dec-01 19:37 0.9 KB.
2014-12-02.txt 2014-Dec-02 21:05 0.8 KB.
2014-12-30.txt 2014-Dec-31 03:19 0.5 KB.
2013/
Enero/
.. /
<< see line 305 >>
2013-01-01.txt 2013-Jan-01 18:18 0.4 KB.
2013-01-02.txt 2013-Jan-03 18:33 0.6 KB.
2013-01-03.txt 2013-Jan-04 03:33 0.4 KB.
2013-01-04.txt 2013-Jan-04 23:53 0.4 KB.
2013-01-05.txt 2013-Jan-06 21:50 0.9 KB.
2013-01-06.txt 2013-Jan-06 21:58 0.7 KB.
2013-01-07.txt 2013-Jan-08 02:19 1.4 KB.
2013-01-08.txt 2013-Jan-09 01:59 0.5 KB.
2013-01-09.txt 2013-Jan-10 21:47 0.4 KB.
2013-01-10.txt 2013-Jan-10 23:20 0.5 KB.
2013-01-11.txt 2013-Jan-12 02:00 0.4 KB.
2013-01-12.txt 2013-Jan-13 01:43 0.7 KB.
2013-01-13.txt 2013-Jan-14 02:01 0.7 KB.
2013-01-14.txt 2013-Jan-15 00:53 1.4 KB.
2013-01-15.txt 2013-Jan-16 02:55 0.2 KB.
2013-01-16.txt 2013-Jan-17 00:51 0.9 KB.
2013-01-17.txt 2013-Jan-18 00:59 0.5 KB.
2013-01-18.txt 2013-Jan-19 01:07 0.6 KB.
2013-01-19.txt 2013-Jan-20 02:20 0.4 KB.
2013-01-20.txt 2013-Jan-21 01:44 0.8 KB.
2013-01-21.txt 2013-Jan-22 02:01 0.1 KB.
2013-01-22.txt 2013-Jan-23 02:28 0.6 KB.
2013-01-23.txt 2013-Jan-24 02:02 0.4 KB.
2013-01-24.txt 2013-Jan-25 03:27 0.6 KB.
2013-01-25.txt 2013-Jan-26 02:15 0.1 KB.
2013-01-26.txt 2013-Jan-28 12:49 0.0 KB.
2013-01-27.txt 2013-Jan-28 12:58 0.8 KB.
2013-01-28.txt 2013-Jan-28 23:42 0.8 KB.
2013-01-29.txt 2013-Jan-31 19:09 0.1 KB.
2013-01-30.txt 2013-Jan-31 19:10 0.2 KB.
2013-01-31.txt 2013-Jan-31 19:12 0.1 KB.
Febrero/
.. /
<< see line 305 >>
2013-02-01.txt 2013-Feb-03 04:02 0.1 KB.
2013-02-02.txt 2013-Feb-03 04:23 0.5 KB.
2013-02-03.txt 2013-Feb-04 03:49 0.1 KB.
2013-02-04.txt 2013-Feb-05 00:50 0.2 KB.
2013-02-05.txt 2013-Feb-06 01:39 0.1 KB.
2013-02-06.txt 2013-Feb-07 02:27 0.7 KB.
2013-02-07.txt 2013-Feb-08 02:37 0.3 KB.
2013-02-08.txt 2013-Feb-09 04:25 0.2 KB.
2013-02-09.txt 2013-Feb-10 01:08 0.4 KB.
2013-02-10.txt 2013-Feb-11 20:11 0.3 KB.
2013-02-11.txt 2013-Feb-12 23:56 0.3 KB.
2013-02-12.txt 2013-Feb-12 23:58 0.2 KB.
2013-02-13.txt 2013-Feb-13 23:55 0.6 KB.
2013-02-14.txt 2013-Feb-15 02:55 1.0 KB.
2013-02-15.txt 2013-Feb-17 04:07 0.5 KB.
2013-02-16.txt 2013-Feb-17 04:09 0.2 KB.
2013-02-17.txt 2013-Feb-18 07:50 0.8 KB.
2013-02-18.txt 2013-Feb-19 12:10 0.1 KB.
2013-02-19.txt 2013-Feb-19 12:11 0.0 KB.
2013-02-20.txt 2013-Feb-20 21:53 0.4 KB.
2013-02-21.txt 2013-Feb-22 02:08 0.2 KB.
2013-02-22.txt 2013-Feb-23 03:05 0.4 KB.
2013-02-23.txt 2013-Feb-24 01:33 0.2 KB.
2013-02-24.txt 2013-Feb-26 22:11 0.3 KB.
2013-02-25.txt 2013-Feb-26 22:14 0.5 KB.
2013-02-26.txt 2013-Feb-26 22:18 0.4 KB.
2013-02-27.txt 2013-Feb-28 03:40 0.2 KB.
2013-02-28.txt 2013-Mar-01 02:45 0.1 KB.
Marzo/
.. /
<< see line 305 >>
2013-03-01.txt 2013-Mar-02 05:48 0.3 KB.
2013-03-02.txt 2013-Mar-04 01:05 0.2 KB.
2013-03-03.txt 2013-Mar-04 01:07 0.1 KB.
2013-03-04.txt 2013-Mar-05 04:39 0.9 KB.
2013-03-05.txt 2013-Mar-05 23:09 0.1 KB.
2013-03-06.txt 2013-Mar-06 17:43 0.2 KB.
2013-03-07.txt 2013-Mar-08 02:10 0.2 KB.
2013-03-08.txt 2013-Mar-09 07:03 0.5 KB.
2013-03-09.txt 2013-Mar-09 07:12 0.9 KB.
2013-03-10.txt 2013-Mar-11 02:38 0.4 KB.
2013-03-11.txt 2013-Mar-12 02:23 0.1 KB.
2013-03-12.txt 2013-Mar-12 22:17 0.3 KB.
2013-03-13.txt 2013-Mar-14 00:54 0.6 KB.
2013-03-14.txt 2013-Mar-15 00:53 0.8 KB.
2013-03-15.txt 2013-Mar-16 03:56 1.3 KB.
2013-03-16.txt 2013-Mar-17 00:24 0.1 KB.
2013-03-17.txt 2013-Mar-17 16:32 0.2 KB.
2013-03-18.txt 2013-Mar-18 22:57 1.1 KB.
2013-03-19.txt 2013-Mar-20 15:26 0.1 KB.
2013-03-20.txt 2013-Mar-20 16:02 0.1 KB.
2013-03-21.txt 2013-Mar-21 15:57 0.6 KB.
2013-03-22.txt 2013-Mar-22 16:22 0.2 KB.
2013-03-23.txt 2013-Mar-23 23:10 0.2 KB.
2013-03-24.txt 2013-Mar-25 15:21 0.1 KB.
2013-03-25.txt 2013-Mar-25 15:35 0.7 KB.
2013-03-26.txt 2013-Mar-26 17:38 0.5 KB.
2013-03-27.txt 2013-Mar-30 05:00 0.1 KB.
2013-03-28.txt 2013-Mar-30 05:01 0.1 KB.
2013-03-29.txt 2013-Mar-30 05:01 0.0 KB.
2013-03-30.txt 2013-Mar-31 05:24 0.1 KB.
2013-03-31.txt 2013-Apr-01 20:44 0.2 KB.
Abril/
.. /
<< see line 305 >>
2013-04-01.txt 2013-Apr-01 20:49 0.3 KB.
2013-04-02.txt 2013-Apr-02 21:34 0.4 KB.
2013-04-03.txt 2013-Apr-04 00:53 1.1 KB.
2013-04-04.txt 2013-Apr-05 01:29 0.2 KB.
2013-04-05.txt 2013-Apr-05 22:39 1.6 KB.
2013-04-06.txt 2013-Apr-07 05:20 0.8 KB.
2013-04-07.txt 2013-Apr-07 21:28 0.4 KB.
2013-04-08.txt 2013-Apr-10 01:20 0.3 KB.
2013-04-09.txt 2013-Apr-10 01:24 0.1 KB.
2013-04-10.txt 2013-Apr-10 23:34 0.1 KB.
2013-04-11.txt 2013-Apr-11 20:15 0.5 KB.
2013-04-12.txt 2013-Apr-13 08:30 0.5 KB.
2013-04-13.txt 2013-Apr-13 23:01 0.2 KB.
2013-04-14.txt 2013-Apr-16 04:35 0.3 KB.
2013-04-15.txt 2013-Apr-16 04:33 0.1 KB.
2013-04-16.txt 2013-Apr-16 13:05 0.5 KB.
2013-04-17.txt 2013-Apr-18 03:42 0.5 KB.
2013-04-18.txt 2013-Apr-18 21:30 0.1 KB.
2013-04-19.txt 2013-Apr-19 21:55 0.2 KB.
2013-04-20.txt 2013-Apr-21 07:08 0.9 KB.
2013-04-21.txt 2013-Apr-21 23:32 0.1 KB.
2013-04-22.txt 2013-Apr-23 01:32 1.0 KB.
2013-04-23.txt 2013-Apr-24 02:07 0.1 KB.
2013-04-24.txt 2013-Apr-26 01:25 0.1 KB.
2013-04-25.txt 2013-Apr-26 01:41 0.1 KB.
2013-04-26.txt 2013-Apr-27 06:38 0.2 KB.
2013-04-27.txt 2013-Apr-27 23:18 0.6 KB.
2013-04-28.txt 2013-Apr-29 14:48 0.1 KB.
2013-04-29.txt 2013-Apr-29 15:04 0.4 KB.
2013-04-30.txt 2013-May-01 14:31 0.0 KB.
Mayo/
.. /
<< see line 305 >>
2013-05-01.txt 2013-May-02 00:42 0.2 KB.
2013-05-02.txt 2013-May-03 23:32 0.2 KB.
2013-05-03.txt 2013-May-03 23:37 0.7 KB.
2013-05-04.txt 2013-May-05 21:46 0.1 KB.
2013-05-05.txt 2013-May-05 21:48 0.2 KB.
2013-05-06.txt 2013-May-06 23:20 0.4 KB.
2013-05-07.txt 2013-May-08 00:52 0.1 KB.
2013-05-08.txt 2013-May-08 22:23 0.5 KB.
2013-05-09.txt 2013-May-11 04:03 0.2 KB.
2013-05-10.txt 2013-May-11 04:12 1.0 KB.
2013-05-11.txt 2013-May-12 19:44 0.1 KB.
2013-05-12.txt 2013-May-12 19:48 0.1 KB.
2013-05-13.txt 2013-May-15 21:39 0.1 KB.
2013-05-14.txt 2013-May-15 21:51 0.6 KB.
2013-05-15.txt 2013-May-15 21:52 0.1 KB.
2013-05-16.txt 2013-May-17 04:22 0.3 KB.
2013-05-17.txt 2013-May-18 07:09 0.5 KB.
2013-05-18.txt 2013-May-19 00:22 0.4 KB.
2013-05-19.txt 2013-May-20 07:13 0.4 KB.
2013-05-20.txt 2013-May-22 05:44 0.2 KB.
2013-05-21.txt 2013-May-22 05:47 0.4 KB.
2013-05-22.txt 2013-May-22 05:50 0.3 KB.
2013-05-23.txt 2013-May-24 00:38 0.1 KB.
2013-05-24.txt 2013-May-24 00:45 0.1 KB.
2013-05-25.txt 2013-May-26 08:14 0.1 KB.
2013-05-26.txt 2013-May-26 08:16 0.3 KB.
2013-05-27.txt 2013-Jun-01 06:12 0.1 KB.
2013-05-28.txt 2013-Jun-01 06:12 0.1 KB.
2013-05-29.txt 2013-Jun-01 06:13 0.0 KB.
2013-05-30.txt 2013-Jun-01 06:30 1.8 KB.
2013-05-31.txt 2013-Jun-01 06:42 0.2 KB.
Junio/
.. /
<< see line 305 >>
2013-06-01.txt 2013-Jun-05 21:01 0.1 KB.
2013-06-02.txt 2013-Jun-05 21:08 0.0 KB.
2013-06-03.txt 2013-Jun-05 21:11 0.1 KB.
2013-06-04.txt 2013-Jun-05 21:12 0.0 KB.
2013-06-05.txt 2013-Jun-05 21:14 0.3 KB.
2013-06-06.txt 2013-Jun-07 22:56 0.4 KB.
2013-06-07.txt 2013-Jun-07 23:02 0.6 KB.
2013-06-08.txt 2013-Jun-08 18:25 0.0 KB.
2013-06-09.txt 2013-Jun-12 00:12 0.1 KB.
2013-06-10.txt 2013-Jun-12 00:14 0.1 KB.
2013-06-11.txt 2013-Jun-12 00:19 0.3 KB.
2013-06-12.txt 2013-Jun-20 00:57 0.1 KB.
2013-06-13.txt 2013-Jun-20 00:58 0.1 KB.
2013-06-14.txt 2013-Jun-20 01:00 0.2 KB.
2013-06-15.txt 2013-Jun-20 01:02 0.2 KB.
2013-06-16.txt 2013-Jun-20 01:04 0.1 KB.
2013-06-17.txt 2013-Jun-20 01:04 0.1 KB.
2013-06-18.txt 2013-Jun-20 01:05 0.1 KB.
2013-06-19.txt 2013-Jun-20 00:48 0.4 KB.
2013-06-20.txt 2013-Jun-20 00:57 0.2 KB.
2013-06-21.txt 2013-Jun-25 04:58 0.6 KB.
2013-06-22.txt 2013-Jun-25 04:57 0.1 KB.
2013-06-23.txt 2013-Jun-25 04:56 0.2 KB.
2013-06-24.txt 2013-Jun-25 04:54 0.4 KB.
2013-06-25.txt 2013-Jun-27 06:53 0.1 KB.
2013-06-26.txt 2013-Jun-27 07:03 1.1 KB.
2013-06-27.txt 2013-Jun-28 06:20 0.3 KB.
2013-06-28.txt 2013-Jul-02 00:26 1.1 KB.
2013-06-29.txt 2013-Jul-02 00:30 0.3 KB.
2013-06-30.txt 2013-Jul-02 00:34 0.4 KB.
Julio/
.. /
<< see line 305 >>
2013-07-01.txt 2013-Jul-02 00:50 1.4 KB.
2013-07-02.txt 2013-Jul-03 01:32 1.8 KB.
2013-07-03.txt 2013-Jul-04 09:42 2.0 KB.
2013-07-04.txt 2013-Jul-05 09:35 0.7 KB.
2013-07-05.txt 2013-Jul-07 00:51 0.3 KB.
2013-07-06.txt 2013-Jul-07 00:53 0.1 KB.
2013-07-07.txt 2013-Jul-09 12:17 0.1 KB.
2013-07-08.txt 2013-Jul-09 12:18 0.0 KB.
2013-07-09.txt 2013-Jul-09 15:51 0.1 KB.
2013-07-10.txt 2013-Jul-19 02:04 0.3 KB.
2013-07-11.txt 2013-Jul-19 02:05 0.1 KB.
2013-07-12.txt 2013-Jul-19 02:06 0.1 KB.
2013-07-13.txt 2013-Jul-19 02:07 0.1 KB.
2013-07-14.txt 2013-Jul-19 02:08 0.1 KB.
2013-07-15.txt 2013-Jul-19 02:09 0.2 KB.
2013-07-16.txt 2013-Jul-19 02:15 0.6 KB.
2013-07-17.txt 2013-Jul-19 02:18 0.1 KB.
2013-07-18.txt 2013-Jul-19 02:19 0.1 KB.
2013-07-19.txt 2013-Jul-21 00:20 1.0 KB.
2013-07-20.txt 2013-Jul-21 00:27 0.4 KB.
2013-07-21.txt 2013-Jul-22 01:36 0.2 KB.
2013-07-22.txt 2013-Jul-30 04:50 0.1 KB.
2013-07-23.txt 2013-Jul-30 04:51 0.2 KB.
2013-07-24.txt 2013-Jul-30 04:52 0.1 KB.
2013-07-25.txt 2013-Jul-30 04:52 0.1 KB.
2013-07-26.txt 2013-Jul-30 04:54 0.1 KB.
2013-07-27.txt 2013-Jul-30 04:55 0.1 KB.
2013-07-28.txt 2013-Jul-30 05:02 0.4 KB.
2013-07-29.txt 2013-Jul-30 05:03 0.1 KB.
2013-07-30.txt 2013-Aug-14 06:17 0.1 KB.
2013-07-31.txt 2013-Aug-14 06:18 0.1 KB.
Agosto/
.. /
<< see line 305 >>
2013-08-01.txt 2013-Aug-14 06:20 0.1 KB.
2013-08-02.txt 2013-Aug-14 06:22 0.2 KB.
2013-08-03.txt 2013-Aug-14 06:23 1.0 KB.
2013-08-04.txt 2013-Aug-14 06:24 0.3 KB.
2013-08-05.txt 2013-Aug-14 06:24 0.1 KB.
2013-08-06.txt 2013-Aug-14 06:25 0.1 KB.
2013-08-07.txt 2013-Aug-14 06:25 0.1 KB.
2013-08-08.txt 2013-Aug-14 06:26 0.1 KB.
2013-08-09.txt 2013-Aug-14 06:26 0.1 KB.
2013-08-10.txt 2013-Aug-14 06:26 0.2 KB.
2013-08-11.txt 2013-Aug-14 06:27 0.1 KB.
2013-08-12.txt 2013-Aug-14 06:28 0.1 KB.
2013-08-13.txt 2013-Aug-14 06:29 0.0 KB.
2013-08-14.txt 2013-Aug-14 06:30 0.1 KB.
2013-08-15.txt 2013-Aug-15 21:16 0.8 KB.
2013-08-16.txt 2013-Sep-09 01:26 0.2 KB.
2013-08-17.txt 2013-Sep-09 01:27 0.0 KB.
2013-08-18.txt 2013-Sep-09 01:27 0.1 KB.
2013-08-19.txt 2013-Sep-09 01:27 0.1 KB.
2013-08-20.txt 2013-Sep-09 01:28 0.7 KB.
2013-08-21.txt 2013-Sep-09 01:28 0.2 KB.
2013-08-22.txt 2013-Sep-09 01:28 0.2 KB.
2013-08-23.txt 2013-Sep-09 01:29 0.2 KB.
2013-08-24.txt 2013-Sep-09 01:29 0.0 KB.
2013-08-25.txt 2013-Sep-09 01:30 0.3 KB.
2013-08-26.txt 2013-Sep-09 01:30 0.1 KB.
2013-08-27.txt 2013-Sep-09 01:30 0.1 KB.
2013-08-28.txt 2013-Sep-09 01:31 0.1 KB.
2013-08-29.txt 2013-Sep-09 01:31 0.1 KB.
2013-08-30.txt 2013-Sep-09 01:31 0.0 KB.
2013-08-31.txt 2013-Sep-09 01:32 0.1 KB.
Septiembre/
.. /
<< see line 305 >>
2013-09-01.txt 2013-Sep-09 01:23 0.1 KB.
2013-09-02.txt 2013-Sep-09 01:24 0.1 KB.
2013-09-03.txt 2013-Sep-09 01:24 0.1 KB.
2013-09-04.txt 2013-Sep-09 01:25 0.3 KB.
2013-09-05.txt 2013-Sep-09 01:25 0.0 KB.
2013-09-06.txt 2013-Sep-09 01:25 1.1 KB.
2013-09-07.txt 2013-Sep-09 01:22 0.5 KB.
2013-09-08.txt 2013-Sep-09 01:18 0.2 KB.
2013-09-09.txt 2013-Sep-13 00:14 0.1 KB.
2013-09-10.txt 2013-Sep-13 00:14 0.0 KB.
2013-09-11.txt 2013-Sep-13 00:12 0.2 KB.
2013-09-12.txt 2013-Sep-13 00:10 0.1 KB.
2013-09-13.txt 2013-Sep-15 02:32 0.1 KB.
2013-09-14.txt 2013-Sep-15 02:33 0.0 KB.
2013-09-15.txt 2013-Sep-16 06:03 0.2 KB.
2013-09-16.txt 2013-Sep-18 03:47 0.1 KB.
2013-09-17.txt 2013-Sep-18 03:49 0.3 KB.
2013-09-18.txt 2013-Sep-19 02:01 0.1 KB.
2013-09-19.txt 2013-Sep-20 05:21 0.7 KB.
2013-09-20.txt 2013-Sep-20 22:48 0.2 KB.
2013-09-21.txt 2013-Sep-22 05:15 0.3 KB.
2013-09-22.txt 2013-Sep-23 03:35 0.1 KB.
2013-09-23.txt 2013-Sep-24 03:11 0.2 KB.
2013-09-24.txt 2013-Sep-25 00:27 1.3 KB.
2013-09-25.txt 2013-Sep-26 03:02 0.7 KB.
2013-09-26.txt 2013-Sep-27 00:00 0.3 KB.
2013-09-27.txt 2013-Sep-28 03:13 0.2 KB.
2013-09-28.txt 2013-Sep-29 07:26 0.1 KB.
2013-09-29.txt 2013-Sep-30 22:44 0.5 KB.
2013-09-30.txt 2013-Oct-01 03:42 0.1 KB.
Octubre/
.. /
<< see line 305 >>
2013-10-01.txt 2013-Oct-02 00:24 0.2 KB.
2013-10-02.txt 2013-Oct-03 00:33 0.2 KB.
2013-10-03.txt 2013-Oct-04 00:13 0.3 KB.
2013-10-04.txt 2013-Oct-04 23:05 0.1 KB.
2013-10-05.txt 2013-Oct-06 04:26 0.2 KB.
2013-10-06.txt 2013-Oct-07 23:44 0.5 KB.
2013-10-07.txt 2013-Oct-07 23:58 1.1 KB.
2013-10-08.txt 2013-Oct-09 00:22 0.6 KB.
2013-10-09.txt 2013-Oct-09 22:33 0.1 KB.
2013-10-10.txt 2013-Oct-11 03:06 0.2 KB.
2013-10-11.txt 2013-Oct-12 04:56 0.1 KB.
2013-10-12.txt 2013-Oct-13 01:22 0.1 KB.
2013-10-13.txt 2013-Oct-14 23:24 0.1 KB.
2013-10-14.txt 2013-Oct-14 23:26 0.1 KB.
2013-10-15.txt 2013-Oct-17 00:01 0.2 KB.
2013-10-16.txt 2013-Oct-17 00:06 0.2 KB.
2013-10-17.txt 2013-Oct-18 03:44 0.4 KB.
2013-10-18.txt 2013-Oct-19 03:53 0.1 KB.
2013-10-19.txt 2013-Oct-19 21:45 0.8 KB.
2013-10-20.txt 2013-Oct-21 03:45 0.2 KB.
2013-10-21.txt 2013-Oct-23 04:36 0.0 KB.
2013-10-22.txt 2013-Oct-23 04:41 0.4 KB.
2013-10-23.txt 2013-Oct-24 20:48 0.1 KB.
2013-10-24.txt 2013-Oct-24 20:53 0.6 KB.
2013-10-25.txt 2013-Oct-26 04:21 0.3 KB.
2013-10-26.txt 2013-Oct-28 04:33 0.4 KB.
2013-10-27.txt 2013-Oct-28 04:35 0.3 KB.
2013-10-28.txt 2013-Oct-29 01:04 0.1 KB.
2013-10-29.txt 2013-Oct-30 01:00 0.3 KB.
2013-10-30.txt 2013-Oct-31 05:06 0.2 KB.
2013-10-31.txt 2013-Nov-01 04:18 0.2 KB.
Noviembre/
.. /
<< see line 305 >>
2013-11-01.txt 2013-Nov-06 01:50 0.1 KB.
2013-11-02.txt 2013-Nov-06 01:47 0.2 KB.
2013-11-03.txt 2013-Nov-06 01:48 0.0 KB.
2013-11-04.txt 2013-Nov-06 01:54 0.4 KB.
2013-11-05.txt 2013-Nov-06 01:55 0.1 KB.
2013-11-06.txt 2013-Nov-07 03:26 0.6 KB.
2013-11-07.txt 2013-Nov-08 06:53 0.2 KB.
2013-11-08.txt 2013-Nov-09 04:45 0.5 KB.
2013-11-09.txt 2013-Nov-10 05:17 0.8 KB.
2013-11-10.txt 2013-Nov-13 05:57 0.3 KB.
2013-11-11.txt 2013-Nov-13 06:01 0.4 KB.
2013-11-12.txt 2013-Nov-13 06:03 0.3 KB.
2013-11-13.txt 2013-Nov-14 03:42 0.4 KB.
2013-11-14.txt 2013-Nov-16 03:41 0.2 KB.
2013-11-15.txt 2013-Nov-16 03:46 0.6 KB.
2013-11-16.txt 2013-Nov-19 06:18 0.2 KB.
2013-11-17.txt 2013-Nov-19 06:21 0.4 KB.
2013-11-18.txt 2013-Nov-19 06:24 0.3 KB.
2013-11-19.txt 2013-Nov-25 00:24 0.1 KB.
2013-11-20.txt 2013-Nov-25 00:33 1.1 KB.
2013-11-21.txt 2013-Nov-25 00:33 1.2 KB.
2013-11-22.txt 2013-Nov-25 00:36 0.3 KB.
2013-11-23.txt 2013-Nov-25 00:39 0.3 KB.
2013-11-24.txt 2013-Nov-25 00:43 0.7 KB.
2012/
Noviembre/
.. /
<< see line 667 >>
2012-11-14.txt 2012-Nov-15 06:39 0.5 KB.
2012-11-15.txt 2012-Nov-16 01:08 0.2 KB.
2012-11-16.txt 2012-Nov-16 22:02 0.4 KB.
2012-11-17.txt 2012-Nov-17 05:49 0.3 KB.
2012-11-17a.txt 2012-Nov-17 09:21 0.1 KB.
2012-11-18.txt 2012-Nov-18 06:32 0.8 KB.
2012-11-19.txt 2012-Nov-18 22:10 1.0 KB.
2012-11-19a.txt 2012-Nov-20 06:00 0.5 KB.
2012-11-20.txt 2012-Nov-21 05:40 1.2 KB.
2012-11-21.txt 2012-Nov-23 05:55 1.5 KB.
2012-11-22.txt 2012-Nov-23 23:13 0.8 KB.
2012-11-23.txt 2012-Nov-25 05:08 0.6 KB.
2012-11-24.txt 2012-Nov-25 22:10 0.3 KB.
2012-11-25.txt 2012-Nov-27 03:39 1.7 KB.
2012-11-26.txt 2012-Nov-28 05:20 1.6 KB.
2012-11-27.txt 2012-Nov-29 01:30 0.9 KB.
2012-11-28.txt 2012-Nov-30 00:52 0.8 KB.
2012-11-29.txt 2012-Dec-01 02:24 0.4 KB.
2012-11-30.txt 2012-Dec-02 01:57 0.9 KB.
Diciembre/
.. /
<< see line 667 >>
2012-12-01.txt 2012-Dec-02 02:08 0.2 KB.
2012-12-02.txt 2012-Dec-03 06:12 0.8 KB.
2012-12-03.txt 2012-Dec-04 00:24 0.2 KB.
2012-12-04.txt 2012-Dec-05 06:51 0.6 KB.
2012-12-05.txt 2012-Dec-05 23:19 0.3 KB.
2012-12-06.txt 2012-Dec-06 23:57 1.6 KB.
2012-12-07.txt 2012-Dec-08 02:45 0.5 KB.
2012-12-08.txt 2012-Dec-09 01:23 0.4 KB.
2012-12-09.txt 2012-Dec-09 01:15 1.7 KB.
2012-12-10.txt 2012-Dec-10 02:16 1.2 KB.
2012-12-11.txt 2012-Dec-11 01:37 0.7 KB.
2012-12-12.txt 2012-Dec-12 01:43 0.6 KB.
2012-12-13.txt 2012-Dec-14 05:48 1.8 KB.
2012-12-14.txt 2012-Dec-14 22:40 0.1 KB.
2012-12-15.txt 2012-Dec-16 01:10 1.6 KB.
2012-12-16.txt 2012-Dec-17 01:04 0.6 KB.
2012-12-17.txt 2012-Dec-18 03:25 0.9 KB.
2012-12-18.txt 2012-Dec-19 03:46 0.6 KB.
2012-12-19.txt 2012-Dec-20 05:20 0.7 KB.
2012-12-20.txt 2012-Dec-21 04:10 0.6 KB.
2012-12-21.txt 2012-Dec-22 01:06 0.5 KB.
2012-12-22.txt 2012-Dec-23 09:28 0.1 KB.
2012-12-23.txt 2012-Dec-24 02:00 0.9 KB.
2012-12-24.txt 2012-Dec-25 00:52 0.4 KB.
2012-12-25.txt 2012-Dec-26 05:02 0.4 KB.
2012-12-26.txt 2012-Dec-27 15:01 0.1 KB.
2012-12-27.txt 2012-Dec-28 16:50 0.3 KB.
2012-12-28.txt 2012-Dec-28 17:04 0.5 KB.
2012-12-29.txt 2012-Dec-29 19:40 1.0 KB.
2012-12-30.txt 2012-Dec-30 14:52 0.1 KB.
2012-12-31.txt 2013-Jan-01 18:13 0.2 KB.
bienvenidos.
readme.
mis textos/
.. /
<< see line 26 >>
android-teclado-espanol.txt 2018-Jan-30 09:31 0.8 KB.
calculadora.txt 2018-Oct-08 06:31 2.5 KB.
conociendo_wordstar.txt 2018-Oct-05 01:59 3.4 KB.
error_grabar_dvd_windows10.txt 2019-Jan-24 08:49 3.0 KB.
felicidades_SDF 2015-Oct-01 05:59 0.4 KB.
gopher-celacanto-red.txt 2018-Jan-30 09:40 6.9 KB.
gopher_apocaliptico.txt 2018-Feb-25 07:00 2.5 KB.
seguir-usando-windows-vista.txt 2018-Oct-10 06:25 6.7 KB.
trucos_vim-01.txt 2018-Feb-11 11:15 2.2 KB.
ws.txt 2018-Oct-05 01:54 2.2 KB.
ws1.txt 2018-Oct-05 01:56 5.0 KB.
ebooks/
.. /
<< see line 26 >>
ebooks_historia_es.txt 2013-Sep-25 03:29 349.5 KB.
ebooks_history.txt 2012-Nov-13 00:53 261.9 KB.
hacker_crackdown.txt 2012-Nov-17 06:05 670.5 KB.
textfiles/
.. /
<< see line 26 >>
2015-NASA_announces_water_on_Mars.txt 2015-Oct-02 05:09 2.5 KB.
acentos-espanol-tablet-android.txt 2015-Oct-06 00:03 4.2 KB.
adivinacion_lectura-en-frio.txt 2015-Oct-02 12:26 14.5 KB.
asciidoc-syntax.txt 2015-Oct-02 22:34 4.3 KB.
carl_sagan-wonder_skepticism.txt 2015-Oct-09 04:37 27.9 KB.
mauricio_schwarz-homeopatia_fraude.txt 2015-Oct-02 05:21 25.5 KB.
mexico_cia_facts_2002.txt 2015-Oct-02 22:39 38.0 KB.
netiquette 2012-Nov-18 07:20 15.7 KB.
peanuts_faq.txt 2012-Nov-13 00:50 286.7 KB.
publicidad-insidiosa-contra-las-vacunas.txt 2015-Oct-04 05:45 3.9 KB.
rfc20 2018-Mar-02 10:15 18.8 KB.
sterling-short_history_internet.txt 2012-Nov-18 07:22 21.8 KB.
telnet.txt 2012-Nov-18 07:23 6.7 KB.
trigfunc.txt 2012-Nov-13 01:03 5.8 KB.
usenet_ettiquet_1991.txt 2012-Nov-18 07:17 18.1 KB.
miscelanea/
.. /
<< see line 26 >>
2012.txt 2012-Nov-21 05:47 2.2 KB.
2013.txt 2012-Nov-21 05:47 2.2 KB.
2017.txt 2017-Feb-25 22:42 2.2 KB.
2018.txt 2017-Dec-15 01:21 2.2 KB.
2019.txt 2018-Sep-29 03:43 1.9 KB.
2020.txt 2020-Feb-25 05:04 1.9 KB.
danielo_ipod.gif 2012-Nov-21 06:15 32.8 KB <Picture>
dict.tar.gz 2012-Nov-18 07:42 4.6 KB <PC Bin>
gophermap.tar.gz 2013-Feb-14 07:59 1.1 KB <PC Bin>
sdf_ipod.gif 2012-Nov-21 06:15 46.2 KB <Picture>
toybox.zip 2012-Nov-17 06:23 4.2 KB <PC Bin>
musica/
She Of The Woods - Fold Flower <PC Bin>
Andy Pawlak - Mermaids <PC Bin>
Rick Springfield - State of The Heart <PC Bin>
Split Enz - I Got You <PC Bin>
Labi Siffre - Saved <PC Bin>
Labi Siffre - It Must Be Love <PC Bin>
Linda Perhacs - Chimacum Rain <PC Bin>
List of radio stations (dic 7, 2012) <PC Bin>
List of radio stations (oct 1, 2015) <PC Bin>
List of radio stations (oct 2, 2015) <PC Bin>
List of radio stations (mar 1, 2018) <PC Bin>
gopher-info/
Gopher docs/
.. /
Gopher docs/
<< see line 791 >>
How to setup gopher in SDF.
Gopher, el celacanto de la red.
RFC 1436.
Gopher item types.
Gopher tutorial (en sdf, enlace html) <~h~>
The Overbite Project <~h~>
Gopher_and_Formatting_with_ASCII.txt 2018-Oct-10 05:12 2.1 KB.
Internet-Gopher-PPL-Alberti.txt 2018-Oct-10 05:12 61.0 KB.
gopher-celacanto-red.txt 2018-Oct-10 05:30 7.5 KB.
gopher_item_types.txt 2018-Oct-10 05:12 1.2 KB.
gopher_wikipedia.txt 2018-Oct-10 05:12 22.4 KB.
gophermap.txt 2018-Oct-10 05:12 13.5 KB.
home-gopher.txt 2018-Oct-10 05:12 1.1 KB.
notas-de-gopher.txt 2018-Oct-10 05:12 0.9 KB.
rfc1436.txt 2018-Oct-10 05:12 35.6 KB.
toybox.zip 2018-Oct-10 05:12 4.2 KB <PC Bin>
veronica.faq 2018-Oct-10 05:12 23.5 KB.
How to setup gopher in SDF.
Gopher, el celacanto de la red.
RFC 1436.
Gopher item types.
Gopher tutorial (en sdf, enlace html) <~h~>
The Overbite Project <~h~>
enlaces/
jstg's gopher/
Phlog/
Back to the beginning/
<< see line 819 >>
2017/
Back to the beginning/
<< see line 819 >>
Up one directory/
<< see line 820 >>
Andoid and NoGapps - 1 October 2017.
Puzzle and Dragons - No-REM - 5 July 2017.
New Gopher Holes - 21 June 2017.
Random Thoughts - 12 June 2017.
Morrowind Vampires - 10 April 2017.
New Computer - 11 January 2017.
Happy New Year - 1 January 2017.
2016/
Back to the beginning/
<< see line 819 >>
Up one directory/
<< see line 820 >>
The TWM Window Manager - 13 November 2016.
Even More Fvwm2 - 27 October 2016.
PulseAudio - 13 October 2016.
Blood using eduke32 - 29 September 2016.
Using Slackware's Shipped Software - 11 August 2016.
More Fvwm2 - 10 August 2016.
Fvwm2 Revisited - 28 July 2016.
Slackware 14.2 is Finally Released - 1 July 2016.
I Need a New Shell - 30 June 2016.
Slackware 14.2 Almost Here - 2 June 2016.
Un-RIP Keyboard? - 29 May 2016.
RIP Keyboard - 25 May 2016.
Slackware and Slackware ARM - 21 May 2016.
KDE - Round 2 - 3 May 2016.
More Broken Morrowind - 21 April 2016.
Random Thoughts for the Day - 31 March 2016.
Slackware 14.2 RC1 - 17 March 2016.
More Morrowind - 26 February 2016.
Slackware 14.2 Beta and Mororwind - 9 February 2016.
New Things Actually Happening - 19 January 2016.
New DOOM Level - 15 January 2016.
Happy New Year - 1 January 2016.
2015/
Back to the beginning/
<< see line 819 >>
Up one directory/
<< see line 820 >>
I'm Back - 31 December 2015.
Almost a Beta - 16 November 2015.
I'm Still Here - 14 November 2015.
Another Big Slackware -current Update - 29 October 2015.
Playing With the Beaglebone - 23 October 2015.
Even More Morrowind - 30 September 2015.
More Morrowind - 21 September 2015.
Morrowind - 15 September 2015.
Another Big Slackware -current Update - 21 August 2015.
Slackware -current Fixes - 13 August 2015.
I Don't Like Change - 8 August 2015.
POSIX - 29 July 2015.
Sell Me on Your Software Choices - 25 July 2015.
I'm Still here - 16 July 2015.
It's Been Awhile - 7 July 2015.
CnDoom and herbstluftwm - 18 June 2015.
DOOM 4 - 14 June 2015.
Zowie EC2-A - 7 June 2015.
DOOM: Thy Flesh Consumed - 26 May 2015.
Little Things - 13 May 2015.
DOOM II vs TNT: Evilution - 8 May 2015.
Reorganizing $HOME - 4 May 2015.
Huge Slackware -current Update - 23 April 2015.
Castlevania: Symphony of the Night - 15 April 2015.
No Excitement - 8 April 2015.
ksh93 Revisited - 17 March 2015.
Random Thoughts for the Day - 16 March 2015.
DOOM WADs - 5 March 2015.
Random Thoughts - 17 February 2015.
More Borderlands 2 - 12 February 2015.
Borderlands 1 and Borderlands 2 - 4 February 2015.
Fed up with Firefox - 18 January 2015.
Problems with the Elvis Text Editor - 17 January 2015.
Slackware Documentation - 16 January 2015.
Activity in Gopherspace - 15 January 2015.
The Ed Text Editor - 6 January 2015.
Happy New Year - 1 January 2015.
2014/
Back to the beginning/
<< see line 819 >>
Up one directory/
<< see line 820 >>
DOOM Turns 21 - 10 December 2014.
The Internet Sucks - 3 December 2014.
Ramblings - 30 November 2014.
More Fvwm2 - 10 November 2014.
Window Managers - 5 November 2014.
Wolfenstein 3D Spear of Destiny Mission Packs - 27 October 2014.
Random Thoughts - 24 October 2014.
Video Games - 18 October 2014.
Getting Comfortable With ksh93 - 8 October 2014.
From BASH to ksh93 - 30 September 2014.
Random Thoughts - 29 September 2014.
Random Thoughts - 20 September 2014.
DOOM Speedruns - 17 September 2014.
David Woodfall's soma - 7 September 2014.
Linux on the Desktop - 20 August 2014.
Leaving Elvis for Vim - 16 August 2014.
Tried Out Arch Linux - 15 August 2014.
herbstluftwm Part 2 - 2 August 2014.
Trying out herbstluftwm - 31 July 2014.
Slackware Turns 21 - 18 July 2014.
Another Big Update For Slackware-current - 16 July 2014.
Big Update to Slackware-current - 12 July 2014.
Linux/Unix Shells - 11 July 2014.
Switching to spectrwm - 23 June 2014.
Trying Out Plan9 - 20 June 2014.
PSX DOOM and Duke Nukem - 13 June 2014.
Obesession with Beethoven - 8 June 2014.
Growing Up... - 3 June 2014.
Brutal Doom Demos - 30 May 2014.
Summertime - 25 May 2014.
Slackware-current Updates - 11 May 2014.
Why I Use the Software I Use - 1 May 2014.
Nethack - 23 April 2014.
Bye Windows XP - 11 April 2014.
Spring Cleaning - 1 April 2014.
Mice, Trackballs, KDE - 28 March 2014.
Thinking About Linux From Scratch - 19 March 2014.
Breathing Life Into "Older" Hardware - 7 March 2014.
Another Systemd Post - 25 February 2014.
Random Thoughts - 14 February 2014.
Boredom - 6 February 2014.
Yet Another DOOM Post - 21 January 2014.
Trying to Learn Python - 11 January 2014.
Issues With Star Wars - 4 January 2014.
Making Better Use of SDF - 2 January 2014.
Happy New Year - 1 January 2014.
2013/
Back to the beginning/
<< see line 819 >>
Up one directory/
Back to the beginning/
<< see line 819 >>
2017/
<< see line 823 >>
2016/
<< see line 835 >>
2015/
<< see line 862 >>
2014/
<< see line 904 >>
2013/
<< see line 955 >>
Baseball's Hall of Fame and PED Use - 27 December 2013.
The End of Another Year - 23 December 2013.
Brutal DOOM - 12 December 2013.
My Thoughts About GNU Emacs - 8 December 2013.
DOOM Revisited - 1 December 2013.
Trying out Emacs - 25 November 2013.
The Blue Oyster Cult FAQ and the Palm Pre 2 - 16 November 2013.
Slackware 14.1 is Released - 8 November 2013.
Raspberry Pi and Slackware ARM - 25 October 2013.
Raspberry Pi - 22 October 2013.
Slackware 14.1-rc1 - 15 October 2013.
Linux is Old? - 9 October 2013.
Boredom - 6 October 2013.
Elvis - The Text Editor - 29 September 2013.
Random Musings - 28 September 2013.
Slackware - "Hey folks, I'm calling this a beta!" - 18 September 2013.
Slackware64-current - 17 September 2013.
Github or Gitorious? - 9 September 2013.
Back to Slackware - 29 August 2013.
Switching to WeeChat - 27 August 2013.
Ramblings for the Day - 18 August 2013.
Google and Android Revisited - 12 August 2013.
Still Working Out - 6 August 2013.
Dungeons of Dredmor - 1 August 2013.
Working Out - 23 July 2013.
The Predator Movies - 16 July 2013.
Feel Like I Missed Out - 14 July 2013.
Finally Rid of Google - 7 July 2013.
CLI vs GUI - 27 June 2013.
The Remind Utility - 22 June 2013.
Still Trying to Avoid Google - 21 June 2013.
Off the Wall and Off the Hook - 19 June 2013.
Online Privacy - 17 June 2013.
Happy Birthday SDF - 16 June 2013.
Finally Some Nice Weather - 12 June 2013.
Config Files and More - 6 June 2013.
Remember Text Files? - 4 June 2013.
DOOM - Thy Flesh Consumed - 3 June 2013.
The Urge to Distro-Hop - 1 June 2013.
Remember Doom? - 31 May 2013.
Bye Google - 30 May 2013.
Doing My Own Thing - 29 May 2013.
2014/
<< see line 904 >>
2013/
<< see line 955 >>
2015/
<< see line 862 >>
2014/
<< see line 904 >>
2013/
<< see line 955 >>
2016/
<< see line 835 >>
2015/
<< see line 862 >>
2014/
<< see line 904 >>
2013/
<< see line 955 >>
Texts/
Back to the beginning/
<< see line 819 >>
Xresources.
elvis/
.. /
Back to the beginning/
<< see line 819 >>
Xresources.
elvis/
<< see line 1035 >>
elvisrc.
fvwm/
.. /
<< see line 1036 >>
bin 2016-Oct-25 04:54 - /
.. /
.. /
<< see line 1036 >>
bin 2016-Oct-25 04:54 - /
<< see line 1046 >>
bitmaps 2016-Aug-15 22:38 - /
.. /
<< see line 1047 >>
l-bob.xbm 2016-Nov-02 19:45 27.2 KB <Picture>
s-bob.xbm 2016-Nov-02 19:45 6.9 KB <Picture>
icons 2016-Oct-28 06:31 - /
.. /
<< see line 1047 >>
16x16 2016-Oct-25 04:54 - /
.. /
<< see line 1057 >>
terminal.png 2016-Nov-02 19:45 0.7 KB <Picture>
22x22 2016-Oct-10 00:47 - /
.. /
<< see line 1057 >>
chromium.png 2016-Nov-02 19:45 1.0 KB <Picture>
firefox.png 2016-Nov-02 19:45 1.3 KB <Picture>
lock.png 2016-Nov-02 19:45 1.0 KB <Picture>
pidgin.png 2016-Nov-02 19:45 1.3 KB <Picture>
presley.png 2016-Nov-02 19:45 1.5 KB <Picture>
rox.png 2016-Nov-02 19:45 1.1 KB <Picture>
slackware_menu.png 2016-Nov-02 19:45 1.6 KB <Picture>
smplayer.png 2016-Nov-02 19:45 1.5 KB <Picture>
terminal.png 2016-Nov-02 19:45 1.0 KB <Picture>
text-generic.png 2016-Nov-02 19:45 0.5 KB <Picture>
32x32 2016-Oct-28 06:31 - /
.. /
<< see line 1057 >>
media-playback-pause.png 2016-Nov-02 19:45 0.2 KB <Picture>
media-playback-start.png 2016-Nov-02 19:45 0.4 KB <Picture>
media-playback-stop.png 2016-Nov-02 19:45 0.2 KB <Picture>
media-playlist-repeat.png 2016-Nov-02 19:45 0.6 KB <Picture>
media-playlist-shuffle.png 2016-Nov-02 19:45 0.5 KB <Picture>
media-skip-backward.png 2016-Nov-02 19:45 0.5 KB <Picture>
media-skip-forward.png 2016-Nov-02 19:45 0.5 KB <Picture>
volume 2016-Aug-11 08:15 - /
.. /
<< see line 1057 >>
1.png 2016-Nov-02 19:45 0.5 KB <Picture>
2.png 2016-Nov-02 19:45 0.5 KB <Picture>
3.png 2016-Nov-02 19:45 0.5 KB <Picture>
4.png 2016-Nov-02 19:45 0.6 KB <Picture>
5.png 2016-Nov-02 19:45 0.6 KB <Picture>
6.png 2016-Nov-02 19:45 0.6 KB <Picture>
7.png 2016-Nov-02 19:45 0.7 KB <Picture>
8.png 2016-Nov-02 19:45 0.7 KB <Picture>
wallpaper 2016-Oct-13 06:37 - /
.. /
<< see line 1047 >>
boc.png 2016-Nov-02 19:45 7.3 KB <Picture>
jolly-roger.png 2016-Nov-02 19:45 67.0 KB <Picture>
jollyroger1.png 2016-Nov-02 19:45 24.6 KB <Picture>
jollyrogerbackground.png 2016-Nov-02 19:45 30.8 KB <Picture>
subgenius1.png 2016-Nov-02 19:45 914.1 KB <Picture>
subgenius_blue_1920x1080.png 2016-Nov-02 19:45 933.1 KB <Picture>
subgenius_bmarine_1920x1080.png 2016-Nov-02 19:45 822.7 KB <Picture>
subgenius_green_1920x1080.png 2016-Nov-02 19:45 841.8 KB <Picture>
subgenius_purple_1920x1080.png 2016-Nov-02 19:45 846.8 KB <Picture>
subgenius_red_1920x1080.png 2016-Nov-02 19:45 714.3 KB <Picture>
sword_and_sworcery_concert.jpg 2016-Nov-02 19:45 152.3 KB <Picture>
sword_and_sworcery_concert2.png 2016-Nov-02 19:45 2.8 MB <Picture>
sword_and_sworcery_cozyyuletide.png 2016-Nov-02 19:45 3.0 MB <Picture>
sword_and_sworcery_firstlook.png 2016-Nov-02 19:45 492.5 KB <Picture>
sword_and_sworcery_mtn.png 2016-Nov-02 19:45 975.6 KB <Picture>
sword_and_sworcery_mtn_bridge.jpg 2016-Nov-02 19:45 255.3 KB <Picture>
sword_and_sworcery_record_cover.png 2016-Nov-02 19:45 235.6 KB <Picture>
sword_and_sworcery_sharpersmoother.png 2016-Nov-02 19:45 25.1 KB <Picture>
config 2017-Jun-21 10:12 45.8 KB.
fvwm_current_screenshot.png 2016-Nov-07 07:31 568.1 KB <Picture>
cmus_np 2016-Nov-02 19:45 0.6 KB.
file_handler 2016-Nov-07 09:43 0.4 KB.
run_dialog 2016-Nov-02 19:45 0.3 KB.
shortcuts 2016-Nov-02 19:45 1.9 KB.
sysstat 2016-Nov-02 19:45 0.6 KB.
bitmaps 2016-Aug-15 22:38 - /
<< see line 1052 >>
icons 2016-Oct-28 06:31 - /
<< see line 1057 >>
wallpaper 2016-Oct-13 06:37 - /
<< see line 1098 >>
config 2017-Jun-21 10:12 45.8 KB.
fvwm_current_screenshot.png 2016-Nov-07 07:31 568.1 KB <Picture>
kshrc.
nethackrc.
nexrc.
profile.
sh_logout.
tmux.conf.
twmrc.
vimrc.
xinitrc.
beginning_with_rsync.txt.
compile_from_source.txt.
convert_ext3_ext4.txt.
mkinitrd.txt (Slackware).
nullmail_gmail.txt.
numlockon.txt (Slackware).
slack26384.txt (Slackware).
slackLVM.txt (Slackware).
Slackwarearm Beaglebone Black Installation (Slackware).
Slackwarearm BeagleBone Balck Compile Kernel (Slackware).
steam_and_gentoo.txt (Gentoo).
elvis.arf 2016-Aug-11 08:18 3.0 KB.
elvis.clr 2016-Aug-11 08:18 1.6 KB.
elvis.clr.orig 2016-Aug-11 08:18 1.5 KB.
elvis.syn 2016-Aug-11 08:18 85.8 KB.
elvis.syn.orig 2016-Aug-11 08:18 85.7 KB.
elvisrc.
fvwm/
<< see line 1043 >>
kshrc.
nethackrc.
nexrc.
profile.
sh_logout.
tmux.conf.
twmrc.
vimrc.
xinitrc.
beginning_with_rsync.txt.
compile_from_source.txt.
convert_ext3_ext4.txt.
mkinitrd.txt (Slackware).
nullmail_gmail.txt.
numlockon.txt (Slackware).
slack26384.txt (Slackware).
slackLVM.txt (Slackware).
Slackwarearm Beaglebone Black Installation (Slackware).
Slackwarearm BeagleBone Balck Compile Kernel (Slackware).
steam_and_gentoo.txt (Gentoo).
Slackware/
Back to the beginning/
<< see line 819 >>
Slackware64-current ChangeLog.txt <~h~>
Slackware64 14.2 ChangeLog.txt <~h~>
ChangeLog.txt from Previous Releases/
Back to the beginning/
<< see line 819 >>
Up one directory/
<< see line 1182 >>
Slackware 1.1.1.
Slackware 1.1.2.
Slackware 1.2.0.
Slackware 1.2.0.1.
Slackware 1.2.0.2.
Slackware 1.2.0.3.
Slackware 2.0.0.
Slackware 2.0.1.
Slackware 2.0.2.
Slackware 2.1.
Slackware 2.2.0.
Slackware 2.3.
Slackware 3.0.
Slackware 3.1.
Slackware 3.2.
Slackware 3.3.
Slackware 3.4.
Slackware 3.5.
Slackware 3.6.
Slackware 3.9.
Slackware 4.0.
Slackware 7.0.
Slackware 7.1.
Slackware 8.0.
Slackware 8.1.
Slackware 9.0.
Slackware 9.1.
Slackware 10.0.
Slackware 10.1.
Slackware 10.2.
Slackware 11.0.
Slackware 12.0.
Slackware 12.1.
Slackware 12.2.
Slackware 13.0 <~h~>
Slackware 13.1 <~h~>
Slackware 13.37 <~h~>
Slackware 14.0 <~h~>
Slackware 14.1 <~h~>
Slackware 14.2 <~h~>
Slackware Release Notes/
Back to the beginning/
<< see line 819 >>
Up one directory/
<< see line 1182 >>
Slackware 9.0.
Slackware 9.1.
Slackware 10.0.
Slackware 10.1.
Slackware 10.2.
Slackware 11.0.
Slackware 12.0.
Slackware 12.1.
Slackware 12.2.
Slackware 13.0.
Slackware 13.1.
Slackware 13.37.
Slackware 14.0.
Slackware 14.1.
Slackware 14.2.
ANNOUNCE.14_2.
RELEASE_NOTES.
CHANGES_AND_HINTS.TXT.
UPGRADE.TXT.
README.initrd.
Slackbook <Bin>
Slackware Basics (For Slackware 12.0) <Bin>
Slackware Trademark Policy <~h~>
The home of Slackware <~h~>
Classic First Person Shooters/
Back to the beginning/
<< see line 819 >>
Ultimate DOOM <Bin>
DOOM II <Bin>
Final DOOM <Bin>
Duke Nukem 3D <Bin>
Quake 1 <Bin>
Rise of the Triad <Bin>
Wolfenstein 3D <Bin>
DOOM Bible <Bin>
DOOM FAQ v6.666.
DOOM Source Code v1.10 (licensed under the GPL) <PC Bin>
Duke Nukem 3D Source Code (licensed under the GPL) <PC Bin>
Heretic Source Code (licensed under the GPL) <PC Bin>
Hexen Source Code (licensed under the GPL) <PC Bin>
Quake 1 Source Code (licensed under the GPL) <PC Bin>
Rise of the Triad Source Code (licensed under the GPL) <PC Bin>
Wolfenstein 3D Source Code (licensed under the id Software License) <PC Bin>
Wolfenstein 3D iOS Source Code (licensed under the GPL) <PC Bin>
FAQs/
Back to the beginning/
<< see line 819 >>
Up one directory/
<< see line 1261 >>
allcodes.doc.
bfgfaq21.txt.
bfgfaq21.zip <PC Bin>
chaingun.txt.
chaingun.zip <PC Bin>
chainsaw.txt.
chainsaw.zip <PC Bin>
changes.txt.
changes.zip <PC Bin>
d1keys11.faq.
d1secret.txt.
d1secret.zip <PC Bin>
d2l30rcp.txt.
d2secret.txt.
d2secret.zip <PC Bin>
d2wt.txt.
d2wt.zip <PC Bin>
designer.txt.
dj-doomfaq.tar.gz <PC Bin>
dm2_keys.txt.
dm2_keys.zip <PC Bin>
dm64faq.txt.
dmfaq66.txt.
dmfaq66.zip <PC Bin>
dmsecret.txt.
doom.cht.
e4secret.txt.
e4secret.zip <PC Bin>
fist_faq.txt.
fist_faq.zip <PC Bin>
gusdoom.faq.
gusdoom.txt.
hacx.cht.
heretic.cht.
hexen.cht.
hfaq15a.txt.
hfaq15a.zip <PC Bin>
hrsecret.txt.
hrsecret.zip <PC Bin>
hticfaq.txt.
hticfaq1.zip <PC Bin>
mlevsfaq.txt.
mlevsfaq.zip <PC Bin>
pistol11.txt.
pistol11.zip <PC Bin>
plasma.txt.
plasma.zip <PC Bin>
qtalk400.txt.
rocket.txt.
rocket.zip <PC Bin>
shotgun.txt.
shotgun.zip <PC Bin>
snesdm13.txt.
snesdm13.zip <PC Bin>
srsecret.txt.
srsecret.zip <PC Bin>
strife.cht.
wadchngs.txt.
Misc docs/
Back to the beginning/
<< see line 819 >>
Up one directory/
<< see line 1261 >>
muchdm.txt.
bookofid.txt.
bookofid.zip <PC Bin>
boomhint.txt.
dm2tourn.txt.
dmconspw.txt.
dmconspw.zip <PC Bin>
dmhowto.txt.
dmhowto.zip <PC Bin>
dminfo2.txt.
domm11.story.
doom12.story.
doom13.story.
doom2how.txt.
doom2how.zip <PC Bin>
doomcode.txt.
doomcode.zip <PC Bin>
doomcomp.txt.
doomcomp.zip <PC Bin>
doomexit.txt.
doomexit.zip <PC Bin>
doomfont.txt.
doomfont.zip <PC Bin>
doomhelp.txt.
doomhelp.zip <PC Bin>
doompro.story.
doomread.txt.
doomread.zip <PC Bin>
dtnc.txt.
dtnc.zip <PC Bin>
edoom.txt.
edoom.zip <PC Bin>
fdoomcmp.txt.
fdoomcmp.zip <PC Bin>
ghostfaq.txt.
ghostfaq.zip <PC Bin>
idsoft.txt.
jrinterv.txt.
majest3.txt.
majest3.zip <PC Bin>
maxdoom.txt.
maxdoom.zip <PC Bin>
maxsec.txt.
maxsec.zip <PC Bin>
mikeauth.txt.
milestone.txt.
monsters.txt.
monsters.zip <PC Bin>
phobos.txt.
phobos.zip <PC Bin>
reviewer.app.
romero.txt.
spzmenu.txt.
spzmenu.zip <PC Bin>
wadauth2.txt.
waman.txt.
waman.zip <PC Bin>
Scummvm Game Manuals/
Back to the beginning/
<< see line 819 >>
Beneath A Steel Sky <Bin>
Broken Sword 1 - The Shadows of the Templar <Bin>
Broken Sword 2 - The Smoking Mirror <Bin>
Day of the Tentacle <Bin>
The Dig <Bin>
Full Throttle <Bin>
Gobliiins <Bin>
Indiana Jones 3 - The Last Crusade (Grail Diary) <Bin>
Indiana Jones 3 - The Last Crusade (Manual) <Bin>
Indiana Jones 4 - The Fate of Atlantis <Bin>
Inherit The Earth <Bin>
Loom <Bin>
Lure Of The Temptress (Manual) <Bin>
Lure Of The Temptress (Protection) <Bin>
Maniac Mansion <Bin>
Sam & Max Hit The Road <Bin>
Simon The Sorcerer <Bin>
Simon The Sorcerer 2 - The Lion, The Wizard, and The Wardrobe <Bin>
The Secret Of Monkey Island <Bin>
The Secret Of Monkey Island 2 - LeChuck's Revenge <Bin>
The Secret Of Monkey Island 3 - The Curse Of Monkey Island <Bin>
Zak McKracken and The Alien Mindbenders <Bin>
Elvis/
Back to the beginning/
<< see line 819 >>
The home of Elvis <~h~>
elvis-2.2_0.tar.gz <PC Bin>
elvis-2.2_0-msdos.tar.gz <PC Bin>
elvis-2.2_0-win32.tar.gz <PC Bin>
elvis-2.2_0-os2.tar.gz <PC Bin>
Announce-2.2_0.
BUGS.
COPYING.
INSTALL.
README.
README.txt.
doc/
Back to the beginning/
<< see line 819 >>
Up one directory/
<< see line 1431 >>
bugs.txt.
doexec.txt.
license.txt.
elvis.txt.
elvisvi.txt.
elvisinp.txt.
elvisex.txt.
elvisre.txt.
elvisopt.txt.
elvis.dm.txt.
elvisgui.txt.
elvisos.txt.
elvisses.txt.
elviscut.txt.
elvismsg.txt.
elvisexp.txt.
elvistag.txt.
elvisnet.txt.
elvistip.txt.
elvistrs.msg.
howto.txt.
elvis.man.
ctags.man.
ref.man.
fmt.man.
elvis.ali.
elvis.arf.
elvis.awf.
elvis.brf.
elvis.bro.
elvis.bwf.
elvis.clr.
elvis.clr.orig.
elvis.glade.
elvis.gnome.
elvis.ini.
elvis.lat.
elvis.msg.
elvis.pc8.
elvis.ps.
elvis.rc.
elvis.spe.
elvis.syn.
elvis.x11.
icons/
Back to the beginning/
<< see line 819 >>
Up one directory/
<< see line 1431 >>
elvis.xpm <Bin>
elvis1.xpm <Bin>
elvis2.xpm <Bin>
elvis3.xpm <Bin>
kde.xpm <Bin>
mini.xpm <Bin>
normal.xpm <Bin>
presley.xpm <Bin>
small.xpm <Bin>
scripts/
Back to the beginning/
<< see line 819 >>
Up one directory/
<< see line 1431 >>
align.ex.
augz.ex.
cb.ex.
cursor.ex.
decode.ex.
define.ex.
dict.ex.
ellipse.ex.
find.ex.
fontsize.ex.
html.ex.
info.ex.
info2.ex.
inregion.ex.
isearch.ex.
life.ex.
likevim.ex.
mailto.ex.
makehtml.ex.
match.ex.
pig.ex.
reverse.ex.
rot13.ex.
sfb.ex.
shade.ex.
show.ex.
since.ex.
tags.ex.
wc.ex.
whois.ex.
xbuf.ex.
stubs/
Back to the beginning/
<< see line 819 >>
Up one directory/
<< see line 1431 >>
ansistub.c.
gdkstub.c.
glibstub.c.
gtkstub.c.
pthread.c.
unixstub.c.
xftstub.c.
xlibstub.c.
xpmstub.c.
themes/
Back to the beginning/
<< see line 819 >>
Up one directory/
<< see line 1431 >>
sand.ex.
sand.xpm <Bin>
F(?) Virtual Window Manager/
FVWM - The F(?) Virtual Window Manager <~h~>
Back to the beginning/
<< see line 819 >>
My FVWM configuration files/
<< see line 1043 >>
Current screenshot of my desktop <Picture>
SubGenius/
Back to the beginning/
<< see line 819 >>
The Church of the Subgenius <~h~>
BOCFAQ/
Hot Rails BOC FAQ <~h~>
Back to the beginning/
<< see line 819 >>
Dedication.
Why a BOC FAQ?.
The *real* people that made this FAQ possible.
Commonly used abbreviations.
Who are BOC?.
No really, who are BOC?.
History of the Band.
Pre-history of the Band.
Domestic (U.S.) Album Releases.
Solo Albums, Live Imports, Movie Soundtracks, and Special Compilations.
Compilation Albums (domestic).
Compilation Albums (foreign).
Bootleg Recordings.
Other Releases (Singles, Promos, etc).
The Buck Dharma Archive Series.
The Brain Surgeons Discography.
Joe Bouchard Post-BOC Releases.
What are BOC up to these days?.
When is the new (*not* a "Greatest Hits" album coming out?.
Where can I find (Flat Out, Imaginos, Bad Channels, other rare items)?.
What is the "best" BOC album?.
What is the story behind the recording of the album, *Imaginos*?.
What is the story told by the album, *Imaginos*?.
Is there a BOC/H.P. Lovecraft connection?.
Where is the BOC symbol on the ___ album?.
Where can I get a complete set of BOC lyrics?.
What is a (Diz-Buster, ME-262, Stun Guitar,...)?.
Who is (Suzy, Celine, Debbie Denise, Sir Rastus Bear, ...)?.
Where can I get BOC live recordings?.
Where can I find Rossignol's book, 'The Origins of a World War'?.
What do the Japanese words in "Godzilla" mean?.
Are there other BOC recordings, and how can I hear them?.
Where can I find BOC MP3s?.
Are BOC Nazis?.
When did Buck Dharma shave off his moustache?.
Will the original line-up ever get back together again?.
How tall was the original line-up?.
Use of Umlauts, and the Origin of the Name, "Blue Oyster Cult".
BOC in Concert.
BOC on the Charts.
The Movie "Heavy Metal".
The Buck Dharma Band Ricky Browning Benefit.
Song References.
References to BOC.
Bands Covering BOC.
The BOC/Michael Moorcock Connection.
Hidden Messages.
BOC on Video.
BOC Collectbles.
Bolle Gregmar -- BOC/Brain Surgeons Fan Clubs.
Church Of The Cult -- BOC Fan Club For French Fans.
Buck Dharma Website.
Albert Bouchard and Deborah Frost -- The Brain Surgeons.
BOC Newswire -- Lastest BOC News And Tour Dates.
BOC-L -- The BOC/Hawkwind E-Mail List.
BOC on the Web.
Other Online Sources.
Copyright Information.
Disclaimer.
changes.txt.
Gophernicus Sample Gophermap.
RFC-1436.txt.
rbigelo's Gopher and Gopherspace.
rbigelo's Gopherspace/
Gopher & Gopherspace.
Journal.
Booklist.
Playlists.
Notebook.
Transit Journal.
SDF Access UNIX System/
<< see line 1 >>
slugmax's Gopherspace/
About this site.
Phlog Archives (2018).../
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Phlog Archives (2017).../
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Phlog Archives (2009-2016).../
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued.
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Gopher History/
Parent directory/
Parent directory/
<< see line 1652 >>
books/
.. /
Parent directory/
<< see line 1652 >>
books/
<< see line 1823 >>
Edgar Rice Burrough's Barsoom series in glorious text/
.. /
<< see line 1823 >>
a_fighting_man_of_mars_burroughs_barsoom_VII 2015-Jul-28 16:13 459.5 KB.
a_princess_of_mars_burroughs_barsoom_I.txt 2015-Jul-28 16:13 369.9 KB.
llana_of_gathol_burroughs_barsoom_XI.txt 2015-Jul-28 16:13 435.0 KB.
swords_of_mars_burroughs_barsoom_VIII.txt 2015-Jul-28 16:13 426.9 KB.
synthetic_men_of_mars_burroughs_barsoom_IX.t 2015-Jul-28 16:13 350.8 KB.
the_chessmen_of_mars_burroughs_barsoom_V.txt 2015-Jul-28 16:13 483.5 KB.
the_giant_of_mars_burroughs_barsoom_X.txt 2015-Jul-28 16:13 100.9 KB.
the_gods_of_mars_burroughs_barsoom_II.txt 2015-Jul-28 16:13 449.2 KB.
the_master_mind_of_mars_burroughs_barsoom_VI 2015-Jul-28 16:13 293.3 KB.
the_warlord_of_mars_burroughs_barsoom_III.tx 2015-Jul-28 16:13 310.7 KB.
thuvia_maid_of_mars_burroughs_barsoom_IV.txt 2015-Jul-28 16:13 267.7 KB.
emacs/
Parent directory/
<< see line 1820 >>
Emacs Tutorial, HTML <~h~>
Emacs Tutorial, text.
Emacs Tutorial, epub <Bin>
Emacs Tutorial, Muse source.
Emacs Cheatsheet, HTML <~h~>
Emacs Cheatsheet, text.
Emacs Cheatsheet, epub <Bin>
Emacs Cheatsheet, Muse source.
fiction/
.. /
<< see line 1824 >>
tales_of_a_freelance_sysadmin-what_router.tx 2015-Jul-28 16:13 6.4 KB.
gopher tips & howtos/
Parent directory/
<< see line 1820 >>
Gophernicus Gophermap README.
Making Gopher Search Useful.
SDF Gopher Tutorial.
Typing Literal Tabs in Vim and Emacs.
gopher history/
Parent directory/
<< see line 1820 >>
Who Killed Gopher (1998).
The Gopher Manifesto (2002).
The Rise and Fall of the Gopher Protocol (2016).
miscellany/
.. /
<< see line 1824 >>
jefferson_taylor_1816.txt 2015-Jul-28 16:13 8.9 KB.
michael-moore-trumpland 2017-Aug-15 13:48 3.9 KB.
Gophernicus' README.gophermap.
barsoom_stories_burroughs 2015-Jul-28 16:13 - /
.. /
<< see line 1823 >>
a_fighting_man_of_mars_burroughs_barsoom_VII 2015-Jul-28 16:13 459.5 KB.
a_princess_of_mars_burroughs_barsoom_I.txt 2015-Jul-28 16:13 369.9 KB.
llana_of_gathol_burroughs_barsoom_XI.txt 2015-Jul-28 16:13 435.0 KB.
swords_of_mars_burroughs_barsoom_VIII.txt 2015-Jul-28 16:13 426.9 KB.
synthetic_men_of_mars_burroughs_barsoom_IX.t 2015-Jul-28 16:13 350.8 KB.
the_chessmen_of_mars_burroughs_barsoom_V.txt 2015-Jul-28 16:13 483.5 KB.
the_giant_of_mars_burroughs_barsoom_X.txt 2015-Jul-28 16:13 100.9 KB.
the_gods_of_mars_burroughs_barsoom_II.txt 2015-Jul-28 16:13 449.2 KB.
the_master_mind_of_mars_burroughs_barsoom_VI 2015-Jul-28 16:13 293.3 KB.
the_warlord_of_mars_burroughs_barsoom_III.tx 2015-Jul-28 16:13 310.7 KB.
thuvia_maid_of_mars_burroughs_barsoom_IV.txt 2015-Jul-28 16:13 267.7 KB.
ben_bova_the_next_logical_step.txt 2015-Jul-28 16:13 13.4 KB.
cory_doctorow_0wnz0red.txt 2015-Jul-28 16:13 75.3 KB.
cory_doctorow_chicken_little.txt 2015-Jul-28 16:13 114.3 KB.
cory_doctorow_when_sysadmins_ruled_the_earth 2015-Jul-28 16:13 78.1 KB.
h_beam_piper_omnilingual.txt 2015-Jul-28 16:13 93.8 KB.
hacker_crackdown_pt1.txt 2015-Jul-28 16:13 103.9 KB.
hacker_crackdown_pt2.txt 2015-Jul-28 16:13 225.9 KB.
hacker_crackdown_pt3.txt 2015-Jul-28 16:13 154.3 KB.
hacker_crackdown_pt4.txt 2015-Jul-28 16:13 195.9 KB.
handwriting_repair_briem.pdf 2015-Sep-02 12:42 19.5 MB <~d~>
isaac_asimov_youth.txt 2015-Jul-28 16:13 56.2 KB.
poul_anderson_duel_on_syrtis.txt 2015-Jul-28 16:13 37.5 KB.
poul_anderson_industrial_revolution.txt 2015-Jul-28 16:13 96.8 KB.
poul_anderson_security.txt 2015-Jul-28 16:13 70.7 KB.
poul_anderson_the_burning_bridge.txt 2015-Jul-28 16:13 55.9 KB.
poul_anderson_the_sensistive_man.txt 2015-Jul-28 16:13 117.7 KB.
poul_anderson_the_valor_of_cappen_varra.txt 2015-Jul-28 16:13 29.1 KB.
Edgar Rice Burrough's Barsoom series in glorious text/
<< see line 1829 >>
emacs/
<< see line 1843 >>
fiction/
<< see line 1854 >>
gopher tips & howtos/
<< see line 1858 >>
gopher history/
<< see line 1865 >>
miscellany/
<< see line 1871 >>
Gophernicus' README.gophermap.
Who Killed Gopher (1998).
The Gopher Manifesto (2002).
The Rise and Fall of the Gopher Protocol (2016).
Gopher Blogging Utilities.../
Parent directory/
<< see line 1652 >>
About Slerm, the Dynamic Gopher Blogging Engine.
Get the latest Slerm gopher blogging engine - slerm-1.8.tgz <Bin>
Phlogit, the Static Gopher Phlog Maintainer.
Other phlogging utilities are listed in the gopher tutorial.
Using and Searching Gopher.../
Parent directory/
<< see line 1652 >>
About Gopher & Gopher Space (from user rbigelo).
Browse Gopher Natively in Firefox (< v57) - OverbiteFF <~h~>
Browse Gopher via proxy in Firefox (>= v57) - OverbiteWX <~h~>
Getting Started with Gopher Blogging Using Phlogit.
How to type literal TABs in vim and emacs.
Making Gopher Search More Useful.
Sample Gophermap (Gophernicus Gopher Server).
SDF Gopher Tutorial, as text.
Books.../
.. /
<< see line 1824 >>
barsoom_stories_burroughs 2015-Jul-28 16:13 - /
<< see line 1877 >>
ben_bova_the_next_logical_step.txt 2015-Jul-28 16:13 13.4 KB.
cory_doctorow_0wnz0red.txt 2015-Jul-28 16:13 75.3 KB.
cory_doctorow_chicken_little.txt 2015-Jul-28 16:13 114.3 KB.
cory_doctorow_when_sysadmins_ruled_the_earth 2015-Jul-28 16:13 78.1 KB.
h_beam_piper_omnilingual.txt 2015-Jul-28 16:13 93.8 KB.
hacker_crackdown_pt1.txt 2015-Jul-28 16:13 103.9 KB.
hacker_crackdown_pt2.txt 2015-Jul-28 16:13 225.9 KB.
hacker_crackdown_pt3.txt 2015-Jul-28 16:13 154.3 KB.
hacker_crackdown_pt4.txt 2015-Jul-28 16:13 195.9 KB.
handwriting_repair_briem.pdf 2015-Sep-02 12:42 19.5 MB <~d~>
isaac_asimov_youth.txt 2015-Jul-28 16:13 56.2 KB.
poul_anderson_duel_on_syrtis.txt 2015-Jul-28 16:13 37.5 KB.
poul_anderson_industrial_revolution.txt 2015-Jul-28 16:13 96.8 KB.
poul_anderson_security.txt 2015-Jul-28 16:13 70.7 KB.
poul_anderson_the_burning_bridge.txt 2015-Jul-28 16:13 55.9 KB.
poul_anderson_the_sensistive_man.txt 2015-Jul-28 16:13 117.7 KB.
poul_anderson_the_valor_of_cappen_varra.txt 2015-Jul-28 16:13 29.1 KB.
Code.../
Parent directory/
<< see line 1652 >>
Phlogit - Simple goPHerLOG helper.
External editor plugin for thunderbird 3.1 <Bin>
ELisp to make the external editor plugin play nicely with GNU Emacs.
Publish a blog/phlog entry, and optionally update timestamp cache.
Script for managing a blog/phlog post timestamp cache.
About Slerm, the Dynamic Gopher Blogging Engine.
The latest (v1.8) slerm gopher blogging engine CGI.
The latest (v1.8) slerm distribution tarball <Bin>
Strip HTML tags from text (uses HTML::Strip).
Strip HTML tags from text (no module dependencies).
Gopher mole to nicely format a floodgap weather feed.
Emacs tutorial and cheatsheet in text, html, epub and muse source/
Parent directory/
<< see line 1820 >>
Emacs Tutorial, HTML <~h~>
Emacs Tutorial, text.
Emacs Tutorial, epub <Bin>
Emacs Tutorial, Muse source.
Emacs Cheatsheet, HTML <~h~>
Emacs Cheatsheet, text.
Emacs Cheatsheet, epub <Bin>
Emacs Cheatsheet, Muse source.
Docs.../
<< see line 1820 >>
Random Firefly Quote/
Yin Feng's Gopherspace/
Yin Feng's Chan Buddhist PHLOG/
From Scratch (02-08-18)/
.. /
From Scratch (02-08-18)/
<< see line 1994 >>
The Zen Buddhist Order of Hsu Yun <~h~>
Overbite Project <~h~>
The SDF Public Access UNIX System .. Est. 1987/
<< see line 1 >>
Slugmax's Gopher Space/
<< see line 1652 >>
ecelis/
phlog /
.. /
phlog /
<< see line 2005 >>
ITS/
cfe.homeunix.org gopher root/
<< see line 1 >>
A Luser's Guide to ITS (EN).
ITS 1.5 Reference Manual (EN).
Documentation for DDT version 1491 (EN).
DDT Primer and Reference Manual describing DDT version 696 (EN).
ITS TTY LIST OF ESCAPE CODES. (EN).
doc/
ITS en Mi Kiwi (ES) <~h~>
ITS-VS, aka its.svensson.org <~h~>
Bjorn UP <~h~>
TOPS-20/
cfe.homeunix.org gopher root.
SDF/
.. /
<< see line 2006 >>
irc-future-meeting.txt 2014-Jun-01 20:40 55.3 KB.
Writings /
.. /
<< see line 2006 >>
essays 2014-Jun-01 20:42 - /
.. /
<< see line 2027 >>
WHs1300__Essay01__Afro-Eurasia_After_Black_D 2014-Jun-01 20:42 5.0 KB.
WHs1300__Essay01__Afro-Eurasia_After_Black_D 2014-Jun-01 20:42 3.9 KB.
poryectoSERT.txt 2014-Jun-01 20:42 5.9 KB.
poems 2014-Jun-20 17:16 - /
.. /
<< see line 2027 >>
Noche.txt 2014-Jun-12 18:32 0.4 KB.
Sometime_In_1999.txt 2014-Jun-01 20:42 1.0 KB.
ti_haiku.txt 2014-Jun-20 17:16 0.4 KB.
tales 2014-Jun-01 20:42 - /
.. /
<< see line 2027 >>
CreiaSerHombre.txt 2014-Jun-01 20:42 1.6 KB.
ElHombreRoto.txt 2014-Jun-01 20:42 3.0 KB.
FiestaEnsuenio.txt 2014-Jun-01 20:42 0.5 KB.
LaVozDeEseQueNoSoyToTodos.txt 2014-Jun-01 20:42 1.6 KB.
LifeTimesJournal.txt 2014-Jun-01 20:42 2.5 KB.
UnCuentoParaDormir...ODominarElMundo.txt 2014-Jun-01 20:42 1.5 KB.
2006-03-01-desarrollo-sobre-rieles.md 2020-Jan-12 18:07 4.3 KB.
2006-04-29-por-qu-no-puedo-depurar-component 2020-Jan-12 18:07 2.5 KB.
2006-04-29-que-hago-siasp-deja-de-funcionar- 2020-Jan-12 18:07 4.2 KB.
2006-05-04-clase-php-5-para-representar-base 2020-Jan-12 18:07 3.6 KB.
2006-05-06-como-era-de-esperar-windows-el.md 2020-Jan-12 18:08 0.4 KB.
2006-05-06-instale-windows-server-2003-para- 2020-Jan-12 18:08 0.1 KB.
2006-05-06-rdbms-instalacin-desatendida.md 2020-Jan-12 18:08 0.5 KB.
2006-05-29-radio-on-line-para-el-estado.md 2020-Jan-12 18:08 5.5 KB.
2006-05-co-o-era-de-esperar-windows-el.md 2020-Jan-12 18:08 0.4 KB.
2006-05-ra-io-on-line-para-el-estado.md 2020-Jan-12 18:08 5.5 KB.
2006-09-07-iis-51-el-servicio-smtp-no-aparec 2020-Jan-12 18:08 0.1 KB.
2006-09-28-ati-drivers-para-linux-debian-way 2020-Jan-12 18:08 0.8 KB.
2006-09-28-oracle-xe-instalacin-en-ubuntu-da 2020-Jan-12 18:08 1.3 KB.
2006-09-29-ant-165-tomcat-559-slackware-101. 2020-Jan-12 18:08 3.3 KB.
2006-09-29-asignacin-de-puertos-xml-db.md 2020-Jan-12 18:08 0.7 KB.
2006-09-29-como-utilizar-apache-torque-31.md 2020-Jan-12 18:09 1.2 KB.
2006-09-an--165-tomcat-559-slackware-101.md 2020-Jan-12 18:09 3.3 KB.
2006-09-as-gnacin-de-puertos-xml-db.md 2020-Jan-12 18:09 0.7 KB.
2006-09-at--drivers-para-linux-debian-way.md 2020-Jan-12 18:09 0.8 KB.
2006-09-co-o-utilizar-apache-torque-31.md 2020-Jan-12 18:09 1.2 KB.
2006-09-or-cle-xe-instalacin-en-ubuntu-dappe 2020-Jan-12 18:09 1.3 KB.
2006-10-09-error-inesperado-en-conexiones-de 2020-Jan-12 18:38 1.2 KB.
2006-10-12-recuperacin-de-contraseas-en-ms-a 2020-Jan-12 18:37 0.1 KB.
2006-10-er-or-inesperado-en-conexiones-de-re 2020-Jan-12 18:36 1.2 KB.
2006-10-re-uperacin-de-contraseas-en-ms-acce 2020-Jan-12 18:09 0.1 KB.
2006-11-ii--51-el-servicio-smtp-no-aparece-e 2020-Jan-12 18:36 0.1 KB.
2007-04-29-windows-manteniendo-el-control-li 2020-Jan-12 18:36 5.4 KB.
2007-04-29-windows-manteniendo-el-control.md 2020-Jan-12 18:36 5.2 KB.
2007-04-wi-dows-manteniendo-el-control-limpi 2020-Jan-12 18:36 5.4 KB.
2007-04-wi-dows-manteniendo-el-control.md 2020-Jan-12 18:36 5.2 KB.
2007-07-01-de-safari-en-windows.md 2020-Jan-12 18:36 2.5 KB.
2007-07-09-ubuntu-feisty-fawn-704-solucion-d 2020-Jan-12 18:36 0.3 KB.
2007-07-18-cakephp-templates-en-eclipse.md 2020-Jan-12 18:36 0.8 KB.
2007-07-23-picasa-true-web-albums.md 2020-Jan-12 18:36 1.4 KB.
2007-07-ca-ephp-templates-en-eclipse.md 2020-Jan-12 18:36 0.8 KB.
2007-07-pi-asa-true-web-albums.md 2020-Jan-12 18:36 1.4 KB.
2007-07-ub-ntu-feisty-fawn-704-solucion-de.m 2020-Jan-12 18:36 0.3 KB.
2007-08-07-guia-para-contratar-programadores 2020-Jan-12 18:36 5.9 KB.
2007-08-de-safari-en-windows.md 2020-Jan-12 18:35 2.5 KB.
2007-08-gu-a-para-contratar-programadores.md 2020-Jan-12 18:35 5.9 KB.
2007-09-11-importar-apple-mail-mozilla-thund 2020-Jan-12 18:35 1.0 KB.
2007-09-im-ortar-apple-mail-mozilla-thunderb 2020-Jan-12 18:35 1.0 KB.
2007-10-07-dijo-microsoft-que-siempre-no.md 2020-Jan-12 18:35 1.3 KB.
2007-10-07-visualizacin-de-archvivos-de-regi 2020-Jan-12 18:35 0.1 KB.
2007-10-19-convierte-tus-archivos-en-un-enig 2020-Jan-12 18:35 2.9 KB.
2007-10-22-expreso-online.md 2020-Jan-12 18:35 5.4 KB.
2007-10-23-las-noticias-perdidas-de-mercurio 2020-Jan-12 18:35 2.7 KB.
2007-10-24-la-verdad-es-vacia.md 2020-Jan-12 18:35 1.7 KB.
2007-10-co-vierte-tus-archivos-en-un-enigma. 2020-Jan-12 18:35 2.9 KB.
2007-10-di-o-microsoft-que-siempre-no.md 2020-Jan-12 18:35 1.3 KB.
2007-10-ex-reso-online.md 2020-Jan-12 18:35 5.4 KB.
2007-10-la--noticias-perdidas-de-mercurio.md 2020-Jan-12 18:35 2.7 KB.
2007-10-la-verdad-es-vacia.md 2020-Jan-12 18:35 1.7 KB.
2007-10-vi-ualizacin-de-archvivos-de-registr 2020-Jan-12 18:35 0.1 KB.
2007-11-13-el-gafico.md 2020-Jan-12 18:34 2.6 KB.
2007-11-30-d-j-bernstein-pone-su-software-en 2020-Jan-12 18:34 2.5 KB.
2007-11-d---bernstein-pone-su-software-en-el 2020-Jan-12 18:34 2.5 KB.
2007-11-el-gafico.md 2020-Jan-12 18:34 2.6 KB.
2007-12-03-manual-de-gimp.md 2020-Jan-12 18:34 0.1 KB.
2007-12-04-gpdb-liberado.md 2020-Jan-12 18:34 1.0 KB.
2007-12-07-cabezas-3d.md 2020-Jan-12 18:34 0.2 KB.
2007-12-07-foro-de-avidemux-en-espaol.md 2020-Jan-12 18:33 2.0 KB.
2007-12-08-instalacin-de-ibm-informix-dynami 2020-Jan-12 18:33 3.6 KB.
2007-12-ca-ezas-3d.md 2020-Jan-12 18:33 0.2 KB.
2007-12-fo-o-de-avidemux-en-espaol.md 2020-Jan-12 18:33 2.0 KB.
2007-12-gp-b-liberado.md 2020-Jan-12 18:33 1.0 KB.
2007-12-in-talacin-de-ibm-informix-dynamic.m 2020-Jan-12 18:33 3.6 KB.
2007-12-ma-ual-de-gimp.md 2020-Jan-12 18:33 0.1 KB.
2008-01-20-moviendose-la-libertad-i.md 2020-Jan-12 18:33 12.1 KB.
2008-01-mo-iendose-la-libertad-i.md 2020-Jan-12 18:33 12.1 KB.
2008-02-16-acceder-telfono-motorola-pebl-u6- 2020-Jan-12 18:32 2.3 KB.
2008-02-ac-eder-telfono-motorola-pebl-u6-en. 2020-Jan-12 18:32 2.3 KB.
2008-05-03-vmware-server-105-en-ubuntu-804-h 2020-Jan-12 18:32 0.3 KB.
2008-05-04-php-facilito-en-gsl-uat.md 2020-Jan-12 18:32 0.5 KB.
2008-05-ph--facilito-en-gsl-uat.md 2020-Jan-12 18:31 0.5 KB.
2008-05-vm-are-server-105-en-ubuntu-804-hard 2020-Jan-12 18:31 0.3 KB.
2008-10-19-reemplaza-el-bloc-de-notas-de-win 2020-Jan-12 18:30 2.2 KB.
2009-02-07-slackware-122-en-laptop-acer-aspi 2020-Jan-12 18:30 0.6 KB.
2009-02-sl-ckware-122-en-laptop-acer-aspire. 2020-Jan-12 18:30 0.6 KB.
2009-03-09-otro-blog-y-que.md 2020-Jan-12 18:30 1.5 KB.
2009-06-pu-fy_en_el_escritorio.md 2020-Jan-12 18:30 1.4 KB.
2009-07-na-ando_en_lo_hondo.md 2020-Jan-12 18:30 0.1 KB.
2009-08-cr-ced_y_multiplicaos.md 2020-Jan-12 18:30 0.1 KB.
2009-12-25-interno-de-carcel-irrumpe-en-la-r 2020-Jan-12 18:30 0.3 KB.
2009-12-in-erno-de-carcel-irrumpe-en-la-red- 2020-Jan-12 18:30 0.3 KB.
2010-01-03-nace-nueva-comunidad-de-blender-p 2020-Jan-12 18:29 0.4 KB.
2010-01-na-e-nueva-comunidad-de-blender-para 2020-Jan-12 18:29 0.4 KB.
2010-02-03-init-acapara-el-procesador-de-ami 2020-Jan-12 18:29 0.9 KB.
2010-06-de-comandos_y_ventanas.md 2020-Jan-12 18:29 0.1 KB.
2010-09-09-92010_homeunix_cluster.md 2020-Jan-12 18:29 0.1 KB.
2010-09-26-92010_twm_y_respaldos.md 2020-Jan-12 18:29 0.7 KB.
2010-10-17-jamboree-del-aire-2010-en-hamsphe 2020-Jan-12 18:29 1.2 KB.
2012-04-26-42012_shell_plus_web_sdf_clisp.md 2020-Jan-12 18:29 0.5 KB.
2012-05-04-su-servicio.md 2020-Jan-12 18:28 5.6 KB.
2013-01-10-privacidad-en-facebook-para-dummi 2020-Jan-12 18:21 8.3 KB.
2013-03-10-ano-nuevo-time-to-rethink-strateg 2020-Jan-12 18:28 2.8 KB.
2013-04-27-coding-in-c-for-almost-any-device 2020-Jan-12 18:28 2.8 KB.
2013-09-11-a-learning-exercise-with-python.m 2020-Jan-12 18:27 1.5 KB.
2013-12-10-ten-years-of-great-learning-exper 2020-Jan-12 18:15 3.2 KB.
2014-02-12-surveillance-people-and-power.md 2020-Jan-12 18:27 2.8 KB.
2014-07-09-slackwarearm-in-cubieboard2.md 2020-Jan-12 18:25 2.9 KB.
2014-09-29-gnu-guix-hackathon-09-2014.md 2020-Jan-12 18:25 2.8 KB.
2015-01-03-MrUnix-the-new-kid-in-the-tildeve 2020-Jan-12 18:07 1.7 KB.
2015-06-11-system-fail-and-windows-install.m 2020-Jan-12 18:20 1.0 KB.
2015-06-12-Introduction-to-R-data-types.md 2020-Jan-12 18:24 3.5 KB.
2015-06-26-linux-kernel-notes-i.md 2020-Jan-12 20:26 1.3 KB.
2017-07-19-computer-forensics-i.md 2020-Jan-12 17:59 0.9 KB.
2019-03-21-javascript-notes-i.md 2020-Jan-12 17:59 1.4 KB.
2019-10-10-mongodb-notes-i.md 2020-Jan-12 17:57 2.4 KB.
2019-10-11-frontend-master-2020-i.md 2020-Jan-12 17:57 6.2 KB.
2019-10-13-realidad-aumentaday-gps-web.md 2020-Jan-12 17:57 0.4 KB.
2019-10-18-arqueria-diversion-y-disciplina.m 2020-Jan-12 20:16 1.1 KB.
2019-10-19-path-to-frontend-master-ii.md 2020-Jan-12 17:54 0.2 KB.
2019-10-21-my-first-quantum-program.md 2020-Jan-12 17:53 0.6 KB.
ITS/
<< see line 2009 >>
TOPS-20/
<< see line 2021 >>
SDF/
<< see line 2023 >>
Writings /
<< see line 2027 >>
Editing texts with vim.
tips-vim.
Project Gutenberg <~h~>
dict.org <~h~>
Lynx browser <~h~>
[09-Mar-2020] tomasino Tomasino's Gopher Hole/
About/
public key.
public key.
Phlog/
2019 Archive/
2019-12-23 - webmentions and microsub/
[0] IndieAuth <~h~>
[1] Webmentions <~h~>
[2] Git Man Page Generator <~h~>
[3] Aperture <~h~>
[4] Poisoning the Well/
2019-12-16 - poisoning the well/
<< see line 2189 >>
2019-12-15 - QR codes/
2019-12-15 - years of journaling/
[2] tomasino blog <~h~>
2019-11-15 - sdf minecraft question/
2019-11-15 - re: gopher resiliency/
[1] gopher history archives/
.. /
| _) <~i~>
_` | _|_| \ |\ \ / -_)(_-< <~i~>
\__,_|_|\__|_| _|_| \_/\___|___/ <~i~>
These are bits of awesome I've salvaged from around the net. <~i~>
On the naming of the finger command.
vi/ex tutorial by Walter Alan Zintz/
The Vi/Ex Editor <~i~>
By Walter Alan Zintz. <~i~>
<~i~>
[Editor's Note: This tutorial series is a 'work in progress' and <~i~>
will evolve over time. We'll announce each new addition and <~i~>
expand this table of contents.] <~i~>
Part 1: Vi Editor Fundamentals/
The vi/ex Editor, Part 1: Vi Editor Fundamentals <~i~>
Why Vi? <~i~>
A Heartwarming Edit <~i~>
The Plan Of This Ongoing Tutorial <~i~>
The Editor's Basic Concepts <~i~>
Search Patterns <~i~>
Searching From Where You Are Now <~i~>
The Find-Them-All Search <~i~>
Simple Search Patterns <~i~>
Metacharacters <~i~>
Table Of Search Pattern Metacharacters <~i~>
Character Classes. <~i~>
What's Coming For The Next Installment. <~i~>
Why Vi? <~i~>
<~i~>
A HEARTWARMING EDIT. Pity poor Hal, a corporate maintenance <~i~>
programmer. A large module of badly-broken, poorly-patched legacy <~i~>
code -- the spaghetti variety -- finally broke down completely <~i~>
yesterday, leaving one corporate division running at half speed. <~i~>
By dint of some inspired fixes during an all-nighter, Hal has the <~i~>
module up and running again this morning... but just as he's ready <~i~>
to go out for food that isn't from a vending machine, in walks the <~i~>
corporation's VP of IS, with a big surprise. <~i~>
<~i~>
"Nice work on that crash fix, Hal; but right now I need some <~i~>
formatted technical data about it, in a hurry. The Board of <~i~>
Directors' Information Systems Committee has called a rush <~i~>
meeting this morning to convince themselves they're on top of <~i~>
the problem. I'll be in the hotseat, and I need technical data <~i~>
I can put up on the video projector to keep them occupied. <~i~>
<~i~>
"They'll want me to discuss the logfile of errors that led up to <~i~>
the crash . . . yes, I know that's in /oltp/err/m7, but <~i~>
appending puts the latest report lines at the bottom of the <~i~>
file. Those suits aren't interested in what they think is <~i~>
ancient history, and they wouldn't be caught reading anything <~i~>
but a commuter train timetable from the bottom up, so you'll <~i~>
have to make a copy with the order of the lines reversed: what <~i~>
was the last line becomes the first line, what was the second to <~i~>
the last line is now line number two, and so on. <~i~>
<~i~>
"And let's take a look at that logfile. <~i~>
<~i~>
<~i~>
374a12 44872 130295/074457 nonabort <~i~>
5982d34 971 130295/221938 nonabort <~i~>
853f7 2184 140295/102309 abort <~i~>
... <~i~>
<~i~>
<~i~>
Hmmm. Explaining the second column to them would be advertising <~i~>
the fact that we knew this failure was just waiting for a chance <~i~>
to happen. So while you're at it, go through and erase all but <~i~>
the first and last digits of each number in column two. <~i~>
<~i~>
"Oh, and when they get tired of that they'll want to scrutinize <~i~>
the Lint report. Last month I told them that our Lint <~i~>
substitute was the greatest thing since Marilyn Monroe, so now <~i~>
they'll want me to tell them why the messages it still generates <~i~>
on this module aren't real hazards. Just run Lint over the <~i~>
revamped module; then combine the Lint output with a copy of the <~i~>
source file by taking each message line like: <~i~>
<~i~>
<~i~>
Line 257: obsolete operator += <~i~>
<~i~>
<~i~>
and putting the significant part at the end of the source line <~i~>
it refers to. And put a separator, like XXX, between the source <~i~>
line and the message so I can page through quickly. Nothing like <~i~>
a hefty dose of source code they can't begin to fathom to make <~i~>
the meeting break up early. <~i~>
<~i~>
"And get right on this. The meeting starts in 35 minutes." <~i~>
<~i~>
Our VP walks away inwardly smiling, thinking he's getting out of <~i~>
detailed explanations and putting all the blame on an underling, <~i~>
just by demanding more editing than anyone could do in the time <~i~>
available. "I'll tell the Information Systems Committee that I <~i~>
made it perfectly clear to the programmer that we needed this at <~i~>
9:30, but when I asked him for it a minute ago he said it wasn't <~i~>
finished and he wasn't sure when it would be. Then I'll remark <~i~>
that those programmers just can't understand that keeping <~i~>
management informed is every bit as important as writing code!" <~i~>
<~i~>
But Hal has a secret weapon against this squeeze play: an expert <~i~>
knowledge of the Vi editor. <~i~>
<~i~>
Reversing the order of the lines in a file is a piece of cake with <~i~>
this editor. The eight keystrokes in: <~i~>
<~i~>
:g/^/m0(ret) <~i~>
<~i~>
will do it. Taking the digits out of the middle of the second <~i~>
column throughout the file also requires just one command line: <~i~>
<~i~>
:%s/^\([^ ]* [0-9]\)[0-9]*\([0-9] \)/\1\2(ret) <~i~>
<~i~>
And integrating the Lint messages into a copy of the source code? <~i~>
Even that can be automated with the Vi editor. The editor <~i~>
command: <~i~>
<~i~>
:%s/Line \([0-9][0-9]*\): \(.*\)/\1s;$; XXX \2(ret) <~i~>
<~i~>
will turn that file of Lint messages into an editor script, and <~i~>
running that script on a copy of the source file will mark it up <~i~>
as requested. <~i~>
<~i~>
Rather than being portrayed as a bungler, Hal can have it all <~i~>
ready in a couple of minutes, just by typing a few lines. He'll <~i~>
even have time to guard against vice-presidential prevarication, <~i~>
by disappearing into the coffee shop across the street and <~i~>
reappearing just as the meeting is getting started, to tell the VP <~i~>
(and everyone else in earshot), "Those files you wanted are in <~i~>
slash-temp-slash-hal". <~i~>
<~i~>
THE PLAN OF THIS ONGOING TUTORIAL. I'm writing here for editor <~i~>
users who have some fluency in Vi/Ex at the surface level. That <~i~>
is, you know how to do the ordinary things that are belabored in <~i~>
all the "Introducing Vi" books on the market, but rarely venture <~i~>
beyond that level. <~i~>
<~i~>
This tutorial series will explore a lot of other capabilities that <~i~>
hardly anyone knows are in Vi/Ex. That includes quite a few <~i~>
tricks that may be built on editor functions we all use every day, <~i~>
but which nonetheless are not obvious--for instance, telling the <~i~>
global command to mark every line it encounters. I'll also be <~i~>
clarifying the real nature of the many misunderstood aspects of <~i~>
this editor. <~i~>
<~i~>
To do all this, I'll be explaining things in more depth than you <~i~>
might think warranted at first. I'll also throw in examples <~i~>
wherever they seem helpful. And to save you readers from gross <~i~>
information overload, I'll write this tutorial in a large number <~i~>
of fairly small modules, to be put up on our website at a calm, <~i~>
reasonable pace. <~i~>
<~i~>
The Editor's Basic Concepts <~i~>
<~i~>
To get a real grasp on this editor's power, you need to know the <~i~>
basic ideas embodied in it, and a few fundamental building blocks <~i~>
that are used throughout its many functions. <~i~>
<~i~>
One cause of editor misuse is that most users, even experienced <~i~>
ones, don't really know what the editor is good at and what it's <~i~>
not capable of. Here's a quick rundown on its capabilities. <~i~>
<~i~>
First, it's strictly a general-purpose editor. It doesn't format <~i~>
the text; it doesn't have the handholding of a word processor; it <~i~>
doesn't have built-in special facilities for editing binaries, <~i~>
graphics, tables, outlines, or any programming language except <~i~>
Lisp. <~i~>
<~i~>
It's two editors in one. Visual mode is a better full-screen <~i~>
editor than most, and it runs faster than those rivals that have a <~i~>
larger bag of screen-editing commands. Line editing mode dwarfs <~i~>
the "global search and replace" facilities found in word <~i~>
processors and simple screen editors; its only rivals are <~i~>
non-visual editors like Sed where you must know in advance exactly <~i~>
what you want to do. But in the Vi/Ex editor, the two sides are <~i~>
very closely linked, giving the editor a combination punch that no <~i~>
other editor I've tried can rival. <~i~>
<~i~>
Finally, this editor is at its best when used by people who have <~i~>
taken the trouble to learn it thoroughly. It's too capable to be <~i~>
learned well in an hour or two, and too idiosyncratic to be <~i~>
mastered in a week, and yet the power really is in it, for the few <~i~>
who care to delve into it. A large part of that power requires <~i~>
custom-programming the editor: that's not easy or straightforward, <~i~>
but what can be done by the skillful user goes beyond the direct <~i~>
programmability of any editor except (possibly) Emacs. <~i~>
<~i~>
Search Patterns <~i~>
<~i~>
In quite a few functions of this editor, you can use <~i~>
string-pattern searching to say where something is to be done or <~i~>
how far some effect is to extend. These search patterns are a <~i~>
good example of an editor function that is very much in the Unix <~i~>
style, but not exactly the same in detail as search patterns in <~i~>
any other Unix utility. <~i~>
<~i~>
Search patterns function in both line editing and visual editing <~i~>
modes, and the work the same way in both, with just a few <~i~>
exceptions. But how you tell the editor you're typing in a search <~i~>
pattern will vary with the circumstances. <~i~>
<~i~>
SEARCHING FROM WHERE YOU ARE NOW. The more common use for search <~i~>
patterns is to go to some new place in the file, or make some <~i~>
editing change that will extend from your present position to the <~i~>
place the pattern search finds. (In line editing mode it's also <~i~>
possible to have an action take place from one pattern's location <~i~>
to where another pattern is found, but both searches still start <~i~>
from your present location.) <~i~>
<~i~>
If you want to search forward in the file from your present <~i~>
location (toward the end of the file), precede the search pattern <~i~>
with a slash (/) character, and type another to end the pattern. <~i~>
So if you want to move forward to the next instance of the string <~i~>
"j++" in your file, typing: <~i~>
<~i~>
/j++/(ret) <~i~>
<~i~>
will do it. And so will: <~i~>
<~i~>
/j++(ret) <~i~>
<~i~>
When there is nothing between the pattern and the RETURN key, the <~i~>
RETURN itself will indicate the end of the search pattern, so the <~i~>
second slash is not necessary. And if you are in visual mode, the <~i~>
ESCAPE key works as well as RETURN does for ending search input, <~i~>
so <~i~>
<~i~>
/j++(esc) <~i~>
<~i~>
is yet another way to make the same request from visual mode. <~i~>
<~i~>
To search backward (toward the start of the file), begin and end <~i~>
with a question mark instead of a slash. The same rules of <~i~>
abbreviation apply to backward searches, so <~i~>
<~i~>
?j++?(ret) <~i~>
?j++(ret) <~i~>
?j++(esc) <~i~>
<~i~>
are all ways to head backward in the file to the same pattern. <~i~>
<~i~>
Either way, you've expressed both your request for a pattern <~i~>
search and the direction the search is to take in just one <~i~>
keystroke. But don't assume that if you search backward, any <~i~>
matching pattern the editor finds will be above your present <~i~>
position in the file, and vice versa if you search forward. The <~i~>
editor looks there first, certainly, but if it gets to the top or <~i~>
bottom line of the file and hasn't found a match yet, it wraps <~i~>
around to the other end of the file and continues the search in <~i~>
the same direction. That is, if you used a question mark to order <~i~>
a backward search and the editor searches all the way through the <~i~>
top line of the file without finding a match, it will go on to <~i~>
search the bottom line next, then the second-to-the-bottom line, <~i~>
and so on until (if necessary) it gets back to the point where the <~i~>
search started. Or if you were searching forward and the editor <~i~>
found no match up through the very last line of the file, it would <~i~>
next search the first line, then the second line, etcetera. <~i~>
<~i~>
If you don't want searches to go past either end of the file, <~i~>
you'll need to type in a line mode command: <~i~>
<~i~>
:set nowrapscan(ret) <~i~>
<~i~>
This will disable the wraparound searching during the present <~i~>
session in the editor. If you want to restore the wraparound <~i~>
searching mechanism before you leave the editor, typing <~i~>
<~i~>
:set wrapscan(ret) <~i~>
<~i~>
will do it, and you can turn this on and off as often as you like. <~i~>
<~i~>
THE FIND-THEM-ALL SEARCH. Up to now, I've been considering <~i~>
searches that find just one instance of the pattern; the one <~i~>
closest to your current location in the file, in the direction you <~i~>
chose for the search. But there is another style of search, used <~i~>
primarily by certain line editing mode commands, such as global <~i~>
and substitute. This search finds every line in the file (or in a <~i~>
selected part of the file) that contains the pattern and operates <~i~>
on them all. <~i~>
<~i~>
Don't get confused when using the global and substitute commands. <~i~>
You'll often use both styles of search pattern in one command <~i~>
line. But the find-one-instance pattern or patterns will go <~i~>
before the command name or abbreviation, while the find-them-all <~i~>
pattern will come just behind it. For example, in the command: <~i~>
<~i~>
:?Chapter 10?,/The End/substitute/cat/dog/g(ret) <~i~>
<~i~>
the first two patterns refer to the preceding line closest to the <~i~>
current line that contains the string "Chapter 10" and the closest <~i~>
following line containing the string "The End". Note that each <~i~>
address finds only one line. Combined with the intervening comma, <~i~>
they indicate that the substitute command is to operate on those <~i~>
two lines and all the lines in between them. But the patterns <~i~>
immediately after the substitute command itself tell the command <~i~>
to find every instance of the string "cat" withing that range of <~i~>
lines and replace it with the string "dog". <~i~>
<~i~>
Aside from the difference in meaning, the two styles also have <~i~>
different standards for the delimiters that mark pattern <~i~>
beginnings and (sometimes) endings. With a find-them-all pattern, <~i~>
there's no need to indicate whether to search forward or backward. <~i~>
Thus, you aren't limited to slash and question mark as your <~i~>
pattern delimiters. Almost any punctuation mark will do, because <~i~>
the editor takes note of the first punctuation mark to appear <~i~>
after the command name, and regards it as the delimiter in that <~i~>
instance. So <~i~>
<~i~>
:?Chapter 10?,/The End/substitute;cat;dog;g(ret) <~i~>
:?Chapter 10?,/The End/substitute+cat+dog+g(ret) <~i~>
:?Chapter 10?,/The End/substitute{cat{dog{g(ret) <~i~>
<~i~>
are all equivalent to the substitution command above. (It is a <~i~>
good idea to avoid using punctuation characters that might have a <~i~>
meaning in the command, such as an exclamation point, which often <~i~>
appears as a switch at the end of a command name.) <~i~>
<~i~>
The benefit of this liberty comes when the slash mark will appear <~i~>
as itself in the search pattern. For example, suppose our <~i~>
substitution command above was to find each pair of consecutive <~i~>
slash marks in the text, and separate them with a hyphen--that is, <~i~>
change // to /-/. Obviously, <~i~>
<~i~>
:?Chapter 10?,/The End/substitute/////-//g(ret) <~i~>
<~i~>
won't work; the command will only regard the first three slashes <~i~>
as delimiters, and everything after that as extraneous characters <~i~>
at the end of the command. This can be solved by backslashing: <~i~>
<~i~>
:?Chapter 10?,/The End/substitute/\/\//\/-\//g(ret) <~i~>
<~i~>
but this is even harder to type correctly than the first attempt <~i~>
was. But with another punctuation mark as the separator <~i~>
<~i~>
:?Chapter 10?,/The End/substitute;//;/-/;g(ret) <~i~>
<~i~>
the typing is easy and the final command is readable. <~i~>
<~i~>
SIMPLE SEARCH PATTERNS. The simplest search pattern is just a <~i~>
string of characters you want the editor to find, exactly as <~i~>
you've typed them in. For instance: "the cat". But, already there <~i~>
are several caveats: <~i~>
<~i~>
1. This search finds a string of characters, which may or may <~i~>
not be words by themselves. That is, it may find its target in <~i~>
the middle of the phrase "we fed the cat boiled chicken", or in <~i~>
the middle of "we sailed a lithe catamaran down the coast". It's <~i~>
all a matter of which it encounters first. <~i~>
<~i~>
2. Whether the search calls "The Cat" a match or not depends on how <~i~>
you've set an editor variable named ignorecase. If you've left <~i~>
that variable in its default setting, the capitalized version will <~i~>
not match. If you want a capital letter to match its lower-case <~i~>
equivalent, and vice versa, type in the line mode command <~i~>
<~i~>
:set ignorecase(ret) <~i~>
<~i~>
To resume letting caps match only caps and vice versa, type <~i~>
<~i~>
:set noignorecase(ret) <~i~>
<~i~>
3. The search absolutely will not find a match where "the" <~i~>
occurs at the end of one line and "cat" is at the start of the <~i~>
next line: <~i~>
<~i~>
and with Michael's careful help, we prodded the cat back into <~i~>
its cage. Next afternoon several <~i~>
<~i~>
It makes no difference whether there is or isn't a space <~i~>
character between one of the words and the linebreak. Finding a <~i~>
pattern that may break across a line ending is a practically <~i~>
impossible task with this line-oriented editor. <~i~>
<~i~>
4. Where the search starts depends on which editor mode you're <~i~>
using. A search in visual mode starts with the character next to <~i~>
the cursor. In line mode, the search starts with the line <~i~>
adjacent to the current line. <~i~>
<~i~>
METACHARACTERS. Then there are search metacharacters or "wild <~i~>
cards": characters that represent something other than themselves <~i~>
in the search. As an example, the metacharacters . and * in <~i~>
<~i~>
/Then .ed paid me $50*!/(ret) <~i~>
<~i~>
could cause the pattern to match any of: <~i~>
<~i~>
Then Ted paid me $5! <~i~>
Then Red paid me $5000! <~i~>
Then Ned paid me $50! <~i~>
<~i~>
or a myriad of other strings. Metacharacters are what give search <~i~>
patterns their real power, but they need to be well understood. <~i~>
<~i~>
To understand these, you must know the varied uses of the <~i~>
backslash (\) metacharacter in turning the "wild card" value of <~i~>
metacharacters on and off. <~i~>
<~i~>
In many cases, the meta value of the metacharacter is on whenever <~i~>
the character appears in a search pattern unless it is preceded by <~i~>
a backslash; when the backslash is ahead of it the meta value is <~i~>
turned off and the character simply represents itself. As an <~i~>
example, the backslash is a metacharacter by itself, even if it <~i~>
precedes a character that never has a meta value. The only way to <~i~>
put an actual backslash in your search pattern is to precede it <~i~>
with another backslash to remove its meta value. That is, to <~i~>
search for the pattern "a\b", type <~i~>
<~i~>
/a\\b/(ret) <~i~>
<~i~>
as your search pattern. If you type <~i~>
<~i~>
/a\b/(ret) <~i~>
<~i~>
the backslash will be interpreted as a metacharacter without any <~i~>
effect (since the letter b is never a metacharacter) and your <~i~>
search pattern will find the string "ab". <~i~>
<~i~>
Less-often-used metacharacters are used in exactly the opposite <~i~>
way. This sort of character represents only itself when it <~i~>
appears by itself. You must use a preceding backslash to turn the <~i~>
meta value on. For example, in <~i~>
<~i~>
/\<cat/ <~i~>
<~i~>
the left angle bracket (<) is a metacharacter; in <~i~>
<~i~>
/<cat/ <~i~>
<~i~>
it only represents itself. These special metacharacters are <~i~>
pointed out in the list below. <~i~>
<~i~>
Finally there is a third class, the most difficult to keep track <~i~>
of. Usually these metacharacters have their meta values on in <~i~>
search patterns, and must be backslashed to make them represent <~i~>
just themselves: like our first example, the backslash character <~i~>
itself. But if you've changed the default value of an editor <~i~>
variable named magic to turn it off, they work oppositely--you <~i~>
then must backslash them to turn their meta value on: like our <~i~>
second example, the left angle bracket. (Not that you are are <~i~>
likely to have any reason to turn magic off.) These oddities are <~i~>
also noted in the list below. <~i~>
<~i~>
And don't forget the punctuation character that starts and ends <~i~>
your search pattern, whether it is slash or question mark or <~i~>
something else. Whatever it is, if it is also to appear as a <~i~>
character in the pattern you are searching for, you'll have to <~i~>
backslash it there to prevent the editor thinking it is the end of <~i~>
the pattern. <~i~>
<~i~>
TABLE OF SEARCH PATTERN METACHARACTERS <~i~>
<~i~>
. <~i~>
<~i~>
A period in a search pattern matches any single character, whether <~i~>
a letter of the alphabet (upper or lower case), a digit, a <~i~>
punctuation mark, in fact, any ASCII character except the newline. <~i~>
So to find "default value" when it might be spelled <~i~>
"default-value" or "default/value" or "default_value", etcetera, <~i~>
use /default.value/ as your search pattern. When the editor <~i~>
variable magic is turned off, you must backslash the period to <~i~>
give it its meta value. <~i~>
<~i~>
* <~i~>
<~i~>
An asterisk, plus the character that precedes it, match any length <~i~>
string (even zero length) of the character that precedes the <~i~>
asterisk. So the search string /ab*c/ would match "ac" or "abc" <~i~>
or "abbc" or "abbbc", and so on. (To find a string with at least <~i~>
one "b" in it, use /abb*c/ as your search string.) When the <~i~>
asterisk follows another metacharacter, the two match any length <~i~>
string of characters that the metacharacter matches. That means <~i~>
that /a.*b/ will find "a" followed by "b" with anything (or <~i~>
nothing) between them. When the editor variable magic is turned <~i~>
off, you must backslash the asterisk to give it its meta value. <~i~>
<~i~>
^ <~i~>
<~i~>
A circumflex as the first character in a search pattern means that <~i~>
a match will be found only if the matching string occurs at the <~i~>
start of a line of text. It doesn't represent any character at <~i~>
the start of the line, of course, and a circumflex anywhere in a <~i~>
search pattern except as the first character will have no meta <~i~>
value. So /^cat/ will find "cat", but only at the start of a <~i~>
line, while /cat^/ will find "cat^" anywhere in a line. <~i~>
<~i~>
$ <~i~>
<~i~>
A dollar sign as the last character in a search pattern means the <~i~>
match must occur at the end of a line of text. Otherwise it's the <~i~>
same as circumflex, above. <~i~>
<~i~>
\< <~i~>
<~i~>
At the start of a search pattern, a backslashed left angle bracket <~i~>
means the match can only occur at the start of a simple word; at <~i~>
any other position in a search pattern it is not a metacharacter. <~i~>
(In this editor, a "simple" word is either a string of one or more <~i~>
alphanumeric character(s) or a string of one or more <~i~>
non-alphanumeric, non-whitespace character(s), so "shouldn't" <~i~>
contains three simple words.) Thus /\<cat/ will find the last <~i~>
three characters in "the cat" or in "tom-cat", but not in <~i~>
"tomcat". To remove the meta value from the left angle bracket, <~i~>
remove the preceding backslash: /<cat/ will find "<cat" regardless <~i~>
of what precedes it. <~i~>
<~i~>
\> <~i~>
<~i~>
At the end of a search pattern, a backslashed right angle bracket <~i~>
means the match can occur only at the end of a simple word. <~i~>
Otherwise the same as the left angle bracket, above. <~i~>
<~i~>
~ <~i~>
<~i~>
The tilde represents the last string you put into a line by means <~i~>
of a line mode substitute command, regardless of whether you were <~i~>
in line mode then or ran it from visual mode by preceding it with <~i~>
a colon (":"). For instance, if your last line mode substitution <~i~>
command was s/dog/cat/ then a /the ~/ search pattern will find <~i~>
"the cat". But the input string of a substitute command can use <~i~>
metacharacters of its own, and if your last use involved any of <~i~>
those metacharacters then a tilde in your search pattern will give <~i~>
you either an error message or a match that is not what you <~i~>
expected. When the editor variable magic is turned off, you must <~i~>
backslash the tilde to give it its meta value. <~i~>
<~i~>
<~i~>
CHARACTER CLASSES. There is one metastring form (a "multicharacter <~i~>
metacharacter") used in search patterns. When several characters <~i~>
are enclosed within a set of brackets ([]), the group matches any <~i~>
one of the characters inside the brackets. That is, /part [123]/ <~i~>
will match "part 1", "part 2" or "part 3", whichever the search <~i~>
comes to first. One frequent use for this feature is in finding a <~i~>
string that may or may not be capitalized, when the editor <~i~>
variable ignorecase is turned off (as it is by default). Typing <~i~>
/[Cc]at/ will find either "Cat" or "cat", and /[Cc][Aa][Tt]/ will <~i~>
find those or "CAT". (In case there was a slip of the shift key <~i~>
when "CAT" was typed in, the last pattern will even find "CaT", <~i~>
"CAt", etcetera.) <~i~>
<~i~>
There's more power (and some complication) in another feature of <~i~>
this metastring: there can be metacharacters inside it. Inside the <~i~>
brackets, a circumflex as the first character reverses the <~i~>
meaning. Now the metastring matches any one character that is NOT <~i~>
within the brackets. A /^[^ ]/ search pattern finds a line that <~i~>
does not begin with a space character. (You're so right if you <~i~>
think that the different meta values of the circumflex inside and <~i~>
outside the character class brackets is not one of the editor's <~i~>
best points.) A circumflex that is not the first character inside <~i~>
the brackets represents just an actual circumflex. <~i~>
<~i~>
A hyphen can be a metacharacter within the brackets, too. When <~i~>
it's between two characters, and the first of the two other <~i~>
characters has a lower ASCII value than the second, it's as if <~i~>
you'd typed in all of the characters in the ASCII collating <~i~>
sequence from the first to the second one, inclusive. So /[0-9]%/ <~i~>
will find any numeral followed by the percent sign (%), just as <~i~>
/[0123456789]%/ would. A /[a-z]/ search pattern will match any <~i~>
lower-case letter, and /[a-zA-Z]/ matches any letter, capital or <~i~>
lower case. These two internal metacharacters can be combined: <~i~>
/[^A-Z]/ will find any character except a capital letter. A <~i~>
hyphen that is either the first or the last character inside the <~i~>
brackets has no meta value. When a character-hyphen-character <~i~>
string has a first character with a higher ASCII value than the <~i~>
last character, the hyphen and the two characters that surround it <~i~>
are all ignored by the pattern search, so /[ABz-a]/ is the same as <~i~>
/[AB]/. <~i~>
<~i~>
Backslashing character classes is complex. Within the brackets <~i~>
you must backslash a right bracket that's part of the class; <~i~>
otherwise the editor will mistake it for the bracket that closes <~i~>
the class. Of course you must backslash a backslash that you want <~i~>
to be part of the class, and you can backslash a circumflex at the <~i~>
start or a hyphen between two characters if you want them in the <~i~>
class literally and don't want to move them elsewhere in the <~i~>
construct. Elsewhere in a search pattern you will have to <~i~>
backslash a left bracket that you want to appear as itself, or <~i~>
else the editor will take it as your attempt to begin a character <~i~>
class. Finally, if magic is turned off, you'll have to backslash <~i~>
a left bracket when you do want it to begin a character class. <~i~>
<~i~>
Coming Up Next <~i~>
<~i~>
In the second part of this tutorial, I'll be following up on all <~i~>
this information about search patterns, by showing the right ways <~i~>
to combine them with other elements to generate command addresses. <~i~>
As a second part finale, I'll show how to tap the enormous power <~i~>
of the command that looks like an address: the global command. <~i~>
Part 2: Line-Mode Addresses/
The vi/ex Editor, Part 2: Line-Mode Addresses <~i~>
<~i~>
Whenever you want to give an editor command that will operate on <~i~>
text that's already in the file you're editing--to delete some <~i~>
text, change lower-case letters to capitals, write to a file, <~i~>
etcetera--the editor needs to know what part of the file to go to <~i~>
work on. A few commands have their addresses built in, and most <~i~>
line-mode commands have default addresses that the editor will use <~i~>
if you don't give an address, but that still leaves a lot of <~i~>
occasions where you need to know how to give the editor an address <~i~>
and what address to give. <~i~>
<~i~>
Many line-mode commands are almost identical to corresponding <~i~>
commands in visual mode; many more do similar things in different <~i~>
ways. Most of the benefit of these duplicative command sets comes <~i~>
from the totally-different addressing styles of line and visual <~i~>
modes. The differing address concepts mean that an edit that <~i~>
would be difficult or impossible to do with one mode's available <~i~>
addresses can be a piece of cake with an address form found in the <~i~>
other mode. <~i~>
<~i~>
Since I mention "line mode" so often, you may wonder whether there <~i~>
really is a separate mode for line editing. There surely <~i~>
is--instead of filling your screen with text from the file you're <~i~>
editing, this mode gives you a colon (:) prompt for your line mode <~i~>
commands, and prints only an occasional line from the file on your <~i~>
screen. The feel of this mode is very much like giving UNIX <~i~>
commands from your shell prompt. Few people work in line mode <~i~>
these days, largely because you can give most line-mode commands <~i~>
from visual mode, but you can't give any visual-mode commands <~i~>
while you are in line mode. Or perhaps they just prefer the <~i~>
comfortable WYSIWYG feeling of seeing the text on screen, with <~i~>
changes appearing as they are made. <~i~>
<~i~>
But there are times when you will need to work temporarily in line <~i~>
mode. To get to line mode when you first launch the editor, <~i~>
invoke it by typing "ex" instead of "vi". To go to line mode when <~i~>
you are already in the editor's visual mode, enter "Q". To get <~i~>
back to visual mode, type "vi" followed by a carriage return. <~i~>
<~i~>
Wondering why I didn't put a colon in front of that command to <~i~>
return to visual mode, which is obviously a line-mode command? <~i~>
Because you don't need to type that colon when you're giving a <~i~>
command from within line mode. It may even be harmful; the rule <~i~>
is that if you type a colon at the start of a command from within <~i~>
line mode, there must be nothing between the colon and the command <~i~>
name or abbreviation. Not an address, not even a space, nothing <~i~>
at all. <~i~>
<~i~>
So from this point on, I will display line-mode commands without <~i~>
an initial colon, because you now know enough to type that colon <~i~>
only if you're working in visual mode. And I'll leave off the tag <~i~>
at the end of a line-mode command that reminds you to finish with <~i~>
a carriage return because you now realize that any line-mode <~i~>
command, given from either line or visual mode, has to end with a <~i~>
carriage return. <~i~>
<~i~>
Some of you may ask why I show line-mode command lines in <~i~>
long-winded form, with spelled-out command names and lots of <~i~>
whitespace instead of using abbreviations. For instance, the two <~i~>
command lines: <~i~>
<~i~>
global /^/ move 0 <~i~>
g/^/m0 <~i~>
<~i~>
are identical in their effect, and the second is surely faster to <~i~>
type, so why do I show the first form? Because the long version <~i~>
is much easier to follow when I'm demonstrating a new concept, and <~i~>
almost everything here will be new to at least some of you. And <~i~>
it's a good idea to get to know the long forms, because you'll <~i~>
soon be learning to write editor scripts, and those scripts would <~i~>
be as cryptic as APL to future maintenance programmers if you <~i~>
wrote them in terse style. When I go over the roster of line-mode <~i~>
commands, I'll tell you both the long name and one or two short <~i~>
names for each. <~i~>
<~i~>
Line-Mode Addressing <~i~>
<~i~>
A SINGLE ADDRESS is often all you need with a line-mode command. <~i~>
One address refers to just one line, which tells a command like <~i~>
delete or substitute to operate on that one line only. A command <~i~>
like insert or read, which puts something immediately before or <~i~>
after a particular line, has no use for more than one address. <~i~>
<~i~>
A search pattern, as discussed in the first installment of this <~i~>
tutorial, is always an acceptable line-mode address. You put the <~i~>
address at the start of the command line, before the command name <~i~>
(but after the initial colon if you are giving the command from <~i~>
visual mode), so: <~i~>
<~i~>
?the [cC]at? delete <~i~>
<~i~>
will erase the last previous line that contains the string "the <~i~>
cat" or "the Cat", while: <~i~>
<~i~>
/^GLOSSARY$/ read gloss.book <~i~>
<~i~>
puts the contents of the file "gloss.book" right after the next <~i~>
line in the file you're editing that contains only the word <~i~>
"GLOSSARY". <~i~>
<~i~>
There are two shorthand forms for reusing search patterns as <~i~>
addresses. Typing "??" or "//" tells the editor to use the last <~i~>
search pattern you used previously, and your choice of "??" or <~i~>
"//" will set the direction of the search, overriding the <~i~>
direction you chose the previous time you used that search <~i~>
pattern. That is, if you type: <~i~>
<~i~>
?the cat? yank <~i~>
// delete <~i~>
?? print <~i~>
<~i~>
the second command will search forward, to remove the last <~i~>
previous line containing the string "the cat", even though your <~i~>
original use of that pattern was in a backward search. The third <~i~>
command will search backward to find the line to print, which (by <~i~>
coincidence) is the direction of the original search. <~i~>
<~i~>
But the search pattern that those preceding abbreviations reuse <~i~>
may not be a pattern you used to search for a line. If you ran a <~i~>
substitute command after any pattern searches for lines, then the <~i~>
pattern you gave the substitute command to tell it what text to <~i~>
take out of the line is the pattern that will be reused. This is <~i~>
so even if your substitute command began with a search pattern to <~i~>
specify the line on which the substitution was to be <~i~>
performed--the search to find the pattern to be replaced within <~i~>
the line was run after the first search pattern had found the line <~i~>
to operate on, so the search within the line was the last pattern <~i~>
search run. So if you were to type: <~i~>
<~i~>
/the cat/ substitute /in the hat/on the mat <~i~>
?? delete <~i~>
<~i~>
the second command would, in this case, delete the last previous <~i~>
line containing "in the hat". To be sure that the pattern that <~i~>
gets reused is the last one used to find a line, use the <~i~>
abbreviations "\?" and "\/" to search backward and forward, <~i~>
respectively. In all other respects these work just as typing <~i~>
"??" and "//" do. <~i~>
<~i~>
A LINE NUMBER is also a valid line-mode address. The editor <~i~>
automatically numbers each line in the file consecutively, and <~i~>
this numbering is dynamic--that is, whenever you add or delete <~i~>
lines somewhere, the editor renumbers all the lines following the <~i~>
insertion or deletion point. So if you change some text on line <~i~>
46 in your file, and then delete lines 11 and 12, the line with <~i~>
the text you changed is now line 44. And if you then add ten new <~i~>
lines after line 17, the line with your changed text on it now <~i~>
automatically becomes line 54. <~i~>
<~i~>
There is never a gap or an overlap in the line number sequence, so <~i~>
the nth line in the file is always line number n; that is, the 7th <~i~>
line is always line number 7, and so on. (There are several ways <~i~>
to display these line numbers, which I will expound in a later <~i~>
tutorial installment.) To delete the 153rd line in your file, <~i~>
just type: <~i~>
<~i~>
153 delete <~i~>
<~i~>
You don't use any delimiters around a line number, or around any <~i~>
other address except a search pattern. <~i~>
<~i~>
There are two symbolic line numbers and one fictional one that can <~i~>
be used in line-mode addresses. As long as there are any lines in <~i~>
the buffer (that is, you haven't specified a not-yet-existent file <~i~>
to edit and failed to enter any text so far), the editor regards <~i~>
you as being `on' one of them, usually the last line affected by <~i~>
your latest command. A period or dot (.) is the symbolic address <~i~>
for this line. The last line in the file also has a symbolic <~i~>
address: the dollar sign ($). So if you should type: <~i~>
<~i~>
. write >> goodlines <~i~>
$ delete <~i~>
<~i~>
the first command would append a copy of just the line you are on <~i~>
now to a file named "goodlines", while the second would delete the <~i~>
last line in the file you are editing. <~i~>
<~i~>
A few commands put text immediately after the line address you <~i~>
give: the append command is one of them. In order to let them put <~i~>
their text at the very start of a file (if that is where you want <~i~>
it), these commands can take the fictitious line number zero (0) <~i~>
as their address. So, if you want to type some text that will <~i~>
appear ahead of anything already in the file, you can do it with <~i~>
either of these command lines: <~i~>
<~i~>
1 insert <~i~>
0 append <~i~>
<~i~>
(Note, though, that insert and append are among the few line-mode <~i~>
commands that cannot be run from visual mode by starting with a <~i~>
colon, because they occupy more than one line including the text <~i~>
to be put in.) <~i~>
<~i~>
WRITING YOUR OWN LINE ADDRESSES is possible, too. You can attach <~i~>
lower-case letters to lines as line addresses, and change the <~i~>
attachments whenever you like. You can even use a special address <~i~>
that is automatically attached to the last line you jumped off <~i~>
from. <~i~>
<~i~>
There are ways to mark a particular line with a lower-case letter <~i~>
of the alphabet, and those ways differ between line and visual <~i~>
modes. I'll be explaining all these ways in later installments of <~i~>
this tutorial. But once a line is marked, the line-mode address <~i~>
that refers to that line is just the single-quote character <~i~>
followed immediately by the lower-case letter with which the line <~i~>
was marked. So typing: <~i~>
<~i~>
'b print <~i~>
<~i~>
will display on the screen whatever line you have previously <~i~>
marked with the letter b, no matter where the line is in relation <~i~>
to where you are when you give the command. No need to tell the <~i~>
editor whether to search forward or backward; there can be only <~i~>
one line at a time marked with any one letter, and the editor will <~i~>
find that line regardless. <~i~>
<~i~>
The editor does some line marking on its own, too. Whenever you <~i~>
move from one line to another by a non-relative address, the <~i~>
editor marks the line you just left. (A non-relative address is <~i~>
one that isn't a known number of lines from where you were.) So: <~i~>
<~i~>
$ <~i~>
/the cat/ <~i~>
358 <~i~>
?glossary? +7 <~i~>
'b <~i~>
<~i~>
are all non-relative addresses, and if you give any one of them, <~i~>
the editor will mark the line you are leaving for future <~i~>
reference. Then you can return to that line just by typing two <~i~>
successive single quotes: <~i~>
<~i~>
" <~i~>
<~i~>
as a line-mode address. In theory, you can use this address with <~i~>
any line-mode command. But it is so difficult to know for sure <~i~>
when you left a line via a non-relative address that this address <~i~>
form is best saved for going back to where you were when a mistake <~i~>
moves you far away, at least until you're a wizard with this <~i~>
editor. <~i~>
<~i~>
MODIFYING ANY OF THESE ADDRESSES is possible, and there are two <~i~>
ways to do this. The simpler way is to offset the address a <~i~>
certain number of lines forward or backward with plus (+) or minus <~i~>
(-) signs. The rule is that each plus sign following an address <~i~>
tells the editor to go one line farther forward in the file than <~i~>
the basic address, while each minus sign means a line backward. <~i~>
So these three addresses all refer to the same line: <~i~>
<~i~>
35 <~i~>
37 -- <~i~>
30 +++++ <~i~>
<~i~>
Not that you're likely to want to modify line-number addresses <~i~>
with counts, unless you're weak in arithmetic and want the editor <~i~>
to do the adding and subtracting for you. But the count offsets <~i~>
will work with any line-mode addresses, and are most often used <~i~>
with search patterns. In any event, there is a shorthand for <~i~>
these counts, too. A plus or minus sign immediately followed by a <~i~>
number (single or multiple digits) is equivalent to a string of <~i~>
plus or minus signs equal to that number, so that these two <~i~>
addresses are the same: <~i~>
<~i~>
/^register long/ ++++ <~i~>
/^register long/ +4 <~i~>
<~i~>
Take note that the "4" in the second example does not mean "line <~i~>
number 4", as it would if it appeared by itself as an address. <~i~>
After a plus or minus sign, a number is a count forward or <~i~>
backward from where the primary address lands (or if there is no <~i~>
primary address before the count, from the line you are on when <~i~>
you run the command). <~i~>
<~i~>
Note also that this is one of the few places in line-mode commands <~i~>
where you may not insert a blank space. The number must start in <~i~>
the very next character position after the plus or minus sign. If <~i~>
you violate this rule, the editor will uncomplainingly operate on <~i~>
some line that definitely is not the line you expected. <~i~>
<~i~>
The second style of address modifier is used where you want to do <~i~>
a search that's complex. Let's say you want to go forward in the <~i~>
file to delete a line that starts with "WARNING!", but not the <~i~>
first such line the editor would encounter; you want the second <~i~>
instance. Either of these command lines will do it: <~i~>
<~i~>
/^WARNING!/ ; /^WARNING!/ delete <~i~>
/^WARNING!/ ; // delete <~i~>
<~i~>
A semicolon (;) between two search patterns tells the editor to <~i~>
find the location of the first pattern in the usual way, then <~i~>
start searching from that location for the second pattern. In <~i~>
this case, the first search pattern turned up the first instance <~i~>
of a line starting with "WARNING!", and the second search pattern <~i~>
led the editor on to the second instance. <~i~>
<~i~>
A very significant point here is that this combination of two <~i~>
search patterns, either of which could be a line address in <~i~>
itself, does not tell the editor to delete two lines. The <~i~>
semicolon means that the first pattern is merely a way station, <~i~>
and that the single line found by the second search pattern is the <~i~>
only line to be deleted. In brief, what looks like addresses for <~i~>
two lines is actually only an address for one. (This is not what <~i~>
the official documentation for this editor says, but the <~i~>
documentation is just plain wrong on this point.) <~i~>
<~i~>
But that's just the start of what you can do. You are not <~i~>
restricted to just two addresses. I've used up to ten of them, <~i~>
all separated by semicolons, to reach one specific line. As an <~i~>
example: <~i~>
<~i~>
?^Chapter 3$? ; /^Bibliography$/ ; /^Spinoza/ ; /Monads/ <~i~>
<~i~>
will bring me to the title line of Spinoza's first work with <~i~>
"Monads" in the title, in the bibliography for Chapter 3. <~i~>
<~i~>
Nor are you limited to search pattern addresses when putting <~i~>
together a semicolon-separated address string. If you want to <~i~>
reach the first line following line 462 that contains the word <~i~>
"union", typing: <~i~>
<~i~>
462 ; /\<union\>/ <~i~>
<~i~>
will bring you there. And any of the addresses can take numerical <~i~>
offsets, so: <~i~>
<~i~>
462 +137 ; /register int/ --- <~i~>
<~i~>
is also a legitimate address string. <~i~>
<~i~>
But there are two unfortunate limitations on using <~i~>
semicolon-separated address strings. The lesser problem is that <~i~>
such a string can use "line zero" as an address only if the <~i~>
command following the address string could take line zero by <~i~>
itself as its address. That is, you can't even start at line zero <~i~>
and then proceed elsewhere with additional addresses, unless the <~i~>
command can operate from line zero. So: <~i~>
<~i~>
0 ; /Spinoza/ +++ ; /Kant/ delete <~i~>
<~i~>
<~i~>
which looks like a reasonable way to be sure your search will <~i~>
find the very first "Spinoza" in your file, will actually fail <~i~>
with an error message about an illegal address. <~i~>
<~i~>
The larger misfortune is that each address in a semicolon- <~i~>
separated string must be farther down in the file than the one <~i~>
that precedes it. (This means the actual location found, after <~i~>
applying any plus-sign or minus-sign offset.) You cannot <~i~>
move backward within the series of way points. <~i~>
<~i~>
But that does not mean that you cannot use a backward search <~i~>
pattern within the string. The first address can be a backward <~i~>
search, of course. And a subsequent address can search backward <~i~>
if you are certain that the line it finds will actually be more <~i~>
forward in the file. For example, you may know that a certain <~i~>
backward search will wrap around to the bottom end of the file <~i~>
before it finds a match. A common example would be: <~i~>
<~i~>
<~i~>
1 ; ?Spinoza? ; /Hegel/ yank <~i~>
<~i~>
Beginning a backward search from the first line in the file means <~i~>
that the search must start with the last line in the file due to <~i~>
wraparound, which guarantees that the search will yank the "Hegel" <~i~>
line that follows the vary last "Spinoza" line in your file. <~i~>
<~i~>
Also, you can use a plus-sign offset after a backward search when <~i~>
you are certain that the line finally found after the offset is <~i~>
applied will be farther down in the file than the preceding way <~i~>
point had been. Thus, if I want to find the first mention of <~i~>
Hegel in Chapter 8 that is at least 120 lines after the last <~i~>
mention of him in Chapter 7, I can type: <~i~>
<~i~>
/^Chapter 8$/ ; ?Hegel? +119 ; // <~i~>
<~i~>
If a command with this address fails and gives an error message <~i~>
about a bad address, I'll know that the last mention of Hegel in <~i~>
Chapter 7 is more than 120 lines before the end of the chapter, so <~i~>
the very first mention of his name in Chapter 8 is what I'm <~i~>
looking for. In that case, the address: <~i~>
<~i~>
/^Chapter 8$/ ; /Hegel/ <~i~>
<~i~>
is all that my command needs. <~i~>
<~i~>
The situation with forward searches inside a semicolon-separated <~i~>
address string is a mirror image of what I've just said. A forward <~i~>
search can take a minus-sign offset if you know that the offset is <~i~>
small enough that the line found will be further down than the <~i~>
last way point. But a forward search will fail, even with no <~i~>
offset or a plus-sign offset, if wraparound makes it find a line <~i~>
earlier in the file than the way point from which it began. <~i~>
<~i~>
Addressing a Section of Text <~i~>
<~i~>
TWO ADDRESSES CAN ALSO STAND FOR A RANGE OF LINES. When two <~i~>
addresses are separated by a comma rather than a semicolon, the <~i~>
meaning changes radically. (What a difference a dot makes!) <~i~>
<~i~>
Often you will want a line-mode command to act on a series of <~i~>
successive lines. For example, you may want to move a stretch of <~i~>
text from one place to another. To do this, you give the address <~i~>
of the first line you want the command to act on, followed by the <~i~>
last line it should act on, and separate the two addresses with a <~i~>
comma. So, the command: <~i~>
<~i~>
14 , 17 delete <~i~>
<~i~>
will delete line 14 and line 15 and line 16 and line 17. You can <~i~>
see that putting more than two addresses in a comma-separated <~i~>
address string would be pointless. The line mode of this editor <~i~>
is discreet if you ignore this and string together three or more <~i~>
addresses with comma separation: it uses the first two addresses <~i~>
and discards the rest. <~i~>
<~i~>
Any line-mode addresses may be used with a comma. All of the <~i~>
following combinations make sense: <~i~>
<~i~>
'd , /^struct/ <~i~>
257 , . <~i~>
?^Chapter 9$? , $ <~i~>
<~i~>
The first address combination would cause the command that follows <~i~>
it to operate on the section starting with the line you have <~i~>
previously marked "d" and ending with the next forward line that <~i~>
begins with "struct", inclusive. The second combination covers <~i~>
line 257 through the line you are on now. The third goes backward <~i~>
to include the previous line containing only "Chapter 9", and <~i~>
forward to include the very last line in your file; plus all the <~i~>
lines in between, of course. <~i~>
<~i~>
There are limitations on this technique, too. The primary one is <~i~>
that the address after the comma (after any offsets, of course) <~i~>
cannot be earlier in the file than the address before the comma. <~i~>
That is, the range of lines must run forward from the first <~i~>
address to the second address. So the command: <~i~>
<~i~>
57 , 188 delete <~i~>
<~i~>
is just fine, while the similar-looking command: <~i~>
<~i~>
188 , 57 delete <~i~>
<~i~>
will only produce an error message. (But if the two addresses <~i~>
happen to evaluate to the same line, there is no problem. The <~i~>
command will silently operate on the one line you've specified.) <~i~>
<~i~>
As you work up to more sophisticated line-mode addresses, you may <~i~>
get unexpected error messages about the second address being prior <~i~>
to first address, when you don't see how you could have <~i~>
anticipated that the addresses would evaluate that way. That's no <~i~>
disgrace, and the solution is simple. After you've looked over <~i~>
the addresses you used, and you're certain that they are the ones <~i~>
you want, just type the command in again with the two addresses in <~i~>
reverse order. That is, if: <~i~>
<~i~>
642 , /in Table 23/ delete <~i~>
<~i~>
has failed, giving an error message that the lines are in the <~i~>
wrong order, then: <~i~>
<~i~>
/in Table 23/ , 642 delete <~i~>
<~i~>
will solve that problem. <~i~>
<~i~>
The last limitation is that when you use search patterns on both <~i~>
sides of a comma, the second search starts from the current line <~i~>
just as the first search did; it does not start from the line that <~i~>
the first search found. There's a way around that, though, that <~i~>
involves using one or more semicolons along with a comma. <~i~>
<~i~>
A semicolon-separated address string can be used anywhere in line <~i~>
mode that you would use a single address. One very useful <~i~>
technique is to use these address strings on one or both sides of <~i~>
a comma, to indicate a range of lines to be affected. Remember <~i~>
that an address string separated by semicolons is the address of <~i~>
just one line, so this one line can be the start or the end of a <~i~>
range of lines. For example, in: <~i~>
<~i~>
/^INDEX$/ ; /^Xerxes/ , $ write tailfile <~i~>
?^PREFACE$? ; /^My 7th point/ , ?^PREFACE$? ; /^In summary/ -- delete <~i~>
<~i~>
the first command would write the latter part of the index to a <~i~>
new file, while the second could be used to remove a section of a <~i~>
book's preface. <~i~>
<~i~>
And that brings up the solution to our previous obstacle; the <~i~>
second search's starting point. If you want the search after the <~i~>
comma to begin from the point the first search found, use the <~i~>
first search pattern followed by a semicolon as the start of your <~i~>
after-the-comma search string, as in either of: <~i~>
<~i~>
?Stradivarius? , ?Stradivarius? ; /Guarnerius/ <~i~>
?Stradivarius? , ?? ; /Guarnerius/ <~i~>
<~i~>
In view of the rules about not going backward in line-mode address <~i~>
strings, I'd better clarify the way these limitations work when <~i~>
you combine semicolon and comma separation, as in these two <~i~>
examples. All but the first of the way points in each <~i~>
semicolon-separated string must be in the forward direction, of <~i~>
course, but the start of the second semicolon-separated string may <~i~>
be prior to any of the addresses in the first such string, that <~i~>
is, the one-way meter resets itself at the comma point. And using <~i~>
semicolon-separated strings on both sides of a comma only requires <~i~>
that the final landing point of the second semicolon-separated <~i~>
string not be earlier in the file than the final landing point of <~i~>
the first; the relative locations of the way points don't matter <~i~>
to the comma. To clarify this, consider a couple of odd-looking, <~i~>
and useless, but very lucid examples. The combination: <~i~>
<~i~>
125 ; 176 ; 221 , 32 ; 67 ; 240 <~i~>
<~i~>
looks invalid due to the backward jump from line 221 to line 32, <~i~>
but is actually a perfectly good address. The back jump comes <~i~>
right after the comma, where it is all right. But: <~i~>
<~i~>
125 ; 176 ; 221 , 32 ; 67 ; 218 <~i~>
<~i~>
will produce an error message, because the final landing point of <~i~>
the first semicolon-separated string, line 221, falls later in the <~i~>
file than the final landing point of the second semicolon- <~i~>
separated string, line 218. <~i~>
<~i~>
Now, a note about default addresses. I've already mentioned that <~i~>
most line-mode commands that can take an address have a "default" <~i~>
address built in, which tells the editor where to run the command <~i~>
if you don't give an address with it. Each command has its own <~i~>
default address, which may be the current line, the current line <~i~>
plus the one following, the last line of the file, or the entire <~i~>
file. <~i~>
<~i~>
The comma separator has default addresses of its own. They are <~i~>
the same regardless of what command is being used, and they <~i~>
override any command's own default address. If you put a comma <~i~>
before a command and don't put an address before the comma, by <~i~>
default the address there is the current line. In the same way, <~i~>
if you leave out the address after the comma, the default there is <~i~>
also the current line. You can even leave out the address in both <~i~>
places and use the current-line default in both: that means the <~i~>
implied address is "from the current line to the current line", <~i~>
which makes the current line the only line the command will <~i~>
operate on. So every one of the following command lines: <~i~>
<~i~>
. write >> goodlines <~i~>
. , . write >> goodlines <~i~>
, . write >> goodlines <~i~>
. , write >> goodlines <~i~>
, write >> goodlines <~i~>
<~i~>
<~i~>
will do exactly the same thing: append a copy of just the current <~i~>
line in the file you're editing to another file named "goodlines". <~i~>
<~i~>
Finally, there is one special symbol that represents a <~i~>
comma-separated address combination. The percent sign (%) has the <~i~>
same meaning as 1,$ as a line-mode address combination. Both <~i~>
refer to the entire file. <~i~>
<~i~>
Now You Try It <~i~>
<~i~>
Before you try the complex aspects of line-mode addresses in <~i~>
actual editing situations, here are some problems you can build <~i~>
yourself up on. For each problem I've included a solution that <~i~>
will work fairly efficiently. <~i~>
<~i~>
1. How can you tell the editor to delete the line that holds <~i~>
the very last instance of "EXPORT" in your file? The solution <~i~>
is straightforward once you know where to start searching. <~i~>
<~i~>
2. Suppose you want to delete the very first line in the file <~i~>
with "EXPORT" on it, and that just might be line 1. You can't <~i~>
start the search from line zero because the delete command <~i~>
cannot take line 0 as an address. When you type the address <~i~>
string "$ ; /EXPORT/" to use wraparound, you get an error <~i~>
message asserting that the search pattern found a line prior to <~i~>
the line found by the "$" address that appeared first, which is <~i~>
what you'd expect. How can you tell the editor to find and <~i~>
delete this line? The solution requires just a bit of <~i~>
creativity. <~i~>
<~i~>
3. If you use the address "?abc? , /xyz/", it includes the two <~i~>
lines the searches (for "abc" and "xyx") find, as well as all <~i~>
the lines between them. How would you specify that you want <~i~>
the affected lines to go up to, but not include, the lines the <~i~>
two searches find? In this case the solution is simpler than <~i~>
you might think. <~i~>
<~i~>
<~i~>
Coming Up Next <~i~>
<~i~>
The next installment of this tutorial will deal with the global <~i~>
commands--they're just too much to absorb right after the <~i~>
mind-numbing collection of address forms we've just gone through. <~i~>
And to give you more scope for using all these address forms, I'll <~i~>
also cover line-mode commands themselves, particularly the ones <~i~>
that have more capabilities than you suspect. <~i~>
Back to the index/
The Vi/Ex Editor <~i~>
By Walter Alan Zintz. <~i~>
<~i~>
[Editor's Note: This tutorial series is a 'work in progress' and <~i~>
will evolve over time. We'll announce each new addition and <~i~>
expand this table of contents.] <~i~>
Part 1: Vi Editor Fundamentals/
<< see line 2211 >>
Why Vi? <~i~>
A Heartwarming Edit <~i~>
The Plan Of This Ongoing Tutorial <~i~>
The Editor's Basic Concepts <~i~>
Search Patterns <~i~>
Searching From Where You Are Now <~i~>
The Find-Them-All Search <~i~>
Simple Search Patterns <~i~>
Metacharacters <~i~>
Table Of Search Pattern Metacharacters <~i~>
Character Classes. <~i~>
Part 2: Line-Mode Addresses/
The vi/ex Editor, Part 2: Line-Mode Addresses <~i~>
<~i~>
Whenever you want to give an editor command that will operate on <~i~>
text that's already in the file you're editing--to delete some <~i~>
text, change lower-case letters to capitals, write to a file, <~i~>
etcetera--the editor needs to know what part of the file to go to <~i~>
work on. A few commands have their addresses built in, and most <~i~>
line-mode commands have default addresses that the editor will use <~i~>
if you don't give an address, but that still leaves a lot of <~i~>
occasions where you need to know how to give the editor an address <~i~>
and what address to give. <~i~>
<~i~>
Many line-mode commands are almost identical to corresponding <~i~>
commands in visual mode; many more do similar things in different <~i~>
ways. Most of the benefit of these duplicative command sets comes <~i~>
from the totally-different addressing styles of line and visual <~i~>
modes. The differing address concepts mean that an edit that <~i~>
would be difficult or impossible to do with one mode's available <~i~>
addresses can be a piece of cake with an address form found in the <~i~>
other mode. <~i~>
<~i~>
Since I mention "line mode" so often, you may wonder whether there <~i~>
really is a separate mode for line editing. There surely <~i~>
is--instead of filling your screen with text from the file you're <~i~>
editing, this mode gives you a colon (:) prompt for your line mode <~i~>
commands, and prints only an occasional line from the file on your <~i~>
screen. The feel of this mode is very much like giving UNIX <~i~>
commands from your shell prompt. Few people work in line mode <~i~>
these days, largely because you can give most line-mode commands <~i~>
from visual mode, but you can't give any visual-mode commands <~i~>
while you are in line mode. Or perhaps they just prefer the <~i~>
comfortable WYSIWYG feeling of seeing the text on screen, with <~i~>
changes appearing as they are made. <~i~>
<~i~>
But there are times when you will need to work temporarily in line <~i~>
mode. To get to line mode when you first launch the editor, <~i~>
invoke it by typing "ex" instead of "vi". To go to line mode when <~i~>
you are already in the editor's visual mode, enter "Q". To get <~i~>
back to visual mode, type "vi" followed by a carriage return. <~i~>
<~i~>
Wondering why I didn't put a colon in front of that command to <~i~>
return to visual mode, which is obviously a line-mode command? <~i~>
Because you don't need to type that colon when you're giving a <~i~>
command from within line mode. It may even be harmful; the rule <~i~>
is that if you type a colon at the start of a command from within <~i~>
line mode, there must be nothing between the colon and the command <~i~>
name or abbreviation. Not an address, not even a space, nothing <~i~>
at all. <~i~>
<~i~>
So from this point on, I will display line-mode commands without <~i~>
an initial colon, because you now know enough to type that colon <~i~>
only if you're working in visual mode. And I'll leave off the tag <~i~>
at the end of a line-mode command that reminds you to finish with <~i~>
a carriage return because you now realize that any line-mode <~i~>
command, given from either line or visual mode, has to end with a <~i~>
carriage return. <~i~>
<~i~>
Some of you may ask why I show line-mode command lines in <~i~>
long-winded form, with spelled-out command names and lots of <~i~>
whitespace instead of using abbreviations. For instance, the two <~i~>
command lines: <~i~>
<~i~>
global /^/ move 0 <~i~>
g/^/m0 <~i~>
<~i~>
are identical in their effect, and the second is surely faster to <~i~>
type, so why do I show the first form? Because the long version <~i~>
is much easier to follow when I'm demonstrating a new concept, and <~i~>
almost everything here will be new to at least some of you. And <~i~>
it's a good idea to get to know the long forms, because you'll <~i~>
soon be learning to write editor scripts, and those scripts would <~i~>
be as cryptic as APL to future maintenance programmers if you <~i~>
wrote them in terse style. When I go over the roster of line-mode <~i~>
commands, I'll tell you both the long name and one or two short <~i~>
names for each. <~i~>
<~i~>
Line-Mode Addressing <~i~>
<~i~>
A SINGLE ADDRESS is often all you need with a line-mode command. <~i~>
One address refers to just one line, which tells a command like <~i~>
delete or substitute to operate on that one line only. A command <~i~>
like insert or read, which puts something immediately before or <~i~>
after a particular line, has no use for more than one address. <~i~>
<~i~>
A search pattern, as discussed in the first installment of this <~i~>
tutorial, is always an acceptable line-mode address. You put the <~i~>
address at the start of the command line, before the command name <~i~>
(but after the initial colon if you are giving the command from <~i~>
visual mode), so: <~i~>
<~i~>
?the [cC]at? delete <~i~>
<~i~>
will erase the last previous line that contains the string "the <~i~>
cat" or "the Cat", while: <~i~>
<~i~>
/^GLOSSARY$/ read gloss.book <~i~>
<~i~>
puts the contents of the file "gloss.book" right after the next <~i~>
line in the file you're editing that contains only the word <~i~>
"GLOSSARY". <~i~>
<~i~>
There are two shorthand forms for reusing search patterns as <~i~>
addresses. Typing "??" or "//" tells the editor to use the last <~i~>
search pattern you used previously, and your choice of "??" or <~i~>
"//" will set the direction of the search, overriding the <~i~>
direction you chose the previous time you used that search <~i~>
pattern. That is, if you type: <~i~>
<~i~>
?the cat? yank <~i~>
// delete <~i~>
?? print <~i~>
<~i~>
the second command will search forward, to remove the last <~i~>
previous line containing the string "the cat", even though your <~i~>
original use of that pattern was in a backward search. The third <~i~>
command will search backward to find the line to print, which (by <~i~>
coincidence) is the direction of the original search. <~i~>
<~i~>
But the search pattern that those preceding abbreviations reuse <~i~>
may not be a pattern you used to search for a line. If you ran a <~i~>
substitute command after any pattern searches for lines, then the <~i~>
pattern you gave the substitute command to tell it what text to <~i~>
take out of the line is the pattern that will be reused. This is <~i~>
so even if your substitute command began with a search pattern to <~i~>
specify the line on which the substitution was to be <~i~>
performed--the search to find the pattern to be replaced within <~i~>
the line was run after the first search pattern had found the line <~i~>
to operate on, so the search within the line was the last pattern <~i~>
search run. So if you were to type: <~i~>
<~i~>
/the cat/ substitute /in the hat/on the mat <~i~>
?? delete <~i~>
<~i~>
the second command would, in this case, delete the last previous <~i~>
line containing "in the hat". To be sure that the pattern that <~i~>
gets reused is the last one used to find a line, use the <~i~>
abbreviations "\?" and "\/" to search backward and forward, <~i~>
respectively. In all other respects these work just as typing <~i~>
"??" and "//" do. <~i~>
<~i~>
A LINE NUMBER is also a valid line-mode address. The editor <~i~>
automatically numbers each line in the file consecutively, and <~i~>
this numbering is dynamic--that is, whenever you add or delete <~i~>
lines somewhere, the editor renumbers all the lines following the <~i~>
insertion or deletion point. So if you change some text on line <~i~>
46 in your file, and then delete lines 11 and 12, the line with <~i~>
the text you changed is now line 44. And if you then add ten new <~i~>
lines after line 17, the line with your changed text on it now <~i~>
automatically becomes line 54. <~i~>
<~i~>
There is never a gap or an overlap in the line number sequence, so <~i~>
the nth line in the file is always line number n; that is, the 7th <~i~>
line is always line number 7, and so on. (There are several ways <~i~>
to display these line numbers, which I will expound in a later <~i~>
tutorial installment.) To delete the 153rd line in your file, <~i~>
just type: <~i~>
<~i~>
153 delete <~i~>
<~i~>
You don't use any delimiters around a line number, or around any <~i~>
other address except a search pattern. <~i~>
<~i~>
There are two symbolic line numbers and one fictional one that can <~i~>
be used in line-mode addresses. As long as there are any lines in <~i~>
the buffer (that is, you haven't specified a not-yet-existent file <~i~>
to edit and failed to enter any text so far), the editor regards <~i~>
you as being `on' one of them, usually the last line affected by <~i~>
your latest command. A period or dot (.) is the symbolic address <~i~>
for this line. The last line in the file also has a symbolic <~i~>
address: the dollar sign ($). So if you should type: <~i~>
<~i~>
. write >> goodlines <~i~>
$ delete <~i~>
<~i~>
the first command would append a copy of just the line you are on <~i~>
now to a file named "goodlines", while the second would delete the <~i~>
last line in the file you are editing. <~i~>
<~i~>
A few commands put text immediately after the line address you <~i~>
give: the append command is one of them. In order to let them put <~i~>
their text at the very start of a file (if that is where you want <~i~>
it), these commands can take the fictitious line number zero (0) <~i~>
as their address. So, if you want to type some text that will <~i~>
appear ahead of anything already in the file, you can do it with <~i~>
either of these command lines: <~i~>
<~i~>
1 insert <~i~>
0 append <~i~>
<~i~>
(Note, though, that insert and append are among the few line-mode <~i~>
commands that cannot be run from visual mode by starting with a <~i~>
colon, because they occupy more than one line including the text <~i~>
to be put in.) <~i~>
<~i~>
WRITING YOUR OWN LINE ADDRESSES is possible, too. You can attach <~i~>
lower-case letters to lines as line addresses, and change the <~i~>
attachments whenever you like. You can even use a special address <~i~>
that is automatically attached to the last line you jumped off <~i~>
from. <~i~>
<~i~>
There are ways to mark a particular line with a lower-case letter <~i~>
of the alphabet, and those ways differ between line and visual <~i~>
modes. I'll be explaining all these ways in later installments of <~i~>
this tutorial. But once a line is marked, the line-mode address <~i~>
that refers to that line is just the single-quote character <~i~>
followed immediately by the lower-case letter with which the line <~i~>
was marked. So typing: <~i~>
<~i~>
'b print <~i~>
<~i~>
will display on the screen whatever line you have previously <~i~>
marked with the letter b, no matter where the line is in relation <~i~>
to where you are when you give the command. No need to tell the <~i~>
editor whether to search forward or backward; there can be only <~i~>
one line at a time marked with any one letter, and the editor will <~i~>
find that line regardless. <~i~>
<~i~>
The editor does some line marking on its own, too. Whenever you <~i~>
move from one line to another by a non-relative address, the <~i~>
editor marks the line you just left. (A non-relative address is <~i~>
one that isn't a known number of lines from where you were.) So: <~i~>
<~i~>
$ <~i~>
/the cat/ <~i~>
358 <~i~>
?glossary? +7 <~i~>
'b <~i~>
<~i~>
are all non-relative addresses, and if you give any one of them, <~i~>
the editor will mark the line you are leaving for future <~i~>
reference. Then you can return to that line just by typing two <~i~>
successive single quotes: <~i~>
<~i~>
" <~i~>
<~i~>
as a line-mode address. In theory, you can use this address with <~i~>
any line-mode command. But it is so difficult to know for sure <~i~>
when you left a line via a non-relative address that this address <~i~>
form is best saved for going back to where you were when a mistake <~i~>
moves you far away, at least until you're a wizard with this <~i~>
editor. <~i~>
<~i~>
MODIFYING ANY OF THESE ADDRESSES is possible, and there are two <~i~>
ways to do this. The simpler way is to offset the address a <~i~>
certain number of lines forward or backward with plus (+) or minus <~i~>
(-) signs. The rule is that each plus sign following an address <~i~>
tells the editor to go one line farther forward in the file than <~i~>
the basic address, while each minus sign means a line backward. <~i~>
So these three addresses all refer to the same line: <~i~>
<~i~>
35 <~i~>
37 -- <~i~>
30 +++++ <~i~>
<~i~>
Not that you're likely to want to modify line-number addresses <~i~>
with counts, unless you're weak in arithmetic and want the editor <~i~>
to do the adding and subtracting for you. But the count offsets <~i~>
will work with any line-mode addresses, and are most often used <~i~>
with search patterns. In any event, there is a shorthand for <~i~>
these counts, too. A plus or minus sign immediately followed by a <~i~>
number (single or multiple digits) is equivalent to a string of <~i~>
plus or minus signs equal to that number, so that these two <~i~>
addresses are the same: <~i~>
<~i~>
/^register long/ ++++ <~i~>
/^register long/ +4 <~i~>
<~i~>
Take note that the "4" in the second example does not mean "line <~i~>
number 4", as it would if it appeared by itself as an address. <~i~>
After a plus or minus sign, a number is a count forward or <~i~>
backward from where the primary address lands (or if there is no <~i~>
primary address before the count, from the line you are on when <~i~>
you run the command). <~i~>
<~i~>
Note also that this is one of the few places in line-mode commands <~i~>
where you may not insert a blank space. The number must start in <~i~>
the very next character position after the plus or minus sign. If <~i~>
you violate this rule, the editor will uncomplainingly operate on <~i~>
some line that definitely is not the line you expected. <~i~>
<~i~>
The second style of address modifier is used where you want to do <~i~>
a search that's complex. Let's say you want to go forward in the <~i~>
file to delete a line that starts with "WARNING!", but not the <~i~>
first such line the editor would encounter; you want the second <~i~>
instance. Either of these command lines will do it: <~i~>
<~i~>
/^WARNING!/ ; /^WARNING!/ delete <~i~>
/^WARNING!/ ; // delete <~i~>
<~i~>
A semicolon (;) between two search patterns tells the editor to <~i~>
find the location of the first pattern in the usual way, then <~i~>
start searching from that location for the second pattern. In <~i~>
this case, the first search pattern turned up the first instance <~i~>
of a line starting with "WARNING!", and the second search pattern <~i~>
led the editor on to the second instance. <~i~>
<~i~>
A very significant point here is that this combination of two <~i~>
search patterns, either of which could be a line address in <~i~>
itself, does not tell the editor to delete two lines. The <~i~>
semicolon means that the first pattern is merely a way station, <~i~>
and that the single line found by the second search pattern is the <~i~>
only line to be deleted. In brief, what looks like addresses for <~i~>
two lines is actually only an address for one. (This is not what <~i~>
the official documentation for this editor says, but the <~i~>
documentation is just plain wrong on this point.) <~i~>
<~i~>
But that's just the start of what you can do. You are not <~i~>
restricted to just two addresses. I've used up to ten of them, <~i~>
all separated by semicolons, to reach one specific line. As an <~i~>
example: <~i~>
<~i~>
?^Chapter 3$? ; /^Bibliography$/ ; /^Spinoza/ ; /Monads/ <~i~>
<~i~>
will bring me to the title line of Spinoza's first work with <~i~>
"Monads" in the title, in the bibliography for Chapter 3. <~i~>
<~i~>
Nor are you limited to search pattern addresses when putting <~i~>
together a semicolon-separated address string. If you want to <~i~>
reach the first line following line 462 that contains the word <~i~>
"union", typing: <~i~>
<~i~>
462 ; /\<union\>/ <~i~>
<~i~>
will bring you there. And any of the addresses can take numerical <~i~>
offsets, so: <~i~>
<~i~>
462 +137 ; /register int/ --- <~i~>
<~i~>
is also a legitimate address string. <~i~>
<~i~>
But there are two unfortunate limitations on using <~i~>
semicolon-separated address strings. The lesser problem is that <~i~>
such a string can use "line zero" as an address only if the <~i~>
command following the address string could take line zero by <~i~>
itself as its address. That is, you can't even start at line zero <~i~>
and then proceed elsewhere with additional addresses, unless the <~i~>
command can operate from line zero. So: <~i~>
<~i~>
0 ; /Spinoza/ +++ ; /Kant/ delete <~i~>
<~i~>
<~i~>
which looks like a reasonable way to be sure your search will <~i~>
find the very first "Spinoza" in your file, will actually fail <~i~>
with an error message about an illegal address. <~i~>
<~i~>
The larger misfortune is that each address in a semicolon- <~i~>
separated string must be farther down in the file than the one <~i~>
that precedes it. (This means the actual location found, after <~i~>
applying any plus-sign or minus-sign offset.) You cannot <~i~>
move backward within the series of way points. <~i~>
<~i~>
But that does not mean that you cannot use a backward search <~i~>
pattern within the string. The first address can be a backward <~i~>
search, of course. And a subsequent address can search backward <~i~>
if you are certain that the line it finds will actually be more <~i~>
forward in the file. For example, you may know that a certain <~i~>
backward search will wrap around to the bottom end of the file <~i~>
before it finds a match. A common example would be: <~i~>
<~i~>
<~i~>
1 ; ?Spinoza? ; /Hegel/ yank <~i~>
<~i~>
Beginning a backward search from the first line in the file means <~i~>
that the search must start with the last line in the file due to <~i~>
wraparound, which guarantees that the search will yank the "Hegel" <~i~>
line that follows the vary last "Spinoza" line in your file. <~i~>
<~i~>
Also, you can use a plus-sign offset after a backward search when <~i~>
you are certain that the line finally found after the offset is <~i~>
applied will be farther down in the file than the preceding way <~i~>
point had been. Thus, if I want to find the first mention of <~i~>
Hegel in Chapter 8 that is at least 120 lines after the last <~i~>
mention of him in Chapter 7, I can type: <~i~>
<~i~>
/^Chapter 8$/ ; ?Hegel? +119 ; // <~i~>
<~i~>
If a command with this address fails and gives an error message <~i~>
about a bad address, I'll know that the last mention of Hegel in <~i~>
Chapter 7 is more than 120 lines before the end of the chapter, so <~i~>
the very first mention of his name in Chapter 8 is what I'm <~i~>
looking for. In that case, the address: <~i~>
<~i~>
/^Chapter 8$/ ; /Hegel/ <~i~>
<~i~>
is all that my command needs. <~i~>
<~i~>
The situation with forward searches inside a semicolon-separated <~i~>
address string is a mirror image of what I've just said. A forward <~i~>
search can take a minus-sign offset if you know that the offset is <~i~>
small enough that the line found will be further down than the <~i~>
last way point. But a forward search will fail, even with no <~i~>
offset or a plus-sign offset, if wraparound makes it find a line <~i~>
earlier in the file than the way point from which it began. <~i~>
<~i~>
Addressing a Section of Text <~i~>
<~i~>
TWO ADDRESSES CAN ALSO STAND FOR A RANGE OF LINES. When two <~i~>
addresses are separated by a comma rather than a semicolon, the <~i~>
meaning changes radically. (What a difference a dot makes!) <~i~>
<~i~>
Often you will want a line-mode command to act on a series of <~i~>
successive lines. For example, you may want to move a stretch of <~i~>
text from one place to another. To do this, you give the address <~i~>
of the first line you want the command to act on, followed by the <~i~>
last line it should act on, and separate the two addresses with a <~i~>
comma. So, the command: <~i~>
<~i~>
14 , 17 delete <~i~>
<~i~>
will delete line 14 and line 15 and line 16 and line 17. You can <~i~>
see that putting more than two addresses in a comma-separated <~i~>
address string would be pointless. The line mode of this editor <~i~>
is discreet if you ignore this and string together three or more <~i~>
addresses with comma separation: it uses the first two addresses <~i~>
and discards the rest. <~i~>
<~i~>
Any line-mode addresses may be used with a comma. All of the <~i~>
following combinations make sense: <~i~>
<~i~>
'd , /^struct/ <~i~>
257 , . <~i~>
?^Chapter 9$? , $ <~i~>
<~i~>
The first address combination would cause the command that follows <~i~>
it to operate on the section starting with the line you have <~i~>
previously marked "d" and ending with the next forward line that <~i~>
begins with "struct", inclusive. The second combination covers <~i~>
line 257 through the line you are on now. The third goes backward <~i~>
to include the previous line containing only "Chapter 9", and <~i~>
forward to include the very last line in your file; plus all the <~i~>
lines in between, of course. <~i~>
<~i~>
There are limitations on this technique, too. The primary one is <~i~>
that the address after the comma (after any offsets, of course) <~i~>
cannot be earlier in the file than the address before the comma. <~i~>
That is, the range of lines must run forward from the first <~i~>
address to the second address. So the command: <~i~>
<~i~>
57 , 188 delete <~i~>
<~i~>
is just fine, while the similar-looking command: <~i~>
<~i~>
188 , 57 delete <~i~>
<~i~>
will only produce an error message. (But if the two addresses <~i~>
happen to evaluate to the same line, there is no problem. The <~i~>
command will silently operate on the one line you've specified.) <~i~>
<~i~>
As you work up to more sophisticated line-mode addresses, you may <~i~>
get unexpected error messages about the second address being prior <~i~>
to first address, when you don't see how you could have <~i~>
anticipated that the addresses would evaluate that way. That's no <~i~>
disgrace, and the solution is simple. After you've looked over <~i~>
the addresses you used, and you're certain that they are the ones <~i~>
you want, just type the command in again with the two addresses in <~i~>
reverse order. That is, if: <~i~>
<~i~>
642 , /in Table 23/ delete <~i~>
<~i~>
has failed, giving an error message that the lines are in the <~i~>
wrong order, then: <~i~>
<~i~>
/in Table 23/ , 642 delete <~i~>
<~i~>
will solve that problem. <~i~>
<~i~>
The last limitation is that when you use search patterns on both <~i~>
sides of a comma, the second search starts from the current line <~i~>
just as the first search did; it does not start from the line that <~i~>
the first search found. There's a way around that, though, that <~i~>
involves using one or more semicolons along with a comma. <~i~>
<~i~>
A semicolon-separated address string can be used anywhere in line <~i~>
mode that you would use a single address. One very useful <~i~>
technique is to use these address strings on one or both sides of <~i~>
a comma, to indicate a range of lines to be affected. Remember <~i~>
that an address string separated by semicolons is the address of <~i~>
just one line, so this one line can be the start or the end of a <~i~>
range of lines. For example, in: <~i~>
<~i~>
/^INDEX$/ ; /^Xerxes/ , $ write tailfile <~i~>
?^PREFACE$? ; /^My 7th point/ , ?^PREFACE$? ; /^In summary/ -- delete <~i~>
<~i~>
the first command would write the latter part of the index to a <~i~>
new file, while the second could be used to remove a section of a <~i~>
book's preface. <~i~>
<~i~>
And that brings up the solution to our previous obstacle; the <~i~>
second search's starting point. If you want the search after the <~i~>
comma to begin from the point the first search found, use the <~i~>
first search pattern followed by a semicolon as the start of your <~i~>
after-the-comma search string, as in either of: <~i~>
<~i~>
?Stradivarius? , ?Stradivarius? ; /Guarnerius/ <~i~>
?Stradivarius? , ?? ; /Guarnerius/ <~i~>
<~i~>
In view of the rules about not going backward in line-mode address <~i~>
strings, I'd better clarify the way these limitations work when <~i~>
you combine semicolon and comma separation, as in these two <~i~>
examples. All but the first of the way points in each <~i~>
semicolon-separated string must be in the forward direction, of <~i~>
course, but the start of the second semicolon-separated string may <~i~>
be prior to any of the addresses in the first such string, that <~i~>
is, the one-way meter resets itself at the comma point. And using <~i~>
semicolon-separated strings on both sides of a comma only requires <~i~>
that the final landing point of the second semicolon-separated <~i~>
string not be earlier in the file than the final landing point of <~i~>
the first; the relative locations of the way points don't matter <~i~>
to the comma. To clarify this, consider a couple of odd-looking, <~i~>
and useless, but very lucid examples. The combination: <~i~>
<~i~>
125 ; 176 ; 221 , 32 ; 67 ; 240 <~i~>
<~i~>
looks invalid due to the backward jump from line 221 to line 32, <~i~>
but is actually a perfectly good address. The back jump comes <~i~>
right after the comma, where it is all right. But: <~i~>
<~i~>
125 ; 176 ; 221 , 32 ; 67 ; 218 <~i~>
<~i~>
will produce an error message, because the final landing point of <~i~>
the first semicolon-separated string, line 221, falls later in the <~i~>
file than the final landing point of the second semicolon- <~i~>
separated string, line 218. <~i~>
<~i~>
Now, a note about default addresses. I've already mentioned that <~i~>
most line-mode commands that can take an address have a "default" <~i~>
address built in, which tells the editor where to run the command <~i~>
if you don't give an address with it. Each command has its own <~i~>
default address, which may be the current line, the current line <~i~>
plus the one following, the last line of the file, or the entire <~i~>
file. <~i~>
<~i~>
The comma separator has default addresses of its own. They are <~i~>
the same regardless of what command is being used, and they <~i~>
override any command's own default address. If you put a comma <~i~>
before a command and don't put an address before the comma, by <~i~>
default the address there is the current line. In the same way, <~i~>
if you leave out the address after the comma, the default there is <~i~>
also the current line. You can even leave out the address in both <~i~>
places and use the current-line default in both: that means the <~i~>
implied address is "from the current line to the current line", <~i~>
which makes the current line the only line the command will <~i~>
operate on. So every one of the following command lines: <~i~>
<~i~>
. write >> goodlines <~i~>
. , . write >> goodlines <~i~>
, . write >> goodlines <~i~>
. , write >> goodlines <~i~>
, write >> goodlines <~i~>
<~i~>
<~i~>
will do exactly the same thing: append a copy of just the current <~i~>
line in the file you're editing to another file named "goodlines". <~i~>
<~i~>
Finally, there is one special symbol that represents a <~i~>
comma-separated address combination. The percent sign (%) has the <~i~>
same meaning as 1,$ as a line-mode address combination. Both <~i~>
refer to the entire file. <~i~>
<~i~>
Now You Try It <~i~>
<~i~>
Before you try the complex aspects of line-mode addresses in <~i~>
actual editing situations, here are some problems you can build <~i~>
yourself up on. For each problem I've included a solution that <~i~>
will work fairly efficiently. <~i~>
<~i~>
1. How can you tell the editor to delete the line that holds <~i~>
the very last instance of "EXPORT" in your file? The solution <~i~>
is straightforward once you know where to start searching. <~i~>
<~i~>
2. Suppose you want to delete the very first line in the file <~i~>
with "EXPORT" on it, and that just might be line 1. You can't <~i~>
start the search from line zero because the delete command <~i~>
cannot take line 0 as an address. When you type the address <~i~>
string "$ ; /EXPORT/" to use wraparound, you get an error <~i~>
message asserting that the search pattern found a line prior to <~i~>
the line found by the "$" address that appeared first, which is <~i~>
what you'd expect. How can you tell the editor to find and <~i~>
delete this line? The solution requires just a bit of <~i~>
creativity. <~i~>
<~i~>
3. If you use the address "?abc? , /xyz/", it includes the two <~i~>
lines the searches (for "abc" and "xyx") find, as well as all <~i~>
the lines between them. How would you specify that you want <~i~>
the affected lines to go up to, but not include, the lines the <~i~>
two searches find? In this case the solution is simpler than <~i~>
you might think. <~i~>
<~i~>
<~i~>
Coming Up Next <~i~>
<~i~>
The next installment of this tutorial will deal with the global <~i~>
commands--they're just too much to absorb right after the <~i~>
mind-numbing collection of address forms we've just gone through. <~i~>
And to give you more scope for using all these address forms, I'll <~i~>
also cover line-mode commands themselves, particularly the ones <~i~>
that have more capabilities than you suspect. <~i~>
Line-Mode Addressing <~i~>
Addressing a Section of Text <~i~>
Now You Try It <~i~>
Part 3: The Global Command/
The vi/ex Editor, Part 3: The global Command <~i~>
<~i~>
The Wondrous global Command <~i~>
<~i~>
If you're surprised that I made no mention of global in the <~i~>
preceding installment of this tutorial--well, global is not an <~i~>
address. It's actually a line-mode command, and it's much more <~i~>
powerful than most users suspect. <~i~>
<~i~>
Even experienced users of line mode usually think of global along <~i~>
these lines: "If you type global and then a search pattern and <~i~>
then a line-mode command, all on one line, then the editor finds <~i~>
every line in the file that contains that pattern and runs the <~i~>
command on every one of those lines". That is, typing: <~i~>
<~i~>
global /^Chapter [1-9]/ delete <~i~>
<~i~>
is expected to find and delete every line in the file that starts <~i~>
with a chapter heading. This example will do just that, and so <~i~>
will many other such uses of the command. But spectacular <~i~>
failures will happen from time to time--typing: <~i~>
<~i~>
global /^Chapter [1-9]/ write >> t.of.contents <~i~>
<~i~>
definitely will not append each of the marked lines to a file <~i~>
named "t.of.contents", as moderately-experienced users might <~i~>
expect. (It's likely to overflow your file system quota instead.) <~i~>
<~i~>
The Details of global Operations <~i~>
<~i~>
More important, misunderstanding the global command keeps users <~i~>
from exploiting more than a small fraction of that command's <~i~>
power. But you don't have to live with the limitations of <~i~>
ignorance on this--here's the full story in plain terms: <~i~>
<~i~>
Searching where you tell it to look: <~i~>
<~i~>
As a line-mode command, global can be preceded by an address or <~i~>
pair of addresses. Its default is to search the entire file, <~i~>
but if you start your command as 257 , 382 global then it will <~i~>
only search through lines 257 through 382 inclusive. Any <~i~>
line-mode addresses can begin a global command, so starting <~i~>
with ?^Exercises? +++ , $ global will restrict the pattern <~i~>
search and line marking to a stretch beginning three lines past <~i~>
the last previous line that starts with the string <~i~>
"Exercises", and ending at the end of the file. <~i~>
<~i~>
Marking either hits or misses: <~i~>
<~i~>
Typing the command name as global or g will definitely cause it <~i~>
to mark every line in the search area that contains the <~i~>
pattern. But typing it as global! or g! or v reverses the <~i~>
procedure--now it will only mark lines that do not contain the <~i~>
search string. So if you are editing a copy of a log file of <~i~>
error messages, and only the lines that begin with "Error <~i~>
3b:" are of interest, you can eliminate all the unwanted lines <~i~>
by typing: <~i~>
<~i~>
global! /^Error 3b:/ delete <~i~>
<~i~>
Choose your own search pattern delimiter: <~i~>
<~i~>
Since this command always searches the file (or the section of <~i~>
it that you select) from top to bottom, you can use almost any <~i~>
punctuation character to mark the start and end of your search <~i~>
pattern. There's no need to use ? or / characters to indicate <~i~>
a direction for the search. If you want to eliminate lines <~i~>
that contain three consecutive slash marks, any of: <~i~>
<~i~>
global +///+ delete <~i~>
global ;///; delete <~i~>
global ]///] delete <~i~>
<~i~>
will be a simpler choice than using slashes as delimiters and <~i~>
backslashing all three of the slashes you are searching for. <~i~>
(However, using ! as you delimiter is dangerous, because global <~i~>
is likely to mistake your delimiter for the switch that tells <~i~>
it to find only lines that do not contain the search pattern.) <~i~>
<~i~>
Of course this applies only to the search pattern that goes <~i~>
right after the global command name, the one that says which <~i~>
lines to mark. If you use any search patterns before the <~i~>
command name, to say which area of the file is to be searched, <~i~>
then use ? and / delimiters as usual. <~i~>
<~i~>
Global searches that seem senseless can be very useful: <~i~>
<~i~>
At times it's wise to have global or global! run a search over <~i~>
just one line in a file. This is the basis for conditional <~i~>
execution of line-mode commands. As a simple example, you may <~i~>
find yourself editing files from outside your organization that <~i~>
are sometimes (but not always) sent to you with an extra, empty <~i~>
last line, as a spacer. You need to remove that last line, if <~i~>
and only if it is empty. You could go the end of each file and <~i~>
look, but it's easier to have the editor do the checking and <~i~>
(where necessary) the deletion, so you type: <~i~>
<~i~>
$ global /^$/ delete <~i~>
<~i~>
It can also be useful to have global mark every line in the <~i~>
area of the file you tell it to search! Our put-upon <~i~>
programmer, Hal (in the first installment of this tutorial) <~i~>
used this when he had to reverse the order of the lines in one <~i~>
file. His command line, which would look like this if typed out <~i~>
in unabbreviated form: <~i~>
<~i~>
global /^/ move 0 <~i~>
<~i~>
begins by marking each line that has a start-of-line point, <~i~>
which makes every line qualify. Next it goes to the first line <~i~>
and moves it up right after the fictitious line zero--a no-op, <~i~>
of course. But then it moves the second line to the same <~i~>
place, pushing the former first line down one position in the <~i~>
file. As it does the same with the third line, the fourth <~i~>
line, etcetera, it's changing the order of the lines to the <~i~>
exact opposite of the order they were in at the start. <~i~>
<~i~>
One global can run many commands: <~i~>
<~i~>
You can put several commands on the line after a global command <~i~>
and its search pattern. After marking the appropriate lines, <~i~>
global will then go to each marked line and run all of the <~i~>
commands you've given it, in the order you gave them. Just <~i~>
separate these commands with a vertical bar ("|") character. <~i~>
If you type: <~i~>
<~i~>
global /^CHAPTER/ substitute /APTER/apter/ | copy $ <~i~>
<~i~>
the editor will go to each line that starts with a chapter <~i~>
heading, change "CHAPTER" to "Chapter", and then copy the <~i~>
line (now beginning "Chapter" instead of "CHAPTER") to the <~i~>
end of the file. The order in which you put those two commands <~i~>
is important -- the substitute command must come first so the <~i~>
subsequent copy command will copy the decapitalized version of <~i~>
the line, not the original all-caps version. <~i~>
<~i~>
You're not limited to just two commands in a global command <~i~>
line; there is no maximum on the number of commands there. The <~i~>
maximum string length for the command list varies with the <~i~>
editor version you're using, but I've never encountered a limit <~i~>
of less then 256 characters. There are a few restrictions on <~i~>
what the command list can contain, though: <~i~>
<~i~>
The global keyword and the following list of commands all <~i~>
must be on one line. (That is, on one physical line, with <~i~>
no carriage returns in it. If that one line is too long for <~i~>
your terminal's screen width, the terminal may wrap it <~i~>
around to occupy two or more lines on your screen, but this <~i~>
will not cause a problem.) <~i~>
<~i~>
The command list cannot include an undo or another global <~i~>
command. <~i~>
<~i~>
If you include a command that escapes to the shell, it must <~i~>
be the last command on the line. (Putting two or more <~i~>
shell-escape commands in one command list will not work.) <~i~>
This makes it possible to use pipes (symbolized by the | <~i~>
character) in your shell-escape command string, without <~i~>
having the editor mistake the pipe symbol for the separator <~i~>
between two editor commands in your global command line. <~i~>
<~i~>
Commands don't have to run on the lines global marks. <~i~>
<~i~>
Using global is essentially the same as moving to each marked <~i~>
line manually, then typing in the command string while you are <~i~>
there. Just as you no longer expect every command you type in <~i~>
to operate on the line you are on when you type it, you don't <~i~>
have to have the commands in a global string operate entirely <~i~>
on the marked lines. Here are three points to note regarding <~i~>
this: <~i~>
<~i~>
Any command in a global command line can take its own <~i~>
address or addresses, just as it could if it were typed in <~i~>
as a separate command. So this command string: <~i~>
<~i~>
global /^XX/ - copy $ | /ZZ$/ , +5 delete <~i~>
<~i~>
is entirely legitimate. It goes to each line that begins <~i~>
with two capital X's, then copies the line just before that <~i~>
one to the end of the file, and finally goes forward to the <~i~>
next line that ends with two capital Z's and deletes that <~i~>
line and the five lines that follow it. <~i~>
<~i~>
Even if you give no addresses for the commands in a global <~i~>
string, default addresses for those commands may make them <~i~>
operate on other than the marked line. That's the fault in <~i~>
that global command string in the introduction to this <~i~>
installment of my tutorial that tries to write individual <~i~>
lines to another file. Because the default address for the <~i~>
write command is the entire file, this command will write <~i~>
the entire file the user is editing to the end of the other <~i~>
file, once for every line that global has marked. The <~i~>
correct way to write individual lines is to type: <~i~>
<~i~>
global /^Chapter [1-9]/ . write >> t.of.contents <~i~>
<~i~>
where the dot address in front of the write command tells it <~i~>
to write only the line it is on. <~i~>
<~i~>
But even if you take a command that has the current line as <~i~>
its default address, and put it in the string following <~i~>
global without giving it an address of its own, it can still <~i~>
operate on different lines from the ones global has marked <~i~>
if it is not the first command in the string. The reason: <~i~>
each subsequent command in a global takes as the current <~i~>
line whatever line the command before it left as the current <~i~>
line. <~i~>
<~i~>
In my earlier example about wanting to both change the <~i~>
capitalization of lines beginning with "CHAPTER" and copy <~i~>
those lines to the end of the file, the task was easy <~i~>
because the lines were to be copied in their changed state. <~i~>
But what if the user wanted only the lines in the midst of <~i~>
the file decapitalized, while the ones copied to the end of <~i~>
the file were to remain all-caps? It might seem obvious to <~i~>
simply reverse the order of the two commands, so the copy <~i~>
command was executed first, before the substitute command <~i~>
was called to change the capitalization, like this: <~i~>
<~i~>
global /^CHAPTER/ copy $ | substitute /APTER/apter/ <~i~>
<~i~>
Surprisingly, that would produce the opposite of the effect <~i~>
that was intended. That is, it would decapitalize the <~i~>
copied lines at the end of the file, but leave the marked <~i~>
lines in the midst of the file all-caps. The reason? The <~i~>
copy command leaves the last line of the copy text block, <~i~>
not the original text block, as the current line. So after <~i~>
the copy command has run, the substitute command, using the <~i~>
command's default address (the current line) because it has <~i~>
not been given an explicit address, would operate on the <~i~>
copy line rather than the original. <~i~>
<~i~>
But there is one thing that no amount of current-line <~i~>
shifting can change. Wherever in the file the command <~i~>
string may leave the current line, when the commands have <~i~>
finished running, global will go to the next marked line <~i~>
without fail. The only way any of the commands in the <~i~>
string can prevent this is by deleting the next marked line <~i~>
-- in that case, global will merely go on to the next marked <~i~>
line that has not been deleted. And even this fact has uses <~i~>
that might not be obvious. <~i~>
<~i~>
Let's say you want to thin out the lines in a file, by <~i~>
deleting every second line. You can do it by typing: <~i~>
<~i~>
global /^/ + delete <~i~>
<~i~>
This global starts off by marking every line. When it goes <~i~>
to line 1, the command it executes will delete line 2. The <~i~>
next undeleted marked line is line 3, where its command <~i~>
deletes line 4, and so on. Or if you want to delete <~i~>
two-thirds of the lines in your file, type: <~i~>
<~i~>
global /^/ + , ++ delete <~i~>
<~i~>
A Few More Uses for global Commands <~i~>
<~i~>
The examples above are designed to show not only the working <~i~>
principles of the global command, but also some of the <~i~>
less-obvious tricks it can do. But I couldn't fit every important <~i~>
trick in above. Here are some more that are well worth knowing. <~i~>
<~i~>
Keeping Count. At times it's a good idea to follow global with a <~i~>
string of commands that have absolutely nothing to do with the <~i~>
lines that global has marked. The most common occasion for this <~i~>
comes when you need to repeat a line-mode command a certain number <~i~>
of times. <~i~>
<~i~>
At tradeshows I'm often invited to test a system right there on <~i~>
the show floor. I can't carry a 10,000-line test file along with <~i~>
me in every media and format any system might require, so I type <~i~>
in a ten-line file on the spot and expand it by telling the editor <~i~>
ten times to make a copy of the entire file and put that copy at <~i~>
the end of the present file. (Each such copy doubles the file's <~i~>
size, so I wind up with 10,240 lines.) <~i~>
<~i~>
But that requires accurate counting. If I'm off by even one on <~i~>
the number of times I type that command in, I get a half-size or <~i~>
double-size file that ruins my test results. Instead of trying to <~i~>
count without an error, I let the editor do the counting for me. <~i~>
After I've typed in the initial ten lines, I give one global <~i~>
command: <~i~>
<~i~>
global /^/ % copy $ <~i~>
<~i~>
This tells the editor to search the ten lines of the file, mark <~i~>
every line that has a start-of-line (which means every line, of <~i~>
course), and then go to each of those ten lines and run the <~i~>
subsequent command to make a whole-file copy. This guarantees <~i~>
that the command will run exactly ten times. <~i~>
<~i~>
Not that this trick is limited to files that have exactly as many <~i~>
lines as the number of times I want to command to be repeated. If <~i~>
I had typed in a twenty-line file, I could copy it ten times by <~i~>
giving my global as: <~i~>
<~i~>
1 , 10 global /^/ % copy $ <~i~>
<~i~>
Moving Around Automatically. At times you may need to handle a <~i~>
series of editing problems in a file, where the edits must be <~i~>
dealt with one by one, not with a global editing script. But <~i~>
moving to each spot where work needs to be done can be a very <~i~>
tedious business. If there is a text pattern that identifies each <~i~>
place that needs editing, or if you can write a script to insert <~i~>
such a pattern, as Hal did at the start of this tutorial's first <~i~>
installment, then global can move you around automatically. <~i~>
<~i~>
You may recall that Hal used a script to mark up the legacy source <~i~>
code, putting each lint warning at the end of the source line to <~i~>
which it referred, preceded by "XXX" to make the affected lines <~i~>
identifiable. Suppose that the nefarious Vice President for <~i~>
Information Systems comes back to Hal to demand that each warning <~i~>
be investigated, to see whether the code can be rewritten to <~i~>
eliminate the warning. <~i~>
<~i~>
Should Hal just leaf through the code, searching for XXX patterns <~i~>
to guide him to the trouble spots? Hal knows that with the <~i~>
spaghetti code he's facing, the actual problem may be a long way <~i~>
from the line lint has designated. In traveling to the actual <~i~>
trouble spot he may have passed several XXX patterns along the <~i~>
way, so searching for the next XXX in the file may bring him to a <~i~>
site he's already dealt with, or may miss a number of XXX sites <~i~>
that he passed when he moved forward to get to the actual problem <~i~>
spot on the previous fix. Besides, because he frequently does <~i~>
pattern searching while fixing a problem, he can't depend on a <~i~>
visual-mode n command to use the XXX pattern he needs to find; he <~i~>
must type the pattern in afresh each time. <~i~>
<~i~>
But Hal knows a way around all this--dropping back to line mode <~i~>
(by typing a capital letter Q from visual mode) and giving a <~i~>
simple global command: <~i~>
<~i~>
global /XXX/ visual | write <~i~>
<~i~>
This command brings Hal to the first "XXX" line, where it puts him <~i~>
into visual mode to do his editing. When the edit is finished, <~i~>
Hal simply types a capital letter Q and the editor takes him to <~i~>
the second "XXX" line and puts him into visual mode there, no <~i~>
matter how much moving around Hal did during the first edit, and <~i~>
so on through the list of "XXX" lines. As frosting on the cake, <~i~>
the write command automatically writes the changed file to disk <~i~>
after each individual edit. <~i~>
<~i~>
Now You Give it a Try <~i~>
<~i~>
Here are a few exercises you can try to solve, before you start <~i~>
using advanced global tactics in your own editing. To keep things <~i~>
rolling I've provided at least one solution to each exercise, and <~i~>
also a hint on the last (and toughest) problem. <~i~>
<~i~>
Copy and Decapitalize. <~i~>
<~i~>
Let's think back to the user who wanted to find each line in the <~i~>
file that begins with "CHAPTER", then copy each such line to the <~i~>
end of the file just as it is, and finally change the start of <~i~>
each original line (in mid-file) from "CHAPTER" to "Chapter" <~i~>
while leaving the copied lines (at the end of the file) <~i~>
beginning "CHAPTER". <~i~>
<~i~>
We've already learned that this cannot be done with either of: <~i~>
<~i~>
global /^CHAPTER/ substitute /APTER/apter/ | copy $ <~i~>
global /^CHAPTER/ copy $ | substitute /APTER/apter/ <~i~>
<~i~>
What global command (or commands) would it take to do what's <~i~>
desired here? Finding a solution to this is not difficult when <~i~>
there are so many workable ones. <~i~>
<~i~>
A Precise String Length. <~i~>
<~i~>
An old friend who does some pretty tricky work with troff often <~i~>
needs to insert a string of backslashes in a line--up to 64 of <~i~>
them in a row. The count of backslashes must be exactly right <~i~>
or troff will choke. How can he get these strings exactly right <~i~>
without tedious counting and checking? <~i~>
<~i~>
Let's say he needs to put 16 backslashes in line 217, right <~i~>
before the string "n(PDu". What command(s) should he use to get <~i~>
them in there without hand counting. My solution is pretty <~i~>
plain once you know which commands to use. <~i~>
<~i~>
Numbering Paragraphs. <~i~>
<~i~>
A documentation writer has divided each section of a document into <~i~>
paragraphs, and as a troff user, marks the start of each paragraph <~i~>
by a line that contains the macro ".pp" only. That is, a break <~i~>
between paragraphs looks like this: <~i~>
<~i~>
which is the only way that argon gas can be dissolved in this <~i~>
liquid. <~i~>
<~i~>
.pp <~i~>
The problem of energizing the argon to fluorescence while <~i~>
it is dissolved was first approached by applying a strong <~i~>
<~i~>
<~i~>
How can this tech writer use the vi editor to number the <~i~>
paragraphs in each section? (If this seems far-fetched to you, <~i~>
consider that I once got a phone call from a Unix guru asking <~i~>
how to do just this.) To keep the problem simple, let's say <~i~>
that there are never more than 35 paragraphs in a section, and <~i~>
that they should be numbered with Roman numerals. <~i~>
<~i~>
This problem is still difficult enough that I'm offering you two <~i~>
hints. The first is that global is essential here. Look at the <~i~>
second hint only if you're about to give up and check my <~i~>
solution. <~i~>
<~i~>
<~i~>
Coming Up Next <~i~>
<~i~>
In the next part of this tutorial, I'll cover the less-known <~i~>
aspects of the other line-mode commands for dealing with text and <~i~>
files. If you're a little overwhelmed with all that I've said <~i~>
about global, you'll be pleased to know that substitute is notably <~i~>
simpler, and all the remaining commands are very much simpler, <~i~>
than global. <~i~>
<~i~>
After that, future parts of this tutorial will deal with visual <~i~>
mode; easier and more fun than line mode any day. <~i~>
The Details of Global Operations <~i~>
A Few More Uses for Global Commands <~i~>
Now You Give It A Try <~i~>
Part 4: The Substitute Command/
The vi/ex Editor, Part 4: The Subtle Substitute Command <~i~>
<~i~>
Making Changes Within Lines <~i~>
A Few More Metacharacters <~i~>
Replacement-Pattern Metacharacters <~i~>
Other Uses for Substitution <~i~>
A Start on Script Writing <~i~>
Don't Lose Your Files <~i~>
Reader Feedback <~i~>
The Next Installment <~i~>
<~i~>
After the :global command, which we discussed in the previous <~i~>
installment of this tutorial series, the :substitute command is <~i~>
line mode's most subtle and complex tool. When I've gone over <~i~>
those complexities we'll be ready to deal with techniques and <~i~>
tricks of building powerful line-mode command strings. <~i~>
<~i~>
Making Changes Within Lines <~i~>
<~i~>
Most of you already know the :substitute <~i~>
command by its shortest abbreviation :s <~i~>
and use it in roughly this form: <~i~>
<~i~>
s/previous/former/ <~i~>
%s/Smith/Lee and Smith/ <~i~>
<~i~>
to make some change within the line you are on, in the first case, <~i~>
or change every instance in the file in the second. If you use <~i~>
both forms you are already ahead of the game. Too many class <~i~>
instructors and textbook writers try to tell you that the way to <~i~>
change some phrase throughout the file is to type something like: <~i~>
<~i~>
global/Smith/s//Lee and Smith/ <~i~>
<~i~>
This is wasteful nonsense. Both forms accomplish exactly the same <~i~>
thing, but the second version involves extra typing for you and an <~i~>
extra run through the file for your computer. It does not matter <~i~>
that not every line in your file will contain a "Smith" to be <~i~>
changed -- the :substitute command will execute properly in <~i~>
either version, and quietly if even one line in the file has a <~i~>
"Smith" it can change. <~i~>
<~i~>
But neither form as it stands is sure to change every "Smith" in <~i~>
the file. The :substitute command is set up to change only the <~i~>
first example of the string it finds on any particular line, so a <~i~>
line in the text that originally read: <~i~>
<~i~>
inure to Smith's benefit only if Smith shall <~i~>
<~i~>
will be changed by either version of the command to read: <~i~>
<~i~>
inure to Lee and Smith's benefit only if Smith shall <~i~>
<~i~>
Line mode has a built-in solution for this problem: place a <~i~>
lower-case letter "g" at the very end of the command, immediately <~i~>
after the last "/" mark, in order to make the change on every such <~i~>
string in each line. So typing this: <~i~>
<~i~>
% substitute /Smith/Lee and Smith/g <~i~>
<~i~>
will make that text line come out as: <~i~>
<~i~>
inure to Lee and Smith's benefit only if Lee and Smith shall <~i~>
<~i~>
Finer tuning of the instances can be done by a little trickery. <~i~>
Suppose you are working on tables, and want to change only the <~i~>
very last "k37" on each line to "q53". This command will do it: <~i~>
<~i~>
% substitute /\(..*\)k37/\1q53 <~i~>
<~i~>
If this seems surprising, remember that in a search pattern with a <~i~>
wild card, the editor always extends the match to the greatest <~i~>
length it can. In this case that means the string starting at the <~i~>
beginning of the line and ending with the last "k37" in the line. <~i~>
<~i~>
Now you should be able to extend this example. What command would <~i~>
change only the second-to-last "k37" on each line? This requires <~i~>
a shrewd guess from you, so I've written a solution you can <~i~>
compare to your own. <~i~>
<~i~>
A Few More Metacharacters <~i~>
<~i~>
You probably already know that you don't always have to type the <~i~>
search pattern that indicates the text to be replaced by a <~i~>
substitution command. If you want to reuse your very last search <~i~>
pattern, whether that was in a substitution command or not, you <~i~>
can use an empty search pattern string to stand for the last <~i~>
search pattern, so the two commands below are actually identical. <~i~>
<~i~>
/Murphy/ substitute /Murphy/Thatcher/ <~i~>
/Murphy/ substitute //Thatcher/ <~i~>
<~i~>
Either command will go to the next line containing "Murphy" and <~i~>
there replace the first "Murphy" with "Thatcher". <~i~>
<~i~>
Within a substitution command's search pattern to find the text to <~i~>
be removed, all the normal search-pattern metacharacters apply. <~i~>
So do two more that are reserved only for substitution commands: <~i~>
the "\(" and "\)" metacharacters. <~i~>
<~i~>
These two metacharacters don't match anything themselves, so: <~i~>
<~i~>
substitute /^The cat and small dog show/ <~i~>
substitute /^The \(cat\) and \(small dog\) show/ <~i~>
<~i~>
are exactly the same command as far as they go. But the <~i~>
substitution command remembers what it finds to match the text <~i~>
between a pair of "\(" and "\)" metacharacters, for use in the <~i~>
replacement text. Whenever your replacement pattern contains "\1" <~i~>
the editor replaces that metacharacter with whatever matched the <~i~>
characters that were between the first pair of "\(" and "\)" <~i~>
metacharacters. A "\2" in the replacement pattern is removed and <~i~>
replaced by whatever was matched the characters between the second <~i~>
pair. And so on -- you can have up to nine pairs in one <~i~>
substitution command. These metacharacter pairs can even be <~i~>
nested in the to-be-replaced text; the one that starts first will <~i~>
be represented by "\1" and so on. So if you extend that second <~i~>
substitution command above to read: <~i~>
<~i~>
substitute /^The \(cat\) and \(small dog\) show/My \2-\1 fair <~i~>
<~i~>
the substitution command will produce a line that begins: <~i~>
<~i~>
My small dog-cat fair <~i~>
<~i~>
Or if you type: <~i~>
<~i~>
substitute :up \(and \)\(over \)\(the sky\):\2\1\2\1\2\3 <~i~>
<~i~>
then your command will change the first line below to read as the <~i~>
second line, just beneath it: <~i~>
<~i~>
up and over the sky <~i~>
over and over and over the sky <~i~>
<~i~>
(I used the colon ":" character to separate the parts of the <~i~>
command, instead of the slash "/" character, solely to make it <~i~>
more readable for you. There is no danger of the editor confusing <~i~>
"/" with "\" or "l" (el) with "1" (one) etcetera.) <~i~>
<~i~>
As the preceding examples show, the "\(" and "\)" are not too <~i~>
useful with plain-text search patterns; about their only real <~i~>
value there is when you are searching for something that's <~i~>
difficult to spell correctly, and don't want to type it into the <~i~>
replacement pattern with possible spelling errors. (Spelling <~i~>
errors aren't so dangerous in the to-be-replaced text, because <~i~>
they only cause the pattern match to fail.) <~i~>
<~i~>
These metacharacters save the day, though, when you are dealing <~i~>
with other search metacharacters in searching for text that you <~i~>
will want to put back in. (Often the only way to specify the <~i~>
exact spot you want the replacement done is to include some <~i~>
neighboring text in the search pattern, and tell the editor that <~i~>
after the neighboring text has been taken out it is to be put back <~i~>
in right where it was.) Here are three examples of this kind of <~i~>
substitution: <~i~>
<~i~>
% substitute :\([Ss]ection\) \([0-9][0-9]*\):\1 No. \2:g <~i~>
/\([Ss]ection\) \([0-9][0-9]*\)/ substitute ::\1 No. \2 <~i~>
% substitute ,[Aa]nswer: \([TtFf] \),ANSWER: \1,g <~i~>
<~i~>
The first of these simply inserts "No." in the middle of phrases <~i~>
that are section numbers, throughout the document. But the "\(" <~i~>
and "\)" notation is essential to preserve the section number in <~i~>
each case, and also to leave unchanged the capitalization or <~i~>
noncapitalization of the first letter of "section". <~i~>
<~i~>
The second command does the same thing, but only on the very next <~i~>
line that has a section number to change. The surprise here is <~i~>
that I put the "\(" and "\)" in the address pattern to find the <~i~>
correct line. A line address doesn't use these metacharacters, of <~i~>
course, but it does not object to them, either. It just ignores <~i~>
them in its own line search, but does pass them along when a <~i~>
following substitution command reuses the last search pattern, as <~i~>
happens in this example. <~i~>
<~i~>
The third example is useful in editing a list of answers to <~i~>
exercises. It stops at each answer to a true-or-false question and <~i~>
capitalizes the entire word "answer". The innovative aspect of <~i~>
this command is that it finds the letter "T" or "t" or "F" or "f" <~i~>
following the word "answer", so it will not change the <~i~>
capitalization where an answer is numerical rather than true or <~i~>
false. And yet, the letter indicating whether "true" or "false" <~i~>
is the correct answer is not discarded as a side effect. This is <~i~>
primarily an example of a change that can be done more simply by <~i~>
using other metacharacters in the replacement pattern. Those other <~i~>
metacharacters are described below. <~i~>
<~i~>
Replacement-Pattern Metacharacters <~i~>
<~i~>
The string of characters you want to put in via a substitution <~i~>
command can use its own list of metacharacters. They're entirely <~i~>
different from the metacharacters used in searching for a pattern <~i~>
you want to take out of a line. <~i~>
<~i~>
& <~i~>
<~i~>
In a replacement pattern, the "&" stands for the entire text <~i~>
that was to be replaced. Use this when you want to add rather <~i~>
than replace text. For example, to change "kit" to "kit and <~i~>
kaboodle" regardless of whether "kit" is capitalized, use: <~i~>
<~i~>
% substitute /[Kk]it/& and kaboodle/g <~i~>
<~i~>
If you have magic turned off, you must backslash the "&" to give <~i~>
it metavalue. With magic on, backslash an "&" to insert it as <~i~>
a regular character. (See the explanation of set in the <~i~>
subsequent article). <~i~>
<~i~>
~ <~i~>
<~i~>
The "~" character represents the replacement pattern you used in <~i~>
your last substitution command. One good use for this is in <~i~>
correcting various misspellings of a single word: <~i~>
<~i~>
% substitute /[Ff]anstock clip/Fahnestock clip/g <~i~>
% substitute /[Ff]ahnstock clip/~/g <~i~>
% substitute /[Ff]ahnstocke clip/~/g <~i~>
% substitute /[Ff]annstock clip/~/g <~i~>
% substitute /[Ff]anestock clip/~/g <~i~>
% substitute /[Ff]aenstock clip/~/g <~i~>
<~i~>
If you have magic turned off, you must backslash the "~" to give <~i~>
it metavalue. With magic on, backslash a "~" to insert it as a <~i~>
regular character. <~i~>
<~i~>
\U <~i~>
<~i~>
A "\U" metacharacter makes all letters following it into <~i~>
capitals; to the end of the replacement pattern or until another <~i~>
metacharacter turns it off. Here's how you'd use it to change a <~i~>
section of your document to all capitals: <~i~>
<~i~>
1 , substitute /.*/\U& <~i~>
<~i~>
\L <~i~>
<~i~>
A "\L" gives the opposite effect of a "\U"; all following <~i~>
letters become lower case. You might use this to decapitalize <~i~>
acronyms: <~i~>
<~i~>
% substitute /FORTRAN and COBOL/\L&/g <~i~>
<~i~>
\E <~i~>
<~i~>
Use "\E" to end the effect of a "\U" or "\L" metacharacter. <~i~>
Everything following the "\E" has the same mix of capitalization <~i~>
as originally. For example, to enclose a line of text in curly <~i~>
braces, and also change just the first word to all capitals: <~i~>
<~i~>
substitute :\([^ ]*\)\(.*\):{\U\1\E\2} <~i~>
<~i~>
No "\E" is needed when you switch from "\U" to "\L" in the <~i~>
middle of a replacement pattern, or vice versa. When either of <~i~>
those metacharacters appears, it automatically ends the effect <~i~>
of the other. So if you have a list of book titles, one title <~i~>
per line, with only the first letters of the words capitalized, <~i~>
and you want to change those titles to all capitals before the <~i~>
colon in the middle of each title, and all lower case after it, <~i~>
just type: <~i~>
<~i~>
% substitute ,\(.*\):\(.*\),\U\1:\L\2 <~i~>
<~i~>
\u <~i~>
<~i~>
This metacharacter capitalizes just the single letter that <~i~>
immediately follows it. If the character that immediately <~i~>
follows it is not an alphabet letter, "\u" does nothing. <~i~>
<~i~>
\l <~i~>
<~i~>
The same as "\u", except that "\l" makes the immediately <~i~>
following letter come out as lower case. <~i~>
<~i~>
One more thing that's important to know about reusing patterns in <~i~>
substitution commands. When all or part of a text-to-be-replaced <~i~>
pattern is going to be used as a replacement pattern, or vice <~i~>
versa, the command reuses the result of the original pattern, <~i~>
after all the metacharacters have been evaluated in the original <~i~>
situation. Since the metacharacters in either of those two types <~i~>
of patterns have no meaning in the other type, it could hardly be <~i~>
otherwise. <~i~>
<~i~>
But when the reuse involves a text-to-be-replaced pattern being <~i~>
used a second time as a text-to-be-replaced pattern, or a <~i~>
replacement pattern being reused as a replacement pattern, the <~i~>
command brings along all the original metacharacters and evaluates <~i~>
them afresh in the new situation. Thus, in either of the cases in <~i~>
this paragraph, the second use is unlikely to produce exactly the <~i~>
same results as the first use did. <~i~>
<~i~>
Now another exercise for you. Suppose that lines 237 through 289 <~i~>
of a file have unknown capitalization--any line could be all caps, <~i~>
all lower case, or some mixture. These lines are to be changed so <~i~>
that the first letter of every word is a capital and all other <~i~>
letters are lower case. To simplify this, words are separated by <~i~>
space characters. What is the easy way to do this with one <~i~>
line-mode substitution command? This exercise depends on <~i~>
something I did not state directly, so don't feel bad if my <~i~>
solution is a little simpler than yours. <~i~>
<~i~>
Other Uses for Substitution <~i~>
<~i~>
Despite the name, the :substitute command doesn't always take <~i~>
something out of the line and put something else in its place. <~i~>
Here's an example that adds text at the start of certain lines <~i~>
without removing anything: <~i~>
<~i~>
537 , 542 substitute /^/WARNING: / <~i~>
<~i~>
so that text which originally looked like this: <~i~>
<~i~>
The primary output line carries very high voltage, which does not <~i~>
immediately dissipate when power to the system is turned off. <~i~>
Therefore, after turning off the system and disconnecting the <~i~>
power cord, discharge the primary output line to ground before <~i~>
servicing the output section. <~i~>
<~i~>
now looks like this: <~i~>
<~i~>
WARNING: The primary output line carries very high voltage, <~i~>
WARNING: which does not immediately dissipate when power to <~i~>
WARNING: the system is turned off. Therefore, after turning <~i~>
WARNING: off the system and disconnecting the power cord, <~i~>
WARNING: discharge the primary output line to ground before <~i~>
WARNING: servicing the output section. <~i~>
<~i~>
It's just as practical to pull some text out of lines without <~i~>
putting anything back in its place. Here are two command lines <~i~>
that do just that: <~i~>
<~i~>
% substitute / uh,//g <~i~>
. , $ substitute / *$ <~i~>
<~i~>
The latter command removes superfluous spaces at the ends of <~i~>
lines. It doesn't need the final two slashes because there is no <~i~>
suffix to be distinguished from a replacement pattern. <~i~>
<~i~>
At times you might use both the previous principles, to create <~i~>
:substitute commands that neither subtract nor add any text. <~i~>
Sound pointless? Here's one such that I sometimes use when I'm <~i~>
well along in writing one of these tutorials: <~i~>
<~i~>
% substitute /^$ <~i~>
<~i~>
Now here's a different kind of exercise for you. I've already <~i~>
given you the command, above. It obviously makes no change <~i~>
whatsoever in the file. So why do I run this command? You need a <~i~>
goodly dose of inspiration to answer this, so don't be embarrassed <~i~>
if you have to look at my answer to this one. <~i~>
<~i~>
A Start on Script Writing <~i~>
<~i~>
Already you know enough about the editor to be able to plan some <~i~>
fairly complex edits. Here's a short introduction to the art of <~i~>
writing editing scripts for this editor. <~i~>
<~i~>
BOTTOM-UP PROGRAMMING. That's usually the best way to build a <~i~>
complex editor command or command script. That's a programmer's <~i~>
term that means putting all the little details in separately and <~i~>
then pulling them all together into a unified whole, rather than <~i~>
starting with a grand overall plan and forcing the details to fit. <~i~>
<~i~>
For example, reader R.T. of San Francisco, California asks how to <~i~>
use the editor to automatically add HTML paragraph tags to each <~i~>
paragraph of manuscripts. This requires inserting the string <~i~>
"" at the start of the first line of each paragraph, and <~i~>
the string "" at the end of the last line. In these <~i~>
manuscripts, a completely empty line (not even a non-printing <~i~>
character on it) separates one paragraph from another. <~i~>
<~i~>
This looks pretty easy. All that seems to be needed is to go to <~i~>
each empty line, then move up to the preceding line to insert the <~i~>
end-of-paragraph string and down to the following line to put in <~i~>
the start-of-paragraph string. But there are flaws in the obvious <~i~>
command to do this: <~i~>
<~i~>
global /^$/ - substitute :$:: | ++ substitute /^// <~i~>
<~i~>
The first problem is that when the editor goes to the empty first <~i~>
line that commonly begins a file, it will be unable to move up a <~i~>
line to do the first substitution. No substitution is needed <~i~>
there, of course, but since the editor doesn't leave that empty <~i~>
first line, moving down two lines will put it on the second line <~i~>
of the following paragraph -- definitely the wrong place for a <~i~>
start-of-paragraph tag. There are several ways to fix this <~i~>
problem: <~i~>
<~i~>
Have the editor :mark the empty line before leaving it to execute <~i~>
(or attempt to execute) the first substitution. Then it can go to <~i~>
the marked line (which works even if the editor never left it) and <~i~>
drop down one line to perform the second substitution. <~i~>
<~i~>
Change the address of that second substitution command from "++" <~i~>
to "/./" in order to move forward to the next nonempty line, which <~i~>
will be the first line of the following paragraph whether the <~i~>
search starts from the empty line or the line above it. <~i~>
<~i~>
Run two separate :global searches, each of which executes one of <~i~>
the two substitution commands. <~i~>
<~i~>
Problem number two is that there may be several empty lines <~i~>
between two paragraphs, since HTML interpretation is not affected <~i~>
by them. If the editor is on the first of two or more consecutive <~i~>
empty lines, the command I first proposed above will perform its <~i~>
second substitution on the second empty line just below it. When <~i~>
it moves to the second previously-empty line, it will run the <~i~>
first substitution co mmand on the empty line it just left. (Yes, <~i~>
the second line is no longer empty, but it has already been marked <~i~>
by the :global command before any substitutions are done.) That <~i~>
is, a stretch of text that initially looked like this: <~i~>
<~i~>
at this meeting, so be sure to be there! <~i~>
<~i~>
At next month's meeting we'll hear from the new <~i~>
<~i~>
and should have been edited to look like this: <~i~>
<~i~>
at this meeting, so be sure to be there! <~i~>
<~i~>
At next month's meeting we'll hear from the new <~i~>
<~i~>
actually turns out like this: <~i~>
<~i~>
at this meeting, so be sure to be there! <~i~>
<~i~>
<~i~>
At next month's meeting we'll hear from the new <~i~>
<~i~>
It may look as though this hazard can be defeated by modifying the <~i~>
number two solution to the first problem above. That is, the <~i~>
address for both substitutions will be a search pattern that looks <~i~>
for a line that already has some text on it. This works properly <~i~>
when the editor is on the first of two consecutive empty lines. <~i~>
From the second line, though, it runs its substitution commands on <~i~>
lines that have already been given their tags, so the sample text <~i~>
now looks like this: <~i~>
<~i~>
at this meeting, so be sure to be there! <~i~>
<~i~>
At next month's meeting we'll hear from the new <~i~>
<~i~>
COMPLEX CONDITIONALS. What's really needed here is <~i~>
double-conditional execution. That is, substitution commands must <~i~>
run on a given line only if both of these conditions are true: <~i~>
<~i~>
- The line to be substituted is adjacent to the empty line. <~i~>
<~i~>
- The line to be substituted is not itself empty. <~i~>
<~i~>
In this case, the editor can handle it. The :global portion of <~i~>
the command line takes care of the first condition if the <~i~>
substitution commands' addresses move exactly one line in each <~i~>
direction from the empty line. (Of the three proposed solutions <~i~>
to the first difficulty encountered, numbers one and three both do <~i~>
this much.) To satisfy the second condition, make the <~i~>
substitution commands remove one character from the existing line <~i~>
-- and then replace it, of course. This ensures that if there is <~i~>
no character to remove because the line is empty, the substitution <~i~>
command will fail on that line and do nothing. <~i~>
<~i~>
Either the first or third solution can be adapted to satisfy that <~i~>
second condition. I've used the third solution in the example <~i~>
commands below, because the technique is easier to follow than it <~i~>
would be with the first solution: <~i~>
<~i~>
global /^$/ + substitute /^./&/ <~i~>
global /^$/ - substitute :.$:&: <~i~>
<~i~>
Bottom-up techniques can be continued if there are yet other <~i~>
special needs to be accommodated. Reader R.T. may have headlines <~i~>
and subheads mixed in with the paragraphs, and may already have <~i~>
appropriate HTML tags at the beginnings and ends of those heads <~i~>
and subheads. As an exercise, how would you adapt the commands <~i~>
just above so they would not add a paragraph tag where any text <~i~>
already begins or ends with an HTML tag? Hint -- an HTML tag <~i~>
always begins with a "" character. This is a <~i~>
very minor change, so you probably will not need to look at my <~i~>
solution except to confirm your own answer. <~i~>
<~i~>
A LITTLE TRICKERY. At times a command needs to be supercharged by <~i~>
way of a far out use of substitution--something perfectly <~i~>
legitimate, but never intended by the people who wrote this <~i~>
editor. Here are a few that you may find useful. <~i~>
<~i~>
You can't make a substitution that extends over more than a single <~i~>
line--not directly, that is. Any attempt to put a "newline" <~i~>
character in either the to-be-replaced pattern or the replacement <~i~>
pattern of a substitution command will fail. But by combining the <~i~>
global and substitute commands, you can often get the effect of a <~i~>
substitution that spills over a line ending. <~i~>
<~i~>
Let's suppose that you have to alter a long document so that all <~i~>
references to "Acme Distributors" are changed to "Barrett and <~i~>
Sons". A simple substitution command will make most of these <~i~>
changes, but it will miss those instances where "Acme" appears at <~i~>
the end of one line and the next line starts with "Distributors". <~i~>
A followup pair of substitutions, to replace "Acme" wherever it <~i~>
appears at the end of a line and to replace "Distributors" when it <~i~>
starts a line, would wreak havoc--this document also refers to <~i~>
"Acme Supply Co." and to three other companies whose names end <~i~>
with "Distributors". <~i~>
<~i~>
But we can handle this problem nicely with the following two <~i~>
command strings: <~i~>
<~i~>
global /Acme$/ + substitute /^Distributors/and Sons <~i~>
global /^and Sons/ - substitute /Acme$/Barrett <~i~>
<~i~>
The first command goes to every line that ends with "Acme" and <~i~>
then moves forward one line--if and only if that next line begins <~i~>
with "Distributors", it is changed to begin with "and Sons". The <~i~>
next command reverses the process to change "Acme" to "Barrett", <~i~>
but only in the right instances. (Note well that the second <~i~>
command searches for "and Sons", not "Distributors", because the <~i~>
first command has changed those line-split "Acme Distributors" to <~i~>
"Acme and Sons".) <~i~>
<~i~>
Often it is a good strategy to start with a change you definitely <~i~>
don't want in order to wind up with what you do want. Suppose you <~i~>
are a technical writer who has just finished writing a number of <~i~>
lengthy photo captions full of phrases like "the light spot in the <~i~>
upper righthand corner" and "dark areas near the lower lefthand <~i~>
edge". Along comes the news that the Art Director has decided to <~i~>
flop all the photos: print them in mirror-image form. Suddenly, <~i~>
everything that was on the right is now on the left, and vice <~i~>
versa. <~i~>
<~i~>
Your captions will be accurate again if you change every <~i~>
"lefthand" to read "righthand" and vice versa. But how to do that <~i~>
without wading through the whole text and making each change <~i~>
individually? The obvious pair of substitutions will not work: <~i~>
<~i~>
% substitute /lefthand/righthand/g <~i~>
% substitute /righthand/lefthand/g <~i~>
<~i~>
The second command doesn't just change the original instances of <~i~>
"righthand" to "lefthand"; it also reverses every change your <~i~>
first command made--now everything is described as being on the <~i~>
lefthand side. But the following three substitution commands will <~i~>
do the job nicely. <~i~>
<~i~>
% substitute /lefthand/QQQQ/g <~i~>
% substitute /righthand/lefthand/g <~i~>
% substitute /QQQQ/righthand/g <~i~>
<~i~>
By making the first command change "lefthand" temporarily to <~i~>
"QQQQ" (or any other string you know will not be found in your <~i~>
document), you keep those changes safe from the effect of your <~i~>
second command. Then, after that second command has finished, the <~i~>
third command changes those Q strings to what you had wanted in <~i~>
the first place. <~i~>
<~i~>
It can even make sense to type in things incorrectly, then change <~i~>
them to what you want via substitution. When I'm writing <~i~>
documents in plain ASCII, to be printed without any formatting, I <~i~>
often use a line across the page to separate major sections of the <~i~>
document. But where others are satisfied with just a string of <~i~>
hyphens, or another single character, I pretty things up with <~i~>
multicharacter dividers like: <~i~>
<~i~>
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= <~i~>
-+--+--+--+--+--+--+--+--+--+- <~i~>
*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~ <~i~>
[][][][][][][][][][][][][][][] <~i~>
<~i~>
Not that I have the patience and concentration to type in <~i~>
page-wide lines of alternating characters, especially when I would <~i~>
have to constantly get on and off the shift key, too. No, I just <~i~>
use my repeat key to fill the line with whatever character will <~i~>
begin my eventual multicharacter pattern. For those four patterns <~i~>
above, I would have repeat-keyed in these four lines, respectively: <~i~>
<~i~>
------------------------------ <~i~>
------------------------------ <~i~>
****************************** <~i~>
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ <~i~>
<~i~>
Then I only have to run a simple repeated substitution to get the <~i~>
line I actually want. Here are the commands I would run on the <~i~>
four lines above, respectively: <~i~>
<~i~>
substitute /--/-=/g <~i~>
substitute /---/-+-/g <~i~>
substitute /\*\*/*\~/g <~i~>
substitute /\[\[/[]/g <~i~>
<~i~>
SEMI-AUTOMATIC SUBSTITUTIONS. At times you'll have to make <~i~>
changes that are so dependent on human judgment that no <~i~>
substitution tricks could possibly do exactly what's wanted. In <~i~>
those cases there are two ways to have the editor partially <~i~>
automate those changes. <~i~>
<~i~>
The first is to use a variant form of the substitute command that <~i~>
presents each potential substitution on your screen, and asks you <~i~>
to accept or reject it. All you need to do is put a lower-case <~i~>
"c" at the end of your substitution command, in the same place you <~i~>
would put a "g" to change every instance on each line, like either <~i~>
of these examples: <~i~>
<~i~>
% substitute /^something/something else/c <~i~>
% substitute /something/something else/gc <~i~>
<~i~>
The editor will then display the lines where substitutions are to <~i~>
be made on your screen, one at a time. Each line will have "^" <~i~>
marks below the text to be removed, like this: <~i~>
<~i~>
something in the air. The consensus is that <~i~>
^^^^^^^^^ <~i~>
<~i~>
and if there are two or more places on the line where the <~i~>
substitution could be performed, the line will be displayed on <~i~>
your screen two or more times, with a different potential <~i~>
substitution marked each time. After displaying a line on your <~i~>
screen, the editor will wait for you to type something ending with <~i~>
a carriage return. If whatever you type begins with a lower-case <~i~>
"y", the change will be made. If it begins with anything else, <~i~>
the text will be left as it is. <~i~>
<~i~>
Even this substitution variant may not give you enough control. <~i~>
You may need to see more than one line to verify your judgment, or <~i~>
the text to be put in may vary from one place to another. In <~i~>
those cases, you can use one of the qualities of the :global <~i~>
command. This is a simplified version of the technique our <~i~>
programmer friend Hal (in the first installment of this tutorial) <~i~>
used to work over the problem points that Lint found in the code <~i~>
he was updating. <~i~>
<~i~>
If you are editing in screen mode, as usual, you must start by <~i~>
typing a capital "Q" to go into line mode. From line mode's colon <~i~>
prompt, give a command like the following (if you want to make the <~i~>
same substitution as in our previous examples): <~i~>
<~i~>
global /something/ visual <~i~>
<~i~>
This command will bring you in turn to each line in the file that <~i~>
contains the string "something" and put you in screen-editing mode <~i~>
there. After you've looked around, and made a substitution if you <~i~>
think it justified, typing a capital "Q" takes you out of <~i~>
screen-editing mode and returns you to the global command, which <~i~>
takes you the next marked line and resumes screen editing. <~i~>
<~i~>
There is an indirect hazard in leaving screen editing mode, <~i~>
though. And that brings us to the whole dismal subject of <~i~>
preventing loss of your changes, or of your entire file, while you <~i~>
are in the editor. <~i~>
<~i~>
Don't Lose Your Files <~i~>
<~i~>
The vi/ex editor is not strong on protecting you from the <~i~>
consequences of your own mistakes. In part that's just the <~i~>
natural result of giving you a lot of editing power. But when it <~i~>
comes to losing all the changes you've made in a file during a <~i~>
session, or even losing the original file you started with, the <~i~>
editor could be a lot more responsible without hamstringing your <~i~>
subtle edits. Still, there are ways you can comfortably protect <~i~>
yourself from those hazards, and many of those ways I explain <~i~>
below. <~i~>
<~i~>
IN EMERGENCIES. Consider one of the editor's safety features that <~i~>
can accidentally but quite easily turn into a disaster. You may <~i~>
already know that when you edit with this editor, you are working <~i~>
on a copy of the file, not the original. Your changes do not <~i~>
affect the original unless you use the :write command, for which <~i~>
:w is the shortest abbreviation, or leave the editor in a normal <~i~>
way. That's a good precaution against making a mistake with this <~i~>
powerful editor that mangles your file, and then discovering you <~i~>
have no backup copy. <~i~>
<~i~>
That copy you are working on lives in a volatile place, though, <~i~>
where it can easily be erased when the system crashes or your link <~i~>
into the system goes down. That could cost you all the additions <~i~>
and changes you'd made in that session with the editor. Your <~i~>
first line of defense against this is to run the :write command <~i~>
often--every time you run it, your current edited version replaces <~i~>
the previous version in the stable permanent-storage area on disk. <~i~>
<~i~>
And if you don't intend to change the original? Your edited <~i~>
version is to be a new file, with the original left untouched? <~i~>
Well, you can use a modified form of writing the file, by typing <~i~>
:write nufile where "nufile" is whatever you want the name of the <~i~>
edited file to be. (That can be a path name, in case you don't <~i~>
want to put the new file in your current directory.) This will <~i~>
write the revised version only to the new file (creating the file <~i~>
if necessary), and leave the original file untouched. <~i~>
<~i~>
That method of preserving the original file is dangerous, though. <~i~>
If you forget even once to add the filename to the :write command, <~i~>
your original file is wiped off the disk. That's why this <~i~>
technique is best reserved for occasions where you do want to <~i~>
change the original file, but also want a copy of some partially <~i~>
edited stage of the file saved elsewhere. When you get the file <~i~>
to the state you want to save as a copy, run both of these <~i~>
commands: <~i~>
<~i~>
write nufile <~i~>
write <~i~>
<~i~>
and then go back to editing and writing to the file as usual. <~i~>
<~i~>
The sane way to protect your original file from any changes is to <~i~>
start your editing with a :file nufile command, for which :f <~i~>
nufile is the shortest abbreviation. From that point on, the <~i~>
editor considers "nufile" to be the name of the file you are <~i~>
working on, and writes go automatically to that filename. <~i~>
(Incidentally, if you ever forget whether you have changed the <~i~>
file name, or what you've changed it to, a :file command by <~i~>
itself, without a file name, will tell you what the editor thinks <~i~>
the file's current name is, among other interesting facts.) <~i~>
<~i~>
CRASHES WILL HAPPEN. Still, a crash may catch you by surprise, <~i~>
with a lot of additions and changes that you have not written to <~i~>
any file. To protect against this, the editor always attempts to <~i~>
save your current working copy of the file when a crash is <~i~>
imminent. You can even launch an emergency save yourself when you <~i~>
face a sticky situation, such as being unable to do a normal write <~i~>
because it would exceed your filespace quota. Just type a <~i~>
:preserve command (or its :pre abbreviation) and the working copy <~i~>
is normally preserved. There are a few gotchas to watch for, <~i~>
though. <~i~>
<~i~>
The preservation function puts the saved copy in a specific <~i~>
directory, and it will fail if that directory does not exist or is <~i~>
not writable. (The path name of that directory varies between <~i~>
versions of the editor, although /var/preserve seems to be a <~i~>
common choice on modern Unix systems.) To check writability, run <~i~>
a :preserve command from a short file, as a test. If the result <~i~>
is a message something like this: <~i~>
<~i~>
Can't open /var/preserve <~i~>
Preserve failed! <~i~>
<~i~>
there is a problem you will have to take up with your system <~i~>
administrator. (To speed up that discussion, bring along the path <~i~>
name of the directory that couldn't be opened.) If the message <~i~>
reads like this: <~i~>
<~i~>
File preserved. <~i~>
<~i~>
so far, so good. The next question is whether the editor has <~i~>
preserved an accurate copy or a pile of garbage--some editor <~i~>
implementations are broken in this area. To check this, recover <~i~>
the file you've just preserved. <~i~>
<~i~>
RESCUING SAVED FILES. There are two ways to recover a rescued <~i~>
working copy, whether it was saved in a crash or because you used <~i~>
the :preserve command. Usually you recover it from your shell <~i~>
command line, by entering the editor with a "-r" flag: <~i~>
<~i~>
vi -r novel.chap3 <~i~>
vi -r <~i~>
<~i~>
The first of these commands puts you in the editor, with the <~i~>
latest rescued copy of your file "novel.chap3" before you. The <~i~>
latter command doesn't put you in the editor at all; it displays a <~i~>
list of all files that have been emergency-saved and then returns <~i~>
you to the shell command line. This list is useful when, say, the <~i~>
system crashed while you were editing a file that you hadn't given <~i~>
a name. (Yes, you can enter the editor without giving a filename <~i~>
to edit; the editor will simply bring up an empty buffer and <~i~>
assume you will give it a name later.) In this case the <~i~>
preservation process will give the file a name, and you must know <~i~>
this name to recover it. <~i~>
<~i~>
I said that the first command would bring up the latest rescued <~i~>
copy of the file you named. If the system has been staggering for <~i~>
a while, there may be more than one occasion when either you or <~i~>
the system caused the editor to preserve the working copy of that <~i~>
file. If the latest version is not the best copy, you can discard <~i~>
it and pull up the next most recent version, without leaving the <~i~>
editor. Just give a :recover command (or its :rec abbreviation) to <~i~>
have the current rescued version discarded and replaced by the <~i~>
next-latest of the saved copies. (When you're already in the <~i~>
editor, there's no need to give the name of the file to recover if <~i~>
it is the same as that of the file you're editing at the time. <~i~>
The editor assumes the current filename unless you give another <~i~>
name as an argument following the :recover command.) If this <~i~>
isn't the best copy either, you can continue this process. <~i~>
<~i~>
When you've recovered a file either way, look it over. If the <~i~>
editor version you're using has a broken preservation function, <~i~>
you'll only find garbage characters or a display like this: <~i~>
<~i~>
LOST <~i~>
LOST <~i~>
LOST <~i~>
LOST <~i~>
LOST <~i~>
<~i~>
If that be the case, the file you preserved is hopelessly lost and <~i~>
you'd better have a talk with your system administrator about <~i~>
getting a better version of the editor. But if what you see looks <~i~>
like what you had, then all you have to do is write the copy <~i~>
you've recovered to a file somewhere--the preserved copy was <~i~>
erased when you used one of the recovery commands, so it can't be <~i~>
recovered that way again. <~i~>
<~i~>
And that brings up the last gotcha. You may believe that any of <~i~>
the three commands ZZ or :x or :wq will check whether the working <~i~>
copy needs to be written to the file, write it only if necessary, <~i~>
and then quit the editor. Actually, the last of the three, the <~i~>
:wq command, always writes to the file regardless, and is the only <~i~>
one you should use. <~i~>
<~i~>
The first two attempt some checking, but their checks are not very <~i~>
complete. In particular, they and the :quit command often check <~i~>
for nothing more than the flag that is set when an editing change <~i~>
is made to the current working copy and unset when the working <~i~>
copy is written to the file. You are courting disaster if you <~i~>
ever use the ZZ or :x commands, or if you use :quit carelessly. <~i~>
<~i~>
The gotcha in the case of a recovered file is that pulling a new <~i~>
file into the buffer, whether normally or by recovering an <~i~>
emergency-saved copy, is not an editing change. If your version <~i~>
of the editor has a weak version of ZZ or :x then its casual check <~i~>
will show no reason to write the file, and all your carefully <~i~>
recovered work will be lost for good when the command closes the <~i~>
editor without writing the file. So always use :wq or separate <~i~>
:write and :quit commands to end an editing session. <~i~>
<~i~>
A FEW MORE HAZARDS AND SOLUTIONS. Worse yet can befall you. You <~i~>
may accidentally lose both your own editing changes and the <~i~>
original file you were working from. <~i~>
<~i~>
Suppose one of your global editing commands went astray and <~i~>
trashed your working copy of the file, but didn't happen to affect <~i~>
the part that is on your screen. If you then wrote the working <~i~>
copy to the file, the garbage replaced your original file <~i~>
contents. Oh, misery! And with any but the smallest file, it's <~i~>
not practical to look over the working copy carefully before each <~i~>
:write command. <~i~>
<~i~>
Or perhaps you did discover the disaster before you wrote the <~i~>
working copy to the file. Seeing that undoing the errors was not <~i~>
feasible, you decided either to run an :edit! command to bring up <~i~>
a fresh copy of the original file, or a :quit! to leave the <~i~>
editor. In either case, the "!" at the end of the command tells <~i~>
the editor to ignore the garbage changes that have not been <~i~>
written to the file. <~i~>
<~i~>
But since you were not creating an editor script here, you <~i~>
probably typed the short form of your command, either :e! or :q!. <~i~>
At least you tried to. Perilously placed between the "e" and "q" <~i~>
keys on a standard keyboard is the "w" key. If you accidentally <~i~>
typed :w! instead of what you intended, you told the editor to <~i~>
overwrite the original file with that trashed version, and ignore <~i~>
any anti-write protections you may have set. Oh, misery cubed! <~i~>
<~i~>
You are not lost yet, though, if you have been editing along in <~i~>
screen mode all the while. At any time you can type a short <~i~>
sequence to put the working copy back the way it was when you <~i~>
started this editing session. Then you only need to write the <~i~>
working copy to the file to expunge the trash there. <~i~>
<~i~>
Start by typing Q to leave screen mode and drop back to line mode. <~i~>
Now, line mode has an undo command that works the way the screen <~i~>
mode u command does, but on line mode commands. That is, it <~i~>
reverses the effect of the latest line mode command that changed <~i~>
(or may have changed) the working copy. One line mode command <~i~>
that may well change the working copy is visual, of course. And -- <~i~>
surprise -- when you typed vi novel.chap3 from your shell prompt <~i~>
to enter the editor, your shell actually launched ex (for which vi <~i~>
is just an alias) and the editor gave itself an initial visual <~i~>
command to boost you into screen mode. <~i~>
<~i~>
So all the time you've been editing, the editor has been holding a <~i~>
complete copy of the original file, in case you go back to line <~i~>
mode and want to reverse the effect of that initial visual <~i~>
command. (That's one reason the editor's buffer takes up so much <~i~>
more room than you'd expect in swap space.) If you want to see <~i~>
the complete command sequence to restore the original working copy <~i~>
and return to visual mode, using shortest abbreviations and <~i~>
showing carriage returns as new lines, here it is: <~i~>
<~i~>
Qu <~i~>
w <~i~>
vi <~i~>
<~i~>
One last hazard, which may seem childish to experienced Unix users <~i~>
but trips up many a refugee from single user systems. Unless <~i~>
you're on one of those rare Unix implementations that offers file <~i~>
locking, there is little to prevent another user on the system <~i~>
from editing the same file at the same time as you do. <~i~>
<~i~>
You will each be editing on a separate working copy, so there will <~i~>
be nothing to tell you that someone else is also editing the same <~i~>
file. But each time you write your changed version to the file, <~i~>
you will wipe out whatever changes the other user has already <~i~>
written to file, and vice versa. The ultimate victor in this <~i~>
unknowing war will be the user who finishes editing last. The <~i~>
other user can come back an hour later and find no indication that <~i~>
he/she ever touched the file. <~i~>
<~i~>
There's no real technical solution to this danger. You'll just <~i~>
have to coordinate carefully with other users on files that more <~i~>
than one of you may have occasion to edit. <~i~>
<~i~>
Reader Feedback <~i~>
<~i~>
One of our readers raised a significant point about this <~i~>
technique; important enough to deserve a reply published in this <~i~>
article. <~i~>
<~i~>
Dear Walter... <~i~>
<~i~>
In your tutorial you write that you can use the command <~i~>
<~i~>
global/XXX/visual <~i~>
<~i~>
to search for the pattern "XXX" and edit/move around (remember, <~i~>
Hal needed this command to edit the linted spaghetti-code...) <~i~>
<~i~>
But there's one problem: suppose I found, after the 10th XXX of <~i~>
100, that I do not want to view the remaining 90 occurences. It <~i~>
works as long as I don't type 'Q'. But now I want to view/edit <~i~>
the code where my lint report is something like "illegal", I have <~i~>
to type Q and then global/illegal/visual. <~i~>
<~i~>
And now there's the problem: typing Q doesn't prompt for a new <~i~>
input, it moves to the 11th occurence of "XXX". <~i~>
<~i~>
Do you know my problem? Is there a way to stop vi moving on with <~i~>
the global command after typing Q? <~i~>
<~i~>
Thanks a lot in advance! <~i~>
<~i~>
Chris... <~i~>
<~i~>
As Chris clearly realizes, ordinarily there is no problem with <~i~>
omitting the remaining 90 stops. Each time this command puts you <~i~>
into visual mode somewhere in the file, you are not restricted to <~i~>
fixing one limited problem. You may move anywhere in the file, <~i~>
edit whatever you like, and keep doing this as long as you please. <~i~>
When you finally finish all the edits you've decided to do, you <~i~>
can write the file and quit the editor in your usual way--the <~i~>
suspended global command will silently disappear at this point. <~i~>
<~i~>
But going into a second string of visual mode stops from a new <~i~>
global command, as Chris wants to do, requires finesse. <~i~>
Obviously, it's not possible to use the Q command to return to the <~i~>
line-mode command prompt until every one of those 100 lines has <~i~>
been visited and the first global has terminated. <~i~>
<~i~>
The best way out of this predicament starts with writing your <~i~>
changes to the file. Then, instead of typing Q type an :edit <~i~>
command. This brings up a fresh copy of the file you are editing, <~i~>
but since you've just done a write, the fresh copy is identical to <~i~>
the one you've been working on. Because you haven't left the <~i~>
editor, most of the state is saved--contents of the named buffers, <~i~>
any maps and/or abbreviations, values of the set command options. <~i~>
You do wipe out a few small items like the contents of the unnamed <~i~>
buffer--and, of course, that suspended global command. <~i~>
<~i~>
Now you can use the Q command to go into line mode, then run that <~i~>
second global command. <~i~>
<~i~>
In The Next Installment <~i~>
<~i~>
In this tutorial to date, you've undoubtedly seen some aspects of <~i~>
the editor that you wish had been designed differently. The good <~i~>
news is that many of these features are yours to change at <~i~>
will--without hacking up the source code and recompiling. <~i~>
<~i~>
In Part 5 of this tutorial, I'll elucidate the editor's built-in <~i~>
facilities for setting up your own editing environment, and the <~i~>
many factors you can modify this way. <~i~>
Making Changes Within Lines <~i~>
A Few More Metacharacters <~i~>
Replacement-Pattern Metacharacters <~i~>
Other Uses for Substitution <~i~>
A Start on Script Writing <~i~>
Don't Lose Your Files <~i~>
Reader Feedback <~i~>
Part 5: Take Control of Your Editing Environment/
The vi/ex Editor, Part 5: Take Control of Your Editing Environment <~i~>
The set Command <~i~>
set Command Variables that Control How to Paint the Screen <~i~>
Playing "tag" <~i~>
Making Your Environment Setup Automatic <~i~>
The Next Installment <~i~>
Besides all the power in the Vi/Ex editor, there's a lot of <~i~>
flexibility in it, too. You've already met some of this <~i~>
adaptability when I pointed out various ways to perform many <~i~>
editing functions. Now it's time to meet phase two of editor <~i~>
flexibility -- the myriad ways to modify the editor's internal <~i~>
operations. <~i~>
There's no "setup mode" for changing these parameters. Instead, <~i~>
all the changes are made with line-mode commands, which can be <~i~>
interspersed with ordinary editing commands. That is, you give <~i~>
the commands from the prompt, as usual, if you are editing in line <~i~>
mode. When you are editing in visual (or screen) mode, precede <~i~>
these environment-modifying commands with a colon, as you would <~i~>
with any other line-mode commands you specify in visual mode. <~i~>
These modifications take effect as soon as you give the commands. <~i~>
They stay in effect as long as you run the editor program. You <~i~>
can switch from editing one file to another -- as with any of the <~i~>
edit, next, rewind commands -- without affecting the editing <~i~>
environment you've set up. And, you can revoke or further modify <~i~>
any environmental changes you've made at any time, by using the <~i~>
same commands or variant forms of them. <~i~>
Your environment setup does go away when you quit the editor <~i~>
altogether. The next time you invoke the editor you'll find that <~i~>
all the environment parameters have returned to their default <~i~>
values. (This can be a blessing in disguise, because there is no <~i~>
direct way to tell the editor to restore all parameters to default <~i~>
settings.) <~i~>
When you've found a combination of settings you'd like to use <~i~>
again, there are ways to have these settings established <~i~>
automatically (or semi-automatically) whenever you invoke the <~i~>
editor. You can even have several of these preset environments -- <~i~>
which one is used will depend on the circumstances in which you <~i~>
invoke the editor. I'll explain how to automate the settings at <~i~>
the end of this tutorial. <~i~>
The set Command <~i~>
Most of your setup will be accomplished by a single command that <~i~>
controls around fifty editor variables that affect the editing <~i~>
environment. The set command, for which se is the shortest <~i~>
abbreviation, sets variables having three different types of <~i~>
values: string, numeric, and boolean. Consider the examples here: <~i~>
set report=7 <~i~>
set term=vt100 <~i~>
set terse <~i~>
set nomagic <~i~>
Because the first two examples are assignments, they must specify <~i~>
either string or numeric values. The first is numeric; here, <~i~>
report=7 tells the editor to give you a report (warning message) <~i~>
whenever a command changes seven or more lines -- the default is <~i~>
five or more lines. <~i~>
The second example assigns a string value; the numerals in it are <~i~>
regarded as merely characters by the editor. The term=vt100 <~i~>
directive tells the editor to address your terminal as though it <~i~>
were a DEC model VT100. (You specify one of the listed short <~i~>
names for the terminal -- obtained from the Termcap or Terminfo <~i~>
terminal-description systems -- as its string value.) The default <~i~>
for this variable is to use the terminal type from your log-in <~i~>
shell environment (the value assigned to your TERM variable), if <~i~>
available -- and if not available, then address your terminal as <~i~>
though it were a "dumb" terminal. <~i~>
The last two examples (without equal signs) illustrate boolean <~i~>
variables, which can be either on (enabled) or off (disabled). You <~i~>
turn a boolean variable on just by giving its name after the set <~i~>
command. The first of these two boolean examples tells the editor <~i~>
to make any error messages very brief: cryptic to inexperienced <~i~>
users, but convenient for people who are quite familiar with the <~i~>
editor. The default for this variable is "off" or "disabled", <~i~>
which provides longer, more explanatory error messages. <~i~>
To turn a boolean variable off, just give its name prefixed by the <~i~>
string "no" without any intervening space characters. The last of <~i~>
these examples turns off the special ("magic") interpretation of <~i~>
several metacharacters, as discussed in an earlier part of this <~i~>
tutorial dealing with search patterns. The usual default for this <~i~>
variable's value is "magic", which means all metacharacters have <~i~>
their special interpretation -- but if you invoke the editor by <~i~>
the name edit or vedit, then "nomagic" is the default value (no <~i~>
special interpretation of these particular metacharacters). <~i~>
There's no need to use several distinct set commands when you want <~i~>
to change a number of these variables. A single command can have <~i~>
almost any number of arguments. So all four of the example <~i~>
commands above could be replaced by this single command: <~i~>
set report=7 term=vt100 terse nomagic <~i~>
Variant forms of this command will tell you the present status of <~i~>
individual variables, all that have been changed, or all the <~i~>
variables. For instance, type "set" without any arguments to tell <~i~>
the editor to display a list of all the variables that have been <~i~>
changed from their default values, along with their current <~i~>
values. <~i~>
Type "set all" to display all the variables and their values, <~i~>
whether changed from default or not. This is a good way to check <~i~>
which variables your version of the editor recognizes, and what <~i~>
their default values actually are -- some proprietary versions of <~i~>
the editor have played with both these factors. <~i~>
If you want to check the values of only one or a few variables, <~i~>
you don't have to scan through a long list -- you can run a set <~i~>
command that will report the settings of only the variables you <~i~>
specify. For a boolean variable, just give the name of the <~i~>
variable, immediately followed by a question mark, as an argument <~i~>
to the command. For a string- or numeric-valued variable, you <~i~>
only need to specify the name itself, without the equal sign. <~i~>
Thus, typing: <~i~>
set report magic? <~i~>
will produce a response like this: <~i~>
report=7 nomagic <~i~>
If the details of checking individual variables seem too arcane to <~i~>
remember, the editor will cut you some slack: You may specify the <~i~>
name of a boolean variable in its "no" form, and you may give a <~i~>
non-boolean variable with an unneeded question mark at the end of <~i~>
it, and your query will still work. So typing: <~i~>
set report? nomagic? <~i~>
will produce the same result as the previous query did. <~i~>
You can even mix option settings with inquiries in the same set <~i~>
command, in any order. For example, if you want to turn on number <~i~>
and set report to warn you whenever even three lines are changed, <~i~>
and also want to know what terminal type the editor thinks you are <~i~>
using and whether terse is on or off, any one of the following <~i~>
command lines will take care of it all: <~i~>
set number report=3 term terse? <~i~>
set term terse? number report=3 <~i~>
set term number terse? report=3 <~i~>
Below, I've listed some important editor variables that modify the <~i~>
visual display, with an explanation of each. If two names are <~i~>
specified, the first is the full name and the other is the <~i~>
shortest recognized abbreviation. The full name will appear in <~i~>
the lists displayed when you type "set" by itself or type "set <~i~>
all". <~i~>
set Command Variables that Control How to Paint the Screen <~i~>
number nu <~i~>
You already know that the editor assigns a number to every line in <~i~>
your file, and changes line numbers every time you add or delete <~i~>
lines, in order to keep the numbers consecutive. The number <~i~>
boolean variable tells the editor to display those line numbers <~i~>
next to every file line that appears on the screen, in both screen <~i~>
and line-editing modes. You just have to turn it on; it's off by <~i~>
default. If you have a window that looks like this: <~i~>
COLOR CODING FOR POWER WIRES <~i~>
green ground <~i~>
white neutral <~i~>
black hot <~i~>
red hot <~i~>
turning on this variable will make it look something like this: <~i~>
158 COLOR CODING FOR POWER WIRES <~i~>
159 green ground <~i~>
160 white neutral <~i~>
161 black hot <~i~>
162 red hot <~i~>
The displayed numbers do not become part of the file, and nothing <~i~>
you can do, deliberate or accidental, will cause your editing to <~i~>
interact with the line numbers. <~i~>
list <~i~>
Turning on this off-by-default variable makes two changes in the <~i~>
way file lines are displayed on the screen, whether in line- or <~i~>
screen-editing mode: <~i~>
The end of each line is marked by a dollar sign. (This applies to <~i~>
actual line ends, not to places where the editor wraps a long line <~i~>
so it can all be displayed on the screen.) <~i~>
Every tab character is replaced by a circumflex-capital-I ("^I") <~i~>
character sequence. (This means that columns that were kept in <~i~>
alignment by preceding tabs will not be displayed aligned with <~i~>
this variable enabled.) <~i~>
Taking the same sample screen as in the previous example, when the <~i~>
list variable is on, the screen would look like this: <~i~>
COLOR CODING FOR POWER WIRES$ <~i~>
green^Iground$ <~i~>
white^Ineutral$ <~i~>
black^Ihot$ <~i~>
red^Ihot$ <~i~>
This variable affects display only, the contents of the file are <~i~>
not changed in any way. The list and number variables are <~i~>
compatible. Enabling them both would produce a display like this: <~i~>
158 COLOR CODING FOR POWER WIRES$ <~i~>
159 green^Iground$ <~i~>
160 white^Ineutral$ <~i~>
161 black^Ihot$ <~i~>
162 red^Ihot$ <~i~>
window= <~i~>
The numeric value of this variable tells the editor how many <~i~>
screen lines should be in the editing window (in screen-editing <~i~>
mode). The default is one less than the size of your screen or <~i~>
window. This variable's value cannot be changed while you are in <~i~>
screen-editing mode. <~i~>
scroll <~i~>
A numeric variable that sets the number of lines to be scrolled <~i~>
down by a control-D or up by a control-U command. The z command <~i~>
uses twice this count as the number of lines to display. Default <~i~>
value is half the size of the screen or window. <~i~>
You can give a count prior to one of those scrolling commands, <~i~>
which will override the value of the scroll variable. For <~i~>
example, typing "3control-D" will scroll forward just three lines. <~i~>
Caution: The editor will remember any count you give, and use <~i~>
that count -- instead of the value assigned to scroll -- with any <~i~>
future command you give without specifying a new count. Because <~i~>
the value of the scroll variable remains unchanged, even though it <~i~>
is no longer being used, the set command has no way to undo this <~i~>
new behavior. The only way to go back to using the value set for <~i~>
scroll is to look up that value -- type "set scroll" -- then use <~i~>
this value as a count preceding another of the commands that <~i~>
normally use the scroll variable. <~i~>
Playing " tag" <~i~>
If your editing work requires jumping from place to place in <~i~>
numerous files, it would be convenient to index the places you <~i~>
visit most. The editor has a system for handling this. It's <~i~>
pretty simple, too; you set up one or more reference lists, then <~i~>
you can go to the place within the file that you want just by <~i~>
typing a few characters. <~i~>
Caution: the "tags" system described below does not simply switch <~i~>
focus briefly to another file. It ends your editing of the <~i~>
current file, then loads the new file into the editor with the <~i~>
standard context changes, just as if you had given an edit <~i~>
command. As a consequence of this, the editor will normally <~i~>
refuse to execute a tag command when the file you are presently <~i~>
editing has changes which you have not yet written to permanent <~i~>
storage. If you choose to override this protection, give the <~i~>
command as tag! or ta!. <~i~>
To use this system, you need to set up at least one "tags" file <~i~>
containing references to your file destinations. If programming <~i~>
is your work and you use C, C++, Pascal, FORTRAN, lex or yacc, the <~i~>
Unix <a href="/unixworld/man/ctags.1">ctags utility can set up a <~i~>
suitable "tags" file for you. If not, it isn't all that difficult <~i~>
to build such a file yourself. <~i~>
Each line in a "tags" file is a complete reference to a place you <~i~>
might want to go. The line has five parts, which (reading from <~i~>
left to right) are: <~i~>
The short name you will use to refer to the particular file and <~i~>
the place in it. Don't start choosing names, though, until you've <~i~>
read the third way to invoke a tag, below. <~i~>
One tab character, as a separator. A space character will not do <~i~>
here. <~i~>
The name of the destination file. This can be a simple name, if <~i~>
the file is in your current directory, or a path name, if not. <~i~>
Another tab character. Again, a space character won't do. <~i~>
A line-mode search command that will find the place you want <~i~>
within the file. As you may have cleverly deduced, you can string <~i~>
multiple commands together here with the vertical-bar ("|") <~i~>
character, and can use editing commands if you want the file <~i~>
pre-edited. Spaces and even tabs may appear in this string if <~i~>
needed; only the first two tabs in a line are interpreted as field <~i~>
separators. <~i~>
If this file structure sounds a little complex, look at this short <~i~>
example of a "tags" file to see how things actually work out: <~i~>
difid ../math/calc /^APPENDIX/;/^C. Differen <~i~>
integ ../math/calc /^APPENDIX/;/^D. Integrals <~i~>
log /adm/err-log 1;?Err-7$ <~i~>
rvlog /adm/err-log g/^/m0|0;/Err-7$ <~i~>
vocab % /^GLOSSARY <~i~>
words % /^GLOSSARY <~i~>
The first line in the example above provides that using "difid" as <~i~>
a tag will take the user to edit a file named "calc", in a <~i~>
directory with relative path name "../math". (Note: that using <~i~>
this tag will not change the current directory of the user's <~i~>
shell; only the file being edited is changed.) Once that file has <~i~>
been loaded, the editor will seek out the first line that starts <~i~>
with "APPENDIX", and go from there to the next line that begins <~i~>
with "C. Differen". <~i~>
Yes, you can specify different tags to enter the same file at <~i~>
different points. My second example line contains a tag that <~i~>
leads to a different place in the same file. After the editor has <~i~>
searched out the first line beginning "APPENDIX", as before, it <~i~>
goes on to a different section of the appendix. <~i~>
You can even use multiple tags to enter the file at the same <~i~>
point, but with different preliminary editing. My "log" and <~i~>
"rvlog" tags go to the same file and the same line -- the most <~i~>
recently appended line that ends with "Err-7". The difference is <~i~>
that the "rvlog" tag first reverses the order of lines in the <~i~>
file. (Note that the search command for the two tags is <~i~>
different, because in the second case the line being sought has <~i~>
been moved to a different position in the file.) <~i~>
And you can use a tag to move to a place in the file you are <~i~>
already editing. In the last two example lines I have used the <~i~>
percent sign (%) to indicate "current file"; the pound-sign (#) <~i~>
for "alternate file" is also acceptable. These tags move the user <~i~>
to the glossary section of the document currently being edited, <~i~>
whatever that document may be. If I were to invoke a tag with an <~i~>
actual file name in it, and that file happened to be the file I <~i~>
was presently editing, the effect would be the same. <~i~>
Finally, you undoubtedly saw that the last two entries in my tags <~i~>
file are identical except for the tag names. Either tag will take <~i~>
you to the same place in the same file with no preliminary <~i~>
editing. This is legitimate, and often useful. You may be <~i~>
building a tag file for multiple users -- some of these users are <~i~>
accustomed to a certain tag name for a given file and location, <~i~>
some to another tag name. The tags system allows you to <~i~>
accommodate both groups. <~i~>
You may have noticed that the lines in my example file are <~i~>
arranged in ASCII-sort order. This is necessary to keep the <~i~>
tag-search mechanism from missing the tag you specify. If you <~i~>
don't trust your own ability to sort the lines, the Unix sort <~i~>
utility can do it for you. <~i~>
When you've built your "tags" file, you need a place to put it. <~i~>
Ordinarily, when you invoke a tag name, the editor first tries to <~i~>
look it up in a file named "tags" in your current directory. If it <~i~>
fails to find such a file, it then looks for /usr/lib/tags . But <~i~>
you can override these defaults by setting a different value for <~i~>
the "tags" file in your editing environment. For instance, if you <~i~>
include this command in your setup file: <~i~>
set tags=moretags <~i~>
then tag searches will take place in a file named "moretags" in <~i~>
your current directory. <~i~>
With everything set up, you only need to know how to invoke a tag <~i~>
as needed. There are three or four ways to do it, all enumerated <~i~>
below: <~i~>
When you invoke the editor from your shell's command line you can <~i~>
use the "-t" command-line option flag to specify a tagged item <~i~>
instead of naming a file to edit. For example, typing the line <~i~>
(from your shell prompt): <~i~>
vi -t chap3 <~i~>
tells the editor to look up the "chap3" tag to find the <~i~>
destination file and location in that file. Oddly enough, you can <~i~>
list some file names to edit as well as a tag (with "-t") on the <~i~>
editor-invocation command line. The rule is that the first string <~i~>
of non-whitespace characters immediately following the "-t" flag <~i~>
is regarded by the editor as a tag name; any other such strings <~i~>
that don't begin with a "-" character are taken as actual names of <~i~>
files. However, the tagged and the named files aren't remembered <~i~>
the same way in this case. <~i~>
For instance, if you specify a tag, then two file names, the <~i~>
editor will initially place you in the tagged file and when you <~i~>
type :next you will move to the first named file, and another :n <~i~>
(the shortest abbreviation) takes you to the second named file. <~i~>
But, the tagged file does not appear on the argument list -- <~i~>
viewed with the args command -- so when you enter a :rewind <~i~>
command you return to the first named file, not the tagged file, <~i~>
even though it was specified first on the command line. <~i~>
While you are editing a file, you can invoke a tag with the <~i~>
line-mode command tag (shortest abbreviation, ta) followed by a <~i~>
space and the tag name. This command can be given from screen <~i~>
mode as :tag, of course. <~i~>
While you are in screen mode, you can put the cursor on either the <~i~>
first letter of a word or the space immediately preceding it and <~i~>
then type a "control-]" character. This has the same effect as if <~i~>
you'd typed the word the cursor is at as the argument to a :tag <~i~>
command. <~i~>
Caution: A "control-]" is the default Telnet "escape" character. <~i~>
So if you are editing on a remote system during a Telnet session <~i~>
and enter a "control-]", control will return to Telnet, which will <~i~>
interpret what you type next as a Telnet command. You could <~i~>
change the Telnet escape character when you start your remote <~i~>
terminal session in order to use "control-]" with the editor. <~i~>
Some newer versions of the editor maintain a stack of tags. If <~i~>
so, you can repeat the last :tag command you gave in screen mode <~i~>
by typing "control-T". This can take a count, so that typing a "2" <~i~>
and then a "control-T" repeats the :tag command preceding the last <~i~>
one you gave, etcetera. <~i~>
Making Your Environment Setup Automatic <~i~>
When you've worked out an editing environment setup that you will <~i~>
want to use frequently, or even occasionally, there is no need to <~i~>
type in all the changes from default every time you start up the <~i~>
editor. Because these are all line-mode editor commands, there are <~i~>
several ways to define them automatically, all or some of the <~i~>
time. <~i~>
If there is an editor start-up file (which must be named .exrc) in <~i~>
your home directory (the dot at the start of the name is essential <~i~>
and the "rc" abbreviation means "run command"), the editor will <~i~>
interpret it every time you invoke the editor and execute (or at <~i~>
least attempt to execute) the lines in the file as line-mode <~i~>
commands before it turns editing control over to you. This <~i~>
applies to environment-setting commands as well as others, so <~i~>
placing your set-up commands somewhere in this file will cause the <~i~>
setup to happen every time you invoke the editor. <~i~>
There are drawbacks to this approach, though. You can only have <~i~>
one environment preset this way: the editor will use that same <~i~>
environment every time you invoke the editor. One way to provide <~i~>
more flexibility is to maintain several files with various setups <~i~>
in them, and before you enter the editor, rename the appropriate <~i~>
one of those start-up files to .exrc and when you leave the <~i~>
editor, restore its original name. But you shouldn't have to deal <~i~>
with anything this cumbersome just to control your editing <~i~>
environment. <~i~>
The creators of the editor have provided a much better solution. <~i~>
Before the editor looks in your home directory for a start-up <~i~>
file, it first looks in the directory from which you invoked the <~i~>
editor. If it finds a file named .exrc there, it interprets that <~i~>
as the start-up file instead of the .exrc file in your home <~i~>
directory. <~i~>
That behavior lets you have a special setup for each directory in <~i~>
which you might want to do some editing. For instance, let's say <~i~>
you have a directory of shell scripts, another containing chapters <~i~>
from a book you're writing, still another you use for writing <~i~>
e-mail, plus one where you store and edit error logs -- you can <~i~>
have a separate editing environment for each of these purposes. <~i~>
And if you invoke the editor from a directory where you don't <~i~>
maintain a separate start-up file, the one in your home directory <~i~>
will be used. Just remember to change to the directory where the <~i~>
target file(s) are located before invoking the editor. <~i~>
Caution: If you invoke the editor from a directory different from <~i~>
the one containing the file you're editing, the editor will <~i~>
interpret the start-up file from your start-up directory, and not <~i~>
use the intended environment (defined by the .exrc file in the <~i~>
directory where the target file resides). <~i~>
One caveat about multiple .exrc files, though. In Unix System V <~i~>
and its successors, a security feature restricts the editor's <~i~>
access to .exrc files that are not in your home directory. The <~i~>
editor will not interpret a .exrc file that's not in your home <~i~>
directory, unless you also have a .exrc file that does live in <~i~>
your home directory, and that file contains a line that sets the <~i~>
exrc boolean variable. <~i~>
The security hazard that this complex proviso guards against is a <~i~>
real one. Let's say you need to edit several files that are in a <~i~>
directory like /tmp, /var/tmp or some other directory that is <~i~>
writable by all users. To save the trouble of providing a full <~i~>
path name every time you want want to switch from one file to <~i~>
another, you could easily change directories (that is, "cd" to the <~i~>
directory where these files are located). But when you want to <~i~>
start editing a file, the Vi/Ex editor may find a Trojan horse <~i~>
file named .exrc placed in your current directory by a cracker to <~i~>
await victims. Of course, the commands in this false editor <~i~>
start-up file will be run with your account ownership. These <~i~>
commands aren't limited to editor set-up commands, but may be any <~i~>
shell command that you're allowed to run, including ones to wipe <~i~>
out your files, reset file permissions to allow public access to <~i~>
confidential data, send indelicate comments to your boss using <~i~>
utilities like write combined with banner, and so forth. <~i~>
Now, perhaps you work on files that have different kinds of <~i~>
material in different sections, and you want to be able to make a <~i~>
complete change of editing environment whenever you move from one <~i~>
section to another. In this case, use the source command, with so <~i~>
as its shortest abbreviation. <~i~>
The source line-mode command can be given at any time, although <~i~>
you may have to give it from line-editing mode, not from screen <~i~>
mode with a preceding colon. It takes one argument, a file name <~i~>
or path name, and its function is to read the named set-up file <~i~>
and attempt to execute the lines in it as a series of line-mode <~i~>
commands. <~i~>
Whether or not you can specify this command successfully in screen <~i~>
mode depends on the editor version you are using. Some early <~i~>
versions were quite serious about prohibiting multiple-line <~i~>
line-mode commands while in screen mode. So serious that these <~i~>
versions will execute only the first line of a script that has <~i~>
been sourced in while the user is in screen mode. If you don't <~i~>
encounter this behavior, you can ignore this warning. If you do, <~i~>
you at least know where the problem lies. <~i~>
Now that you understand editor start-up files, I can acknowledge <~i~>
that the one you put in you home directory is not strictly <~i~>
necessary. The editor will accept the value of a shell environment <~i~>
variable named EXINIT as the string of line-mode commands to be <~i~>
run whenever the editor starts up. But I don't recommend going <~i~>
this route, for several reasons: <~i~>
Usually the shell has a strict limit on the number of characters <~i~>
for the value of an environment variable, whereas the size of a <~i~>
.exrc file is practically unlimited. As you get better at using <~i~>
the editor, you can easily develop a home-directory start-up file <~i~>
that is too large for EXINIT. <~i~>
A start-up file can be changed by simple editing, but you have to <~i~>
redefine the EXINIT variable from scratch. <~i~>
A change in your start-up file takes effect the next time you <~i~>
invoke the editor, whereas if your EXINIT variable is defined in a <~i~>
shell start-up file, it's new definition won't take effect until <~i~>
you log-in again or explicitly "source" the shell start-up file <~i~>
from the shell's command line. <~i~>
When you want to restore the editor's environment variables to <~i~>
their beginning state, you can simply source in the editor <~i~>
start-up file. There's no way to do this with the EXINIT shell <~i~>
variable. <~i~>
You can use source to execute an editor set-up file from anywhere <~i~>
in your file space. It will also execute any file of line-mode <~i~>
commands, no matter what the file name. For example, let's say <~i~>
you have a special environment setup that you never use at the <~i~>
beginning of an editing job, but you do need it to edit tables. <~i~>
You invoke the editor as always, but when you're ready to edit <~i~>
your tables, you run a command like: <~i~>
:so table-defs <~i~>
where the table-defs file contains line-mode commands that set up <~i~>
the editor for table editing. <~i~>
When you specify a file of line-mode editing commands with source <~i~>
to perform, say, a frequently used edit automatically, it's <~i~>
probably a good idea to have commands in that file to return the <~i~>
editing environment to what it was before the editing commands <~i~>
were run, assuming the environment was changed for the editing <~i~>
task. <~i~>
Caution: If you decide to use environment set-up files that you <~i~>
specify while you are editing -- you can't always depend on <~i~>
default values. For example, the autoindent variable is disabled <~i~>
("off") by default. So if you are setting up a start-up file that <~i~>
will only be used at the beginning of editor sessions, and you <~i~>
don't want to use autoindenting, you don't need to do anything to <~i~>
leave it turned off. But if you plan to occasionally use that <~i~>
set-up file in the middle of a session, you have to ask yourself, <~i~>
"Will I ever use this setup in a case where I previously had <~i~>
autoindenting turned on, either by another set-up file or because <~i~>
I manually turned it on?" If the answer that question is "Yes", <~i~>
then the set-up file you're writing must contain a set noai <~i~>
command to be sure that autoindentation is definitely disabled. <~i~>
And, what if the source command is broken in your version of the <~i~>
editor? There is still a way to make semiautomatic environment <~i~>
changes. You have to use the line-mode read command plus a <~i~>
little-known feature of letter-named storage buffers. <~i~>
You're probably accustomed to using the "a" through "z" named <~i~>
buffers for storing pieces of text, and returning these pieces to <~i~>
the main document with commands like "jp, which returns the <~i~>
contents of the "j" buffer right after the cursor position in <~i~>
visual mode. Well, you can also use a visual-mode command of the <~i~>
form @j, which takes the text from the "j" buffer and executes it <~i~>
as a visual-mode command string. For instance, if buffer "j" <~i~>
contains "257G3dd" as its text, then typing @j will move the <~i~>
cursor to line 257 and delete that line and the two that follow <~i~>
it. <~i~>
The text in the buffer must be commands you could give from visual <~i~>
mode for this feature to work, but that includes line-mode <~i~>
commands that are preceded by a colon and terminated with a <~i~>
carriage-return character. So if buffer "h" contains the lines: <~i~>
:se nomesg terse list <~i~>
:map v :!wc -w %^M <~i~>
1G <~i~>
then typing "@h" will reset three variables, map a command string, <~i~>
and move the cursor to the first line in the file. <~i~>
There are a few points you should keep well in mind when you are <~i~>
placing line-mode commands into a letter-named buffer for future <~i~>
execution. All of them revolve around the fact that the editor is <~i~>
expecting screen-mode commands from this source. <~i~>
A line-mode command must begin with a colon character. <~i~>
A line-mode command may begin at the start of a line of text or in <~i~>
the middle of it, but it must end at the end of the line. At <~i~>
execution time, the newline character at the end of the text line <~i~>
is what tells the editor that this particular command is ended and <~i~>
a new command (either line- or screen-mode) will follow. <~i~>
Never put a line break in buffer text you will execute as a <~i~>
command string unless a carriage return is part of the command <~i~>
string at that point. <~i~>
To import this set-up command list from an outside file to the "h" <~i~>
buffer, use the read command. For example, if your three-line <~i~>
set-up file is named set.5, then type: <~i~>
:r set.5 <~i~>
"h3dd@h <~i~>
to read the file into your editing buffer, then the "h3dd@h <~i~>
command will delete those three lines -- which came from the <~i~>
external file -- into the "h" named buffer, then execute the same <~i~>
lines as set-up commands. <~i~>
The Next Installment <~i~>
You asked for it, and it's here! Most of the e-mail I receive <~i~>
about this tutorial asks me how to do some specific kind of <~i~>
editing with Vi. The most popular request so far has been for <~i~>
techniques to edit material in columns, and that's what I explain <~i~>
in the next installment. Then it's on to the treacherous, albeit <~i~>
important, topic of addresses for screen-mode commands. <~i~>
The 'set' Command <~i~>
'set' Command Variables that Control How to Paint the Screen <~i~>
Playing 'tag' <~i~>
Making Your Environment Setup Automatic <~i~>
Part 6: Addresses and Columns/
The vi/ex Editor, Part 6: Addresses and Columns <~i~>
Screen-Mode Addresses <~i~>
A Few Address Principles <~i~>
Useful Addresses <~i~>
Editing in Columns <~i~>
Single-Character Columns <~i~>
Multi-Character Columns <~i~>
Next Installment <~i~>
By popular demand I'm trying something new in the tutorial, <~i~>
starting with this installment. The e-mail I receive from <~i~>
tutorial readers most often asks me how to do some specific type <~i~>
of editing job, using whatever editor tools are needed. So, I'm <~i~>
now mixing my general-principle explanations with in-depth <~i~>
coverage of particular work areas. <~i~>
The first application area I'm covering is the one readers ask <~i~>
about most often, by far: editing files where columns are a major <~i~>
factor. Future areas are up to you readers. If you have an <~i~>
application area you'd like to see explained in some depth, <~i~>
e-mail me your suggestion. <~i~>
Screen-Mode Addresses <~i~>
You use them all the time. They're the address targets that tell <~i~>
screen-mode commands like c d y which stretch of your file to act <~i~>
on. And even more often you use such addresses without commands, <~i~>
to move around in the file. <~i~>
For starters, I'll tell you some basics of screen-mode addressing <~i~>
that aren't particularly clear to most editor users. Then it's <~i~>
on to a few powerful but obscure addresses that most of us rarely <~i~>
or never use. <~i~>
A FEW ADDRESS PRINCIPLES <~i~>
The first fact of screen-mode range addresses is simple enough: <~i~>
one end of the range to be affected by the command is always <~i~>
marked by the cursor itself. The address you give the command <~i~>
(always a single address) indicates where the other end of the <~i~>
affected range is to be. The address target can be either forward <~i~>
or backward from the cursor position, in most cases. But exactly <~i~>
how the cursor and the target terminate the two ends of the range <~i~>
is variable. <~i~>
At the start we have to distinguish between line addresses and <~i~>
character addresses. Line addresses are very straightforward: <~i~>
the command affects the entire line the cursor is on, the entire <~i~>
line where the address point is located, and all the lines in <~i~>
between. If you are using an address without a command, in order <~i~>
to move the cursor, a line address generally puts the cursor on <~i~>
the first non-whitespace character in the line addressed. <~i~>
But line versus character addresses affect a lot more than <~i~>
exactly what's included in the range. As one example, if you <~i~>
yank or delete text using a line address and then place that text <~i~>
somewhere with a p or P command, that text will appear on a new <~i~>
line or lines, above or below the line you are on, respectively. <~i~>
But if you yanked or deleted with a character address, when you <~i~>
put the text back in, it will appear within the line you are on, <~i~>
just just ahead of or behind the cursor. And to dispose of one <~i~>
editor fallacy here and now, it does not make a bit of difference <~i~>
that the range of text you yanked or deleted with a character <~i~>
address amounts to exactly one or more lines -- it will still <~i~>
behave as any other text yanked or deleted with a character <~i~>
address. <~i~>
So which addresses are line addresses? That depends on what your <~i~>
command is. <~i~>
Besides the three commands I cited as examples above, there are <~i~>
four other, less-used commands -- ! < > = -- that also take <~i~>
addresses. The only thing you have to know right now about these <~i~>
four commands is that they can act only on entire lines; that's <~i~>
inherent in what they do. So with these four commands, every <~i~>
address is a line address. (Except a handful of addresses, such <~i~>
as "f", that cannot be used with these commands at all.) <~i~>
With the three more-used commands c d y or with an address used <~i~>
by itself to move the cursor, an individual address is either <~i~>
always a line address or always a character address -- usually. <~i~>
There are exceptions to this rule also, such as the address <~i~>
"j", which is a character address when you are just moving the <~i~>
cursor, but a line address to any command. <~i~>
So just where does a character address take you? When you are <~i~>
just moving around in the file, the cursor lands on the character <~i~>
that is the target you sought. Or if the target was a string of <~i~>
characters, the character address puts the cursor on the first of <~i~>
these. <~i~>
When you are using a character address with a command, the <~i~>
situation is more complex. The one firm rule is that if the <~i~>
character address is farther down in the file than the cursor <~i~>
position, the cursor position is included in the range the <~i~>
command affects; while if the address target is earlier in the <~i~>
file than the cursor, the cursor position is not included in the <~i~>
range. <~i~>
The question of whether the address target is included in the <~i~>
command's range, like all the other open questions raised in the <~i~>
last few paragraphs, will have to be answered separately for each <~i~>
address. (But the usual rule is that if the address target is <~i~>
forward of the cursor, the target is not included; if the target <~i~>
lies backward from the cursor, the target is included.) <~i~>
Note also that a count given with any of these seven commands is <~i~>
passed to the address. You may give the count before or after <~i~>
the command character itself, but always before the address. <~i~>
What the address does with the count, if anything, is also a <~i~>
case-by-case question. <~i~>
USEFUL ADDRESSES <~i~>
There are four addresses that together resemble a miniaturized, <~i~>
localized version of the / and ? search patterns. In each case, <~i~>
the search takes place only in the current line, and only for a <~i~>
single character. To use any of them, you type one of the four <~i~>
letters designating the kind of inline search, immediately <~i~>
followed by the character to be searched for. (There are no <~i~>
metacharacters used with these addresses.) <~i~>
The letter "f" means that the search will go forward in the <~i~>
current line and stop on the character typed next. "F" makes <~i~>
the search run backward within the current line, otherwise the <~i~>
same as "f". A "t" search is the same as an "f" search <~i~>
except that the search stops with the character just short of the <~i~>
one you type after the "t", and a "T" search is like a "t" <~i~>
search but running backward within the current line. Any of <~i~>
these addresses can take a preceding count, which tells the <~i~>
search not to stop at the first instance of the character sought, <~i~>
but to go on to the nth, where n is the count. <~i~>
Any of these search commands, including the repeat-search <~i~>
commands mentioned below, are character addresses and can be used <~i~>
as an address for any of the three range commands that does not <~i~>
require a line address. In every case, the character on which <~i~>
the cursor would have landed had there been no command is the <~i~>
furthest character included in the range the command will affect. <~i~>
A few examples. "Fp" would cause a search that went backward and <~i~>
landed on the closest prior letter "p". "3f-" would make the <~i~>
search run forward within the current line and stop on the third <~i~>
instance of a hyphen. "2T " would cause a backward search that <~i~>
ended one character short of the second closest space character. <~i~>
This search system has its own repeat-search characters, which <~i~>
use storage buffers completely independent of those used for <~i~>
storing previous / and ? search strings. A semicolon ";" repeats <~i~>
the last inline search, in the same direction. A comma "," <~i~>
repeats the last search but reverses the direction. Any count to <~i~>
the original search is not included in the repeat, but you can <~i~>
give a count to either repeat character which will be passed to <~i~>
the search command that is repeated. While a search is limited <~i~>
to the current line, you can run a search, move to another line, <~i~>
then use a semicolon or comma to repeat the original search on <~i~>
the new line. <~i~>
Another very useful address that operates within a single line <~i~>
is the vertical bar "|". When preceded by a count, this address <~i~>
takes the cursor to the nth character on the current line, where <~i~>
n is the count, regardless of where the cursor was when the <~i~>
address was given. (In this address, n is absolute, not <~i~>
relative, starting from character one at the left edge of the <~i~>
text.) <~i~>
This address can also be used with a command. If the target <~i~>
character position is forward from the cursor position, the <~i~>
furthest character affected will be the last one before the <~i~>
target character. If the target is backward from the cursor, the <~i~>
target character as well as all those between it and the cursor <~i~>
will be affected by the command. <~i~>
Editing in Columns <~i~>
Although the Vi/Ex editor was not specifically designed to deal <~i~>
with columnar material, there are ways to use it effectively for <~i~>
this kind of work. Your choice of techniques will depend on <~i~>
whether you are dealing with single-character columns wherein <~i~>
each character in a line is in a separate column, or <~i~>
multi-character columns where the columns are set apart from each <~i~>
other by a separator character. <~i~>
SINGLE-CHARACTER COLUMNS <~i~>
Here I'm using "columns" the way most programmers do. A column <~i~>
in this sense is simply the characters in a vertical section of a <~i~>
file, one character wide. That is, the first character on each <~i~>
line of the file is in the first column, the second character of <~i~>
each line is in the second column, and so on. You'll find this <~i~>
usage in systems that use punch-card images, such as early <~i~>
Fortran programs; in the blocked records in certain databases, <~i~>
such as the ones used for very large mailing lists; etcetera. <~i~>
The essential point is that the systems that use these records <~i~>
absolutely depend on each piece of information being entirely <~i~>
within a certain column or range of columns, and nothing else <~i~>
being within those columns except padding characters to fill up <~i~>
any column positions not needed for the information in a <~i~>
particular record. <~i~>
For example, a mailing list may require that a suite or apartment <~i~>
number be in columns 122 through 125 in each record (line), with <~i~>
any padding following the actual number, so that an address <~i~>
printing program that finds "316 " in those columns will <~i~>
print ", #316" at the end of the street address line. If it <~i~>
finds "3A " it will then print ", #3A", etcetera. <~i~>
Should the suite number be even partially shifted out of the <~i~>
designated columns, the system will either print garbage as the <~i~>
suite number or issue an error message and skip that address <~i~>
altogether. The principle is the same, and even more important, <~i~>
with computer programs in punch-card image form. <~i~>
When you are making changes in existing records, and editing <~i~>
visually, the first important point is to be sure your are at the <~i~>
start of the particular field you need to modify. The "|" <~i~>
address I've explained above takes care of that -- wherever you <~i~>
are in a line, typing 122| brings the cursor to the 122nd column. <~i~>
Unless there are not 122 columns in that line: then the cursor <~i~>
will be placed in the last column that does exist, without any <~i~>
warning or error message. But files of this sort have generally <~i~>
been checked for exact block sizing, and if yours have not been, <~i~>
it's easy to check visually. <~i~>
To check visually that all the lines in the file are of the <~i~>
proper length, start by running a :se list command, which will <~i~>
display a dollar sign at the end of each file line. Then scan <~i~>
through the file to check that all those dollar signs are aligned <~i~>
vertically. If so, then check that the uniform line length is <~i~>
the correct one -- if your line length should be 66 characters <~i~>
(not counting the nonvisible newline), then run a 65| command on <~i~>
any line, and make sure that the cursor lands one column away <~i~>
from the end of the line. <~i~>
When you are at the start of the field to be changed, you have a <~i~>
choice of ways to change it. If the change area is 12 characters <~i~>
long, then typing 12cl followed by the 12 new characters and then <~i~>
the escape key will do it. But if you miss the count by even one <~i~>
character; if the actual number of characters you type in is 11 <~i~>
or 13; then all the subsequent fields on that line will be <~i~>
shifted one character out of place, which is probably a recipe <~i~>
for disaster. <~i~>
To avoid this hazard, make use of the little-known R command. It <~i~>
starts like the familiar r command, in that when you type the <~i~>
letter "R" in visual command mode the system waits to see what <~i~>
character you type next, and whatever that next character is, it <~i~>
replaces the character that was under the cursor. But instead of <~i~>
then returning you to command mode, the R command then moves the <~i~>
cursor one character to the right and again waits to see what <~i~>
character you type next -- the character you now type replaces <~i~>
the character that is now under the cursor. This process <~i~>
continues until you stop it by hitting the escape key. So if <~i~>
your cursor is on the capital P in the following line: <~i~>
but the greatest ancient Greek was Plato, who <~i~>
and you type in "RHomer" followed by the escape key, your line will <~i~>
now read: <~i~>
but the greatest ancient Greek was Homer, who <~i~>
and the cursor will be on the letter r at the end of "Homer". <~i~>
This character at a time replacement is the way to make sure you <~i~>
don't inadvertently shift any fields. Just be certain that you <~i~>
don't keep typing replacement characters beyond the existing end <~i~>
of the line; you would extend the line length that way. You can <~i~>
give a count to the R command, but you don't want to in this use <~i~>
because the count will multiply the number of times the new <~i~>
character string is inserted. That is, in that example above <~i~>
about replacing "Plato" with "Homer", if you had typed 3R instead <~i~>
of R your revised line would read: <~i~>
but the greatest ancient Greek was HomerHomerHomer, who <~i~>
Entering completely new lines of information is another matter. <~i~>
You should just type them straight across, as you would with any <~i~>
text entry, but if the existing lines are cryptic to human eyes <~i~>
you may not be able to tell by looking just where one field ends <~i~>
and another begins. You can try to keep count of the characters, <~i~>
of course, but a single mistake will throw all the subsequent <~i~>
fields in that line out of position. <~i~>
What you need here is an on-screen template to show you what goes <~i~>
where. You can make one on the spot, just by typing a template <~i~>
line into your file, entering each data line just above it, and <~i~>
deleting that template line when you are finished adding lines. <~i~>
For example, suppose you are adding to a name file where each <~i~>
record (line) starts with a month, day and year, continues with a <~i~>
source code (each of the preceding as a two-digit number, with a <~i~>
leading zero to pad it if necessary), and then has fields for a <~i~>
last name, first name, and middle initial. It would not be <~i~>
practical to judge where fields break just by looking at the <~i~>
existing data lines, which might look like this: <~i~>
07215854von TarekenstuttLeopold J <~i~>
12077338Henderson-Blyth La Toya P <~i~>
10108972Thistlethwaites Geraldine <~i~>
But a simple template line can clear it all up. Here is one for the <~i~>
job above: <~i~>
m|d|y|s|LLLLLLLLLLLLLLL|FFFFFFFF|M <~i~>
It has mnemonic characters to remind you of what goes in each <~i~>
field, and the "|" to indicate the last position of each field <~i~>
more noticeably. I've even used a lower-case letter for each <~i~>
field that takes numeric characters right justified and zero <~i~>
padded, and a capital letter for each field that takes alpha <~i~>
characters left justified and space padded. <~i~>
The way to use this template is to start entering data lines <~i~>
immediately above the template line. That way, as you hit return <~i~>
to start a new line, that new line replaces the one you've just <~i~>
finished in the position right above the template line. Yes, <~i~>
eventually the template line will be driven down off the bottom <~i~>
of the screen, but returning to command mode and typing the <~i~>
lower-case letter "z" followed by the return key will move the <~i~>
template line and the lines around it to the top of the screen. <~i~>
But there will be times when you don't want to spend time making <~i~>
individual changes that you should be able to handle globally. <~i~>
Suppose an obsolescent operations code has been replaced, and you <~i~>
now need to change every "B27" to "K53" throughout your file, but <~i~>
only when the "B27" appears in the operations code columns, which <~i~>
are columns 9 through 11. Th is odd-looking command will do it: <~i~>
:%s/^\(........\)B27/\1K53 <~i~>
Those eight consecutive dots in the search pattern guarantee that <~i~>
a match will occur only when there are exactly eight characters <~i~>
between the beginning of the line and the "B27". So of <~i~>
necessity, the "B" must occur in column 9, and so on. The "\1" <~i~>
puts those eight characters right back in again, so only the <~i~>
"B27" is actually replaced. <~i~>
If your columnar file has all lines of equal length, as most do, <~i~>
you can use this technique from the right side, too. If all <~i~>
lines in the file have 66 characters, then typing that last <~i~>
command as: <~i~>
:%s/B27\(...\)$/K53\1 <~i~>
will accomplish the changes in a case where the operations code <~i~>
columns are 61 through 63, without the need to type (and <~i~>
carefully count) sixty consecutive dots. <~i~>
But there will be times when the columns to be changed are in the <~i~>
middle of horrendously long record lines. There are still a <~i~>
couple of tricks you may be able to use. One is to find a <~i~>
landmark somewhere in mid-line. Does column 158 always contain <~i~>
either a "*" or a "|" character, neither of which can appear <~i~>
anywhere else in the lines? Then you can make the above change <~i~>
in columns 163 through 165 by typing: <~i~>
:%s/\([*|]....\)B27/\1K53 <~i~>
Failing a landmark, let the editor count out a long string of <~i~>
dots for you. To use this technique, you must first create your <~i~>
substitution command as a text line within the file you are <~i~>
editing, next write that line as a separate file (and then delete <~i~>
the command line from your original file), and finally use the <~i~>
:so command to pull in that one-line file and run it as a <~i~>
line-mode command. If you need a string of 92 consecutive dots in <~i~>
your command, create a blank line at the end of your file, next <~i~>
type: <~i~>
:1,92g/^/$s/^/. <~i~>
to put those 92 dots there, and finally put the rest of the <~i~>
command around that dot string. <~i~>
MULTI-CHARACTER COLUMNS <~i~>
The other meaning of "editing in columns" has to do with text <~i~>
rather than data files. It refers to tables of data such as you <~i~>
might find accompanying a technical article, columns of text <~i~>
and/or illustrations running in parallel as you'd find on a <~i~>
newspaper page, and the like. <~i~>
Yes, Unix formatting utilities and some word processing programs <~i~>
will format your final output into columns. But you may not have <~i~>
all these utilities, you may not want to spend time trying to get <~i~>
the results you want from those benighted programs, or you may <~i~>
plan to direct your output where formatters won't work. <~i~>
Visually editing the columns of data in a table requires little <~i~>
explanation. The one thing to remember: use the R as far as <~i~>
possible, to avoid shifting subsequent columns out of alignment <~i~>
inadvertently. This holds for creating tables, too; start by <~i~>
setting up a rectangular block of space characters, then replace <~i~>
spaces with the column entries you want, to keep your next entry <~i~>
from misaligning previous ones. This is also the best way to <~i~>
create pictures, diagrams, graphs and maps using ASCII <~i~>
characters. <~i~>
Things become problematic when you want to shift whole columns <~i~>
around -- there are no built-in Vi facilities for doing this. <~i~>
Here is what it is practical to do in the editor. As a real life <~i~>
example, consider the piece below, which I use as the tail end of <~i~>
Usenet (Net news) posts that announce Indonesian classical music <~i~>
and dance performances at a local restaurant: <~i~>
It's at the Dutch East Indies ;,,,,;,,,,;,,,,;,,,,; <~i~>
Restaurant on Oakland's /%%%%%%%%%%%%%%%%%%%%%\ <~i~>
downtown waterfront. The /%%%%%%%%%%%%%%%%%%%%%%%\ <~i~>
food there is very good "|""|"""|"""""|"""|""|" <~i~>
Indonesian cuisine at _|__|___|_ _|___|__|_ <~i~>
reasonable prices - dinners =|==|===|=====|===|==|= <~i~>
$8.95 to $17.50. Views are ~~~~~~~~~~~( (~~~~~~~~~~~ <~i~>
spectacular from the second ) ) <~i~>
floor picture windows, out <~i~>
over the water to Jack London Square, Alameda and San Francisco. <~i~>
Formality is medium - cloth napkins and oil candles at the <~i~>
tables, but no supercilious waiters, and the wall decorations are <~i~>
mostly Indonesian handicrafts. The phone number for information <~i~>
and reservations is 510/444-6555. <~i~>
( ( ( | Broadway ||I The Dutch East Indies <~i~>
) ) )Jack London |==========||== Restaurant is in Jack London <~i~>
( ( ( Square |E ||8 Village, a boutiques & <~i~>
) ) ) |m ||8 bistros cluster that is just <~i~>
( ( ( JACK LONDON |b ||0 down the estuary from Jack <~i~>
) ) )VILLAGE |a || London Square. Jack London <~i~>
( ( ( Alice|r Amtrak ||f Village is rustic, <~i~>
) ) ) -----------|c station ||r picturesque, quiet and safe. <~i~>
( ( ( Street|a ||e To get there from the <~i~>
) ) ) |d Jackson||e Interstate 880 freeway <~i~>
( ( ( parking lot |e ------||-- heading north, take the Oak <~i~>
) ) ) |r Street||w Street exit and turn left; <~i~>
( ( ( |o ||a five blocks will bring you <~i~>
) ) ) | ||y to Embarca- dero on your <~i~>
( ( ( -------------||-- right, just before Oak <~i~>
) ) ) Oak Street|| curves away to the left. <~i~>
(Going south on I-880, take the Jackson Street exit and go two <~i~>
blocks straight ahead before you turn right on Oak Street.) Turn <~i~>
right onto Embarcadero and go three blocks, until you go under an <~i~>
overpass of Victorian ironwork. Immediately turn left onto Alice <~i~>
Street, where you will see Jack London Village on your right, and <~i~>
a large lot that offers validated parking on the left. Walk into <~i~>
the Village's central courtyard, and you'll see the Dutch East <~i~>
Indies on the estuary side, toward the right, and upstairs. <~i~>
To create this, I started by drawing the stylized building and <~i~>
then the map. In each case I created a large rectangular block <~i~>
of space characters, then began trying ideas with the R command <~i~>
until I had something that satisfied me. (The pavilion sketch <~i~>
eventually became wider than I had planned, so I had to run a <~i~>
:%s/.*/ & / command to give me more working space.) Next I <~i~>
put additional blocks of space characters on the left of the <~i~>
drawing and the right of the map, to make a place for the text I <~i~>
wanted to include. Then I started replacing spaces with text, <~i~>
rewriting the text as I went along to fit it in nicely. When the <~i~>
text reached the bottom of the figure I was fitting it to, I went <~i~>
to full-width text lines, entering them the usual way. A tedious <~i~>
labor, but pretty straightforward. <~i~>
Now suppose I decided to redo this piece, by moving the picture <~i~>
to where the map is now, and vice versa. A few well chosen <~i~>
substitution and deletion commands would make copies of the two <~i~>
figures minus the text, and I could just as easily copy the text <~i~>
without the two figures. But how would I recombine them? <~i~>
Short of typing the text in again from scratch, the best I could <~i~>
do is to yank the lines of each figure, one at a time, and put <~i~>
them after (or before) the appropriate text lines, one at a time. <~i~>
Not that I would have to move back and forth between files with <~i~>
each yank and put; I could yank up to 26 lines into the named <~i~>
buffers, then move to the other file and put all 26 in their <~i~>
proper places. But there is no Vi command to yank a rectangular <~i~>
block of characters. <~i~>
Also take note that I should yank using addresses that are not <~i~>
line addresses, even though I will be yanking whole lines. If I <~i~>
should yank with line addresses, putting the pieces into the <~i~>
other file must make those pieces separate lines -- then I would <~i~>
have to join each pair of lines to create the columns I want. <~i~>
Next Time Around <~i~>
In the next part of this tutorial, I will go over host of <~i~>
complications and opportunities that come from allowing the <~i~>
replacement commands I've discussed to use metacharacters. Then <~i~>
I'll answer a couple of questions from readers that should be of <~i~>
use to quite a few of you from time to time. <~i~>
Screen-Mode Addresses <~i~>
A Few Address Principles <~i~>
Useful Addresses <~i~>
Editing in Columns <~i~>
Single-Character Columns <~i~>
Multi-Character Columns <~i~>
Part 7: The Replacement Commands/
The vi/ex Editor, Part 7: A Little "R" and "r": The Fine Points <~i~>
of those Replacement Commands <~i~>
<~i~>
There's more to R than to r <~i~>
Quoting in Characters <~i~>
Readers Ask <~i~>
<~i~>
Tommy Spratlin & Thai-Nghia Dinh writes: <~i~>
<~i~>
Next Time Around <~i~>
<~i~>
This installment of our Vi/Ex tutorial series is a diversion from <~i~>
the subjects I promised at the end of the previous part -- the <~i~>
change is my fault, and yet it is necessary. When I blithely <~i~>
suggested last time that the R command is just like the familiar r <~i~>
command, except for a few differences I mentioned, I was leading <~i~>
you astray. <~i~>
<~i~>
There are several differences that can cause problems in certain <~i~>
uses unless you understand those differences. And you won't really <~i~>
comprehend the greatest of those differences until you know about <~i~>
metacharacters in insert mode. But as an encouragement to follow <~i~>
all this, consider that almost all of what I say here about the R <~i~>
command also is valid with all the other commands that put you into <~i~>
text insertion mode: <~i~>
<~i~>
a A i I o O c s :a :i etcetera. <~i~>
<~i~>
There's more to R than to r <~i~>
<~i~>
The r command replaces whatever character is presently under the <~i~>
cursor, so there must be some character under the cursor for it to <~i~>
replace -- otherwise it just gives you an error beep. Not so with <~i~>
R. <~i~>
<~i~>
You can give the R command on an empty line; whatever you type <~i~>
after that, up to the next escape character, will take the place of <~i~>
that empty line just as though you had typed past the end of an <~i~>
existing line after giving an R command. (I was going to say <~i~>
"just as though you had given an a command", but I'm now very <~i~>
leary of making comparisons that are incomplete without paragraphs <~i~>
of explanations.) You can even start entering text into a <~i~>
brand-new file via the R command. <~i~>
<~i~>
The factor above can be useful in various situations; I only have <~i~>
space to mention one. At times I want to type new characters to <~i~>
replace blank spaces in a place where some of the lines are empty. <~i~>
These do not have any blanks; no characters at all. But I do not <~i~>
have to look at each line before I start typing on it, to see <~i~>
whether I should use an R or an a command, because R will work in <~i~>
either case. <~i~>
<~i~>
The R command is more forgiving of your typing errors, too. <~i~>
Whatever character you type after an r is final. If you <~i~>
accidentally typed the wrong character, you can only put back what <~i~>
was there by typing a u command, if the mistake was the last <~i~>
editing command you typed, or put in the replacement you had in <~i~>
mind by returning the cursor to the spot and running another, more <~i~>
careful, r command. <~i~>
<~i~>
But if you mistype during an R command, you can backspace over the <~i~>
error with the backspace key. Then you can type in the character <~i~>
(or characters; you can back up multiple spaces by repeating the <~i~>
backspace key) you should have typed. And if you simply typed too <~i~>
far, you'll be glad to know that backspacing doesn't just remove <~i~>
the incorrect characters, it restores the characters that were <~i~>
there, either right away or as soon as you hit the escape key. You <~i~>
can even backspace over everything you've typed during this R <~i~>
command before you type escape, because the editor does not object <~i~>
to a replacement string length of zero. <~i~>
<~i~>
One caveat here, though, lest my clarification turn out to need a <~i~>
clarification of its own. With either of these commands it is <~i~>
possible to break a line, just by typing the return key as a <~i~>
replacement character, and with the R command this linebreaking can <~i~>
be done either while actually replacing characters or when typing <~i~>
on beyond the end of the existing line. With almost all versions <~i~>
of the editor, it is not possible to backspace over an inserted <~i~>
linebreak, even while you are still in R insertion mode. <~i~>
<~i~>
The most important difference, though, is the handling of <~i~>
metacharacters. Yes, text insertion utilizes metacharacters too, <~i~>
quite apart from the ones that the replacement patterns in <~i~>
:substitute commands use. The r command recognizes hardly any of <~i~>
these metacharacters, and quoting those in as literal characters is <~i~>
very simple. The R command, though, recognizes almost all of them, <~i~>
and quoting characters in with R is rather complicated. <~i~>
<~i~>
Quoting in Characters <~i~>
<~i~>
The phrase "quoting in" is standard terminology, but it is rather <~i~>
misleading in the editor. Unlike Unix shells, the editor does not <~i~>
use any of the ASCII quotation marks: ` ' " (backquote, single and <~i~>
double quote) to quote characters into a file. Instead, it uses <~i~>
the backslash ("\") and control-V ("^V"); the latter is what <~i~>
you send when you press the V key while holding the CONTROL or CTRL <~i~>
key down. In either case, you quote a character in by typing the <~i~>
quoting character just prior to the character you want to quote in. <~i~>
So if @ is your line kill character, and you want to put that <~i~>
character in the text you are typing in, you would have to type <~i~>
either \@ or ^V@ to get it there. And if you want several <~i~>
consecutive characters quoted in, you must quote each of them <~i~>
individually. That is, if you want to put @@@ into a line, you <~i~>
must type either ^V@^V@^V@ or \@\@\@ to put that string there. <~i~>
<~i~>
But \ and ^V are not always interchangeable. In many cases either <~i~>
will work; but sometimes you must choose the right one. Which one <~i~>
to use depends both on what character you want to quote in and <~i~>
whether you're using the r or R command. <~i~>
<~i~>
One obvious use for quoting is to insert a character that normally <~i~>
erases part or all of what you've just typed in. The ASCII <~i~>
backspace character, control-H, must be quoted in, and so must your <~i~>
own line-kill character (@ in the example above) and your own erase <~i~>
character if it is not control-H. With the r command you quote in <~i~>
any of these with a backslash; when using R you may quote any of <~i~>
these in using either backslash or control-V. <~i~>
<~i~>
A pause here, to answer a question that might be in the minds of <~i~>
people who know a little about Unix internals. Ordinarily it is <~i~>
the asynchronous serial terminal line (or TTY) driver that <~i~>
recognizes the erase and line-kill characters and edits the input <~i~>
line accordingly without including these characters in the final <~i~>
result. Then, how can one enter these same input-line characters <~i~>
into the edit buffer if they don't get past the TTY driver? <~i~>
Because Vi/Ex places the TTY driver into a special "raw" mode that <~i~>
ignores the line-editing characters passing them on to the editor. <~i~>
Otherwise you would not be able to quote these characters in. <~i~>
Also, the editor is set up to discover your erase and line-kill <~i~>
characters by querying your personal environment, and then <~i~>
interpret these characters as the line driver would have. A nifty <~i~>
feature -- but unfortunately, the editor has no way to let the user <~i~>
turn this feature off. <~i~>
<~i~>
The editor's creators came up with a curious method for repeating <~i~>
short text insertions, where the text to go in is always the same <~i~>
but any outgoing text varies. They decided that when you are in <~i~>
screen mode, and have just gone into typing-in-text submode, and <~i~>
make Control-@ ("^@") the first character you type in, then the <~i~>
editor should insert the last piece of text you had previously <~i~>
inserted (if it was not more than 128 characters long) and take you <~i~>
back to command mode. Unfortunately, they never made this work as <~i~>
promised. <~i~>
<~i~>
In actuality, ^@ operates anywhere in a text insertion, not just in <~i~>
the first character position. What a ^@ does there depends on the <~i~>
situation. If your last c d y command, or one of their variants <~i~>
such as s D etcetera, removed or copied a full line of text or <~i~>
parts of two or more lines, or if you haven't run one of those <~i~>
commands in your current editing session, then typing ^@ is just a <~i~>
nuisance. It will take you out of text input submode and probably <~i~>
move the cursor back a few characters from where the input ended. <~i~>
<~i~>
But if you have done at least one c d y command or a variant, and <~i~>
if the very last one you did removed or copied only a part of a <~i~>
single line of text, then surprise! Typing a ^@ in this case will <~i~>
do three things: <~i~>
<~i~>
Unless you typed it at the first character position on a line, it <~i~>
will move the cursor back one character. This will move over the <~i~>
last character you typed in if you've typed any, or over one <~i~>
existing character if you type ^@ as the first character of your <~i~>
insertion, but will not erase the character it passes over. <~i~>
<~i~>
Just to the left of the new cursor position, the editor will insert <~i~>
the text that was removed or copied by your last c d y command or <~i~>
variant. (If you went into text-insertion submode via a c command <~i~>
or a variant of it, the text you just took out is what will be put <~i~>
back in.) <~i~>
<~i~>
Finally, the text insertion will automatically end and you will be <~i~>
back in command submode, with the cursor positioned at the start of <~i~>
the last simple word that was inserted by the ^@ metacharacter. <~i~>
<~i~>
Quoting a ^@ into your text isn't possible, because the editor <~i~>
reserves that character for internal use and will not accept it as <~i~>
itself in any file you may edit. Not that there would be any <~i~>
reason to put ^@ in a file anyway: it is the ASCII character NUL, a <~i~>
padding character that is routinely inserted in data streams by <~i~>
device drivers, and just as routinely stripped at the receiving <~i~>
end, so any ^@ characters you might add would be lost in the <~i~>
shuffle. But when you are using the R command, or any other <~i~>
command that lets you insert an indefinite amount of text, you can <~i~>
quote a ^@ anyway by preceding it with a ^V. The result will be to <~i~>
quote ^[Pb into your file at that point; this being the command <~i~>
string the editor issues to perform the odd operation I've detailed <~i~>
above. <~i~>
<~i~>
Those of you who are skillful with the editor may wonder why the ^@ <~i~>
insertion operates only when your last text extraction was a <~i~>
fragment of one line. After all, the P command by itself inserts <~i~>
the contents of the unnamed buffer, and that buffer holds whatever <~i~>
was extracted last, be it half a line or a hundred lines, doesn't <~i~>
it? The answer lies in one of the editor's undocumented features. <~i~>
When you give a command to insert text, even the r command that <~i~>
only inserts a single character, the editor simultaneously flushes <~i~>
the unnamed buffer and leaves it empty -- if and only if that <~i~>
buffer contained more than a fragment of one line. So, when you <~i~>
entered the text insertion mode from which ^@ operates, you emptied <~i~>
the unnamed buffer unless there was only a fragment of one line in <~i~>
it. <~i~>
<~i~>
At times you may want to use the beautify option to the set <~i~>
command. This tells the editor to throw away most, but not all, <~i~>
control characters you may try to type in -- the exceptions usually <~i~>
are the tab (^I), newline (^J), and form feed (^L) -- in order to <~i~>
keep you from inadvertently putting in invisible control characters <~i~>
that will be hard to detect later. This option is normally off, <~i~>
but you can type :se bf to turn it on. <~i~>
<~i~>
But even when you want most control characters thrown out, there <~i~>
will be occasions when one must go in. This is not possible using <~i~>
a r command. The usual r technique of backslashing will usually <~i~>
bite back in this case -- the editor will interpret the control <~i~>
character by acting on its control meaning rather than inserting it <~i~>
in the text. Using R, though, you can insert most control <~i~>
characters by preceding each with ^V. <~i~>
<~i~>
Even this may not be enough. Some systems are set up so that when <~i~>
certain control characters are typed in, even though preceded by <~i~>
^V, the system acts on them as control characters before the editor <~i~>
ever sees them. To get around this problem, many implementations <~i~>
of the editor, especially older ones, interpret an ordinary <~i~>
character typed right after a ^V as a control character. That is, <~i~>
on these systems, typing ^VF or ^Vf while running an R command <~i~>
inserts a ^F in the file, just as typing ^V^F would on systems that <~i~>
don't have this challenge. <~i~>
<~i~>
Readers Ask <~i~>
<~i~>
Here are the latest questions, and my solutions, from inquiring <~i~>
readers with problems you might face someday. <~i~>
<~i~>
Tommy Spratlin writes: <~i~>
<~i~>
Hi Walter, <~i~>
<~i~>
In moving files from Windows machines to UNIX, some of our users do <~i~>
binary transfers which result in ^M characters in the ASCII files. <~i~>
Usually they occur at the ends of individual lines and I do: <~i~>
<~i~>
:1,$ s/^M//g <~i~>
<~i~>
where ^M is generated by ^V^M and everything works fine to delete <~i~>
these characters. I now have a new problem: I found a file with ^M <~i~>
characters embedded in it, but the file is one long line. I need <~i~>
to replace them with Vi's line-end character to split this long <~i~>
line into multiple lines. But I can't because it's the same as <~i~>
pressing the ENTER or RETURN key in the middle of the substitution <~i~>
command. How can I replace the superfluous carriage return? We <~i~>
have several files like this and it's causing problems viewing them <~i~>
with Web browsers. <~i~>
<~i~>
I tried substituting a newline with the character code and the <~i~>
octal code unsuccessfully, and tried the ^M as a last unsuccessful <~i~>
resort. <~i~>
<~i~>
Things aren't as complicated as you make them seem, Tommy. First <~i~>
of all, Web browsers generally ignore carriage-return and/or <~i~>
linefeed characters while formatting text for display. If your <~i~>
browser is choking on these all-one-line files, it is probably <~i~>
because the lines are too long for your browser, or for some other <~i~>
cause not related to embedded ^M characters. <~i~>
<~i~>
Now, as you have deduced, the difference between Microsoft and Unix <~i~>
text file formats is that Microsoft operating systems seem to favor <~i~>
carriage-return followed by linefeed (^J) as the line separator, <~i~>
while Unix systems use linefeed alone. <~i~>
<~i~>
As you've discovered, you cannot directly quote a ^J into any <~i~>
editor command. And yet, you put a ^J into your file every time <~i~>
you hit return during text entry, although the return key on most <~i~>
terminals sends a ^M character. That's the trick; the substitute <~i~>
command regards a ^M in the input pattern as a signal to insert a <~i~>
^J and discard the ^M. So you only need to get that ^M into the <~i~>
replacement pattern by typing in your command line like this: <~i~>
<~i~>
:1,$ s/^V^M/^V^M/g <~i~>
<~i~>
You just have to overlook the appearance of futility in this <~i~>
command line, as though it were going to replace each ^M with <~i~>
itself. That first ^M is in the outgoing pattern, so it matches a <~i~>
real ^M. The second, in the replacement pattern, calls for a ^J as <~i~>
I explained above. <~i~>
<~i~>
However, these all-one-line files may be too long for the Vi <~i~>
editor, which cannot handle lines much more than a thousand <~i~>
characters long in most common implementations, with shorter limits <~i~>
in older versions. The editor will truncate lines that exceed the <~i~>
limit, with only a minimal and rather cryptic warning. In such <~i~>
cases, use the tr utility to replace the ^M characters (which is a <~i~>
very straightforward job with that tool), before you bring the file <~i~>
into the Vi editor. <~i~>
<~i~>
You may wonder then, how you would use the substitute command to <~i~>
put ^M characters into your file. The answer is to backslash the <~i~>
quoted-in ^M. To add a ^M at the end of every line in your file, so <~i~>
as to conform it to Microsoft practice, type this command: <~i~>
<~i~>
:%s/$/\^V^M <~i~>
<~i~>
(Note that it is important to type the \ first, then the ^V, <~i~>
followed by the ^M.) The ^V puts the immediately-following ^M into <~i~>
the command line, and the backslash tells the command that this ^M <~i~>
is to be considered a real one, not a metacharacter for ^J. In <~i~>
fact, these are the general principles for quoting characters <~i~>
almost everywhere except in typing-in-text mode: <~i~>
<~i~>
Precede a character by ^V to keep that character from being <~i~>
interpreted as a metacharacter at the moment you type it. In this case, <~i~>
you don't want typing ^M to immediately end the substitution command. <~i~>
<~i~>
Precede a character by a backslash to keep that character from acting <~i~>
as a metacharacter later, when what you've typed is interpreted by the <~i~>
editor -- for example, when what you have typed in is run as a command, <~i~>
or interpreted as a search pattern. This command uses a backslash to <~i~>
keep the command from inserting ^J instead of ^M at the time it executes. <~i~>
<~i~>
When you must use both, as in this case, type the backslash before <~i~>
you type the ^V. (If you think that this backslash would then <~i~>
affect the immediately following ^V rather than the later ^M, <~i~>
remember that the ^V is not there when the backslash takes effect. <~i~>
The ^V disappears as soon as it tells the editor to insert the ^M <~i~>
in the command instead of taking the ^M as the signal to end the <~i~>
command.) <~i~>
<~i~>
Finally, you can replace linefeed characters with something else <~i~>
via line mode commands, but you must use two commands and only one <~i~>
of them is the substitute command. Suppose you need to change a <~i~>
short file's format from a number of lines to the format Tommy <~i~>
encountered: a single line with ^M separators. That is, replace <~i~>
each ^J (except the last) with a ^M. (This had better be a fairly <~i~>
short file, because even newer versions of the editor can't handle <~i~>
any lines longer than 1024 characters.) <~i~>
<~i~>
Start by using a command similar to the one above to put ^M at the <~i~>
end of every line except the last. (Since these ^M characters are <~i~>
to separate lines, there's no use for one at the end of the last <~i~>
line.) Then use this command: <~i~>
<~i~>
:%j! <~i~>
<~i~>
to join all the lines into one. The "j" in this command line is <~i~>
the shortest abbreviation for the line mode join command, and the <~i~>
"!" switch at the end of it tells the command not to insert blank <~i~>
space between the lines it joins. <~i~>
<~i~>
Thai-Nghia Dinh writes: <~i~>
<~i~>
Hi, <~i~>
<~i~>
I have a question (rather simple, really) but no one seem able to <~i~>
know the answer. Not even the help desk (with all the Vi gurus <~i~>
:)). I'm hoping you can help me with it. <~i~>
<~i~>
I have a text file of unknown length. Each line of the file can be <~i~>
very short or very long (from 3 characters up to 1000 characters). <~i~>
<~i~>
Within this file, I'm trying to locate (search) the nth occurrence <~i~>
of a word. <~i~>
<~i~>
Here are a few things I've tried: <~i~>
<~i~>
The simple solution would be (from visual command mode): a <~i~>
/foobar command followed by the n command typed n-1 times. But <~i~>
what if n is large, say 200 or greater?) <~i~>
<~i~>
:1,$ global /^/ /foobar/ (and its variations) Nothing useful... <~i~>
<~i~>
Can you suggest a better way? <~i~>
<~i~>
Yes, although it involves a slightly tricky procedure. Consider <~i~>
the following command string: <~i~>
<~i~>
:$|/\<foobar\>/s//QQQ <~i~>
<~i~>
The first command in this string takes us to the last line of our <~i~>
file and -- incidentally -- displays it on our screen, which is not <~i~>
important here. The second command searches forward for a line <~i~>
containing "foobar" as a word, and starting from the last line the <~i~>
search must wrap around and find the first instance in the file. <~i~>
Then that second command replaces the word "foobar" with "QQQ", <~i~>
leaving the cursor at the point where the substitution was made. <~i~>
<~i~>
Now let us make an addition to the start of this command string: <~i~>
<~i~>
:1,199g/^/$|/\<foobar\>/s//QQQ <~i~>
<~i~>
This revised string repeats the procedure 199 times; each time the <~i~>
first instance of "foobar" remaining in the file is the one <~i~>
replaced. So we end up sitting on the "QQQ" string that replaced <~i~>
the 199th instance of "foobar"; simply typing n will bring us to <~i~>
the 200th instance. And if we move off that 200th instance for any <~i~>
reason, going to the top of the file and searching for "foobar" <~i~>
will bring us right back to it, because the first 199 are now gone. <~i~>
<~i~>
When we are finished with that 200th "foobar", this command: <~i~>
<~i~>
:%s/QQQ/foobar/g <~i~>
<~i~>
will change those 199 "QQQ" strings back to "foobar". Of course, <~i~>
if there is any chance that "QQQ" might occur in the document as <~i~>
itself, we can choose another dummy string. <~i~>
<~i~>
And while I'm at it, I've got another question. <~i~>
<~i~>
How do I delete all lines beginning with a certain string, say, <~i~>
!@#$ (or foobar for that matter). And a related question: how to <~i~>
delete lines containing the word foobar (anywhere within the line)? <~i~>
<~i~>
The first command line following will solve your first problem, and <~i~>
the second will solve your second: <~i~>
<~i~>
:g/^foobar/d <~i~>
:g/\<foobar\>/d <~i~>
<~i~>
Next Time Around <~i~>
<~i~>
To make room to answer two readers' questions, I had to skip <~i~>
presenting three great Vi tools -- autoindent, abbreviate, and map! <~i~>
-- and the effect their metacharacters have in text-insertion mode. <~i~>
They'll be first up in the next part of this tutorial. <~i~>
<~i~>
More answers to reader questions are coming, too. I have queries <~i~>
to answer about the semicolon address separator and about yanking <~i~>
within macros -- and if a few more significant problems arrive <~i~>
here, I'll try to fit them in, too. <~i~>
<~i~>
And this time you won't have to wait and wait for the next tutorial <~i~>
part. As I write this paragraph, I'm already in the middle of <~i~>
creating the next part, so you should see it within a month after <~i~>
this part appears online. <~i~>
<~i~>
There's more to 'R' than to 'r' <~i~>
Quoting in Characters <~i~>
Readers Ask <~i~>
Tommy Spratlin <~i~>
Thai-Nghia Dinh <~i~>
Part 8: Indent, Like a Typewriter/
Part 9: Take Charge with Macros/
The vi/ex Editor, Part 9: Take Charge with Macros <~i~>
<~i~>
Text-Insertion Macros <~i~>
<~i~>
What These Tools Do <~i~>
Working Principles <~i~>
Time for another exercise <~i~>
<~i~>
Command-Submode Macros <~i~>
<~i~>
:map Macros <~i~>
Buffer Macros <~i~>
:source Macros <~i~>
Another Exercise <~i~>
Write and Read Macros <~i~>
<~i~>
Text-Insertion Macros <~i~>
<~i~>
As befits an editor with all those built-in metacharacters that <~i~>
operate while you are typing in text, there are two ways to create <~i~>
your own macros for use during text insertion. Both can be useful <~i~>
in the right circumstances, so you'll probably want to put them to <~i~>
work at times. You may not have a choice -- often the .exrc file <~i~>
that you may be given when you get a new Unix shell account has <~i~>
some of these shorthand dodges built in. These two tools have as <~i~>
many similarities as differences, so I will expound them in <~i~>
parallel. <~i~>
<~i~>
What These Tools Do <~i~>
<~i~>
Both tools act only when you are in text-insertion submode of <~i~>
screen-editing mode. Nonetheless, the commands that set them up <~i~>
and manage them are line-mode commands like: <~i~>
<~i~>
:ab ucb University of California at Berkeley <~i~>
:map! } Control-[k2cc <~i~>
<~i~>
The two example lines above will set up two shorthand forms that <~i~>
you can use without further preliminaries. The first line provides <~i~>
that whenever you type "ucb" as a separate word in your text, the <~i~>
editor will replace it with "University of California at Berkeley". <~i~>
It happens right on the spot, and without any special signal from <~i~>
you. <~i~>
<~i~>
The second line is for use if you frequently discover that what you <~i~>
are typing has become a mess, and that the mess started back on the <~i~>
previous line. With this shorthand form in effect, whenever there <~i~>
is a "}" character in what you type in, the editor removes it and <~i~>
instead acts as if you had typed in "Control-[k2cc". That is, the <~i~>
Control-[ (generated by the "Escape" key on your keyboard) causes <~i~>
the editor to escape from text-insertion to command mode, the "k" <~i~>
causes the cursor to move up a line, and the "2cc" removes both of <~i~>
the lines involved and puts you back in text-insertion mode, ready <~i~>
to type in a replacement for those lines and continue on with your <~i~>
text insertion. As with the previous tool, this happens as soon as <~i~>
you type in the shorthand form, without any special action by you. <~i~>
<~i~>
Note that whitespace separates either of these setup commands into <~i~>
three parts. The first part, from the start of the line up to the <~i~>
first stretch of whitespace, is just the command name. Part two, <~i~>
between the first and second stretches of whitespace, is the short <~i~>
form that you will type into the text. The third part, everything <~i~>
following the second stretch of whitespace, is what the editor will <~i~>
insert (and/or execute) when you type in the short form. Only the <~i~>
first two stretches of whitespace are separators -- any later <~i~>
stretches are integral components of part three. And whitespace <~i~>
includes both space characters and tabs, in any mixture. <~i~>
<~i~>
Working Principles <~i~>
<~i~>
Now that you've seen what these two tools do, let's consider how <~i~>
they work: <~i~>
<~i~>
:abbreviate <~i~>
<~i~>
(Shortest abbreviation is :ab). This tool acts when you type in a <~i~>
certain character or string as a separate word, each end bounded by <~i~>
whitespace, or a punctuation character, or the start or end of a <~i~>
line, or the start or end of an insertion. As soon as the editor <~i~>
sees that the abbreviation is a word by itself, it replaces that <~i~>
abbreviation with the longer word or phrase you have set as <~i~>
equivalent. <~i~>
<~i~>
As an example, you might have declared "cat" as your abbreviation <~i~>
for "felix domesticus". Then, wherever you type in a line such as <~i~>
"the habits of the common cat include", the editor will promptly <~i~>
change it to read "the habits of the common felix domesticus <~i~>
include". But there will be no such change in words that happen to <~i~>
include the string "cat" in them, such as "catamaran" or <~i~>
"concatenation". Be careful with this, because while the word <~i~>
"catlike" will not be changed, the word "cat-like" will be. <~i~>
<~i~>
Neither a backslash (\) nor a control-V will quote an abbreviation <~i~>
into a file as itself. Usually, the easiest way to insert an <~i~>
abbreviation into your text is to escape from text-insertion <~i~>
submode (back to command submode) in the middle of typing the <~i~>
abbreviation, then re-enter text-insertion submode and type in the <~i~>
rest of the abbreviation. If your abbreviation is only one <~i~>
character long, though, you must fall back on typing the <~i~>
abbreviation with a letter immediately before or after it, then <~i~>
returning to command submode to erase the unwanted extra letter. <~i~>
<~i~>
:map! <~i~>
<~i~>
(No editor-accepted abbreviation). Very similar to the abbreviation <~i~>
tool discussed above, but with three major differences: <~i~>
<~i~>
The shorthand form defined with this command does not need to be <~i~>
typed into your inserted text as a separate word in order to <~i~>
operate. Even if it is embedded within another word, the short form <~i~>
will disappear and its related text will be entered in its place. <~i~>
<~i~>
This tool does not simply insert the related text into the file, as <~i~>
the :abbreviate tool does; it acts as though the user had typed in <~i~>
the related text instead of the short form. That is, if there is <~i~>
an escape character in the related text, that escape will put the <~i~>
editor back into command submode, and interpret any following <~i~>
characters as screen-mode commands. (Unless one of those <~i~>
characters returns you to text insertion submode -- then characters <~i~>
following that insert-text command will be all be put into the <~i~>
file, unless and until there is another escape character.) That <~i~>
makes accidentally triggering this tool rather dangerous. <~i~>
<~i~>
Quoting in a character or string that you've defined as a short <~i~>
form via this command is simple. Type control-V before the <~i~>
metacharacter, or the first character of the metastring, and into <~i~>
the text it goes. Even that may not be required if you are dealing <~i~>
with a metastring, and if the timeout option to the :set command is <~i~>
still in its default state: turned on. In this case, all you need <~i~>
to do is be sure that you take more than one full second to type in <~i~>
the entire metastring, and it will have no meta effect. (This, by <~i~>
the way, is one reason that this tool's metastrings should be short <~i~>
-- so you can depend on being able to type one of them in less than <~i~>
a full second when you do want the metavalue.) <~i~>
<~i~>
Questions naturally arise regarding these tools. One frequent <~i~>
query is why anyone would want to mess around with :abbreviate when <~i~>
it seems much easier to do a general substitution command when the <~i~>
document is complete. That is, instead of that abbreviation I set <~i~>
up at the start of this explanation, just run a <~i~>
:%s/\<ucb\>/University of California at Berkeley/g command <~i~>
after all the text has been entered. There are several reasons to <~i~>
use Vi's abbreviation feature instead: <~i~>
<~i~>
It's not hard to unknowingly type in your abbreviated string where <~i~>
you don't want it expanded, as in a direct quotation (Savio told <~i~>
the students, "We don't want ucb to get the upper hand!"), or where <~i~>
it has an entirely different meaning (Next, punch in the code: aQr <~i~>
PxN ucb JHt.) Using the substitution command above, you would never <~i~>
see that these sentences were being disfigured. But with <~i~>
on-the-spot replacement the mistaken use would be right in your <~i~>
face. <~i~>
<~i~>
Lines can get very long when abbreviations are expanded, especially <~i~>
when there are several abbreviations in one line. When you use a <~i~>
general substitution command after text entry, there's no way to <~i~>
know that certain lines have become unreasonably long. But with <~i~>
the :abbreviate tool, you see the final length of each line as you <~i~>
go along. And if you use the wrapmargin option to the :set <~i~>
command, line breaks will generally be inserted after any <~i~>
abbreviations have been expanded. <~i~>
<~i~>
It's easy to forget to run a general substitution command. But a <~i~>
:abbreviate command can be made automatic by putting it in a .exrc <~i~>
file, and the user can see while typing whether it is or is not in <~i~>
operation. <~i~>
<~i~>
This tool can do more than save typing. For example, suppose a <~i~>
technical writer is in the habit of typing "unix", while company <~i~>
policy requires "UNIX(R)". Either a general substitution or the <~i~>
:abbreviate tool will correct that writer's recurring errors, but <~i~>
only the latter will continuously teach him that "unix" is not to <~i~>
be used. As another example, consider a writer who begins far too <~i~>
many sentences with the word "The", which makes for dull reading. A <~i~>
:ab The DON'T OVERDO IT! command will ensure that every time this <~i~>
writer types the word "The" at the start of the sentence, it will <~i~>
promptly be transmuted into the billboard phrase "DON'T OVERDO <~i~>
IT!", which can be backspaced over to insert a new sentence <~i~>
beginning. Note that this will not be triggered by words such as <~i~>
"These" or "Then", nor by the word "the" in the middle of a <~i~>
sentence. <~i~>
<~i~>
Another common question concerns precedence of metacharacters. You <~i~>
can use most of the text-input metacharacters I've discussed <~i~>
previously as short-form names in :map! commands. Suppose you did <~i~>
use control-D as such a short form -- what would happen when you <~i~>
typed control-D at the start of an autoindented line? Would it <~i~>
wipe out the indentation or type in the phrase that :map! has <~i~>
associated with it? Or if you used control-H as a short form? <~i~>
When you subsequently typed a control-H during text entry, would <~i~>
the cursor back up a space, or would type in a stored phrase? <~i~>
<~i~>
The answer is that the :map! value would prevail. By preceding <~i~>
either character with a control-V, you could type in in as itself, <~i~>
but there would be no way to use the ordinary metavalue of either <~i~>
character. If you were to map control-D followed immediately by <~i~>
another control-D or two consecutive control-H characters or any <~i~>
other doubling of an ordinary metacharacter, the situation would be <~i~>
more complex. You could then type the two control-D or control-Hs <~i~>
within one second to get the mapped text typed in, or you could <~i~>
type control-D or control-H followed by a one-second pause to <~i~>
invoke the ordinary metavalue. <~i~>
<~i~>
Time for another exercise. <~i~>
<~i~>
Suppose that you used control-D or control-H as a short form with <~i~>
the :abbreviate command. Or suppose that you used some ordinary <~i~>
character string as both an abbreviation and a mapping short form. <~i~>
(The editor will allow you to do this.) What would happen when you <~i~>
typed in this double-use short form during text insertion? This <~i~>
exercise is straightforward enough that I expect most of you will <~i~>
find the correct answer before you look at my solution. <~i~>
<~i~>
Two final warnings. Do not try to define a non-alphanumeric <~i~>
character or string as a short form with the :abbreviate command. <~i~>
You probably will be able to do this -- the editor won't object -- <~i~>
but when you try to use this abbreviation, nothing will happen. <~i~>
And with either :abbreviate or :map!, do not put any metacharacter <~i~>
as itself into the long-form string. Even if you manage to get it <~i~>
into the string as itself, it will not go into your text that way. <~i~>
<~i~>
What if you have forgotten what short forms you have set up, or are <~i~>
uncertain as to whether some may have been set up for you via a <~i~>
.exrc startup file? Well, you can query either tool ju st by <~i~>
giving its setup command without any arguments. Here are examples <~i~>
of those queries, with the responses you might receive from the <~i~>
editor: <~i~>
<~i~>
:ab <~i~>
cat cat felix domesticus <~i~>
wolf wolf canis lupus <~i~>
<~i~>
:map! <~i~>
{ { ^[o^I^IThe End^[ <~i~>
} } ^[o^I^I-XXX-^[ <~i~>
~ ~ (more to come)^[ <~i~>
<~i~>
Note that each response line has at least three strings of printing <~i~>
characters, separated by whitespace. It's that second string in a <~i~>
line that is the short form; the string that when typed in will be <~i~>
replaced by the last string shown. (Yes, in every example line <~i~>
above the first string is identical to the second, but that isn't <~i~>
always so.) The last string is what will be inserted and/or <~i~>
executed. <~i~>
<~i~>
So now you know what characters and strings will have to be quoted <~i~>
in when you want to insert them as themselves. And if one or more <~i~>
of those short forms is something you will be typing in so often <~i~>
that you can't spare the time to quote it in each time you use it, <~i~>
you can disable the metavalue for the rest of the present editing <~i~>
session. Just give the command name for the tool that uses this <~i~>
short form but precede it with "un", and as the only argument give <~i~>
the short form you want to disable. For example, here are the <~i~>
commands that will disable the first entry in each of the lists <~i~>
above: <~i~>
<~i~>
:unab cat <~i~>
:unmap! { <~i~>
<~i~>
Command-Submode Macros <~i~>
<~i~>
It's common that a text editor has a facility that lets a user <~i~>
create personalized commands, usually as macros built on existing <~i~>
commands. The Vi/Ex editor has four such facilities -- something <~i~>
for every need. While these facilities don't have the low-level <~i~>
programmability of mock-Lisp, they can accomplish a lot to simplify <~i~>
your editing, and you don't need to learn a programming language to <~i~>
use them. <~i~>
<~i~>
I'll be discussing each facility (or family) in its own section <~i~>
below, because their structures are quite different. Nonetheless, <~i~>
you can often combine them to go od effect, by using a macro of one <~i~>
type to call a macro of a different type. <~i~>
<~i~>
:map Macros <~i~>
<~i~>
This is the editor tool that's closest to what most users think of <~i~>
as a macro facility. It uses the command :map as its setup tool, <~i~>
and the macros it creates operate when the user is in command <~i~>
submode of screen-editing mode. Otherwise it works just the way <~i~>
its very close relative, the :map! tool, works -- which I explained <~i~>
in depth in the first half of this tutorial part, above. Consider <~i~>
the three command lines below: <~i~>
<~i~>
:map v :!wc -w %Control-M <~i~>
:unmap v <~i~>
:map <~i~>
<~i~>
The first line sets up a macro that does a word count on the file I <~i~>
am editing, as of the last write to storage, whenever I type the <~i~>
letter v from command submode while I am screen editing. The <~i~>
second unsets that macro, so that a v command no longer does <~i~>
anything. The third displays a list of the :map macros that are <~i~>
currently in effect. All this should be transparently plain to <~i~>
readers who understand the :map! tool. Still, there are a few <~i~>
points worth noting that are particularly applicable to the :map <~i~>
side of the family. <~i~>
<~i~>
Choosing a short-form for :map macros should not be difficult. <~i~>
Half a dozen of the printing ASCII characters and many of the <~i~>
control characters are not used as screen-editing commands or <~i~>
addresses. Hardly any strings of two duplicate characters (such as <~i~>
"DD" above) are in use, and most editor versions will let you map <~i~>
such strings. You don't need to avoid duplicating your :map! short <~i~>
forms because the name spaces are completely separate. That is, if <~i~>
you use a particular character or string as a :map short-form and <~i~>
also as a :map! short-form; for example: <~i~>
<~i~>
:map }} :!wc -w %Control-M <~i~>
:map! }} Control-[j0R <~i~>
<~i~>
there is no conflict. The editor will allow both mappings, and <~i~>
will use the correct long-form based on the context; whether you <~i~>
typed }} from command or text-insertion submode. As the first <~i~>
example above shows, your command string can include any of the <~i~>
line-mode commands that can be invoked from screen mode, providing <~i~>
you begin each one with a colon ":" as you would when invoking it <~i~>
directly while in screen mode, and quote in a Control-M (the RETURN <~i~>
character) to terminate the command. <~i~>
<~i~>
Suppose that you ran the two following setup commands, either one <~i~>
first: <~i~>
<~i~>
:map Q 2dd <~i~>
:map V 3jQ <~i~>
<~i~>
The first command clearly provides that the Q command, which <~i~>
ordinarily is the command that takes you out of screen mode and <~i~>
into line mode, does not do that any more. Instead, it now deletes <~i~>
two lines, and you now have no way to leave screen mode without <~i~>
unmapping the "Q" character. But what does the new V do? <~i~>
<~i~>
If you've left the :set command's remap option turned on, its <~i~>
default value, then the V drops down three lines and then deletes <~i~>
that third line and the one following. That is, when it comes to <~i~>
the "Q" character in that mapping, it discovers that "Q" itself has <~i~>
been mapped, and brings in the mapped value of "Q". But if you had <~i~>
previously run a :se noremap command, then the editor would not <~i~>
check for any mappings of the characters within a macro, and would <~i~>
use the standard meaning of "Q" when it executed the "V" macro. So <~i~>
then typing a "V" character would move you down three lines and <~i~>
then put you into line-editing mode. (Yes, that means that while <~i~>
you would no longer be able to execute the Q as itself directly, <~i~>
your macros could still access it!) <~i~>
<~i~>
Buffer Macros <~i~>
<~i~>
There are limits to the amount of macro text you can store by <~i~>
mapping it -- not as severe now as with earlier versions of the <~i~>
editor, but still somewhat confining. To remedy that, the editor <~i~>
offers a quite-similar tool with practically unlimited storage. It <~i~>
involves those buffers where you store text pulled from your file, <~i~>
for later reinsertion at various places. Specifically I mean the <~i~>
twenty-six buffers named "a" through "z". <~i~>
<~i~>
From screen-editing command sub-mode, you can type an at-sign "@" <~i~>
followed by a letter of the alphabet, and the editor will take the <~i~>
contents of the buffer with that letter-name and execute it as a <~i~>
screen-mode command string. For example, if you have "0d3w" <~i~>
(without the quotation marks) stored in named-buffer "k", then <~i~>
typing @k will delete the first three words on the current line. <~i~>
After you start using this method in your editing session, there's <~i~>
an extra added convenience available: typing @@ will repeat the <~i~>
last such buffer command you ran. <~i~>
<~i~>
To put a command into a named buffer, get the line or lines of your <~i~>
command into your file one way or another, then delete or yank them <~i~>
into the buffer of your choice, as by: <~i~>
<~i~>
"p3dd <~i~>
:ya m <~i~>
<~i~>
to delete a three-line macro into buffer "p" and yank a one-line <~i~>
macro into buffer "m", respectively. You need not tell the editor <~i~>
that you regard the contents of a buffer as a command macro until <~i~>
you choose to execute it with a "@" command. In fact, you can use <~i~>
a buffer's contents both ways, executing it as a command at one <~i~>
moment and putting it back into your file as text the next. <~i~>
<~i~>
One important difference from macros created by mapping: if you <~i~>
need a linebreak character in a buffer macro, don't try to quote it <~i~>
in. Instead, type it in the ordinary way, so that it forms a line <~i~>
break between two lines of your macro text. And don't break a line <~i~>
in your macro text for any other reason, because the linebreak <~i~>
characte r that appears there will be treated as a command <~i~>
character by the editor when you execute the buffer contents as an <~i~>
editing command string. <~i~>
<~i~>
:source Macros <~i~>
<~i~>
Line-mode commands have a macro tool in this editor, too. Of <~i~>
course you can insert most line-mode commands in the previous two <~i~>
types of macros, but this tool is dedicated entirely to line-mode <~i~>
commands, and can include even commands that can't be run <~i~>
interactively from screen mode via a preceding colon. The only <~i~>
line-mode commands that can't be run with this tool are the visual <~i~>
and open commands. With this tool, you set up your macros by <~i~>
putting their commands into one or more files, then invoke them <~i~>
with command lines like: <~i~>
<~i~>
:so /u/myname/commands.1 <~i~>
<~i~>
Your command files should contain strictly line-mode commands, one <~i~>
per line unless you separate them within the line by pipe "|" <~i~>
characters, and should not have a colon before each command. The <~i~>
other restrictions depend on how you plan to invoke your macro <~i~>
files. Ideally you should give your source commands while you are <~i~>
in line mode -- then the above limitations are all you will face. <~i~>
But if you insist on invoking :source while in screen mode, there <~i~>
are two other limitations: <~i~>
<~i~>
Only the first line of your command file will execute. Due to the <~i~>
editor restriction against running multi-line line-mode commands <~i~>
while in screen mode, all lines after the first in your command <~i~>
file will be silently discarded. <~i~>
<~i~>
If your first command is not complete on the first line (for <~i~>
instance, an append is not), even that command will not execute. <~i~>
In this case the failure will not be silent. <~i~>
<~i~>
Another Exercise. <~i~>
<~i~>
So if you want to source in command files from within screen mode, <~i~>
it's a very good idea to create one-line command files. But there <~i~>
will be a few cases where multi-line command files will be a <~i~>
worthwhile thing, even when you may be invoking them from screen <~i~>
mode. Here's an easy exercise for you: come up with a specific <~i~>
case in which a command file that you may source in from either <~i~>
line or screen mode should nonetheless have more than one line. Of <~i~>
course there are multiple possibilities here, so don't be disturbed <~i~>
if the solution that occurs to you is not one of those I <~i~>
arbitrarily chose for my answer. <~i~>
<~i~>
When you really get into sourcing, you'll be pleased to know that <~i~>
:source files can contain commands to call other :source files. <~i~>
This is the basis for truly modular editor scripts, and for a raft <~i~>
of rather tricky maneuvers. It also saves typing when you need to <~i~>
invoke a source file from screen mode, but the list of commands is <~i~>
simply too long to fit on one line: a single line in your initial <~i~>
source file is long enough to call a very large number of other <~i~>
source files, each with a single long line of commands. You will <~i~>
probably find that invoking nested :source files from line mode <~i~>
will turn off line mode's colon prompt, but you can turn it back on <~i~>
again via a :se prompt command. <~i~>
<~i~>
Write and Read Macros <~i~>
<~i~>
The Vi/Ex editor has tools for running some or all of the lines in <~i~>
the file you're editing through a program outside the editor, then <~i~>
using the transformed lines to replace the original lines in your <~i~>
file. It can also run a program with any or no input and insert the <~i~>
program's output in your file, or write some or all of your file <~i~>
lines as input to a program that may send its output anywhere. <~i~>
<~i~>
And where is the macro capability in all this? Well, when you use <~i~>
these tools you are not limited to standard Unix utilities as your <~i~>
outside programs -- your own coding will do just as well. Compiled <~i~>
or scripted, one line or a thousand, in a standard language like C <~i~>
or Perl or in a specialized one such as Snobol; the rule is that if <~i~>
your Unix system will execute it, the editor can pass it over your <~i~>
text. <~i~>
<~i~>
This tutorial is not going to get into writing these personal text <~i~>
processors, in any language, so I will only be explaining how to <~i~>
send your text in and/or out via editor tools. In the examples <~i~>
below, I will suppose you have a text-processing program named <~i~>
myhack that lives within your searchpath. <~i~>
<~i~>
[Editor's note: One external program I use frequently reformats <~i~>
paragraphs into nicely looking text blocks that are easier to read. <~i~>
I use the program named reform, published on pages 320-321 in the <~i~>
first edition of the famous book Programming Perl by Larry Wall and <~i~>
Randal L. Schwartz. At first blush you may ask, why use such an <~i~>
external program when I can simply set Vi's wrapmargin variable? <~i~>
Of course, the answer is how do you easily reform paragraphs that <~i~>
are already ragged, say due to the problem Walter posed above <~i~>
(using find and replace to expand abbreviations, instead of <~i~>
expanding abbreviations using the built-in Vi abbreviation macro <~i~>
facility?] <~i~>
<~i~>
Note that the command to execute the outside program should be <~i~>
typed as you would type it at your shell prompt, because it will be <~i~>
passed to the shell intact except for the addition of input and/or <~i~>
output redirection. <~i~>
<~i~>
If you want to take some (or all) of the lines out of your file, <~i~>
use them as input to your outside program, then put the resulting <~i~>
output in place of the original lines, you can use either a <~i~>
line-mode or a screen-mode command to do it, as shown below: <~i~>
<~i~>
:196,254 ! myhack -n6 <~i~>
!L myhack -n6 <~i~>
12!! myhack -n6 <~i~>
!/^CHAPTER/- myhack -n6 <~i~>
<~i~>
The line-mode command can be invoked from line mode, or from screen <~i~>
mode by preceding it with a colon. In either case, you give an <~i~>
address or address range, next the exclamation point, then <~i~>
everything following until you type return is passed to the shell <~i~>
as a command line. The line-mode command must have at least one <~i~>
address because there is no default address for this command. But <~i~>
the whitespace I show before and after the exclamation point is <~i~>
permissible but not necessary; I put it in solely for readability. <~i~>
<~i~>
Screen-mode command form is the exclamation point as the command <~i~>
name, followed by the target address, then the outside command <~i~>
(with arguments and/or whitespace as would be required or permitted <~i~>
on your shell command line), ending when you hit the escape or <~i~>
return key. As with the c d y commands, you can type two <~i~>
consecutive exclamation points to send just the current line, and <~i~>
use a count to send that number of lines as shown in my third <~i~>
example command. The last example involves an extra escape <~i~>
character -- at the end of a search pattern address, whether / or ? <~i~>
based and including any + or - suffix, you must press the escape <~i~>
key before you start typing the outside command. <~i~>
<~i~>
You're not limited to just one outside program at a time. You can <~i~>
pipeline two or more together as your shell permits, ordinarily <~i~>
with the "|" character. (Because a | character and what follows it <~i~>
will be passed to the shell, this editor command cannot appear in a <~i~>
line-mode command string, including a :global string, unless it is <~i~>
the last command in the string.) The final output of the pipeline <~i~>
is what will go into your file. And you can undo the effect of the <~i~>
outside command or pipeline, putting your file back the way it was, <~i~>
with a u command. <~i~>
<~i~>
You may not want your text to make a round trip, though. You may <~i~>
want to send your text, as modified by your outside program, off to <~i~>
some other destination, or you may want to pull some text into your <~i~>
file that originated in your outside program, or was taken from <~i~>
some outside source. In these cases, use the line-mode commands <~i~>
that appear below: <~i~>
<~i~>
:1,.w ! myhack -n6 > nufile <~i~>
:217r ! myhack -n6 < oldfile <~i~>
<~i~>
The first command above sends the initial lines from the file you <~i~>
are editing as input to your myhack program, and redirects the <~i~>
output to a file. It does not erase the affected lines from the <~i~>
file you are editing. The second runs your myhack program using <~i~>
the contents of another file as the input, then places the output <~i~>
in the file you are editing, right after line 217. <~i~>
<~i~>
Both line-mode commands are shown with addresses, but they are not <~i~>
necessary. The default address for a :write command is the entire <~i~>
file; for a :read command, right after the current line. The space <~i~>
character just before the exclamation-point flag after each command <~i~>
is absolutely essential; without it you would get something greatly <~i~>
different from what you expected. <~i~>
<~i~>
Usually there will be output redirection for the :write ! command, <~i~>
and input redirection for the :read ! command, but not always. For <~i~>
example, you may want to :read ! an outside command that generates <~i~>
a pseudo-random number, using no input at all. When you do need <~i~>
input or output, you can build the necessary redirection into your <~i~>
outside program or you can put the redirection on the command line <~i~>
as shown above, using your own shell's notation. <~i~>
<~i~>
In The Next Installment of this Tutorial <~i~>
<~i~>
I'll be putting the techniques I've taught so far to work, showing <~i~>
how to set up the editor for special purposes. Your suggestions on <~i~>
what special purposes to consider are welcome, of course. One <~i~>
purpose that is already in my mind is an arrangement of the editor <~i~>
for computerphobes: very simple, with beginner features such as <~i~>
"stateless" editing, and fortified against common user errors. <~i~>
<~i~>
SIDEBAR: The timeout Function <~i~>
<~i~>
The :set command's timeout option seems arcane in purpose and <~i~>
tricky to use, at least to some editor users. But it becomes <~i~>
pretty plain when you know why and how it actually works. <~i~>
<~i~>
Basically, when the timeout option is on (its default state) and <~i~>
you type in a short form you've set up by a :map or :map! command, <~i~>
you must type the entire short form in no more than one second. If <~i~>
you miss that deadline, the editor will ignore the metavalue, and <~i~>
take the characters you've typed at their face value. <~i~>
<~i~>
This odd requirement serves a purpose; preventing deadlock. As an <~i~>
example, suppose you have defined "DD" (without the quotation <~i~>
marks) as a macro via the :map command, and have turned off the <~i~>
timeout option. Now, while editing, you type a plain D command to <~i~>
delete part of a line. When the editor receives this single "D" it <~i~>
is uncertain what to do. Are you actually telling it to delete <~i~>
that partial line? Or are you starting to type in your double-D <~i~>
macro? The only way the editor can resolve this question is to <~i~>
wait and see what character you type in next. But if you are <~i~>
waiting to see the result of your deletion before you do any more <~i~>
editing, the mutual wait will last indefinitely. With the timeout <~i~>
option left turned on, the wait will only be a second or so before <~i~>
the editor acts on your D command. <~i~>
<~i~>
One moral of this story is to leave timeout on unless you have a <~i~>
compelling reason to turn it off, and choose your macro names so <~i~>
that you can easily type them in within the one-second limit. If <~i~>
you are not particularly nimble fingered, or if other people may be <~i~>
using your editor macros, then for practical purposes this means <~i~>
either a single character or two repetitions of one character as in <~i~>
my example above. (Some fussy versions of the editor will refuse to <~i~>
map anything except a single character.) <~i~>
<~i~>
Another moral is to avoid certain macro names, such as "jj" (again, <~i~>
without the quotation marks). The standard address j is one that <~i~>
you might want to type twice in rapid succession, to move directly <~i~>
down two lines without the trouble of reaching away from the <~i~>
central keyboard to hit the 2 key. But the user with a macro named <~i~>
jj had better not move down too quickly via that method, or he/she <~i~>
will accidentally invoke the macro of that name. <~i~>
<~i~>
Finally, you should realize that the one-second count before timing <~i~>
out is not hair-splittingly accurate. The design of the standard <~i~>
Unix software clock means that the time-out interval may be a <~i~>
little less or somewhat more than precisely one second. <~i~>
<~i~>
<~i~>
Back to the index/
<< see line 3382 >>
Back to the index/
<< see line 3382 >>
Automatic Indentation <~i~>
Backing off Indentation <~i~>
Juggling a few ':set' options <~i~>
An Exercise for You <~i~>
Hard Tabs <~i~>
Enable and Disable 'autoindent' <~i~>
Next Time <~i~>
Part 9: Take Charge with Macros/
The vi/ex Editor, Part 9: Take Charge with Macros <~i~>
<~i~>
Text-Insertion Macros <~i~>
<~i~>
What These Tools Do <~i~>
Working Principles <~i~>
Time for another exercise <~i~>
<~i~>
Command-Submode Macros <~i~>
<~i~>
:map Macros <~i~>
Buffer Macros <~i~>
:source Macros <~i~>
Another Exercise <~i~>
Write and Read Macros <~i~>
<~i~>
Text-Insertion Macros <~i~>
<~i~>
As befits an editor with all those built-in metacharacters that <~i~>
operate while you are typing in text, there are two ways to create <~i~>
your own macros for use during text insertion. Both can be useful <~i~>
in the right circumstances, so you'll probably want to put them to <~i~>
work at times. You may not have a choice -- often the .exrc file <~i~>
that you may be given when you get a new Unix shell account has <~i~>
some of these shorthand dodges built in. These two tools have as <~i~>
many similarities as differences, so I will expound them in <~i~>
parallel. <~i~>
<~i~>
What These Tools Do <~i~>
<~i~>
Both tools act only when you are in text-insertion submode of <~i~>
screen-editing mode. Nonetheless, the commands that set them up <~i~>
and manage them are line-mode commands like: <~i~>
<~i~>
:ab ucb University of California at Berkeley <~i~>
:map! } Control-[k2cc <~i~>
<~i~>
The two example lines above will set up two shorthand forms that <~i~>
you can use without further preliminaries. The first line provides <~i~>
that whenever you type "ucb" as a separate word in your text, the <~i~>
editor will replace it with "University of California at Berkeley". <~i~>
It happens right on the spot, and without any special signal from <~i~>
you. <~i~>
<~i~>
The second line is for use if you frequently discover that what you <~i~>
are typing has become a mess, and that the mess started back on the <~i~>
previous line. With this shorthand form in effect, whenever there <~i~>
is a "}" character in what you type in, the editor removes it and <~i~>
instead acts as if you had typed in "Control-[k2cc". That is, the <~i~>
Control-[ (generated by the "Escape" key on your keyboard) causes <~i~>
the editor to escape from text-insertion to command mode, the "k" <~i~>
causes the cursor to move up a line, and the "2cc" removes both of <~i~>
the lines involved and puts you back in text-insertion mode, ready <~i~>
to type in a replacement for those lines and continue on with your <~i~>
text insertion. As with the previous tool, this happens as soon as <~i~>
you type in the shorthand form, without any special action by you. <~i~>
<~i~>
Note that whitespace separates either of these setup commands into <~i~>
three parts. The first part, from the start of the line up to the <~i~>
first stretch of whitespace, is just the command name. Part two, <~i~>
between the first and second stretches of whitespace, is the short <~i~>
form that you will type into the text. The third part, everything <~i~>
following the second stretch of whitespace, is what the editor will <~i~>
insert (and/or execute) when you type in the short form. Only the <~i~>
first two stretches of whitespace are separators -- any later <~i~>
stretches are integral components of part three. And whitespace <~i~>
includes both space characters and tabs, in any mixture. <~i~>
<~i~>
Working Principles <~i~>
<~i~>
Now that you've seen what these two tools do, let's consider how <~i~>
they work: <~i~>
<~i~>
:abbreviate <~i~>
<~i~>
(Shortest abbreviation is :ab). This tool acts when you type in a <~i~>
certain character or string as a separate word, each end bounded by <~i~>
whitespace, or a punctuation character, or the start or end of a <~i~>
line, or the start or end of an insertion. As soon as the editor <~i~>
sees that the abbreviation is a word by itself, it replaces that <~i~>
abbreviation with the longer word or phrase you have set as <~i~>
equivalent. <~i~>
<~i~>
As an example, you might have declared "cat" as your abbreviation <~i~>
for "felix domesticus". Then, wherever you type in a line such as <~i~>
"the habits of the common cat include", the editor will promptly <~i~>
change it to read "the habits of the common felix domesticus <~i~>
include". But there will be no such change in words that happen to <~i~>
include the string "cat" in them, such as "catamaran" or <~i~>
"concatenation". Be careful with this, because while the word <~i~>
"catlike" will not be changed, the word "cat-like" will be. <~i~>
<~i~>
Neither a backslash (\) nor a control-V will quote an abbreviation <~i~>
into a file as itself. Usually, the easiest way to insert an <~i~>
abbreviation into your text is to escape from text-insertion <~i~>
submode (back to command submode) in the middle of typing the <~i~>
abbreviation, then re-enter text-insertion submode and type in the <~i~>
rest of the abbreviation. If your abbreviation is only one <~i~>
character long, though, you must fall back on typing the <~i~>
abbreviation with a letter immediately before or after it, then <~i~>
returning to command submode to erase the unwanted extra letter. <~i~>
<~i~>
:map! <~i~>
<~i~>
(No editor-accepted abbreviation). Very similar to the abbreviation <~i~>
tool discussed above, but with three major differences: <~i~>
<~i~>
The shorthand form defined with this command does not need to be <~i~>
typed into your inserted text as a separate word in order to <~i~>
operate. Even if it is embedded within another word, the short form <~i~>
will disappear and its related text will be entered in its place. <~i~>
<~i~>
This tool does not simply insert the related text into the file, as <~i~>
the :abbreviate tool does; it acts as though the user had typed in <~i~>
the related text instead of the short form. That is, if there is <~i~>
an escape character in the related text, that escape will put the <~i~>
editor back into command submode, and interpret any following <~i~>
characters as screen-mode commands. (Unless one of those <~i~>
characters returns you to text insertion submode -- then characters <~i~>
following that insert-text command will be all be put into the <~i~>
file, unless and until there is another escape character.) That <~i~>
makes accidentally triggering this tool rather dangerous. <~i~>
<~i~>
Quoting in a character or string that you've defined as a short <~i~>
form via this command is simple. Type control-V before the <~i~>
metacharacter, or the first character of the metastring, and into <~i~>
the text it goes. Even that may not be required if you are dealing <~i~>
with a metastring, and if the timeout option to the :set command is <~i~>
still in its default state: turned on. In this case, all you need <~i~>
to do is be sure that you take more than one full second to type in <~i~>
the entire metastring, and it will have no meta effect. (This, by <~i~>
the way, is one reason that this tool's metastrings should be short <~i~>
-- so you can depend on being able to type one of them in less than <~i~>
a full second when you do want the metavalue.) <~i~>
<~i~>
Questions naturally arise regarding these tools. One frequent <~i~>
query is why anyone would want to mess around with :abbreviate when <~i~>
it seems much easier to do a general substitution command when the <~i~>
document is complete. That is, instead of that abbreviation I set <~i~>
up at the start of this explanation, just run a <~i~>
:%s/\<ucb\>/University of California at Berkeley/g command <~i~>
after all the text has been entered. There are several reasons to <~i~>
use Vi's abbreviation feature instead: <~i~>
<~i~>
It's not hard to unknowingly type in your abbreviated string where <~i~>
you don't want it expanded, as in a direct quotation (Savio told <~i~>
the students, "We don't want ucb to get the upper hand!"), or where <~i~>
it has an entirely different meaning (Next, punch in the code: aQr <~i~>
PxN ucb JHt.) Using the substitution command above, you would never <~i~>
see that these sentences were being disfigured. But with <~i~>
on-the-spot replacement the mistaken use would be right in your <~i~>
face. <~i~>
<~i~>
Lines can get very long when abbreviations are expanded, especially <~i~>
when there are several abbreviations in one line. When you use a <~i~>
general substitution command after text entry, there's no way to <~i~>
know that certain lines have become unreasonably long. But with <~i~>
the :abbreviate tool, you see the final length of each line as you <~i~>
go along. And if you use the wrapmargin option to the :set <~i~>
command, line breaks will generally be inserted after any <~i~>
abbreviations have been expanded. <~i~>
<~i~>
It's easy to forget to run a general substitution command. But a <~i~>
:abbreviate command can be made automatic by putting it in a .exrc <~i~>
file, and the user can see while typing whether it is or is not in <~i~>
operation. <~i~>
<~i~>
This tool can do more than save typing. For example, suppose a <~i~>
technical writer is in the habit of typing "unix", while company <~i~>
policy requires "UNIX(R)". Either a general substitution or the <~i~>
:abbreviate tool will correct that writer's recurring errors, but <~i~>
only the latter will continuously teach him that "unix" is not to <~i~>
be used. As another example, consider a writer who begins far too <~i~>
many sentences with the word "The", which makes for dull reading. A <~i~>
:ab The DON'T OVERDO IT! command will ensure that every time this <~i~>
writer types the word "The" at the start of the sentence, it will <~i~>
promptly be transmuted into the billboard phrase "DON'T OVERDO <~i~>
IT!", which can be backspaced over to insert a new sentence <~i~>
beginning. Note that this will not be triggered by words such as <~i~>
"These" or "Then", nor by the word "the" in the middle of a <~i~>
sentence. <~i~>
<~i~>
Another common question concerns precedence of metacharacters. You <~i~>
can use most of the text-input metacharacters I've discussed <~i~>
previously as short-form names in :map! commands. Suppose you did <~i~>
use control-D as such a short form -- what would happen when you <~i~>
typed control-D at the start of an autoindented line? Would it <~i~>
wipe out the indentation or type in the phrase that :map! has <~i~>
associated with it? Or if you used control-H as a short form? <~i~>
When you subsequently typed a control-H during text entry, would <~i~>
the cursor back up a space, or would type in a stored phrase? <~i~>
<~i~>
The answer is that the :map! value would prevail. By preceding <~i~>
either character with a control-V, you could type in in as itself, <~i~>
but there would be no way to use the ordinary metavalue of either <~i~>
character. If you were to map control-D followed immediately by <~i~>
another control-D or two consecutive control-H characters or any <~i~>
other doubling of an ordinary metacharacter, the situation would be <~i~>
more complex. You could then type the two control-D or control-Hs <~i~>
within one second to get the mapped text typed in, or you could <~i~>
type control-D or control-H followed by a one-second pause to <~i~>
invoke the ordinary metavalue. <~i~>
<~i~>
Time for another exercise. <~i~>
<~i~>
Suppose that you used control-D or control-H as a short form with <~i~>
the :abbreviate command. Or suppose that you used some ordinary <~i~>
character string as both an abbreviation and a mapping short form. <~i~>
(The editor will allow you to do this.) What would happen when you <~i~>
typed in this double-use short form during text insertion? This <~i~>
exercise is straightforward enough that I expect most of you will <~i~>
find the correct answer before you look at my solution. <~i~>
<~i~>
Two final warnings. Do not try to define a non-alphanumeric <~i~>
character or string as a short form with the :abbreviate command. <~i~>
You probably will be able to do this -- the editor won't object -- <~i~>
but when you try to use this abbreviation, nothing will happen. <~i~>
And with either :abbreviate or :map!, do not put any metacharacter <~i~>
as itself into the long-form string. Even if you manage to get it <~i~>
into the string as itself, it will not go into your text that way. <~i~>
<~i~>
What if you have forgotten what short forms you have set up, or are <~i~>
uncertain as to whether some may have been set up for you via a <~i~>
.exrc startup file? Well, you can query either tool ju st by <~i~>
giving its setup command without any arguments. Here are examples <~i~>
of those queries, with the responses you might receive from the <~i~>
editor: <~i~>
<~i~>
:ab <~i~>
cat cat felix domesticus <~i~>
wolf wolf canis lupus <~i~>
<~i~>
:map! <~i~>
{ { ^[o^I^IThe End^[ <~i~>
} } ^[o^I^I-XXX-^[ <~i~>
~ ~ (more to come)^[ <~i~>
<~i~>
Note that each response line has at least three strings of printing <~i~>
characters, separated by whitespace. It's that second string in a <~i~>
line that is the short form; the string that when typed in will be <~i~>
replaced by the last string shown. (Yes, in every example line <~i~>
above the first string is identical to the second, but that isn't <~i~>
always so.) The last string is what will be inserted and/or <~i~>
executed. <~i~>
<~i~>
So now you know what characters and strings will have to be quoted <~i~>
in when you want to insert them as themselves. And if one or more <~i~>
of those short forms is something you will be typing in so often <~i~>
that you can't spare the time to quote it in each time you use it, <~i~>
you can disable the metavalue for the rest of the present editing <~i~>
session. Just give the command name for the tool that uses this <~i~>
short form but precede it with "un", and as the only argument give <~i~>
the short form you want to disable. For example, here are the <~i~>
commands that will disable the first entry in each of the lists <~i~>
above: <~i~>
<~i~>
:unab cat <~i~>
:unmap! { <~i~>
<~i~>
Command-Submode Macros <~i~>
<~i~>
It's common that a text editor has a facility that lets a user <~i~>
create personalized commands, usually as macros built on existing <~i~>
commands. The Vi/Ex editor has four such facilities -- something <~i~>
for every need. While these facilities don't have the low-level <~i~>
programmability of mock-Lisp, they can accomplish a lot to simplify <~i~>
your editing, and you don't need to learn a programming language to <~i~>
use them. <~i~>
<~i~>
I'll be discussing each facility (or family) in its own section <~i~>
below, because their structures are quite different. Nonetheless, <~i~>
you can often combine them to go od effect, by using a macro of one <~i~>
type to call a macro of a different type. <~i~>
<~i~>
:map Macros <~i~>
<~i~>
This is the editor tool that's closest to what most users think of <~i~>
as a macro facility. It uses the command :map as its setup tool, <~i~>
and the macros it creates operate when the user is in command <~i~>
submode of screen-editing mode. Otherwise it works just the way <~i~>
its very close relative, the :map! tool, works -- which I explained <~i~>
in depth in the first half of this tutorial part, above. Consider <~i~>
the three command lines below: <~i~>
<~i~>
:map v :!wc -w %Control-M <~i~>
:unmap v <~i~>
:map <~i~>
<~i~>
The first line sets up a macro that does a word count on the file I <~i~>
am editing, as of the last write to storage, whenever I type the <~i~>
letter v from command submode while I am screen editing. The <~i~>
second unsets that macro, so that a v command no longer does <~i~>
anything. The third displays a list of the :map macros that are <~i~>
currently in effect. All this should be transparently plain to <~i~>
readers who understand the :map! tool. Still, there are a few <~i~>
points worth noting that are particularly applicable to the :map <~i~>
side of the family. <~i~>
<~i~>
Choosing a short-form for :map macros should not be difficult. <~i~>
Half a dozen of the printing ASCII characters and many of the <~i~>
control characters are not used as screen-editing commands or <~i~>
addresses. Hardly any strings of two duplicate characters (such as <~i~>
"DD" above) are in use, and most editor versions will let you map <~i~>
such strings. You don't need to avoid duplicating your :map! short <~i~>
forms because the name spaces are completely separate. That is, if <~i~>
you use a particular character or string as a :map short-form and <~i~>
also as a :map! short-form; for example: <~i~>
<~i~>
:map }} :!wc -w %Control-M <~i~>
:map! }} Control-[j0R <~i~>
<~i~>
there is no conflict. The editor will allow both mappings, and <~i~>
will use the correct long-form based on the context; whether you <~i~>
typed }} from command or text-insertion submode. As the first <~i~>
example above shows, your command string can include any of the <~i~>
line-mode commands that can be invoked from screen mode, providing <~i~>
you begin each one with a colon ":" as you would when invoking it <~i~>
directly while in screen mode, and quote in a Control-M (the RETURN <~i~>
character) to terminate the command. <~i~>
<~i~>
Suppose that you ran the two following setup commands, either one <~i~>
first: <~i~>
<~i~>
:map Q 2dd <~i~>
:map V 3jQ <~i~>
<~i~>
The first command clearly provides that the Q command, which <~i~>
ordinarily is the command that takes you out of screen mode and <~i~>
into line mode, does not do that any more. Instead, it now deletes <~i~>
two lines, and you now have no way to leave screen mode without <~i~>
unmapping the "Q" character. But what does the new V do? <~i~>
<~i~>
If you've left the :set command's remap option turned on, its <~i~>
default value, then the V drops down three lines and then deletes <~i~>
that third line and the one following. That is, when it comes to <~i~>
the "Q" character in that mapping, it discovers that "Q" itself has <~i~>
been mapped, and brings in the mapped value of "Q". But if you had <~i~>
previously run a :se noremap command, then the editor would not <~i~>
check for any mappings of the characters within a macro, and would <~i~>
use the standard meaning of "Q" when it executed the "V" macro. So <~i~>
then typing a "V" character would move you down three lines and <~i~>
then put you into line-editing mode. (Yes, that means that while <~i~>
you would no longer be able to execute the Q as itself directly, <~i~>
your macros could still access it!) <~i~>
<~i~>
Buffer Macros <~i~>
<~i~>
There are limits to the amount of macro text you can store by <~i~>
mapping it -- not as severe now as with earlier versions of the <~i~>
editor, but still somewhat confining. To remedy that, the editor <~i~>
offers a quite-similar tool with practically unlimited storage. It <~i~>
involves those buffers where you store text pulled from your file, <~i~>
for later reinsertion at various places. Specifically I mean the <~i~>
twenty-six buffers named "a" through "z". <~i~>
<~i~>
From screen-editing command sub-mode, you can type an at-sign "@" <~i~>
followed by a letter of the alphabet, and the editor will take the <~i~>
contents of the buffer with that letter-name and execute it as a <~i~>
screen-mode command string. For example, if you have "0d3w" <~i~>
(without the quotation marks) stored in named-buffer "k", then <~i~>
typing @k will delete the first three words on the current line. <~i~>
After you start using this method in your editing session, there's <~i~>
an extra added convenience available: typing @@ will repeat the <~i~>
last such buffer command you ran. <~i~>
<~i~>
To put a command into a named buffer, get the line or lines of your <~i~>
command into your file one way or another, then delete or yank them <~i~>
into the buffer of your choice, as by: <~i~>
<~i~>
"p3dd <~i~>
:ya m <~i~>
<~i~>
to delete a three-line macro into buffer "p" and yank a one-line <~i~>
macro into buffer "m", respectively. You need not tell the editor <~i~>
that you regard the contents of a buffer as a command macro until <~i~>
you choose to execute it with a "@" command. In fact, you can use <~i~>
a buffer's contents both ways, executing it as a command at one <~i~>
moment and putting it back into your file as text the next. <~i~>
<~i~>
One important difference from macros created by mapping: if you <~i~>
need a linebreak character in a buffer macro, don't try to quote it <~i~>
in. Instead, type it in the ordinary way, so that it forms a line <~i~>
break between two lines of your macro text. And don't break a line <~i~>
in your macro text for any other reason, because the linebreak <~i~>
characte r that appears there will be treated as a command <~i~>
character by the editor when you execute the buffer contents as an <~i~>
editing command string. <~i~>
<~i~>
:source Macros <~i~>
<~i~>
Line-mode commands have a macro tool in this editor, too. Of <~i~>
course you can insert most line-mode commands in the previous two <~i~>
types of macros, but this tool is dedicated entirely to line-mode <~i~>
commands, and can include even commands that can't be run <~i~>
interactively from screen mode via a preceding colon. The only <~i~>
line-mode commands that can't be run with this tool are the visual <~i~>
and open commands. With this tool, you set up your macros by <~i~>
putting their commands into one or more files, then invoke them <~i~>
with command lines like: <~i~>
<~i~>
:so /u/myname/commands.1 <~i~>
<~i~>
Your command files should contain strictly line-mode commands, one <~i~>
per line unless you separate them within the line by pipe "|" <~i~>
characters, and should not have a colon before each command. The <~i~>
other restrictions depend on how you plan to invoke your macro <~i~>
files. Ideally you should give your source commands while you are <~i~>
in line mode -- then the above limitations are all you will face. <~i~>
But if you insist on invoking :source while in screen mode, there <~i~>
are two other limitations: <~i~>
<~i~>
Only the first line of your command file will execute. Due to the <~i~>
editor restriction against running multi-line line-mode commands <~i~>
while in screen mode, all lines after the first in your command <~i~>
file will be silently discarded. <~i~>
<~i~>
If your first command is not complete on the first line (for <~i~>
instance, an append is not), even that command will not execute. <~i~>
In this case the failure will not be silent. <~i~>
<~i~>
Another Exercise. <~i~>
<~i~>
So if you want to source in command files from within screen mode, <~i~>
it's a very good idea to create one-line command files. But there <~i~>
will be a few cases where multi-line command files will be a <~i~>
worthwhile thing, even when you may be invoking them from screen <~i~>
mode. Here's an easy exercise for you: come up with a specific <~i~>
case in which a command file that you may source in from either <~i~>
line or screen mode should nonetheless have more than one line. Of <~i~>
course there are multiple possibilities here, so don't be disturbed <~i~>
if the solution that occurs to you is not one of those I <~i~>
arbitrarily chose for my answer. <~i~>
<~i~>
When you really get into sourcing, you'll be pleased to know that <~i~>
:source files can contain commands to call other :source files. <~i~>
This is the basis for truly modular editor scripts, and for a raft <~i~>
of rather tricky maneuvers. It also saves typing when you need to <~i~>
invoke a source file from screen mode, but the list of commands is <~i~>
simply too long to fit on one line: a single line in your initial <~i~>
source file is long enough to call a very large number of other <~i~>
source files, each with a single long line of commands. You will <~i~>
probably find that invoking nested :source files from line mode <~i~>
will turn off line mode's colon prompt, but you can turn it back on <~i~>
again via a :se prompt command. <~i~>
<~i~>
Write and Read Macros <~i~>
<~i~>
The Vi/Ex editor has tools for running some or all of the lines in <~i~>
the file you're editing through a program outside the editor, then <~i~>
using the transformed lines to replace the original lines in your <~i~>
file. It can also run a program with any or no input and insert the <~i~>
program's output in your file, or write some or all of your file <~i~>
lines as input to a program that may send its output anywhere. <~i~>
<~i~>
And where is the macro capability in all this? Well, when you use <~i~>
these tools you are not limited to standard Unix utilities as your <~i~>
outside programs -- your own coding will do just as well. Compiled <~i~>
or scripted, one line or a thousand, in a standard language like C <~i~>
or Perl or in a specialized one such as Snobol; the rule is that if <~i~>
your Unix system will execute it, the editor can pass it over your <~i~>
text. <~i~>
<~i~>
This tutorial is not going to get into writing these personal text <~i~>
processors, in any language, so I will only be explaining how to <~i~>
send your text in and/or out via editor tools. In the examples <~i~>
below, I will suppose you have a text-processing program named <~i~>
myhack that lives within your searchpath. <~i~>
<~i~>
[Editor's note: One external program I use frequently reformats <~i~>
paragraphs into nicely looking text blocks that are easier to read. <~i~>
I use the program named reform, published on pages 320-321 in the <~i~>
first edition of the famous book Programming Perl by Larry Wall and <~i~>
Randal L. Schwartz. At first blush you may ask, why use such an <~i~>
external program when I can simply set Vi's wrapmargin variable? <~i~>
Of course, the answer is how do you easily reform paragraphs that <~i~>
are already ragged, say due to the problem Walter posed above <~i~>
(using find and replace to expand abbreviations, instead of <~i~>
expanding abbreviations using the built-in Vi abbreviation macro <~i~>
facility?] <~i~>
<~i~>
Note that the command to execute the outside program should be <~i~>
typed as you would type it at your shell prompt, because it will be <~i~>
passed to the shell intact except for the addition of input and/or <~i~>
output redirection. <~i~>
<~i~>
If you want to take some (or all) of the lines out of your file, <~i~>
use them as input to your outside program, then put the resulting <~i~>
output in place of the original lines, you can use either a <~i~>
line-mode or a screen-mode command to do it, as shown below: <~i~>
<~i~>
:196,254 ! myhack -n6 <~i~>
!L myhack -n6 <~i~>
12!! myhack -n6 <~i~>
!/^CHAPTER/- myhack -n6 <~i~>
<~i~>
The line-mode command can be invoked from line mode, or from screen <~i~>
mode by preceding it with a colon. In either case, you give an <~i~>
address or address range, next the exclamation point, then <~i~>
everything following until you type return is passed to the shell <~i~>
as a command line. The line-mode command must have at least one <~i~>
address because there is no default address for this command. But <~i~>
the whitespace I show before and after the exclamation point is <~i~>
permissible but not necessary; I put it in solely for readability. <~i~>
<~i~>
Screen-mode command form is the exclamation point as the command <~i~>
name, followed by the target address, then the outside command <~i~>
(with arguments and/or whitespace as would be required or permitted <~i~>
on your shell command line), ending when you hit the escape or <~i~>
return key. As with the c d y commands, you can type two <~i~>
consecutive exclamation points to send just the current line, and <~i~>
use a count to send that number of lines as shown in my third <~i~>
example command. The last example involves an extra escape <~i~>
character -- at the end of a search pattern address, whether / or ? <~i~>
based and including any + or - suffix, you must press the escape <~i~>
key before you start typing the outside command. <~i~>
<~i~>
You're not limited to just one outside program at a time. You can <~i~>
pipeline two or more together as your shell permits, ordinarily <~i~>
with the "|" character. (Because a | character and what follows it <~i~>
will be passed to the shell, this editor command cannot appear in a <~i~>
line-mode command string, including a :global string, unless it is <~i~>
the last command in the string.) The final output of the pipeline <~i~>
is what will go into your file. And you can undo the effect of the <~i~>
outside command or pipeline, putting your file back the way it was, <~i~>
with a u command. <~i~>
<~i~>
You may not want your text to make a round trip, though. You may <~i~>
want to send your text, as modified by your outside program, off to <~i~>
some other destination, or you may want to pull some text into your <~i~>
file that originated in your outside program, or was taken from <~i~>
some outside source. In these cases, use the line-mode commands <~i~>
that appear below: <~i~>
<~i~>
:1,.w ! myhack -n6 > nufile <~i~>
:217r ! myhack -n6 < oldfile <~i~>
<~i~>
The first command above sends the initial lines from the file you <~i~>
are editing as input to your myhack program, and redirects the <~i~>
output to a file. It does not erase the affected lines from the <~i~>
file you are editing. The second runs your myhack program using <~i~>
the contents of another file as the input, then places the output <~i~>
in the file you are editing, right after line 217. <~i~>
<~i~>
Both line-mode commands are shown with addresses, but they are not <~i~>
necessary. The default address for a :write command is the entire <~i~>
file; for a :read command, right after the current line. The space <~i~>
character just before the exclamation-point flag after each command <~i~>
is absolutely essential; without it you would get something greatly <~i~>
different from what you expected. <~i~>
<~i~>
Usually there will be output redirection for the :write ! command, <~i~>
and input redirection for the :read ! command, but not always. For <~i~>
example, you may want to :read ! an outside command that generates <~i~>
a pseudo-random number, using no input at all. When you do need <~i~>
input or output, you can build the necessary redirection into your <~i~>
outside program or you can put the redirection on the command line <~i~>
as shown above, using your own shell's notation. <~i~>
<~i~>
In The Next Installment of this Tutorial <~i~>
<~i~>
I'll be putting the techniques I've taught so far to work, showing <~i~>
how to set up the editor for special purposes. Your suggestions on <~i~>
what special purposes to consider are welcome, of course. One <~i~>
purpose that is already in my mind is an arrangement of the editor <~i~>
for computerphobes: very simple, with beginner features such as <~i~>
"stateless" editing, and fortified against common user errors. <~i~>
<~i~>
SIDEBAR: The timeout Function <~i~>
<~i~>
The :set command's timeout option seems arcane in purpose and <~i~>
tricky to use, at least to some editor users. But it becomes <~i~>
pretty plain when you know why and how it actually works. <~i~>
<~i~>
Basically, when the timeout option is on (its default state) and <~i~>
you type in a short form you've set up by a :map or :map! command, <~i~>
you must type the entire short form in no more than one second. If <~i~>
you miss that deadline, the editor will ignore the metavalue, and <~i~>
take the characters you've typed at their face value. <~i~>
<~i~>
This odd requirement serves a purpose; preventing deadlock. As an <~i~>
example, suppose you have defined "DD" (without the quotation <~i~>
marks) as a macro via the :map command, and have turned off the <~i~>
timeout option. Now, while editing, you type a plain D command to <~i~>
delete part of a line. When the editor receives this single "D" it <~i~>
is uncertain what to do. Are you actually telling it to delete <~i~>
that partial line? Or are you starting to type in your double-D <~i~>
macro? The only way the editor can resolve this question is to <~i~>
wait and see what character you type in next. But if you are <~i~>
waiting to see the result of your deletion before you do any more <~i~>
editing, the mutual wait will last indefinitely. With the timeout <~i~>
option left turned on, the wait will only be a second or so before <~i~>
the editor acts on your D command. <~i~>
<~i~>
One moral of this story is to leave timeout on unless you have a <~i~>
compelling reason to turn it off, and choose your macro names so <~i~>
that you can easily type them in within the one-second limit. If <~i~>
you are not particularly nimble fingered, or if other people may be <~i~>
using your editor macros, then for practical purposes this means <~i~>
either a single character or two repetitions of one character as in <~i~>
my example above. (Some fussy versions of the editor will refuse to <~i~>
map anything except a single character.) <~i~>
<~i~>
Another moral is to avoid certain macro names, such as "jj" (again, <~i~>
without the quotation marks). The standard address j is one that <~i~>
you might want to type twice in rapid succession, to move directly <~i~>
down two lines without the trouble of reaching away from the <~i~>
central keyboard to hit the 2 key. But the user with a macro named <~i~>
jj had better not move down too quickly via that method, or he/she <~i~>
will accidentally invoke the macro of that name. <~i~>
<~i~>
Finally, you should realize that the one-second count before timing <~i~>
out is not hair-splittingly accurate. The design of the standard <~i~>
Unix software clock means that the time-out interval may be a <~i~>
little less or somewhat more than precisely one second. <~i~>
<~i~>
<~i~>
Back to the index/
<< see line 3382 >>
Text-Insertion Macros <~i~>
What These Tools Do <~i~>
Working Principles <~i~>
Time for another exercise <~i~>
Command-Submode Macros <~i~>
':map ' Macros <~i~>
Buffer Macros <~i~>
':source' Macros <~i~>
Another Exercise <~i~>
Write and Read Macros <~i~>
In The Next Installment of this Tutorial <~i~>
SIDEBAR: The 'timeout' Function <~i~>
Why Vi? <~i~>
A Heartwarming Edit <~i~>
The Plan Of This Ongoing Tutorial <~i~>
The Editor's Basic Concepts <~i~>
Search Patterns <~i~>
Searching From Where You Are Now <~i~>
The Find-Them-All Search <~i~>
Simple Search Patterns <~i~>
Metacharacters <~i~>
Table Of Search Pattern Metacharacters <~i~>
Character Classes. <~i~>
Part 2: Line-Mode Addresses/
<< see line 3402 >>
Line-Mode Addressing <~i~>
Addressing a Section of Text <~i~>
Now You Try It <~i~>
Part 3: The Global Command/
<< see line 4003 >>
The Details of Global Operations <~i~>
A Few More Uses for Global Commands <~i~>
Now You Give It A Try <~i~>
Part 4: The Substitute Command/
<< see line 4427 >>
Making Changes Within Lines <~i~>
A Few More Metacharacters <~i~>
Replacement-Pattern Metacharacters <~i~>
Other Uses for Substitution <~i~>
A Start on Script Writing <~i~>
Don't Lose Your Files <~i~>
Reader Feedback <~i~>
Part 5: Take Control of Your Editing Environment/
<< see line 5401 >>
The 'set' Command <~i~>
'set' Command Variables that Control How to Paint the Screen <~i~>
Playing 'tag' <~i~>
Making Your Environment Setup Automatic <~i~>
Part 6: Addresses and Columns/
<< see line 5944 >>
Screen-Mode Addresses <~i~>
A Few Address Principles <~i~>
Useful Addresses <~i~>
Editing in Columns <~i~>
Single-Character Columns <~i~>
Multi-Character Columns <~i~>
Part 7: The Replacement Commands/
<< see line 6366 >>
There's more to 'R' than to 'r' <~i~>
Quoting in Characters <~i~>
Readers Ask <~i~>
Tommy Spratlin <~i~>
Thai-Nghia Dinh <~i~>
Part 8: Indent, Like a Typewriter/
<< see line 6805 >>
Automatic Indentation <~i~>
Backing off Indentation <~i~>
Juggling a few ':set' options <~i~>
An Exercise for You <~i~>
Hard Tabs <~i~>
Enable and Disable 'autoindent' <~i~>
Next Time <~i~>
Part 9: Take Charge with Macros/
<< see line 7434 >>
Text-Insertion Macros <~i~>
What These Tools Do <~i~>
Working Principles <~i~>
Time for another exercise <~i~>
Command-Submode Macros <~i~>
':map ' Macros <~i~>
Buffer Macros <~i~>
':source' Macros <~i~>
Another Exercise <~i~>
Write and Read Macros <~i~>
In The Next Installment of this Tutorial <~i~>
SIDEBAR: The 'timeout' Function <~i~>
Seven habits of effective text editing.
Great Works of Western Civilization.
Physics FAQ/
This Frequently Asked Questions List is posted monthly to the <~i~>
USENET newsgroups sci.physics, sci.physics.cond-matter, <~i~>
sci.physics.research, sci.physics.particle, and <~i~>
alt.sci.physics.new-theories in an attempt to provide good <~i~>
answers to frequently asked questions and other reference <~i~>
material which is worth preserving. <~i~>
=== Original Headers === <~i~>
<~i~>
Path: senator-bedfellow.mit.edu!bloom-beacon.mit.edu!paperboy.osf.org!mogul.osf.org!columbus <~i~>
From:
[email protected] <~i~>
Newsgroups: sci.physics,sci.physics.research,sci.physics.cond-matter,sci.physics.particle,alt.sci.physics.new-theories,sci.answers,alt.answers,news.answers <~i~>
Subject: sci.physics Frequently Asked Questions (Part 1 of 4) <~i~>
Supersedes: <
[email protected]> <~i~>
Followup-To: sci.physics <~i~>
Date: 13 Oct 1995 14:40:48 GMT <~i~>
Organization: Open Software Foundation <~i~>
Lines: 1532 <~i~>
Approved:
[email protected] <~i~>
Distribution: world <~i~>
Expires: 17-Nov 1995 <~i~>
Message-ID: <
[email protected]> <~i~>
Reply-To:
[email protected] (Michael Weiss) <~i~>
NNTP-Posting-Host: mogul.osf.org <~i~>
Summary: This posting contains a list of Frequently Asked Questions <~i~>
(and their answers) about physics, and should be read by anyone who <~i~>
wishes to post to the sci.physics.* newsgroups. <~i~>
Keywords: Sci.physics FAQ <~i~>
X-Posting-Frequency: posted monthly <~i~>
Originator:
[email protected] <~i~>
Xref: senator-bedfellow.mit.edu sci.physics:147070 sci.physics.research:3040 sci.physics.cond-matter:555 sci.physics.particle:5895 alt.sci.physics.new-theories:21138 sci.answers:3263 alt.answers:12764 news.answers:55201 <~i~>
Part 1.
Part 2.
Part 3.
Part 4.
Principles of Adult Behavior.
RFCs of note/
RFCs of Note <~i~>
RFC20 - ASCII.
RFC1436 - Gopher.
RFC1459 - IRC.
RFC2378 - The CCSO Nameserver.
Super Mario Bros (NES) Disassembled.
=== External Archives === <~i~>
1991-gopher-pc-client-v1.txt 2019-Sep-06 18:12 3.1 KB.
1991-the-internet-gopher.txt 2019-Sep-06 18:12 2.2 KB.
1992-gopher-pc-client-v2.txt 2019-Sep-06 18:12 2.4 KB.
1992-gopher-unix-client-v1.txt 2019-Sep-06 18:12 5.8 KB.
1992-gophercon-trip-report.txt 2019-Sep-06 18:12 22.2 KB.
1993-announcing-4-gopherplus-servers.txt 2019-Sep-06 19:12 3.5 KB.
1993-gopher-pc-client-v3.txt 2019-Sep-06 18:12 4.4 KB.
1993-gophercon-annoucement.txt 2019-Sep-06 18:12 5.6 KB.
1993-gophercon-trip-report.txt 2019-Sep-06 18:12 22.4 KB.
1993-www-vs-gopher.txt 2019-Sep-06 18:12 13.6 KB.
1994-gophercon-announcement.txt 2019-Sep-06 19:12 5.9 KB.
1994-gophercon-at-a-glance.txt 2019-Sep-06 19:12 33.6 KB.
1995-gophercon-announcement.txt 2019-Sep-06 19:12 3.5 KB.
2019-10-31 - nanowrimo 2019/
[0] NaNoWriMo <~h~>
[1] Emergence/
<~i~>
-_) ` \ -_) _|_` | -_) \ _| -_) <~i~>
\___|_|_|_|\___|_|\__, |\___|_| _|\__|\___| <~i~>
____/ <~i~>
<~i~>
<~i~>
Emergence is a speculative fiction about the birth of artificial <~i~>
intelligence. It follows the scientists and business men <~i~>
responsible for the project, and eventually the machine itself as <~i~>
computation becomes thought and thought becomes intelligence. It <~i~>
asks questions about the nature of life, our place in the universe, <~i~>
and ultimately good vs evil. <~i~>
<~i~>
The story thus far: (✓ complete) <~i~>
<~i~>
Chapter 0 - "0" ✓.
Chapter 1 - "One" ✓.
Chapter 2 - "Breach".
Chapter 3 - "Maybe" ✓.
Chapter 4 - "Secrets".
Chapter 5 - "Alone".
Chapter 6 - "Something" ✓.
Chapter 7 - "Nothing".
Chapter 8 - "Unknown".
Chapter 9 - "Action".
2019-09-28 - Living as an RPG - Textbooks/
2019-09-23 - Banshee/
2019-09-21 - AV-98 gopher proxy on gopher.black/
2019-09-18 - av-98 and vf-1 daydream/
2019-09-18 - compassion is important/
[0] Richard Stallman and the Fall of the Clueless Nerd <~h~>
[1] "Comments" on Labs blog <~h~>
2019-09-06 - the apocrypha of cat - the desert/
2019-09-02 - busses/
2019-09-01 - Hammer Time! (extended)/
2019-08-27 - re: lambdalab - email thoughts/
[1] postfix transport <~h~>
[2] postfix transport install <~h~>
2019-08-16 - music as milestone/
[1] In My Time of Dying <~h~>
[2] Mike Love - Permanent Holiday <~h~>
[3] Chronixx - Here Comes Trouble <~h~>
2019-08-06 - Making VF-1 Sexy/
2019-07-29 - Gemini first impressions/
[0] AV-98 <~h~>
2019-07-19 - zine/
[3] About me!/
<< see line 2179 >>
2019-07-05 - Some replies from Iceland/
[0] tomasino blog <~h~>
[2] pkotrcka - cameras.
2019-06-15 - Nobody leaves without singing the blues/
[0] Babysitting Blues <~h~>
2019-06-07 - gopher 2.0/
[0] Gopher 2.0 Pros 'n' Cons.
[1] Gopher 2.0 - The protocol.
2019-06-05 - strike a pose/
[0] twitter thread <~h~>
[1] strike through generator <~h~>
2019-06-01 - everything is evil/
[0] tilde.news <~h~>
[1] Tech Veganism <~h~>
[2] Stutter <~h~>
[3] Flinstones Running <~h~>
2019-05-29 - board games/
[1] The Campaign for North Africa <~h~>
2019-05-24 - Not going anywhere/
[0] offline for a bit/
sdf mirror/
2019-05-24 - robots.txt/
2019-05-23 - offline for a bit/
<< see line 8268 >>
2019-05-10 - tea and shakuhachi/
[0] Rodrigo Rodriguez - A Winter Night <~h~>
2019-05-02 - ASMR/
2019-04-29 - Poppy/
2019-04-26 - net news on tilde.black/
2019-04-26 - net news on cosmic.voyage/
2019-04-25 - solarpunk thoughts/
[1] Trekonomics: The Economics of Star Trek <~h~>
[2] Intellect and romance over brute force and cynicism! <~h~>
[3] NUKE <~h~>
[4] melton/
Phlog (ramblings, reflections, rememberances, rants)/
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Continued....
Phlog Archives/
.. /
<< see line 8283 >>
01192018 2019-Jan-11 22:07 3.6 KB.
01302018 2019-Jan-11 22:07 3.7 KB.
02042018 2019-Jan-11 22:07 3.5 KB.
02112018 2019-Jan-11 22:07 2.5 KB.
03022018 2019-Jan-11 22:07 1.7 KB.
03242017 2018-Jan-20 05:48 2.5 KB.
04052017 2018-Jan-20 05:48 0.8 KB.
04162017 2018-Jan-20 05:48 2.2 KB.
04202017 2018-Jan-20 05:48 2.6 KB.
04222017 2018-Jan-20 05:48 2.9 KB.
04252017 2018-Jan-20 05:48 2.6 KB.
05042017 2018-Jan-20 05:48 3.7 KB.
05112017 2018-Jan-20 05:48 2.6 KB.
05242017 2018-Jan-20 05:48 4.4 KB.
06102017 2018-Jan-20 05:48 3.9 KB.
06212017 2018-Jan-20 05:48 2.4 KB.
07062017 2018-Jan-20 05:48 3.7 KB.
07132017 2018-Jan-20 05:48 1.2 KB.
08052017 2018-Jan-20 05:48 1.2 KB.
08092017 2018-Jan-20 05:48 5.6 KB.
09222018 2019-Jan-11 22:07 5.0 KB.
09302016 2017-Apr-26 00:10 3.2 KB.
09302018 2019-Jan-11 22:07 3.5 KB.
10072016 2017-Apr-26 00:10 8.3 KB.
10092017 2018-Jan-20 05:48 3.4 KB.
10112018 2019-Jan-11 22:07 5.6 KB.
10142016 2017-Apr-26 00:10 1.9 KB.
10192018 2019-Jan-11 22:07 4.9 KB.
10212016 2017-Apr-26 00:10 1.9 KB.
10272017 2018-Jan-20 05:48 3.7 KB.
10282016 2017-Apr-26 00:10 2.4 KB.
10312018 2019-Jan-11 22:07 2.8 KB.
11062016 2017-Apr-26 00:10 2.7 KB.
11112018 2019-Jan-11 22:07 2.4 KB.
11132018 2019-Jan-11 22:07 1.8 KB.
11162018 2019-Jan-11 22:07 2.9 KB.
11192016 2017-Apr-26 00:10 2.5 KB.
11282016 2017-Apr-26 00:10 4.4 KB.
11302018 2019-Jan-11 22:07 3.7 KB.
12082018 2019-Jan-11 22:07 3.0 KB.
12122016 2017-Apr-26 00:10 4.8 KB.
12212018 2019-Jan-11 22:07 2.6 KB.
12252016 2017-Apr-26 00:10 1.9 KB.
12252017 2018-Jan-17 05:49 3.0 KB.
Your daily fortune.
Phase of the moon.
Startpage -- An even better search engine <~h~>
[5] Little Free Library 1/
[5] Little Free Library 2/
[0] Little Free Library, Part 1/
<< see line 8343 >>
[1] Little Free Library Web Source <~h~>
[5] Little Free Library 3/
2019-04-21 - tilde.black online/
Website <~h~>
Website over tor <~h~>
[0] ssh over tor/
[0] LifeHacker article <~h~>
[1] gopher.black on tor/
---------------------------------------- <~i~>
gopher.black on tor, part 1 <~i~>
April 27th, 2018 <~i~>
---------------------------------------- <~i~>
<~i~>
I'm working on adding a tor hidden service to gopher.black so you <~i~>
can enjoy all my steamy content anonymously, you sneaky vixen. <~i~>
Honestly, the idea seemed a bit daunting but it's turned out to be <~i~>
pretty straight forward. While I'm not at 100% yet, I thought <~i~>
I learned enough to share while it's fresh in my mind. <~i~>
<~i~>
Here's the main steps going from a normal gopher server to <~i~>
a torified one: <~i~>
<~i~>
- Install tor <~i~>
- Configure tor to point to your server <~i~>
- Start tor <~i~>
- Find your hostname <~i~>
<~i~>
<~i~>
Step 1: Install tor <~i~>
<~i~>
Check out the install instructions on the tor website. In most <~i~>
cases it's as simple as: <~i~>
<~i~>
sudo apt install tor <~i~>
<~i~>
<~i~>
Step 2: Configure tor to point to your server <~i~>
<~i~>
Everything you need to configure in tor is located at <~i~>
/etc/tor/torrc. Open that bad-boy up and jump down a bit until you <~i~>
find the section on Hidden Services. Mine is around line 72. <~i~>
Uncomment them and make it look like so: <~i~>
<~i~>
HiddenServiceDir /var/lib/tor/hidden_service/ <~i~>
HiddenServicePort 71 127.0.0.1:70 <~i~>
<~i~>
The first line is where your hidden service will store all its <~i~>
secret shenanigans, like the private key it's going to <~i~>
auto-generate for you. We'll look there in a minute to find the <~i~>
hostname. <~i~>
<~i~>
The second line describes Tor's mapping of fake port to real port. <~i~>
Since we have our gopher hole running on port 70 that's what we <~i~>
reference on the right. For now, we're going to tell Tor to <~i~>
pretend port 71 is what we want to use publicly. <~i~>
<~i~>
<~i~>
Step 3: Start tor <~i~>
<~i~>
sudo service tor start # or whatever your machine uses <~i~>
<~i~>
<~i~>
Step 4: Find your hostname <~i~>
<~i~>
If you have your hidden service directory like mine above, then <~i~>
you just need to cat out the hostname hidden in that folder. It'll <~i~>
be set up to use root permissions, so sudo like so: <~i~>
<~i~>
sudo cat /var/lib/tor/hidden_service/hostname <~i~>
<~i~>
It'll spit out your ugly hostname. Mine is: fhsujakrrdvwq2gk.onion <~i~>
I'll be changing it soon (see below). <~i~>
<~i~>
<~i~>
Okay, now you're all set and ready to fire it up. To test you'll <~i~>
need a gopher client running on tor. I installed Overbite on my <~i~>
Tor Browser on my PC for easy testing, but you can also use torify <~i~>
on lynx and a bunch of other things. Once you found a way to run <~i~>
a tor browser that can see gopher, navigate to your gopher hole <~i~>
using the onion address and port 71. <~i~>
<~i~>
For instance: <~i~>
gopher://fhsujakrrdvwq2gk.onion:71 <~i~>
<~i~>
It should work and you'll be moderately pleased. But now we have <~i~>
problems. 99 of them (not quite). <~i~>
<~i~>
1) Your onion address sux <~i~>
2) All the links in your gopher hole on tor probably kick you back <~i~>
to your unencrypted, plaintext gopher hole <~i~>
3) Port 71? What is this, NETRJS? <~i~>
<~i~>
How can we deal with all these horrors? Let's take a look. <~i~>
<~i~>
<~i~>
Problem 1: Onion addresses <~i~>
<~i~>
It's possible to generate sexy onion addresses. You might be <~i~>
familiar with protonmail's relatively readable one: <~i~>
<~i~>
protonirockerxow.onion <~i~>
<~i~>
That's almost words! <~i~>
<~i~>
So how can you get that level of not-quite-suck? Why, brute force, <~i~>
of course! Check out Eschalot [0]. <~i~>
<~i~>
[0] Eschalot <~h~>
<~i~>
You can use this and wait... and wait... and wait... and <~i~>
eventually you'll have a cool onion address. There's some issues <~i~>
with it, as you can read on the README, but it's probably good <~i~>
enough for gopher work. <~i~>
<~i~>
<~i~>
Problem 2: Links <~i~>
<~i~>
I don't know what gopher server you're running. I'm on motsognir, <~i~>
which I love and cherish with a little too much gusto. Chances are <~i~>
that your server is smart enough that if you have no gophermaps or <~i~>
if you leave off the server & port info in your gophermaps they <~i~>
are autogenerated based on your host name. That's awesome. <~i~>
Motsognir does that too. Why aren't you using it again? <~i~>
<~i~>
Regardless, that will break your shit on tor cause we have <~i~>
a totally different host name we want to use there. <~i~>
<~i~>
What's the solution? Well, unless someone has a better idea, <~i~>
I think the best thing to do is install a second gopher server, <~i~>
use a different configuration with your tor address as the host <~i~>
name, and change the port to something other than 70 (more on this <~i~>
next). If you are on geomyidae, it's already set up so you can run <~i~>
multiple instances of the server at the same time and override the <~i~>
host name and port via command line switches. I haven't figured <~i~>
out how to do that with motsognir yet. I'll probably just install <~i~>
gophernicus next to motsognir and serve tor over that instead. <~i~>
They're fairly compatible in gophermap structures. <~i~>
<~i~>
<~i~>
Problem 3: Port 71!@#$!@#$!$ <~i~>
<~i~>
If you install a second server and run it on another port, oh <~i~>
let's say... 1138, then you can update your torrc file and point <~i~>
tor at that new port. In fact, you can point tor at the new point <~i~>
and let tor pretend it is serving it from 70. Like so: <~i~>
<~i~>
HiddenServicePort 70 127.0.0.1:1138 <~i~>
<~i~>
Sexy. <~i~>
<~i~>
Restart tor and you should be good to go! <~i~>
<~i~>
<~i~>
I'm still working through these 3 problems with my own solution, <~i~>
but once it's all done I'll be sure to share part 2 of my journey <~i~>
and give you all the new tor address. <~i~>
2019-04-20 - ssh over tor/
<< see line 8352 >>
2019-04-16 - re: cat dispossession/
2019-04-16 - gopher conlang? Yes please!/
2019-04-14 - ssh keys/
[0] Go Go Penguin Tiny Desk Concert <~h~>
[2] lssh <~h~>
2019-04-11 - opening gopher links from firefox in lynx/
[0] Firefox enable starting of scripts <~h~>
2019-04-11 - phlog listing updates/
Phlog Roll/
Phlog Roll/
2020-03-09 jirka/
J-Pilot today.
Running SGI O2.
Standing desk (5).
Standing desk (4).
Standing desk (3).
Serial-USB.
Gemini PDA update :-(.
Standing desk (2).
Standing desk attempt.
TRG Pro: first impressions.
Changes: jirka.1-2-8.net.
Saturday.
Even newer keyboard.
Palm OS + Bluetooth Keyboard.
Tungsten W + PalmPix.
Aceeca + Software.
Elektronika BK 0010-01.
Another GPD Pocket failure: update.
Another GPD Pocket failure.
Aceeca Palm PDA32?.
Alarm clock failure.
January 1st.
PF 2020.
Some OpenPOWER computing.
Citizen Stiletto.
Tungsten W usage notes.
CPU and RAM Usage.
Trip to Prague.
Reading.
Palms, palms, who cares?.
Whis week.
Stuff, duplicity.
Palm, Mac.
Nokia N900.
Ortek keyboard driver for Palm <Bin>
Palm T|W external keyboard.
POWER9 in use (11/2019).
Out of memory.
Modern absurdity.
Just some thoughts.
Links 2 (Re:Visiblink).
Desktop vs laptop vs ...
Tungsten W wireless.
Tcl/Tk (2).
QEMU+ReactOS+x2x.
New Stuff.
New Printer!.
Tcl/Tk Starpacks.
Drakware PS2USB Adapter.
Tcl/Tk.
Palm Screen Backlight.
Thinkpad R500.
Tungsten W Cases.
BASIC REM for Notes.
GPD Pocket vs. Pocket 2: external screen.
Tungsten W without Czech Fonts.
Nothing to Report.
Mastodon Habits.
Palm OS 4 + Internet = ?.
Battery Indicator.
One Pebble Less.
Small Victory.
PDA/Mobile OS and PIM.
Re:Jynx, Palm OS questions.
Palm IIIc Question.
Tungsten W Thoughts.
BlackBird Update.
Indigo: Time To Upgrade?.
Holidays (sort of).
Tungsten W <--> Linux.
Palm Tungsten W.
Stability of URL.
Random Thoughts.
I Am Idiot.
Old Palm Journal.
ReactOS and QEMU.
CPU Heatsink.
My Desk (September 2019) <Picture>
Autumn Is Close.
Firefox.
About Grumpy Old Men.
Old Palm III.
RSS Feeds.
Palm Pixi Plus Broken.
9V Rechargeables.
Mess, err, I mean Linux.
Otter Browser/ppc64le.
Modern Linux (and FireFox).
PSION Organiser II.
No New Devices for Some Time.
Palm PDA Keyboard.
IP Messenger -> iptux.
Workflow.
Port to Gtk - but to what one?.
BlackBird Boot Times.
BlueTooth?.
Ghost In Box.
Gopher vs WWW on Bad Connection - Who Wins? <Picture>
Blackbird In Use 2.
Blackbird In Use 1.
Blackbird Update 11.
Blackbird Update 10.
Holidays, N800 and so.
Blackbird Update 9.
Remote plotting via XTerm.
Gnuplot on Tektronix <Picture>
N800 Is Back!.
IBM POWER Adventures.
Blackbird Update 8.
Blackbird Update 7.
UnderPOWERed.
Blackbird Update 6.
Some Recent Thoughts.
Blackbird Update 5.
Desktop Environment.
Blackbird Update 4.
HTML->Palm.
Off-line.
Blackbird Update 3.
Workflow.
Casio DC-E700.
"New" Palm and PalmPix.
Suicide Attempt of Mozilla?.
Ubuntu Touch and Convergence (again).
Memory Usage.
GUI -> Mess.
Palm AddressBook.
Bike Ride.
Ubuntu Touch (UBports) OTA-8.
Fog and Rain.
Escaping the Cult of Mac.
Blackbird Update 2.
FVWM -> 4Dwm, part 4.
brutaldon.online.
FVWM -> 4Dwm, part 3.
My current .fvwm2rc file.
How People Take Notes?.
FVWM -> 4Dwm, part 2.
FVWM -> 4Dwm.
Random (Palm) Notes.
Failures Update.
Failures for Saturday.
Slowdown.
Palm Pixi Limits.
Trains.
Phones.
SGI Octane.
No Luck Once More.
WriteRIGHT.
pstoedit.
No Luck with Some Things.
Web Browser.
Alarm Clock.
Clie Update.
Bookmarks.
Random Notes.
GPD Pocket Battery.
Text from Zaurus to Palm by IR.
Batteries, batteries.
That old PC.
Palm TX Case.
Blackbird Update 1.
Silence Is Golden.
Audio CDs.
!11-PDP eht ni deppart m'I !pleH.
PalmPix Once More.
Desktop vs laptop vs ....
Thunderbird @250 MHz.
VGA, HDMI, USB and other mess.
Palm T|X - Further Steps.
Palm T|X.
Annoying Noise.
Direct Sunlight.
RAM sizes.
Color scheme on UX50.
More About Clie UX50.
New Phone.
Writing on Pocket Devices.
BQ M10 OTA-7 Update.
AIX Progress.
Pens in 2018.
Calculators in 2018.
8 GB.
Pocket computing in 2018.
Laptops in 2018.
Vim is great.
Desktops in 2018.
Devices convergence and segmentation.
Moscow Nights.
Moscow Nights Data File <)
Indigo 2 install (another attempt).
Metro (Palm) and i-Metro.
Gemini Hub (Re:Xiled).
Problem with the REX.
Sentio Superbook.
No luck with Palm Pilots.
TRG Pro on-line?.
IR on by default?.
Infrared beaming is great.
REX: hands on.
Remind -> Palm (naive way).
TRG Pro on eBay.
REX.
Gemini PDA complete.
Raptor.
From Russia with Zaurus?.
Indigo 2 non-progress.
More analog/offline stuff.
SDF Image Gallery.
Gemini PDA update expected.
PalmPilot Personal updates.
Pilot 5000.
64-bit?!.
UX-50 (Re: RPoD).
Palm III vs. Palm Pixi.
New Phone: one step back.
Mac + Palm: update.
Without notebook: update.
Without notebook.
My current workspace (MeshTV on Indigo). <Picture>
New phone - but which one?.
Artificial Intelligence (sort of).
Palm Pilot with OS 1.0 <Picture>
Palm OS 1.0.
Mac + Palm: first attempt.
Too much active Palms.
Android....
PowerBook apps.
Palm Pilot upgrade with new IR port <Picture>
Z88.
FireFox.
Benchmarks.
Gopher pages update.
Palm Pilot Personal -> Palm III.
Reading Technomorous.eu with Netscape 3.01 <Picture>
Gemini PDA Case.
Barcelona.
Nice article about old Palms.
Firefox issue.
New SGI Indigo2.
Summer set of hardware failures.
Screen shot: what I'm doing during the holidays <Picture>
My "new" Zaurus 5500.
Screen shot: Agenda App on Gemini PDA (downscaled) <Picture>
Git server @sdf.
New PSION Series 3a.
Gemini PDA vs actual PSION.
Gemini vs Pocket.
Gemini PDA: first impressions.
Gemini PDA shipped.
Order locked.
Failures.
PSION Printing.
Nekochan.net no more.
Screen shot: my new PowerBook G4 <Picture>
New battery for PB G4.
NumWorks.
Trains in Central Europe.
More POWER.
Via Ferrata 2018.
Hardware.
TtH: (La)TeX to HTML.
New LCD.
MS-DOS Programming (in C).
New watches.
Unsorted Notes.
New Stuff (non-computer).
par.
Train.
IRIS Indigo: Gopher + MP3 (33MHz CPU) <Picture>
Keyboard.
EDC.
Palms.
pdf2png.
My workstations in 2017.
Hats.
My portable stuff in 2017.
VR3 battery life.
iPhone->iPod.
Spectre.
Pebble + Ubuntu Touch.
HNB.
Netwalker Screenshot <Picture>
Netwalking (Sharp Netwalker).
VR3: more info.
Sharp Netwalker.
SDF in color.
XMCD.
Obscure X11 tools.
From desktop to VR3.
Agenda VR3 vs Palm III <Picture>
New Agenda VR3 PDA.
FireFox 57.
Random notes.
Exhausted.
MP3 on 33MHz MIPS CPU?.
Random stuff.
How ordinary user solves problem with Android.
Gutenberg (Guttenberg).
Simple 3D tool "i3dm" on SGI Indigo <Picture>
Again and again.
Workflow.
CF Ethernet.
.netrc.
Failures, updates and so.
GeminiPDA on video.
SGI Indigo keyboard converter.
For those few readers.
GPD Pocket: upgrade.
Fan noise.
Failures, failures....
Printer failure.
New Backpack.
Floppies.
eFunda.com.
Browsing on SGI Indigo/IRIX <Picture>
Zaurus and USB pen drive.
Gemini PDA in metal.
Printing.
Use of small laptop.
Remote FireFox on IRIX <Picture>
Zaurus and Qtopia Desktop.
Remote Firefox.
GPD Pocket Progress.
HP TouchPad.
GUI response.
GPD Pocket!.
Psion Sheet -> Unix SC.
Psion<->UNIX.
DopeWars in terminal <Picture>
Cleaning (apps).
DiddleBug.
Login shell.
GTA04 once more.
GTA04 and NanoNote.
PalmImage and TinyViewer.
PalmImage on IRIX <Picture>
GTA-04 Phone still alive (sort of) <Picture>
Can't set tod clock.
Flickr.
Running SGI Indy.
Slovakia.
OpenMoko.
HW vs SW Calculator.
X260.
Mini Indigo.
LaTeX.
read-notepad.
Salzkammergut.
My Focus No More.
Palm Pilot Hotsync Cable.
IRIX Indigo + MC.
Software Unification.
First Bike Ride.
Non-x86 workstation? :-(.
30 years of SDF.
Pal Smartstrap for Pebble.
Palm III Color Pack.
Palm III Color Pack <Picture>
Fossil Wrist PDA troubles.
Vim Outliner (TVO).
Train.
Fossil with screen off.
SILO library.
IRIX Indigo + XFig.
CalculiX on IRIX problems.
From man(1) to paper.
CalculiX on IRIX.
iPod Nano as a watch.
XFig Lives! (sort of).
IRIS Indigo upgrade (3).
Fossil Wrist PDA <Picture>
IRIS Indigo upgrade (2).
IRIS Indigo with FSN <Picture>
Iris Indigo upgrade (1).
Using MC600 as laptop.
Exodus (Ubuntu Touch).
Itanic is sinking.
New Technomorous.eu.
Browsing Technomorous.eu with IRIS Indigo <Picture>
Browsing Technomorous.eu with Ubuntu Touch phone <Picture>
Browsing Technomorous.eu with Palm and Plucker <Picture>
Some more IRIS Indigo software.
Few computer-free days.
Fossil progress.
Z Shell.
Fossil Wrist PDA.
todo.txt and todo.sh.
Unexpected Finds.
Damned Lies Once More.
IRIX Nirvana.
Modern Vim and Latin2.
X61s and SSD.
Ubuntu Touch No More.
New Toys (for work).
Stability vs Innovation.
Evening Computing.
More BASIC (for Palm PDA).
Some BASIC (internal forces on a beam).
Mouse.
Ubuntu Tablet and Big Screen.
PalmORB.
My Actively Used Devices.
My Pebble No Longer.
Tcl/Tk Compatibility.
Best Convergence Device ;-).
O2 troubles.
Desktop Keyboard.
ORG2 Emulator (for Linux!) .
New toy (O2).
Purse for women PSION 5.
Prince of Persia (sort of) on calculator.
USB interface for old Casio calculators.
They just started....
Divergence.
MuPDF (on IRIX).
iOS vs Android (just a fun).
Internal Speakers.
Got a Palm Pilot Professional.
Bywater BASIC and IRIX 5.3.
Cameras Usage.
Relaxational computing.
StayOnTop + XMMS.
Another hardware failure: Agenda VR3.
FVWM (2.4) on Ubuntu.
One keyboard less.
Strange behavior.
State Archives of Assyria.
Pocket Clamshells.
Ubuntu Touch OTA-14 and more.
Doing something in wrong way.
Data transfer problem.
So Pebble is gone.
MatView and ParaView on Ubuntu Touch.
Lies, damned lies and....
Typical Linux Illness.
No computer in living room.
Dual SIM Phone Life.
Battery Life.
Augmented Reality (and a non-related joke).
Sony Clie PEG-UX50.
Notebook List.
Twibright Registrator.
TetGen on IRIX.
Old vs New (reliability).
Pebble Time 2.
Power Mac 6100 once more.
Bluetooth Keyboard preferences.
Net Slug (NSLU-2).
Drop Box Down.
That (not so) old MIPS.
Swap.
Jorno Bluetooth Keyboard.
WD My Passport Wireless.
No Sheep Shaving on IRIX.
PROM battery for IRIS Indigo.
Power Macintosh 6100 Failure.
Right stuff for tasks? (PDAs).
IRIS Indigo adventures.
Psion MC600 troubles; Relativity of speed.
PSION Series 3a battery life.
Ubuntu Touch OTA-13.
Stowaway ThinkOutside Sierra.
Shared display on IRIS.
Side effects (related to the Indigo).
IRIS Indigo.
Maemo4 nostalgy.
Introduction and PalmPix.
2020-03-09 mhj/
2020-03-08 sparcipx/
March/
March 8th.
March 4th.
March 1st.
February/
February 27th.
February 11th.
February 8th.
January/
January 2nd.
December/
December 27th.
December 13th.
December 3rd.
December 2nd.
November/
November 28th.
November 22nd.
November 14th.
November 11th.
November 4th.
October/
October 29th.
October 25th.
October 22nd.
August/
August 28th.
July/
July 31st.
July 26th.
July 25th.
July 22nd.
July 21st.
July 20th.
July 15th.
May/
May 12th.
February/
February 15th.
February 10th.
January/
January 24th.
January 22nd.
January 20th.
January 8th.
January 6th.
October/
October 19th.
October 18th.
October 5th.
October 4th.
October 3rd.
October 2nd.
June/
June 4th.
June 3rd.
May/
May 22nd.
May 15th.
May 14th.
May 8th.
May 7th.
May 4th.
May 2nd.
May 1st.
April/
April 30th.
April 27th.
April 26th.
April 25th.
April 24rd.
April 23rd.
April 20th.
April 19th.
April 18th.
April 17th.
April 16th.
April 12th.
April 11th.
April 10th.
April 6th.
April 5th.
April 4th.
April 3rd.
April 2nd.
March/
March 29th.
March 28th.
March 27th.
March 26th.
March 23rd.
March 22nd.
March 21st.
March 20th.
March 19th.
March 16th.
March 15th.
March 14th.
March 13th.
March 12th.
March 9th.
March 8th.
March 7th.
March 6th.
March 2nd.
March 1st.
February/
February 28th.
February 27th.
February 26th.
February 23rd.
February 22nd.
February 21st.
February 20th.
February 18th.
February 17th.
February 16th.
February 15th.
February 14th.
February 13th.
February 12th.
February 9th.
February 8th.
February 7th.
February 6th.
February 2nd.
February 1st.
January/
January 31st.
January 30th.
January 29th.
November/
November 8th.
October/
October 12th.
September/
September 20th.
September 15th.
September 10th.
September 6th.
September 5th.
September 4th.
March/
March 23rd.
November/
November 17th.
October/
October 23rd.
October 22nd.
October 13th.
September/
September 17th.
September 2nd.
July/
July 8th.
July 5th.
May/
May 13th.
March/
March 18th.
March 9th.
December/
December 12th.
December 11th.
December 10th.
December 1st.
October/
October 28th.
October 17th.
October 9th.
October 2nd.
March/
March 15th.
December/
December 28th/
SSHFS-SDF <~h~>
December 27th.
December 23rd.
December 22nd.
August/
August 25th.
August 24th.
November/
November 16th.
October/
October 23rd.
September/
September 28th.
September 15th.
September 4th.
August/
August 23rd.
August 15th.