Image of a keyboard

Editing files with FreeDOS Edlin

0

Back in the early days of PC computing, Tim Paterson created the Edlin editor for an early “DOS” operating system called 86-DOS (also called “QDOS”). Paterson’s Edlin was a line editor, based on the CP/M editor ed, which itself was loosely based on the Unix editor ed.

Paterson has since said that he never intended Edlin to have a long life, it was just something he created so he could write programs. He always meant for Edlin to be replaced by a better text editor. But Edlin did the job, and when 86-DOS became PC-DOS (and later, MS-DOS) Edlin became the default editor. And it remained so until MS-DOS 5 in 1991, which replaced the line editor with Edit, a full-screen editor.

The Edlin editor lives on in FreeDOS Edlin, originally written by Gregory Pietsch. FreeDOS Edlin is very similar to the classic Edlin, but I find it’s easier to use. And unlike classic Edlin, FreeDOS Edlin is highly portable, which means you can download the source code from FreeDOS Edlin on SourceForge and compile it on your favorite operating system.

Here’s a brief primer to using FreeDOS Edlin:

Start by editing a file

The most common way to start Edlin is by giving it the name of a file to edit. I’ll start by writing a simple “Hello world” program in C. If this is a new file, Edlin will let you know:

$ edlin hello.c
hello.c: New file.
*

The * is Edlin’s friendly prompt where you can enter commands. Like other line editors, with Edlin, you are either in command mode at the Edlin prompt, or you are in edit mode to enter text. To see a list of commands you can use in Edlin, type ?:

*?
edlin 2.24, copyright (c) 2003 Gregory Pietsch
This program comes with ABSOLUTELY NO WARRANTY.
It is free software, and you are welcome to redistribute it
under the terms of the GNU General Public License -- either
version 2 of the license, or, at your option, any later
version.


edlin has the following subcommands:

#                 edit a single line    [#],[#],#m        move
a                 append                [#][,#]p          page
[#],[#],#,[#]c    copy                  q                 quit
[#][,#]d          delete                [#][,#][?]r$,$    replace
e<>               end (write & quit)    [#][,#][?]s$      search
[#]i              insert                [#]t<>            transfer
[#][,#]l          list                  [#]w<>            write

where $ above is a string, <> is a filename,
# is a number (which may be .=current line, $=last line,
or either number + or - another number).

*

These commands will become more familiar as you get some practice in editing files in Edlin.

Appending new lines

If you have an empty file, you can use either the a (append) or i (insert) command to start entering new lines. Let’s use the a command to append some new text at the end of the file; since this is an empty file, this adds new lines:

*a
 : int main()
 : {
 :   puts("Hello world");
 : .
*

When entering text, the Edlin prompt changes to : so you know that you are in edit mode. Type . on a line by itself to stop entering text and go back to command mode.

Viewing the file

To see what you’ve entered into the file, use the l (list) command. This will automatically display ten lines above the current line and ten lines after it, but for this short file it displays everything:

*l
1: int main()
2: {
3:*  puts("Hello world");
*

Each line is numbered so you can refer to a specific line as you edit the file. The * on line 3 indicates that this is the current line.

However, the a (append) command always appends to the end of the file, which can be a little misleading if our current line is already the last line in the file. Just remember that a will append to the end. Let’s use the a command to add the missing curly brace to end the program:

*a
 : }
 : .
*l
1: int main()
2: {
3:   puts("Hello world");
4:*}
*

Inserting new lines

It’s important to know where you are in a file when working in Edlin, so that * after the line number is an important indicator. Let’s say we wanted to insert a new line before the current line. We can use the i command, which will always insert before a line. Let’s add the missing return statement to our C program:

*i
 :   return 0;
 : .
*l
1: int main()
2: {
3:   puts("Hello world");
4:   return 0;
5:*}
*

After inserting the new line, the current line is still the last line in the file, which is now line 5.

But you don’t have to limit yourself to only working on the current line. You can also use a line number with the i command to insert new text before another line. Let’s add an #include statement to the start of our C program, before line 1:

*1i
 : #include <stdio.h>
 : 
 : .
*l
1: #include <stdio.h>
2: 
3:*int main()
4: {
5:   puts("Hello world");
6:   return 0;
7: }
*

Editing lines

If you want to edit a specific line in a file, type the line number that you want to change. Edlin will print the line from the file, then automatically replace that line with whatever new text you enter. Let’s change line 5 to print a slightly different message:

*5
5:*  puts("Hello world");
5:   puts("Hi there!");
*l
1: #include <stdio.h>
2: 
3: int main()
4: {
5:*  puts("Hi there!");
6:   return 0;
7: }
*

After editing the line, Edlin returns you to command mode and sets the current line to the line you just entered. This makes it easy to insert new lines before it with the i command, if you needed to keep modifying the file at this line.

Moving lines

A handy feature of any text editor is to move text around a file. Because Edlin is a line editor, Edlin can only move entire lines at a time. But for most files, this is usually what you want to do anyway.

Let’s demonstrate it by entering a comment about the program, but appending it at the end of the file with the a command. Notice that the current line is line 5, but the a command actually adds text at the end of the file. We can move this new line later:

*l
1: #include <stdio.h>
2: 
3: int main()
4: {
5:*  puts("Hi there!");
6:   return 0;
7: }
*a
 : /* a sample program */
 : .
*l
1: #include <stdio.h>
2: 
3: int main()
4: {
5:   puts("Hi there!");
6:   return 0;
7: }
8:*/* a sample program */
*

A better place for this comment is on the first line of the file. We can move one or more lines with the m (move) command, which has the general syntax of [#],[#],#m. That is, the first line to move, the last line to move, then the new line where the text should go, all separated with commas. In our case, we want to move line 8 to before line 1:

*8,8,1m
*l
1: /* a sample program */
2: #include <stdio.h>
3: 
4: int main()
5: {
6:   puts("Hi there!");
7:   return 0;
8:*}
*

And we can make it look nice by inserting (i) a blank line before line 2:

*2i
 : 
 : .
*l
1: /* a sample program */
2: 
3:*#include <stdio.h>
4: 
5: int main()
6: {
7:   puts("Hi there!");
8:   return 0;
9: }
*

Saving and exiting

When you’re done making changes, don’t forget to save your new file using the w (write) command:

*w
hello.c: 9 lines written
*

Once the file is safely written to disk, you can exit Edlin using the q (quit) command:

*q
Really quit (Y/n)? y

There’s more to explore

Edlin is a classic editor from the early DOS days, but it’s still a fun and useful editor. I use Edlin when I want to write something quickly, like a test program or a brief note. Edlin is also very useful if you want to capture some commands into a FreeDOS batch file; you can write the new batch file while any commands you ran are still visible on the screen.

You can get pretty far with inserting, appending, editing, and moving lines in a file. But there’s more to explore! Use the ? (help) command to see all the commands supported in FreeDOS Edlin.

Leave a Reply