59 — Editor — a tiny text editor
A text file is one long string. An editor works on a buffer — the same text
split into a list of lines, one per row. You add, remove, and list those rows,
then save writes the whole buffer back to the file.
Steps
"\n".join(lines)merges lines into one text with newlines between them;.splitlines()is the exact opposite. It printsHello,World!, then['Hello', 'World!']:
run it →lines = ["Hello", "World!"] text = "\n".join(lines) show text back = text.splitlines() show backThe buffer lives in the file between runs. As in guide 13, a saved file becomes a list of lines, and a first run starts empty:
run it →use file latest import os if os.path.exists("notes.txt"): buffer = file_read("notes.txt").splitlines() else: buffer = []Commands arrive as whole lines.
line.split()splits on spaces,parts[0]is the command word, and" ".join(parts[1:])reconnects the rest — the text foradd. It printsadd, thenHello world; guide 49 split tokens the same way:
run it →line = "add Hello world" parts = line.split() show parts[0] show " ".join(parts[1:])remove <n>needs a number.int(parts[1])turns typed text into an integer,- 1makes it zero-based, andbuffer.pop(i)deletes that row. It prints['a', 'c']— line 2 was removed:
run it →buffer = ["a", "b", "c"] n = 2 i = int(n) - 1 buffer.pop(i) show bufferThe whole editor. Save
editor.nme:
run it →# editor.nme — a tiny line-based text editor. # Run: nme r editor # Type add <text>, list, remove <n>, save, or quit. use file latest import os # Load the saved buffer, or start with an empty one. if os.path.exists("notes.txt"): buffer = file_read("notes.txt").splitlines() else: buffer = [] show "Tiny editor — notes.txt" while True: show "Commands: add, list, remove, save, quit" ask line, "> " parts = line.split() command = parts[0] if parts else "" if command == "add": # The text after the command word is the new line. text = " ".join(parts[1:]) buffer.append(text) show f"Added line {len(buffer)}" elif command == "list": show f"{len(buffer)} lines" for i in range(len(buffer)): show f"{i + 1}: {buffer[i]}" elif command == "remove": # Remove line N: 1 is the first line. i = int(parts[1]) - 1 if i >= 0 and i < len(buffer): buffer.pop(i) show "Removed" else: show "No such line" elif command == "save": file_write("notes.txt", "\n".join(buffer)) show "Saved" elif command == "quit": show "Bye!" break else: show "Unknown command"addappends to the list,listwalks it withf"{i + 1}:"so line numbers start at 1, andsavedoes the join from step 1 in reverse —"\n".join(buffer)into the file.Run it and feed the commands through a pipe.
add Helloandadd World!fill the buffer,remove 1deletesHello, andsavekeepsWorld!:printf 'add Hello\nadd World!\nlist\nremove 1\nlist\nsave\nquit\n' | nme r editorTiny editor — notes.txt Commands: add, list, remove, save, quit > Added line 1 Commands: add, list, remove, save, quit > Added line 2 Commands: add, list, remove, save, quit > 2 lines 1: Hello 2: World! Commands: add, list, remove, save, quit > Removed Commands: add, list, remove, save, quit > 1 lines 1: World! Commands: add, list, remove, save, quit > Saved Commands: add, list, remove, save, quit > Bye!cat notes.txtshows the saved buffer — a singleWorld!line. Run the editor again andlistloads that line back, so the file and the buffer stay in sync across sessions.
Try it yourself
Add an upper command that uppercases the whole buffer before saving
([l.upper() for l in buffer]), or a clear command that empties the list.
Make save print how many lines it wrote.
What you learned
- A buffer is a list of lines;
"\n".join(buffer)saves it and.splitlines()loads it. line.split()separates a command word from its text;" ".join(parts[1:])reconnects the text.int(...) - 1turns a typed line number into a list index;buffer.pop(i)removes a row.savewrites the file, so the buffer survives between runs.