reslop 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/LICENSE +1 -1
  3. package/README.md +12 -13
  4. package/bin/reslop.js +3 -8
  5. package/lib/ansi.js +32 -19
  6. package/lib/capabilities.js +8 -12
  7. package/lib/cli.js +40 -74
  8. package/lib/clipboard.js +48 -18
  9. package/lib/dashboard/git.js +128 -0
  10. package/lib/dashboard/model.js +332 -0
  11. package/lib/dashboard/npm.js +193 -0
  12. package/lib/dashboard/tree.js +278 -0
  13. package/lib/deps-diff.js +196 -404
  14. package/lib/deps.js +240 -399
  15. package/lib/detect.js +8 -18
  16. package/lib/diff/align.js +41 -113
  17. package/lib/diff/diff.js +12 -43
  18. package/lib/diff/display.js +25 -36
  19. package/lib/diff/edit.js +6 -20
  20. package/lib/diff/inline.js +138 -141
  21. package/lib/diff/items.js +33 -47
  22. package/lib/diff/parse.js +28 -56
  23. package/lib/diff/patch.js +12 -33
  24. package/lib/diff/unit.js +90 -206
  25. package/lib/editor.js +98 -55
  26. package/lib/files.js +86 -103
  27. package/lib/git-branches.js +254 -416
  28. package/lib/git-deps.js +182 -344
  29. package/lib/git-reword-todo.js +5 -13
  30. package/lib/git-worktree.js +141 -212
  31. package/lib/git.js +21 -49
  32. package/lib/github.js +67 -181
  33. package/lib/gitlab.js +40 -90
  34. package/lib/highlight/bash.js +55 -177
  35. package/lib/highlight/core.js +157 -132
  36. package/lib/highlight/css.js +25 -58
  37. package/lib/highlight/csv.js +19 -37
  38. package/lib/highlight/dart.js +72 -213
  39. package/lib/highlight/dot.js +16 -26
  40. package/lib/highlight/html.js +42 -63
  41. package/lib/highlight/js.js +177 -506
  42. package/lib/highlight/json.js +17 -37
  43. package/lib/highlight/log.js +22 -35
  44. package/lib/highlight/txt.js +9 -22
  45. package/lib/highlight.js +17 -46
  46. package/lib/keys.js +62 -85
  47. package/lib/manifest.js +67 -130
  48. package/lib/npm-commands.js +119 -189
  49. package/lib/remote.js +141 -197
  50. package/lib/render/branches.js +66 -73
  51. package/lib/render/chrome.js +264 -323
  52. package/lib/render/commits.js +187 -500
  53. package/lib/render/dash-activity.js +212 -0
  54. package/lib/render/dash-blocks.js +245 -0
  55. package/lib/render/dash-table.js +290 -0
  56. package/lib/render/dashboard.js +62 -0
  57. package/lib/render/diff.js +123 -228
  58. package/lib/render/files.js +45 -99
  59. package/lib/render/frame.js +129 -183
  60. package/lib/render/notes.js +144 -160
  61. package/lib/render/npm.js +234 -112
  62. package/lib/render/present.js +4 -11
  63. package/lib/render/primitives.js +131 -170
  64. package/lib/render/render.js +5 -14
  65. package/lib/render/report.js +43 -0
  66. package/lib/render/tiles.js +260 -0
  67. package/lib/render/unit.js +15 -28
  68. package/lib/report-model.js +110 -33
  69. package/lib/report-parse.js +56 -38
  70. package/lib/report-render.js +102 -59
  71. package/lib/report-run.js +87 -78
  72. package/lib/report-test.js +256 -141
  73. package/lib/report-tools.js +96 -161
  74. package/lib/review-merge.js +114 -152
  75. package/lib/review.js +115 -189
  76. package/lib/runs.js +225 -0
  77. package/lib/select.js +89 -75
  78. package/lib/session/accessors.js +14 -21
  79. package/lib/session/actions.js +82 -63
  80. package/lib/session/branches.js +193 -247
  81. package/lib/session/change-actions.js +171 -214
  82. package/lib/session/commit.js +280 -342
  83. package/lib/session/compose.js +559 -674
  84. package/lib/session/dashboard.js +385 -0
  85. package/lib/session/dispatch.js +164 -157
  86. package/lib/session/edit-click.js +57 -0
  87. package/lib/session/files-pane.js +85 -53
  88. package/lib/session/items.js +73 -104
  89. package/lib/session/lifecycle.js +403 -541
  90. package/lib/session/load.js +48 -68
  91. package/lib/session/navigation.js +96 -87
  92. package/lib/session/npm.js +409 -345
  93. package/lib/session/ops.js +196 -63
  94. package/lib/session/pointer.js +23 -15
  95. package/lib/session/progress.js +33 -21
  96. package/lib/session/review.js +33 -54
  97. package/lib/session/tasks.js +333 -0
  98. package/lib/session/templates.js +51 -59
  99. package/lib/session/terminal.js +85 -136
  100. package/lib/session/unit.js +3 -4
  101. package/lib/session/update.js +76 -97
  102. package/lib/session/view.js +52 -83
  103. package/lib/session/watch.js +208 -204
  104. package/lib/session.js +112 -237
  105. package/lib/update.js +45 -116
  106. package/lib/utilities.js +67 -89
  107. package/lib/wrap.js +33 -44
  108. package/package.json +1 -1
  109. package/lib/session/todos.js +0 -293
