comparison src/app/Session.ts @ 462:2624bb55dbf6

Fix ordering of adding to history (after an action). Add functions for stepping through the history.
author Lucas Thompson <dev@lucas.im>
date Fri, 30 Jun 2017 13:59:21 +0100
parents ccce2c09502e
children caef9a302bec
comparison
equal deleted inserted replaced
461:34db9d45663f 462:2624bb55dbf6
62 }; 62 };
63 63
64 export class PersistentStack<T> { 64 export class PersistentStack<T> {
65 private stack: T[]; 65 private stack: T[];
66 private history: T[][]; 66 private history: T[][];
67 private historyOffset: number;
67 68
68 constructor() { 69 constructor() {
69 this.stack = []; 70 this.stack = [];
70 this.history = []; 71 this.history = [[]];
72 this.historyOffset = 0;
71 } 73 }
72 74
73 shift(): T { 75 shift(): T {
74 this.history.push([...this.stack]);
75 const item = this.stack[0]; 76 const item = this.stack[0];
76 this.stack = this.stack.slice(1); 77 this.stack = this.stack.slice(1);
78 this.history.push([...this.stack]);
77 return item; 79 return item;
78 } 80 }
79 81
80 unshift(item: T): number { 82 unshift(item: T): number {
83 this.stack = [item, ...this.stack];
81 this.history.push([...this.stack]); 84 this.history.push([...this.stack]);
82 this.stack = [item, ...this.stack];
83 return this.stack.length; 85 return this.stack.length;
84 } 86 }
85 87
86 findIndex(predicate: (value: T, 88 findIndex(predicate: (value: T,
87 index: number, 89 index: number,
96 get(index: number): T { 98 get(index: number): T {
97 return this.stack[index]; 99 return this.stack[index];
98 } 100 }
99 101
100 set(index: number, value: T) { 102 set(index: number, value: T) {
101 this.history.push([...this.stack]);
102 this.stack = [ 103 this.stack = [
103 ...this.stack.slice(0, index), 104 ...this.stack.slice(0, index),
104 value, 105 value,
105 ...this.stack.slice(index + 1) 106 ...this.stack.slice(index + 1)
106 ]; 107 ];
108 this.history.push([...this.stack]);
107 } 109 }
108 110
109 map<U>(transform: (value: T, index: number, array: T[]) => U): U[] { 111 map<U>(transform: (value: T, index: number, array: T[]) => U): U[] {
110 return this.stack.map(transform); 112 return this.stack.map(transform);
111 } 113 }
117 initialValue: U): U { 119 initialValue: U): U {
118 return this.stack.reduce(reducer, initialValue); 120 return this.stack.reduce(reducer, initialValue);
119 } 121 }
120 122
121 remove(...indices: number[]) { 123 remove(...indices: number[]) {
122 this.history.push([...this.stack]);
123 this.stack = this.stack.reduce((acc, item, i) => { 124 this.stack = this.stack.reduce((acc, item, i) => {
124 if (!indices.includes(i)) { 125 if (!indices.includes(i)) {
125 acc.push(item); 126 acc.push(item);
126 } 127 }
127 return acc; 128 return acc;
128 }, [] as T[]); 129 }, [] as T[]);
130 this.history.push([...this.stack]);
131 }
132
133 stepBack(): void {
134 const latest = this.history.length - 1;
135 if (++this.historyOffset <= latest) {
136 this.stack = this.history[latest - this.historyOffset];
137 } else {
138 this.historyOffset = latest;
139 }
140 }
141
142 stepForward(): void {
143 const latest = this.history.length - 1;
144 if (--this.historyOffset >= 0) {
145 this.stack = this.history[latest - this.historyOffset];
146 } else {
147 this.historyOffset = 0;
148 }
129 } 149 }
130 150
131 toIterable(): Iterable<T> { 151 toIterable(): Iterable<T> {
132 return this.stack; 152 return this.stack;
133 } 153 }