| Bytes | Lang | Time | Link |
|---|---|---|---|
| 088 | Charcoal | 230725T084921Z | Neil |
| 145 | Ruby | 230725T042530Z | Value In |
| 228 | Python 3.8 prerelease | 230725T041111Z | Ethan C |
| 248 | Q | 230724T171115Z | scottste |
Charcoal, 88 bytes
Sθ≔⁻LθNηWS≡ι´⟲≔∧υ⊟υι⊞υιFυ≡ι´←≧⁺‹ηLθη´→≧⁻‹⁰ηη´⮌≔⁺✂θ⁰±⊕η¹✂θ⁻LθηLθ¹θ≔⁺⁺✂θ⁰⁻Lθη¹ι✂θ⁻LθηLθ¹θθ
Try it online! Link is to verbose version of code. Takes the input sequence as a list of newline-terminated strings where ⟲ is undo, ← is left, → is right, and ⮌ is backspace. Explanation:
Sθ≔⁻LθNη
Input the starting string and position, but calculate the position as a count from the end of the string, because that remains invariant under insertion and deletion.
WS
Loop through each command string.
≡ι´⟲≔∧υ⊟υι⊞υι
If it's a ⟲ then remove the previous command if any otherwise add the command.
Fυ≡ι
Loop through the remaining commands.
´←≧⁺‹ηLθη
Handle left.
´→≧⁻‹⁰ηη
Handle right.
´⮌≔⁺✂θ⁰±⊕η¹✂θ⁻LθηLθ¹θ
Handle backspace.
≔⁺⁺✂θ⁰⁻Lθη¹ι✂θ⁻LθηLθ¹θ
Handle everything else.
θ
Output the resulting string.
Ruby, 145 bytes
Not sure if it breaks the rules to have the special commands as integers. U=0, L=-1, R=1, B=8
The only reason B=8 is because the control code for backspace is \x08 lol
->s,l,i{i[(x=i.index 0)-[1,x].min..x]=[]while[]!=[0]&i
i.map{|e|l=l.clamp 0,s.size;e.ord==e ?e<5?l+=e:(s[l-=1]=''if l>0):(s[l,0]=e;l+=e.size)}
s}
Ruby, 153 bytes
Version that uses characters only in case the above answer breaks the rules: U=\x00, L=\x01, R=\x03, B=\x08
->s,l,i{i[(x=i.index"\0")-[1,x].min..x]=[]while[]!=[?\0]&i
i.map{|e|l=l.clamp 0,s.size;c=e.ord;c<9?c<5?l+=c-2:(s[l-=1]=''if l>0):(s[l,0]=e;l+=e.size)}
s}
Python 3.8 (pre-release), 228 bytes
def f(s,c,Z,d=[]):
for i in Z:d=d[:-1]if i[0]and'T'<i[1]else d+[i]
for S,D in d:
if S:
if'Q'<D:c=min(c+1,len(s))
elif'K'<D:c=max(c-1,0)
else:s=s[:(f:=max(c-1,0))]+s[c:];c=f
else:s=s[:c]+D+s[c:];c+=len(D)
return s
The first for loop uses the stack d to get rid of all the undos. The second for loop loops over each instruction and modifies the string s accordingly. Almost definitely still golfable.
Inputs: list of tuples: (opcode, string). The opcode is 1 if the string is a special command, and 0 otherwise. Ex: [(1, 'R'), (1, 'U'), (0, 'hi')] This may be stretching the acceptable input format a bit, so I made a version which can accept the input format that the OP used:
Python 3.8 (pre-release), 267 bytes
def f(s,c,Z,d=[]):
for i in Z.split(';'):g='['in i;i=i[1]if g else i;d=d[:-1]if g and'T'<i else d+[(g,i)]
for S,D in d:
if S:
if'Q'<D:c=min(c+1,len(s))
elif'K'<D:c=max(c-1,0)
else:s=s[:(f:=max(c-1,0))]+s[c:];c=f
else:s=s[:c]+D+s[c:];c+=len(D)
return s
Q, 248 bytes
w:{s:{x like"[[]",y,"[]]"};if[10=(@:)z;z:";"vs z];while[z[0]~"[U]";z:1_z];$[0=(#:)z;x;not(^:)r:(*:)(&:)s[z;"U"];w[x;y;_[z _ r;r-1]];s[o:z 0;"R"];w[x;(#:)[x]&y+1;1_z];s[o;"L"];w[x;0|y-1;1_z];s[o;"B"];w[x _ y-1;0|y-1;1_z];w[#[y;x],o,_[y;x];y+1;1_z]]}
ungolfed:
wp: { [text; cursor; input]
if[10h=type input; input: ";" vs input]; // convert semicolon-delimited string to list of strings
special: {x like "[[]",y,"[]]"}; // function to check whether a string is like e.g. "[E]"
while[input[0]~"[U]"; input: 1 _ input]; // remove leading undo's since there's nothing to undo
if[not null rm: first where special[input; "U"]; // find the first "[U]" operation -- re-call this function after removing it and the preceding operation
: wp[text; cursor; _[input _ rm;rm-1]];
];
if[0=count input; : text]; // base case -- return text if there are no more operations
op: input 0;
if[special[op; "R"]; // re-call this function with 1 added to cursor (capping at length of text)
: wp[text; count[text]&cursor+1; 1_input]];
if[special[op; "L"]; // re-call this function with 1 removed from the cursor (capping at 0)
: wp[text; 0|cursor-1; 1_input]];
if[special[op; "B"]; // re-call this function with a) the character before the cursor removed from text and b) 1 removed from the cursor (capping at 0)
: wp[text _ cursor-1; 0|cursor-1; 1_input]];
: wp[ #[cursor;text],op,_[cursor;text]; cursor+1; 1_input]; // re-call this function with the characters added after the cursor in text
}