package/lib/diff/patch.js CHANGED
@@ -3,14 +3,7 @@
3
3
  const align = require('./align.js');
4
4
  const { isCtxType } = align;
5
5
 
6
- const LINE_MARK = {
7
- add: '+',
8
- del: '-',
9
- ctx: ' ',
10
- warn: ' ',
11
- note: ' ',
12
- noteSep: ' ',
13
- };
6
+ const LINE_MARK = { add: '+', del: '-' };
14
7
 
15
8
  const splitHunk = (hunk) => {
16
9
  const { oldStart, oldCount, newStart, newCount, header } = hunk;
@@ -33,9 +26,8 @@ const splitHunk = (hunk) => {
33
26
  return { hunk: nextHunk, blocks };
34
27
  };
35
28
 
36
- const otherContext = (contextSide, blockId) => {
37
- if (contextSide === 'new') return 'new';
38
- if (contextSide === 'old') return 'old';
29
+ const sideOf = (contextSide, blockId) => {
30
+ if (typeof contextSide === 'string') return contextSide;
39
31
  return contextSide[blockId] ?? 'old';
40
32
  };
41
33
 
@@ -46,12 +38,8 @@ const flattenBlock = (hunk, blockId, contextSide) => {
46
38
  out.push(line);
47
39
  continue;
48
40
  }
49
- const side = otherContext(contextSide, line.blockId);
50
- if (side === 'old' && line.type === 'del') {
51
- out.push({ type: 'ctx', text: line.text, noNl: line.noNl });
52
- continue;
53
- }
54
- if (side === 'new' && line.type === 'add') {
41
+ const kept = sideOf(contextSide, line.blockId) === 'old' ? 'del' : 'add';
42
+ if (line.type === kept) {
55
43
  out.push({ type: 'ctx', text: line.text, noNl: line.noNl });
56
44
  }
57
45
  }
@@ -62,8 +50,8 @@ const countSides = (lines) => {
62
50
  let oldCount = 0;
63
51
  let newCount = 0;
64
52
  for (const line of lines) {
65
- if (isCtxType(line.type) || line.type === 'del') oldCount += 1;
66
- if (isCtxType(line.type) || line.type === 'add') newCount += 1;
53
+ if (line.type !== 'add') oldCount += 1;
54
+ if (line.type !== 'del') newCount += 1;
67
55
  }
68
56
  return { oldCount, newCount };
69
57
  };
@@ -71,24 +59,15 @@ const countSides = (lines) => {
71
59
  const formatHunkHeader = (oldStart, oldCount, newStart, newCount) =>
72
60
  `@@ -${oldStart},${oldCount} +${newStart},${newCount} @@`;
73
61
 
74
- const formatBodyLine = (line) => {
75
- const rows = [`${LINE_MARK[line.type] ?? ' '}${line.text}`];
76
- if (line.noNl) rows.push('\');
77
- return rows;
78
- };
79
-
80
62
  const formatPatch = (file, hunk, blockId, contextSide) => {
81
63
  const lines = flattenBlock(hunk, blockId, contextSide);
82
- const counts = countSides(lines);
83
- const header = formatHunkHeader(
84
- hunk.oldStart,
85
- counts.oldCount,
86
- hunk.newStart,
87
- counts.newCount,
88
- );
64
+ const { oldCount, newCount } = countSides(lines);
65
+ const { oldStart, newStart } = hunk;
66
+ const header = formatHunkHeader(oldStart, oldCount, newStart, newCount);
89
67
  const parts = [...file.preamble, header];
90
68
  for (const line of lines) {
91
- for (const row of formatBodyLine(line)) parts.push(row);
69
+ parts.push(`${LINE_MARK[line.type] ?? ' '}${line.text}`);
70
+ if (line.noNl) parts.push('\');
92
71
  }
93
72
  return `${parts.join('\n')}\n`;
94
73
  };
package/lib/diff/unit.js CHANGED
@@ -5,16 +5,14 @@ const { attachInline } = align;
5
5
  const files = require('../files.js');
6
6
  const { listPath } = files;
7
7
 
8
- const splitEditor = (text) => {
9
- const lines = `${text}`.split('\n');
10
- if (!lines.length) return [''];
11
- return lines;
12
- };
8
+ const LCS_CELLS = 4000000;
9
+
10
+ const splitEditor = (text) => text.split('\n');
13
11
 
14
12
  const splitFile = (text) => {
15
13
  if (!text) return [];
16
- const lines = `${text}`.split('\n');
17
- if (lines.length && lines[lines.length - 1] === '') lines.pop();
14
+ const lines = text.split('\n');
15
+ if (lines[lines.length - 1] === '') lines.pop();
18
16
  return lines;
19
17
  };
20
18
 
@@ -28,53 +26,13 @@ const hunkKey = (item) => {
28
26
 
29
27
  const sameHunk = (left, right) => {
30
28
  if (!left || !right) return false;
31
- if (left.hunk && right.hunk && left.hunk === right.hunk) {
29
+ if (left.hunk && left.hunk === right.hunk) {
32
30
  return listPath(left) === listPath(right);
33
31
  }
34
- const key = hunkKey(left);
35
- if (!key) return false;
36
- return key === hunkKey(right);
37
- };
38
-
39
- const emptyMarks = (last) => {
40
- const size = last + 1;
41
- const dels = new Array(size);
42
- const adds = new Array(size);
43
- for (let i = 0; i < size; i++) {
44
- dels[i] = [];
45
- adds[i] = null;
46
- }
47
- return { dels, adds };
48
- };
49
-
50
- const clipAt = (n, last) => Math.min(Math.max(1, n), last);
51
-
52
- const applyHunk = (marks, item) => {
53
- const hunk = item.hunk;
54
- if (!hunk || !hunk.lines) return;
55
- const last = marks.dels.length - 1;
56
- let newLine = hunk.newStart > 0 ? hunk.newStart : 1;
57
- for (const line of hunk.lines) {
58
- const extra = {
59
- text: line.text ?? '',
60
- item,
61
- blockId: line.blockId,
62
- origin: item.origin,
63
- };
64
- if (line.type === 'del') {
65
- marks.dels[clipAt(newLine, last)].push(extra);
66
- continue;
67
- }
68
- if (line.type === 'add') {
69
- marks.adds[clipAt(newLine, last)] = extra;
70
- newLine += 1;
71
- continue;
72
- }
73
- newLine += 1;
74
- }
32
+ return hunkKey(left) === hunkKey(right);
75
33
  };
76
34
 
77
- const tagged = (type, text, extra = {}) => ({
35
+ const tagged = (type, text, extra) => ({
78
36
  type,
79
37
  text,
80
38
  noNl: false,
@@ -83,20 +41,35 @@ const tagged = (type, text, extra = {}) => ({
83
41
  item: extra.item ?? null,
84
42
  });
85
43
 
86
- const itemsForPath = (items, rel) => {
87
- const out = [];
88
- for (const item of items) {
89
- if (listPath(item) === rel) out.push(item);
44
+ const NO_EXTRA = {};
45
+
46
+ const clipAt = (n, last) => Math.min(Math.max(1, n), last);
47
+
48
+ const markHunk = (marks, item) => {
49
+ if (!item.hunk) return;
50
+ const last = marks.dels.length - 1;
51
+ let newLine = item.hunk.newStart > 0 ? item.hunk.newStart : 1;
52
+ for (const line of item.hunk.lines) {
53
+ const { type, text, blockId } = line;
54
+ const mark = { text, item, blockId, origin: item.origin };
55
+ if (type === 'del') {
56
+ marks.dels[clipAt(newLine, last)].push(mark);
57
+ continue;
58
+ }
59
+ if (type === 'add') marks.adds[clipAt(newLine, last)] = mark;
60
+ newLine += 1;
90
61
  }
91
- return out;
92
62
  };
93
63
 
64
+ const itemsForPath = (items, rel) =>
65
+ items.filter((item) => listPath(item) === rel);
66
+
94
67
  const rowsFromAdds = (items) => {
95
68
  const rows = [];
96
69
  for (const item of items) {
97
- const lines = item.hunk && item.hunk.lines ? item.hunk.lines : [];
98
- for (const line of lines) {
99
- if (line.type === 'add') rows.push(line.text ?? '');
70
+ if (!item.hunk) continue;
71
+ for (const line of item.hunk.lines) {
72
+ if (line.type === 'add') rows.push(line.text);
100
73
  }
101
74
  }
102
75
  return rows;
@@ -105,75 +78,57 @@ const rowsFromAdds = (items) => {
105
78
  const unitLines = (text, items) => {
106
79
  let rows = splitFile(text);
107
80
  if (!rows.length) rows = rowsFromAdds(items);
108
- const marks = emptyMarks(rows.length + 1);
109
- for (const item of items) applyHunk(marks, item);
81
+ const size = rows.length + 2;
82
+ const marks = {
83
+ dels: Array.from({ length: size }, () => []),
84
+ adds: new Array(size).fill(null),
85
+ };
86
+ for (const item of items) markHunk(marks, item);
110
87
  const out = [];
111
88
  for (let i = 0; i < rows.length; i++) {
112
- const n = i + 1;
113
- for (const del of marks.dels[n]) out.push(tagged('del', del.text, del));
114
- const add = marks.adds[n];
89
+ for (const del of marks.dels[i + 1]) out.push(tagged('del', del.text, del));
90
+ const add = marks.adds[i + 1];
115
91
  if (add) out.push(tagged('add', rows[i], add));
116
- else out.push(tagged('ctx', rows[i], {}));
92
+ else out.push(tagged('ctx', rows[i], NO_EXTRA));
117
93
  }
118
94
  for (const del of marks.dels[rows.length + 1]) {
119
95
  out.push(tagged('del', del.text, del));
120
96
  }
121
- if (!out.length) out.push(tagged('ctx', '', {}));
97
+ if (!out.length) out.push(tagged('ctx', '', NO_EXTRA));
122
98
  return attachInline(out);
123
99
  };
124
100
 
125
- const sameBlock = (line, item) => {
126
- if (!line || !item) return false;
127
- if (line.item !== item) return false;
128
- return line.blockId === item.blockId;
129
- };
101
+ const sameBlock = (line, item) =>
102
+ line.item === item && line.blockId === item.blockId;
130
103
 
131
- const blockLineRange = (lines, item) => {
132
- let start = 0;
104
+ const changedLineRange = (lines, item, belongs) => {
105
+ let start = -1;
133
106
  let end = 0;
134
- let found = false;
135
- if (!item) return { start, end };
107
+ if (!item) return { start: 0, end };
136
108
  for (let i = 0; i < lines.length; i++) {
137
109
  const line = lines[i];
138
- if (!sameBlock(line, item)) continue;
139
- if (line.type === 'ctx') continue;
140
- if (!found) {
141
- start = i;
142
- found = true;
143
- }
110
+ if (line.type === 'ctx' || !belongs(line, item)) continue;
111
+ if (start < 0) start = i;
144
112
  end = i;
145
113
  }
146
- return { start, end };
114
+ return { start: Math.max(start, 0), end };
147
115
  };
148
116
 
117
+ const blockLineRange = (lines, item) =>
118
+ changedLineRange(lines, item, sameBlock);
119
+
149
120
  const blockLineIndex = (lines, item) => blockLineRange(lines, item).start;
150
121
 
151
- const hunkLineRange = (lines, item) => {
152
- let start = 0;
153
- let end = 0;
154
- let found = false;
155
- if (!item) return { start, end };
156
- for (let i = 0; i < lines.length; i++) {
157
- const line = lines[i];
158
- if (!sameHunk(line.item, item)) continue;
159
- if (line.type === 'ctx') continue;
160
- if (!found) {
161
- start = i;
162
- found = true;
163
- }
164
- end = i;
165
- }
166
- return { start, end };
167
- };
122
+ const hunkLineRange = (lines, item) =>
123
+ changedLineRange(lines, item, (line) => sameHunk(line.item, item));
168
124
 
169
125
  const fileOffset = (lines, at) => {
170
126
  let offset = 0;
171
- const target = Math.max(0, at);
172
127
  for (let i = 0; i < lines.length; i++) {
173
128
  const line = lines[i];
174
129
  if (line.type === 'del') continue;
175
- if (i >= target) return offset;
176
- offset += (line.text ?? '').length + 1;
130
+ if (i >= at) return offset;
131
+ offset += line.text.length + 1;
177
132
  }
178
133
  return offset;
179
134
  };
@@ -190,37 +145,27 @@ const fileLineIndex = (lines, fileLine) => {
190
145
  return last;
191
146
  };
192
147
 
193
- const lastEditableIndex = (lines) => {
194
- for (let i = lines.length - 1; i >= 0; i--) {
195
- if (lines[i].type !== 'del') return i;
196
- }
197
- return -1;
198
- };
199
-
200
148
  const attachEditSpans = (lines) => {
149
+ let lastAt = lines.length - 1;
150
+ while (lastAt >= 0 && lines[lastAt].type === 'del') lastAt -= 1;
201
151
  let offset = 0;
202
- const lastAt = lastEditableIndex(lines);
203
152
  for (let i = 0; i < lines.length; i++) {
204
153
  const line = lines[i];
205
154
  if (line.type === 'del') continue;
206
- const text = line.text ?? '';
207
- const last = i === lastAt;
208
155
  line.wrap = true;
209
156
  line.editStart = offset;
210
- line.editEnd = offset + text.length;
211
- line.editLast = last;
212
- offset = last ? offset + text.length : offset + text.length + 1;
157
+ line.editEnd = offset + line.text.length;
158
+ line.editLast = i === lastAt;
159
+ offset = line.editEnd + 1;
213
160
  }
214
161
  return lines;
215
162
  };
216
163
 
217
- const LCS_CELLS = 4000000;
218
-
219
164
  const lcsTable = (prev, next) => {
220
165
  const n = prev.length;
221
166
  const m = next.length;
222
167
  const dp = new Array(n + 1);
223
- for (let i = 0; i <= n; i++) dp[i] = new Array(m + 1).fill(0);
168
+ for (let i = 0; i <= n; i++) dp[i] = new Uint32Array(m + 1);
224
169
  for (let i = n - 1; i >= 0; i--) {
225
170
  for (let j = m - 1; j >= 0; j--) {
226
171
  if (prev[i] === next[j]) dp[i][j] = dp[i + 1][j + 1] + 1;
@@ -232,44 +177,35 @@ const lcsTable = (prev, next) => {
232
177
 
233
178
  const zipOps = (prev, next) => {
234
179
  const n = Math.min(prev.length, next.length);
235
- const ops = new Array(Math.max(prev.length, next.length));
236
- let at = 0;
237
- for (let i = 0; i < n; i++) ops[at++] = { kind: 'rep', text: next[i] };
238
- for (let i = n; i < prev.length; i++) ops[at++] = { kind: 'del' };
180
+ const ops = [];
181
+ for (let i = 0; i < n; i++) ops.push({ kind: 'rep', text: next[i] });
182
+ for (let i = n; i < prev.length; i++) ops.push({ kind: 'del' });
239
183
  for (let i = n; i < next.length; i++) {
240
- ops[at++] = { kind: 'ins', text: next[i] };
184
+ ops.push({ kind: 'ins', text: next[i] });
241
185
  }
242
186
  return ops;
243
187
  };
244
188
 
245
- const walkLcs = (prev, next, dp) => {
246
- const ops = new Array(prev.length + next.length - dp[0][0]);
247
- let n = 0;
189
+ const lcsOps = (prev, next) => {
190
+ const dp = lcsTable(prev, next);
191
+ const ops = [];
248
192
  let i = 0;
249
193
  let j = 0;
250
194
  while (i < prev.length && j < next.length) {
251
195
  if (prev[i] === next[j]) {
252
- ops[n++] = { kind: 'eq', text: next[j] };
196
+ ops.push({ kind: 'eq', text: next[j] });
253
197
  i += 1;
254
198
  j += 1;
255
- continue;
256
- }
257
- if (dp[i + 1][j] >= dp[i][j + 1]) {
258
- ops[n++] = { kind: 'del' };
199
+ } else if (dp[i + 1][j] >= dp[i][j + 1]) {
200
+ ops.push({ kind: 'del' });
259
201
  i += 1;
260
- continue;
202
+ } else {
203
+ ops.push({ kind: 'ins', text: next[j] });
204
+ j += 1;
261
205
  }
262
- ops[n++] = { kind: 'ins', text: next[j] };
263
- j += 1;
264
- }
265
- while (i < prev.length) {
266
- ops[n++] = { kind: 'del' };
267
- i += 1;
268
- }
269
- while (j < next.length) {
270
- ops[n++] = { kind: 'ins', text: next[j] };
271
- j += 1;
272
206
  }
207
+ for (; i < prev.length; i++) ops.push({ kind: 'del' });
208
+ for (; j < next.length; j++) ops.push({ kind: 'ins', text: next[j] });
273
209
  return ops;
274
210
  };
275
211
 
@@ -278,13 +214,10 @@ const collapseRep = (ops) => {
278
214
  for (let i = 0; i < ops.length; i++) {
279
215
  const op = ops[i];
280
216
  const next = ops[i + 1];
281
- if (op.kind === 'del' && next && next.kind === 'ins') {
282
- out.push({ kind: 'rep', text: next.text });
283
- i += 1;
284
- continue;
285
- }
286
- if (op.kind === 'ins' && next && next.kind === 'del') {
287
- out.push({ kind: 'rep', text: op.text });
217
+ const delIns = op.kind === 'del' && next?.kind === 'ins';
218
+ const insDel = op.kind === 'ins' && next?.kind === 'del';
219
+ if (delIns || insDel) {
220
+ out.push({ kind: 'rep', text: delIns ? next.text : op.text });
288
221
  i += 1;
289
222
  continue;
290
223
  }
@@ -296,91 +229,44 @@ const collapseRep = (ops) => {
296
229
  const lineOps = (prev, next) => {
297
230
  if (prev.length === next.length) return zipOps(prev, next);
298
231
  if (prev.length * next.length > LCS_CELLS) return zipOps(prev, next);
299
- return collapseRep(walkLcs(prev, next, lcsTable(prev, next)));
232
+ return collapseRep(lcsOps(prev, next));
300
233
  };
301
234
 
302
- const copyRow = (row, text) => ({
303
- type: row.type,
304
- text,
305
- noNl: row.noNl === true,
306
- blockId: row.blockId ?? null,
307
- origin: row.origin ?? '',
308
- item: row.item ?? null,
309
- });
310
-
311
235
  const pushDels = (out, base, at) => {
312
236
  let i = at;
313
237
  while (i < base.length && base[i].type === 'del') {
314
- out.push(copyRow(base[i], base[i].text ?? ''));
238
+ out.push(tagged('del', base[i].text, base[i]));
315
239
  i += 1;
316
240
  }
317
241
  return i;
318
242
  };
319
243
 
320
- const mergeEditRows = (baseRows, nextTexts) => {
321
- const base = baseRows ?? [];
322
- const texts = nextTexts && nextTexts.length ? nextTexts : [''];
244
+ const mergeEditRows = (base, nextTexts) => {
245
+ const texts = nextTexts.length ? nextTexts : [''];
323
246
  const prev = [];
324
- for (const row of base) {
325
- if (row.type === 'del') continue;
326
- prev.push(row.text ?? '');
327
- }
328
- const ops = lineOps(prev, texts);
247
+ for (const row of base) if (row.type !== 'del') prev.push(row.text);
329
248
  const out = [];
330
249
  let at = 0;
331
- for (const op of ops) {
250
+ for (const op of lineOps(prev, texts)) {
332
251
  at = pushDels(out, base, at);
333
252
  if (op.kind === 'ins') {
334
- out.push(tagged('ctx', op.text, {}));
253
+ out.push(tagged('ctx', op.text, NO_EXTRA));
335
254
  continue;
336
255
  }
337
256
  if (at >= base.length) continue;
338
- if (op.kind === 'del') {
339
- at += 1;
340
- continue;
341
- }
342
- out.push(copyRow(base[at], op.text));
257
+ if (op.kind !== 'del') out.push(tagged(base[at].type, op.text, base[at]));
343
258
  at += 1;
344
259
  }
345
260
  pushDels(out, base, at);
346
- if (!out.length) out.push(tagged('ctx', '', {}));
261
+ if (!out.length) out.push(tagged('ctx', '', NO_EXTRA));
347
262
  return attachEditSpans(attachInline(out));
348
263
  };
349
264
 
350
- const fileLines = (text) => {
351
- const rows = splitFile(text);
352
- if (!rows.length) rows.push('');
353
- const { length } = rows;
354
- const out = new Array(length);
355
- let offset = 0;
356
- for (let i = 0; i < length; i++) {
357
- const row = rows[i];
358
- const start = offset;
359
- const end = start + row.length;
360
- const last = i === length - 1;
361
- out[i] = {
362
- type: 'ctx',
363
- text: row,
364
- noNl: false,
365
- wrap: true,
366
- editStart: start,
367
- editEnd: end,
368
- editLast: last,
369
- blockId: null,
370
- origin: '',
371
- item: null,
372
- };
373
- offset = last ? end : end + 1;
374
- }
375
- return out;
376
- };
377
-
378
265
  module.exports = {
379
266
  splitFile,
380
267
  splitEditor,
381
268
  itemsForPath,
382
269
  unitLines,
383
- sameBlock,
384
270
  sameHunk,
385
271
  hunkKey,
386
272
  blockLineRange,
@@ -388,7 +274,5 @@ module.exports = {
388
274
  blockLineIndex,
389
275
  fileOffset,
390
276
  fileLineIndex,
391
- attachEditSpans,
392
277
  mergeEditRows,
393
- fileLines,
394
278
  };