One-Line Editor
MediumOnline Assessment
Replay a stream of editing commands on a one-line text box that has a cursor, a selection, and undo/redo.
The text box starts empty. It has a cursor, a position from 0 to the text length (0 is before the first character), and an optional anchor. When an anchor is set and differs from the cursor, the characters between the two positions are selected. If there is no anchor, or the anchor equals the cursor, nothing is selected. Each command is a string: a command name, optionally followed by one space and an argument (the argument is everything after that first space, so it may itself contain spaces).
type <text>: with a non-empty selection, replace the selection with<text>; otherwise insert<text>at the cursor. The cursor ends right after the inserted text and the anchor is cleared.backspace: with a non-empty selection, delete it (the cursor goes to the start of the selection). Otherwise delete the character before the cursor, if there is one. The anchor is cleared (even if nothing was deleted).delete: the same, but without a selection it deletes the character after the cursor, if there is one. The anchor is cleared.left <k>/right <k>: move the cursorkcharacters, stopping at the ends of the text. The anchor stays where it is, so moving aftermarkgrows or shrinks the selection.home/end: move the cursor to the start / end of the text. The anchor stays.mark: set the anchor at the cursor, replacing any earlier anchor.undo/redo: described below.
Undo history. Every command that actually changes the text is an edit: a type, backspace or delete that left the text different from before. Each edit is recorded with the full state (text, cursor and anchor) from just before it and just after it. Moves, mark, and commands that change nothing are not edits.
undotakes the most recent recorded step that has not been undone and restores the text, cursor and anchor that existed just before it. If there is nothing to undo, it does nothing.redore-applies the most recently undone step, restoring the text, cursor and anchor that existed just after it. If there is nothing to redo, it does nothing.- Any new edit discards everything that could still be redone.
- Typing is grouped. A
typecommand is *plain* if it replaced no selection. A plaintypethat comes immediately after another plaintypein the command list (no other command of any kind between them, even one that changed nothing) is merged into that earlier step instead of creating a new one: the merged step restores the state from before the firsttypeof the run, and re-does to the state after the last. Atypethat replaced a selection is never merged, and thetypeafter it starts a new step.
Anything else (an unknown command, a missing argument, type with nothing after it, a left or right whose argument is not a whole number) is ignored. It still counts as a command, so it breaks up a run of typing.
Input: commands, a list of command strings.
Output: a list [text, cursor] with the final text and the final cursor position.
Example 1
- Input:
- [["type ab","type cd","undo","type x","left 1","type y","undo","redo","redo"]]
- Output:
- ["yx",1]
- Explanation
type abandtype cdare consecutive plain typing, so they form a single undo step: textabcd.undoremoves both (text empty, cursor 0).type xgivesx.left 1moves the cursor to 0, so the nexttype yis a separate step:yx, cursor 1.undorestores the state before it (x, cursor 0). The firstredore-applies it (yx, cursor 1); the second finds nothing to redo.
Example 2
- Input:
- [["type hello world","left 5","mark","left 3","type J","undo","type there","backspace","backspace"]]
- Output:
- ["hel theworld",7]
- Explanation
- The cursor is at 11 after typing;
left 5moves it to 6,markanchors there andleft 3moves the cursor to 3, selectinglo.type Jreplaces the selection (helJworld), andundorestores the text, the cursor (3) and the anchor (6), so the selection is back.type there(the text is a space andthere) replaces that same selection:hel thereworld, cursor 9. Two backspaces deleteeandrand leavehel theworldwith the cursor at 7.
Example 3
- Input:
- [["type abc","left 0","type d","type e","undo","undo","undo","redo","redo","redo","redo"]]
- Output:
- ["abcde",5]
- Explanation
type abcgivesabc.left 0changes nothing but is a command in between, sotype dstarts a new undo step;type ejoins it. Undo reversesde(abc), thenabc(empty); the third undo finds nothing. Redo re-appliesabc, thenabcdewith the cursor at 5; the last two redos find nothing.
Constraints
- 0 ≤ commands.length ≤ 300
- Text given to
typeis 1 to 6 characters of lowercase letters and spaces; the text buffer never exceeds 2000 characters - Numbers given to
leftandrightare integers from 0 to 3000