1
\$\begingroup\$

Golf Me a Text Editor

(similar challenges: Create a simple line editor and Line editor (more text here))

I seem to have forgotten which program to use to open, read, and write text files. Something like Noteleaf or VSBro or ... You see my conundrum. But never fear! I know some people who can write one. But I'm a bit limited on space, so shorter programs would be much appreciated.

The Challenge

Create a program, in your language of choice, that can open, read, and write plaintext files. The program should take input from your language's equivalent of STDIN and write the contents of the file to STDOUT (or equivalent). The program should close the file after the user is done with it (when they type 'q'). If the file does not exist, then the program should create a new one with the given filename. Editing is done line-by-line. The user gives the line number they wish to edit, and then give the new content of that line. If there is no content given, the line should be removed. Additional specifications are listed below.

Commands

filename?> - opens the specified file. If a file with the given name can not be found, create a new file. If the user types DELETE, then the program should prompt with delete?>.
delete?> - "deletes" the file. This is done by blanking it (i.e. replacing its contents with ""), which will suffice for this challenge. If the file can not be found, then print FILE NOT FOUND.
line?> - the given line number is where the text will be changed when content?> is given. If q is entered, then close the file and exit. If a is entered, then append a new empty line to the end of the file. If the index is out of bounds (i.e. does not exist (the text files can be 1 or 0 based indexed)) then print Error!.
content?> - input that is given here will replace that of the previous content of the line given earlier (line?>). If empty then delete that line (remove content from the line and shift all lines after it up one).

After each filename?> and content?> the contents of the file should be printed, as well as -- followed by the number of lines in the file.

Examples

A (rather bad) example program in Python3 can be found here.

Example deletions:

filename?>DELETE
delete?>passwords.txt
filename?>DELETE
delete?>evidence.txt
FILE NOT FOUND

Example run:

filename?>passwords.txt
password
admin
1234
********
p@$$w0rd
c0d3_1$_l!f3
--
6
line?>3
content?>12345678
password
admin
12345678
********
p@$$w0rd
c0d3_1$_l!f3
--
6
line?>4
content?>
password
admin
12345678
p@$$w0rd
c0d3_1$_l!f3
--
6
line?>a
password
admin
12345678
p@$$w0rd
c0d3_1$_l!f3


--
7
line?>9
Error!

line?>1
content?>passcode
passcode
admin
12345678
p@$$w0rd
c0d3_1$_l!f3


--
7
line?>5
content?>
password
admin
12345678
p@$$w0rd


--
6
line?>q

Remember, this is , so the shortest answer in bytes wins!

| improve this question | | | | |
New contributor
nope is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
\$\endgroup\$
  • \$\begingroup\$ Is the “FILE NOT FOUND” error only visible in sample code and sample run mandatory? \$\endgroup\$ – manatwork May 22 at 20:20
  • \$\begingroup\$ @manatwork. Yes. I thought I had made it mandatory, but I must have forgotten when I created the list of commands. Edited. \$\endgroup\$ – nope May 22 at 20:27
  • 2
    \$\begingroup\$ The file handling could benefit of some clarifications. Do we have to care about directories and lack of permissions, or we can assume only names of readable & writable regular files will be typed in? \$\endgroup\$ – manatwork May 22 at 20:31
  • 3
    \$\begingroup\$ How does the user create a file called DELETE? \$\endgroup\$ – Abigail May 22 at 21:15
  • \$\begingroup\$ @manatwork you do not have to deal with directories or lack of permissions. Assume only names of readable and writable regular text files (*.txt) will be inputted. \$\endgroup\$ – nope May 22 at 22:14
3
\$\begingroup\$

Bash, 388 characters

Note that I am aware that further clarifications may come which will invalidate my solution.
Feel free to carry out any necessary modification in the requirement.
I posted this because the challenge is complex and may help to see how someone else understood it when editing for clarification.

IFS=
read -pfilename?\> f
[[ $f = DELETE ]]&&{
read -pdelete?\> f
[[ -f $f ]]&&>$f||echo FILE NOT FOUND
exit
}
[[ -f $f ]]&&mapfile t<"$f"
echo "${t[*]}--"
while read -plineno?\> l;do
[[ $l = q ]]&&break
[[ $l = a ]]&&t+=('
')||{ ((l>=${#t[@]}))&&echo Error!&&continue
read -pcontent?\> c
[[ $c ]]&&t[l]="$c
"||t=("${t[@]::l}" "${t[@]:l+1}")
}
echo "${t[*]}--"
done
echo -n "${t[*]}">"$f"
| improve this answer | | | | |
\$\endgroup\$
  • \$\begingroup\$ I think with set -f you could unquote a lot of things, and use [ instead of [[. \$\endgroup\$ – GammaFunction 7 hours ago
1
\$\begingroup\$

Zsh, 309 bytes

p(){print -l - "$t[@]" -- $#t}
read f'?filename?>'
[ $f = DELETE ]&&{
read f'?delete?>'
[ -f $f ]&&:>$f||echo FILE NOT FOUND
exit}
[ -f $f ]&&t=("${(@f)"$(<$f)"}")
p
while read l'?lineno?>'&&[ ${l/q} ];do
[ $l = a ]&&t+=('')||{((l&&l<=$#t))&&read c'?content?>'&&t[l]=($c);}||echo Error!
p
done
<<<${(F)t}>"$f"

Compared to Bash, we use [ instead of [[, get rid of unnecessary quotes (although many are still necessary due to $foo expanding to no words if foo is empty. We take advantage of this with the array[index]=(a list) syntax to insert in a new line unless $c is empty, in which case t[l]=() deletes it.

| improve this answer | | | | |
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.