reslop 0.2.6 → 0.3.0

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 (158) hide show
  1. package/CHANGELOG.md +27 -1
  2. package/README.md +16 -14
  3. package/bin/reslop.js +8 -5
  4. package/lib/agents/agents.js +504 -0
  5. package/lib/agents/allow.js +71 -0
  6. package/lib/agents/allow.json +16 -0
  7. package/lib/agents/models.js +460 -0
  8. package/lib/api.js +15 -12
  9. package/lib/cli.js +61 -66
  10. package/lib/{files.js → common/files.js} +51 -52
  11. package/lib/common/find.js +61 -0
  12. package/lib/common/format.js +101 -0
  13. package/lib/{utilities.js → common/process.js} +7 -95
  14. package/lib/common/tasks.json +27 -0
  15. package/lib/common/utilities.js +112 -0
  16. package/lib/dashboard/git.js +9 -16
  17. package/lib/dashboard/model.js +117 -51
  18. package/lib/dashboard/npm.js +133 -32
  19. package/lib/dashboard/tree.js +27 -30
  20. package/lib/{session → dashboard}/watch.js +41 -31
  21. package/lib/dashboard/workspace.js +151 -0
  22. package/lib/{deps.js → deps/deps.js} +31 -45
  23. package/lib/{deps-diff.js → deps/diff.js} +35 -25
  24. package/lib/{manifest.js → deps/manifest.js} +47 -30
  25. package/lib/diff/align.js +1 -2
  26. package/lib/diff/diff.js +2 -2
  27. package/lib/diff/display.js +29 -5
  28. package/lib/diff/inline.js +10 -14
  29. package/lib/diff/items.js +6 -4
  30. package/lib/diff/patch.js +39 -3
  31. package/lib/diff/unit.js +45 -16
  32. package/lib/{git-branches.js → git/branches.js} +53 -48
  33. package/lib/{git-deps.js → git/deps.js} +123 -95
  34. package/lib/git/git.js +71 -0
  35. package/lib/git/worktree.js +475 -0
  36. package/lib/highlight/bash.js +1 -2
  37. package/lib/highlight/csv.js +1 -2
  38. package/lib/highlight/dot.js +1 -2
  39. package/lib/{highlight.js → highlight/highlight.js} +42 -11
  40. package/lib/highlight/html.js +20 -18
  41. package/lib/highlight/json.js +1 -2
  42. package/lib/highlight/log.js +1 -2
  43. package/lib/highlight/txt.js +1 -2
  44. package/lib/{session → input}/actions.js +240 -71
  45. package/lib/{editor.js → input/editor.js} +7 -8
  46. package/lib/{keys.js → input/keys.js} +36 -39
  47. package/lib/input/line-edit.js +77 -0
  48. package/lib/input/menu-pick.js +70 -0
  49. package/lib/render/agents.js +640 -0
  50. package/lib/render/branches.js +4 -5
  51. package/lib/render/commits.js +54 -64
  52. package/lib/render/{dash-activity.js → dashboard/activity.js} +25 -40
  53. package/lib/render/dashboard/blocks.js +490 -0
  54. package/lib/render/{dashboard.js → dashboard/dashboard.js} +25 -22
  55. package/lib/render/diff.js +166 -45
  56. package/lib/render/field.js +131 -0
  57. package/lib/render/files.js +22 -8
  58. package/lib/render/footer.js +383 -0
  59. package/lib/render/frame.js +127 -25
  60. package/lib/render/header.js +176 -0
  61. package/lib/render/log.js +319 -0
  62. package/lib/render/menu.js +60 -0
  63. package/lib/render/notes.js +29 -13
  64. package/lib/render/npm.js +322 -196
  65. package/lib/render/packages.js +89 -0
  66. package/lib/render/primitives.js +109 -16
  67. package/lib/render/render.js +7 -11
  68. package/lib/render/repos.js +214 -0
  69. package/lib/render/status.js +370 -0
  70. package/lib/render/status.json +85 -0
  71. package/lib/render/{dash-table.js → table.js} +19 -61
  72. package/lib/render/tiles.js +203 -47
  73. package/lib/render/unit.js +32 -13
  74. package/lib/{report-model.js → report/model.js} +4 -6
  75. package/lib/{report-parse.js → report/parse.js} +9 -14
  76. package/lib/{report-render.js → report/render.js} +46 -14
  77. package/lib/{report-run.js → report/run.js} +42 -30
  78. package/lib/{report-test.js → report/test.js} +56 -55
  79. package/lib/{report-tools.js → report/tools.js} +24 -33
  80. package/lib/review/agent-instructions.md +9 -0
  81. package/lib/review/format.js +426 -0
  82. package/lib/{review-merge.js → review/merge.js} +9 -8
  83. package/lib/review/review.js +190 -0
  84. package/lib/review/store.js +281 -0
  85. package/lib/review/templates.js +83 -0
  86. package/lib/runs/commands.js +14 -0
  87. package/lib/runs/logs.js +299 -0
  88. package/lib/runs/output.js +174 -0
  89. package/lib/runs/process.js +113 -0
  90. package/lib/{runs.js → runs/runs.js} +84 -36
  91. package/lib/runs/scripts.js +150 -0
  92. package/lib/session/agents/agents.js +958 -0
  93. package/lib/session/agents/job.js +320 -0
  94. package/lib/session/agents/jobs.js +355 -0
  95. package/lib/session/agents/options.js +153 -0
  96. package/lib/session/agents/plans.js +83 -0
  97. package/lib/session/branches.js +36 -44
  98. package/lib/session/change-actions.js +34 -100
  99. package/lib/session/commit.js +122 -56
  100. package/lib/session/compose.js +197 -146
  101. package/lib/session/dashboard.js +183 -37
  102. package/lib/session/dispatch.js +120 -22
  103. package/lib/session/files-pane.js +60 -24
  104. package/lib/session/find.js +81 -0
  105. package/lib/session/import.js +82 -0
  106. package/lib/session/items.js +8 -17
  107. package/lib/session/lifecycle.js +96 -66
  108. package/lib/session/load.js +2 -4
  109. package/lib/session/navigation.js +8 -3
  110. package/lib/session/npm/history.js +249 -0
  111. package/lib/session/npm/npm.js +815 -0
  112. package/lib/session/npm/packages.js +150 -0
  113. package/lib/session/ops.js +125 -34
  114. package/lib/session/pointer.js +216 -10
  115. package/lib/session/prefs.js +112 -0
  116. package/lib/session/reads.js +109 -0
  117. package/lib/session/review.js +28 -10
  118. package/lib/session/run-panel.js +40 -0
  119. package/lib/{session.js → session/session.js} +166 -59
  120. package/lib/session/tasks.js +321 -66
  121. package/lib/session/templates.js +1 -1
  122. package/lib/session/terminal.js +94 -12
  123. package/lib/session/unit.js +35 -30
  124. package/lib/session/update.js +194 -6
  125. package/lib/session/view.js +72 -59
  126. package/lib/session/workspace.js +416 -0
  127. package/lib/{capabilities.js → source/capabilities.js} +3 -12
  128. package/lib/{github.js → source/github.js} +102 -32
  129. package/lib/{gitlab.js → source/gitlab.js} +87 -10
  130. package/lib/{remote.js → source/remote.js} +144 -40
  131. package/lib/source/review-threads.graphql +20 -0
  132. package/lib/source/source.js +74 -0
  133. package/lib/term/ansi.js +396 -0
  134. package/lib/{clipboard.js → term/clipboard.js} +3 -6
  135. package/lib/{select.js → term/select.js} +2 -2
  136. package/lib/term/themes/dark.json +122 -0
  137. package/lib/term/themes/light.json +122 -0
  138. package/lib/term/wide.txt +21 -0
  139. package/lib/{wrap.js → term/wrap.js} +4 -4
  140. package/package.json +2 -2
  141. package/lib/ansi.js +0 -505
  142. package/lib/detect.js +0 -34
  143. package/lib/diff/edit.js +0 -33
  144. package/lib/git-worktree.js +0 -437
  145. package/lib/git.js +0 -79
  146. package/lib/npm-commands.js +0 -522
  147. package/lib/render/chrome.js +0 -628
  148. package/lib/render/dash-blocks.js +0 -245
  149. package/lib/render/present.js +0 -19
  150. package/lib/render/report.js +0 -43
  151. package/lib/review.js +0 -744
  152. package/lib/session/accessors.js +0 -26
  153. package/lib/session/edit-click.js +0 -57
  154. package/lib/session/npm.js +0 -452
  155. package/lib/session/progress.js +0 -41
  156. package/lib/source.js +0 -36
  157. package/lib/update.js +0 -192
  158. /package/lib/{git-reword-todo.js → git/reword-todo.js} +0 -0
@@ -1,6 +1,13 @@
1
1
  'use strict';
2
2
 
3
- const LIST_PANES = ['files', 'branches', 'commits', 'npm'];
3
+ const LIST_PANES = [
4
+ 'files',
5
+ 'branches',
6
+ 'commits',
7
+ 'npm',
8
+ 'packages',
9
+ 'agents',
10
+ ];
4
11
 
5
12
  const ACTIONS = {
6
13
  add: ['a'],
@@ -10,20 +17,20 @@ const ACTIONS = {
10
17
  commit: ['c'],
11
18
  prev: ['left', 'p', 'k'],
12
19
  next: ['right', 'n', 'j'],
13
- check: ['x', ' '],
20
+ check: [' '],
14
21
  layout: ['m'],
15
- feedback: ['f'],
22
+ feedback: [],
16
23
  tasks: ['t'],
17
24
  code: ['e'],
18
25
  branch: ['b'],
19
26
  file: ['f'],
20
27
  diff: ['d'],
21
- quit: ['q', 'ctrl-c'],
28
+ quit: ['ctrl-c'],
22
29
  };
23
30
  const ACTION_IDS = Object.keys(ACTIONS);
24
31
 
25
32
  const BRANCH_ACTIONS = {
26
- newBranch: ['n'],
33
+ newBranch: ['insert'],
27
34
  rebase: ['e'],
28
35
  drop: ['delete'],
29
36
  pull: ['p'],
@@ -31,73 +38,148 @@ const BRANCH_ACTIONS = {
31
38
  };
32
39
 
33
40
  const COMMIT_ACTIONS = {
34
- amend: ['a'],
41
+ newCommit: ['insert'],
35
42
  apply: ['p'],
36
43
  reword: ['e'],
37
- fixup: ['x'],
38
44
  drop: ['delete'],
39
45
  view: ['v'],
40
46
  };
41
47
 
48
+ const PACKAGE_ACTIONS = {
49
+ packageNew: ['insert'],
50
+ packageDrop: ['delete'],
51
+ packageWanted: ['w'],
52
+ packageLatest: ['l'],
53
+ };
54
+
42
55
  const NPM_ACTIONS = {
43
56
  npm: ['n'],
44
57
  npmEdit: ['e'],
45
- npmNew: ['i'],
58
+ npmNew: ['insert'],
46
59
  npmDrop: ['delete'],
47
60
  npmLogs: ['l'],
48
- npmStop: ['escape'],
61
+ npmStop: ['s'],
49
62
  npmVerbose: ['v'],
50
63
  npmRerun: ['r'],
51
64
  };
52
65
 
53
- const DASH_ACTIONS = {
54
- dashFiles: ['f'],
55
- dashDiffs: ['d'],
56
- dashTasks: ['t'],
57
- dashBranches: ['b'],
58
- dashCommits: ['c'],
59
- dashRun: ['r'],
60
- dashNpm: ['n'],
66
+ const AGENT_ACTIONS = {
67
+ agentModel: ['m'],
68
+ agentEffort: ['e'],
69
+ agentFast: ['a'],
70
+ agentContext: ['t'],
71
+ agentReview: ['p'],
72
+ agentStop: ['s'],
73
+ agentRerun: ['r'],
61
74
  };
62
- const DASH_IDS = Object.keys(DASH_ACTIONS);
63
- const DASH_BLOCKS = {
64
- dashFiles: 'files',
65
- dashDiffs: 'diffs',
66
- dashCommits: 'commits',
67
- dashBranches: 'branches',
68
- dashNpm: 'npm',
69
- dashRun: 'run',
70
- dashTasks: 'tasks',
75
+
76
+ const AGENT_LIST_ACTIONS = {
77
+ agentModel: AGENT_ACTIONS.agentModel,
78
+ agentEffort: AGENT_ACTIONS.agentEffort,
79
+ agentFast: AGENT_ACTIONS.agentFast,
80
+ agentContext: AGENT_ACTIONS.agentContext,
81
+ agentReview: AGENT_ACTIONS.agentReview,
71
82
  };
72
- const DASH_ALLOWED = [...DASH_IDS, 'quit', 'theme'];
83
+
84
+ const DASH_TILES = [
85
+ { id: 'files', key: 'f', action: 'dashFiles', footer: true },
86
+ { id: 'diffs', key: 'd', action: 'dashDiffs', footer: true },
87
+ { id: 'tasks', key: 't', action: 'dashTasks', footer: true },
88
+ { id: 'branches', key: 'b', action: 'dashBranches', footer: true },
89
+ { id: 'commits', key: 'c', action: 'dashCommits', footer: true },
90
+ { id: 'run', key: 'r', action: 'dashRun', footer: true },
91
+ { id: 'npm', key: 'n', action: 'dashNpm', footer: true },
92
+ { id: 'agents', key: 'a', action: 'dashAgents', footer: false },
93
+ ];
94
+ const DASH_ACTIONS = {};
95
+ const DASH_BLOCKS = {};
96
+ const DASH_KEYS = {};
97
+ for (const tile of DASH_TILES) {
98
+ if (tile.footer) DASH_ACTIONS[tile.action] = [tile.key];
99
+ DASH_BLOCKS[tile.action] = tile.id;
100
+ DASH_KEYS[tile.key] = tile.action;
101
+ }
102
+ const DASH_IDS = Object.keys(DASH_ACTIONS);
103
+ const DASH_ALLOWED = [
104
+ ...Object.keys(DASH_BLOCKS),
105
+ 'back',
106
+ 'pull',
107
+ 'push',
108
+ 'quit',
109
+ 'theme',
110
+ ];
111
+ const REPOS_ALLOWED = [
112
+ 'repoLeft',
113
+ 'repoRight',
114
+ 'repoUp',
115
+ 'repoDown',
116
+ 'open',
117
+ 'back',
118
+ 'quit',
119
+ 'theme',
120
+ ];
73
121
  const DASH_HIDDEN = ACTION_IDS.filter((id) => id !== 'quit');
74
122
 
75
123
  const ACTION_HOT = {
76
124
  prev: '←',
77
125
  next: '→',
78
126
  drop: 'del',
127
+ newBranch: 'ins',
128
+ newCommit: 'ins',
129
+ feedback: 'q',
130
+ check: 'space',
131
+ taskUp: 'ctrl+up',
132
+ taskDown: 'ctrl+down',
133
+ taskNudge: 'up/dn',
134
+ plan: 'p',
135
+ import: 'i',
136
+ theme: 'l',
137
+ lines: '+l',
138
+ npmNew: 'ins',
79
139
  npmDrop: 'del',
80
- npmStop: 'esc',
140
+ npmStop: 's',
141
+ packageNew: 'ins',
142
+ packageDrop: 'del',
81
143
  };
82
144
 
83
145
  const ACTION_LABEL = {
84
146
  ...DASH_BLOCKS,
85
147
  revert: 'drop',
86
- check: 'x',
148
+ check: 'space',
149
+ taskUp: 'ctrl+up',
150
+ taskDown: 'ctrl+down',
151
+ taskNudge: 'ctrl+up/dn',
152
+ plan: 'plan',
153
+ import: 'import',
154
+ theme: 'light',
155
+ lines: 'ctrl+l',
87
156
  layout: 'mode',
88
157
  tasks: 'tasks',
89
158
  view: 'view',
90
159
  code: 'edit',
91
160
  reword: 'edit',
92
161
  drop: 'delete',
93
- newBranch: 'new',
162
+ newBranch: 'insert',
163
+ newCommit: 'insert',
164
+ feedback: 'quote',
94
165
  npmEdit: 'edit',
95
166
  npmNew: 'insert',
96
167
  npmDrop: 'delete',
97
168
  npmLogs: 'cleanup',
98
- npmStop: 'esc',
169
+ packageNew: 'insert',
170
+ packageDrop: 'delete',
171
+ packageWanted: 'wanted',
172
+ packageLatest: 'latest',
173
+ npmStop: 'stop',
99
174
  npmVerbose: 'verbose',
100
175
  npmRerun: 're-run',
176
+ agentModel: 'model',
177
+ agentEffort: 'effort',
178
+ agentFast: 'fast',
179
+ agentContext: 'context',
180
+ agentReview: 'plan',
181
+ agentStop: 'stop',
182
+ agentRerun: 're-run',
101
183
  quit: 'q',
102
184
  prev: '←',
103
185
  next: '→',
@@ -113,7 +195,7 @@ const DIFF_DISABLED = [
113
195
  'diff',
114
196
  ];
115
197
  const UNIT_DISABLED = [...DIFF_DISABLED, 'layout', 'ignore'];
116
- const FILES_DISABLED = ['layout', 'feedback', 'code'];
198
+ const FILES_DISABLED = ['layout', 'feedback'];
117
199
  const FILES_HIDDEN = [
118
200
  ...FILES_DISABLED,
119
201
  'check',
@@ -126,7 +208,7 @@ const FILES_HIDDEN = [
126
208
  'branch',
127
209
  ];
128
210
  const FILES_GIT_DISABLED = ['add', 'unstage', 'revert', 'ignore'];
129
- const FILES_TASKS_DISABLED = [...FILES_GIT_DISABLED, ...FILES_DISABLED];
211
+ const FILES_TASKS_DISABLED = [...FILES_GIT_DISABLED, ...FILES_DISABLED, 'code'];
130
212
  const TASKS_DISABLED = [
131
213
  'add',
132
214
  'unstage',
@@ -163,8 +245,44 @@ const BRANCHES_DISABLED = [
163
245
  const COMMITS_DISABLED = BRANCHES_DISABLED.filter((id) => id !== 'commit');
164
246
  const NPM_DISABLED = [...BRANCHES_DISABLED, 'pull', 'push'];
165
247
 
166
- const isTasksTarget = (item) =>
167
- !!(item && (item.kind === 'tasks' || item.origin === 'task'));
248
+ const isTasksTarget = (item) => {
249
+ if (!item) return false;
250
+ const tasks = item.kind === 'tasks';
251
+ const task = item.origin === 'task';
252
+ return tasks || task;
253
+ };
254
+
255
+ const DIFF_MOVE_IDS = ['add', 'unstage', 'revert'];
256
+
257
+ const entryHasDiff = (entry) => {
258
+ if (!entry || entry.kind === 'tasks') return false;
259
+ const keys = [
260
+ 'added',
261
+ 'removed',
262
+ 'stagedAdded',
263
+ 'stagedRemoved',
264
+ 'unstagedAdded',
265
+ 'unstagedRemoved',
266
+ 'remaining',
267
+ ];
268
+ let total = 0;
269
+ for (const key of keys) total += entry[key] ?? 0;
270
+ return total > 0;
271
+ };
272
+
273
+ const lineHasDiff = (line) => {
274
+ if (!line) return false;
275
+ return line.type === 'add' || line.type === 'del';
276
+ };
277
+
278
+ const withoutMoves = (off, hasDiff) => {
279
+ if (hasDiff) return off;
280
+ const next = off.slice();
281
+ for (const id of DIFF_MOVE_IDS) {
282
+ if (!next.includes(id)) next.push(id);
283
+ }
284
+ return next;
285
+ };
168
286
 
169
287
  const diffGitDisabled = (item) => {
170
288
  if (!item || isTasksTarget(item)) return [];
@@ -172,13 +290,8 @@ const diffGitDisabled = (item) => {
172
290
  return ['unstage'];
173
291
  };
174
292
 
175
- const BRANCH_REMOTE = ['pull', 'push'];
176
-
177
- const branchGitDisabled = (item) => {
178
- const off = item && !item.current ? [] : ['rebase', 'drop'];
179
- if (!item || !item.current) return [...off, ...BRANCH_REMOTE];
180
- return off;
181
- };
293
+ const branchGitDisabled = (item) =>
294
+ item && !item.current ? [] : ['rebase', 'drop'];
182
295
 
183
296
  const isFixupCommit = (item) =>
184
297
  `${item && item.subject ? item.subject : ''}`.startsWith('fixup!');
@@ -196,24 +309,44 @@ const commitWriteDisabled = (item) => {
196
309
  return ['amend', 'apply'];
197
310
  };
198
311
 
312
+ const commitChord = (item) => {
313
+ if (!item || item.pending || !item.sha) return 'commit';
314
+ if (item.head) return 'amend';
315
+ return 'fixup';
316
+ };
317
+
199
318
  const commitGitDisabled = (item) => {
200
319
  const off = [...commitWriteDisabled(item)];
201
320
  if (!isFixupCommit(item)) off.push('apply');
202
- if (item && item.canCommit === true) return off;
203
- return [...off, 'commit', 'fixup'];
321
+ const chord = commitChord(item);
322
+ const ready = item && item.canCommit === true;
323
+ if (chord === 'amend') return off;
324
+ if (!ready) off.push('commit');
325
+ return off;
204
326
  };
205
327
 
206
328
  const disabledActions = (pane, item) => {
207
329
  const onTodos = isTasksTarget(item);
208
- if (pane === 'files') return onTodos ? FILES_TASKS_DISABLED : FILES_DISABLED;
209
- if (pane === 'unit') return [...UNIT_DISABLED, ...diffGitDisabled(item)];
330
+ if (pane === 'dashboard' || pane === 'repos') return [];
331
+ if (pane === 'files') {
332
+ const base = onTodos ? FILES_TASKS_DISABLED : FILES_DISABLED;
333
+ if (onTodos) return base;
334
+ return withoutMoves(base, entryHasDiff(item));
335
+ }
336
+ if (pane === 'unit') {
337
+ const off = [...UNIT_DISABLED, ...diffGitDisabled(item)];
338
+ const onDiff = !item || item.lineDiff !== false;
339
+ return withoutMoves(off, onDiff);
340
+ }
210
341
  if (pane === 'branches') {
211
342
  return [...BRANCHES_DISABLED, ...branchGitDisabled(item)];
212
343
  }
213
344
  if (pane === 'commits') {
214
345
  return [...COMMITS_DISABLED, ...commitWriteDisabled(item)];
215
346
  }
216
- if (pane === 'npm') return NPM_DISABLED;
347
+ if (pane === 'npm' || pane === 'packages' || pane === 'agents') {
348
+ return NPM_DISABLED;
349
+ }
217
350
  if (pane === 'tasks' || onTodos) return TASKS_DISABLED;
218
351
  return [...DIFF_DISABLED, ...diffGitDisabled(item)];
219
352
  };
@@ -250,25 +383,37 @@ const keysForActions = (actions) => {
250
383
 
251
384
  const PANE_ONLY = ['branch', 'file', 'diff'];
252
385
  const REVIEW_DROP = { d: 'revert' };
386
+ const DIFF_KEYS = { ...REVIEW_DROP, q: 'feedback', 'ctrl-l': 'lines' };
253
387
  const BRANCH_KEYS = keysForActions(BRANCH_ACTIONS);
254
- const COMMIT_KEYS = { ...keysForActions(COMMIT_ACTIONS), c: 'commit' };
388
+ const COMMIT_KEYS = { ...keysForActions(COMMIT_ACTIONS), s: 'push' };
255
389
  const NPM_KEYS = {
256
390
  e: 'npmEdit',
257
- i: 'npmNew',
391
+ insert: 'npmNew',
258
392
  delete: 'npmDrop',
259
393
  l: 'npmLogs',
260
394
  };
261
- const DASH_KEYS = keysForActions(DASH_ACTIONS);
262
- const SCREEN_KEYS = DASH_KEYS;
395
+ const SCREEN_KEYS = keysForActions(DASH_ACTIONS);
263
396
  const PANE_KEYS = {
264
- dashboard: DASH_KEYS,
397
+ dashboard: { ...DASH_KEYS, p: 'pull', s: 'push' },
265
398
  files: REVIEW_DROP,
266
- diff: REVIEW_DROP,
267
- unit: REVIEW_DROP,
399
+ diff: DIFF_KEYS,
400
+ unit: DIFF_KEYS,
268
401
  branches: BRANCH_KEYS,
269
402
  commits: COMMIT_KEYS,
270
403
  npm: NPM_KEYS,
271
- tasks: { delete: 'drop' },
404
+ packages: keysForActions(PACKAGE_ACTIONS),
405
+ agents: keysForActions(AGENT_LIST_ACTIONS),
406
+ tasks: { delete: 'drop', p: 'plan', i: 'import' },
407
+ repos: {
408
+ left: 'repoLeft',
409
+ right: 'repoRight',
410
+ up: 'repoUp',
411
+ down: 'repoDown',
412
+ k: 'repoUp',
413
+ j: 'repoDown',
414
+ p: 'repoLeft',
415
+ n: 'repoRight',
416
+ },
272
417
  };
273
418
 
274
419
  const KEY_TO_ACTION = {
@@ -291,13 +436,17 @@ const actionFromKey = (key, pane) => {
291
436
  return KEY_TO_ACTION[key] ?? null;
292
437
  };
293
438
 
294
- const actionKeys = (id) =>
295
- ACTIONS[id] ??
296
- BRANCH_ACTIONS[id] ??
297
- COMMIT_ACTIONS[id] ??
298
- NPM_ACTIONS[id] ??
299
- DASH_ACTIONS[id] ??
300
- [];
439
+ const ACTION_KEYS = {
440
+ ...DASH_ACTIONS,
441
+ ...AGENT_ACTIONS,
442
+ ...PACKAGE_ACTIONS,
443
+ ...NPM_ACTIONS,
444
+ ...COMMIT_ACTIONS,
445
+ ...BRANCH_ACTIONS,
446
+ ...ACTIONS,
447
+ };
448
+
449
+ const actionKeys = (id) => ACTION_KEYS[id] ?? [];
301
450
 
302
451
  const actionLetter = (id) => ACTION_HOT[id] ?? actionKeys(id)[0];
303
452
 
@@ -315,15 +464,13 @@ const YES_NO = [
315
464
 
316
465
  const CONFIRM = {
317
466
  confirmQuit: {
318
- choices: [
319
- { letter: 'f', label: 'finish as ready', lead: ' ' },
320
- { letter: 'c', label: 'continue next time', lead: ' ' },
321
- ],
467
+ choices: YES_NO,
468
+ prefix: (view) => view.quitWarning || ' exit will terminate subprocesses',
322
469
  keys: {
323
- f: 'ready',
324
- c: 'editing',
325
- 'ctrl-c': 'ready',
470
+ y: 'confirm',
471
+ n: 'cancel',
326
472
  escape: 'cancel',
473
+ 'ctrl-c': 'cancel',
327
474
  },
328
475
  },
329
476
  confirmUpdate: {
@@ -356,6 +503,25 @@ const CONFIRM = {
356
503
  escape: 'cancel',
357
504
  },
358
505
  },
506
+ confirmCommit: {
507
+ choices: [
508
+ { letter: 'esc', label: 'esc cancel', lead: ' ' },
509
+ { letter: 'u', label: 'update', lead: ' ' },
510
+ { letter: 'c', label: 'commit', lead: ' ' },
511
+ { letter: 'a', label: 'amend', lead: ' ' },
512
+ { letter: 'f', label: 'fixup', lead: ' ' },
513
+ ],
514
+ prefix: ' what do you want to do?',
515
+ keys: {
516
+ esc: 'cancel',
517
+ escape: 'cancel',
518
+ enter: 'update',
519
+ u: 'update',
520
+ c: 'commit',
521
+ a: 'amend',
522
+ f: 'fixup',
523
+ },
524
+ },
359
525
  };
360
526
 
361
527
  const CONFIRM_MODE = Object.keys(CONFIRM);
@@ -377,14 +543,14 @@ const promptFromChoices = (choices) =>
377
543
 
378
544
  module.exports = {
379
545
  LIST_PANES,
546
+ DASH_TILES,
380
547
  DASH_IDS,
381
548
  DASH_BLOCKS,
382
549
  DASH_ALLOWED,
383
550
  DASH_HIDDEN,
551
+ REPOS_ALLOWED,
384
552
  ACTIONS,
385
553
  ACTION_IDS,
386
- BRANCH_ACTIONS,
387
- COMMIT_ACTIONS,
388
554
  DIFF_DISABLED,
389
555
  UNIT_DISABLED,
390
556
  FILES_DISABLED,
@@ -396,6 +562,9 @@ module.exports = {
396
562
  COMMITS_DISABLED,
397
563
  NPM_DISABLED,
398
564
  disabledActions,
565
+ entryHasDiff,
566
+ lineHasDiff,
567
+ withoutMoves,
399
568
  diffGitDisabled,
400
569
  branchGitDisabled,
401
570
  commitGitDisabled,
@@ -1,9 +1,8 @@
1
1
  'use strict';
2
2
 
3
- const ansi = require('./ansi.js');
4
- const { graphemes, visibleWidth } = ansi;
5
- const wrap = require('./wrap.js');
6
- const { wrapMove } = wrap;
3
+ const { clamp } = require('../common/utilities.js');
4
+ const { graphemes, visibleWidth } = require('../term/ansi.js');
5
+ const { wrapMove } = require('../term/wrap.js');
7
6
 
8
7
  const UNDO_CAP = 100;
9
8
  const WORD_RE = /[\p{L}\p{N}_]/u;
@@ -127,7 +126,7 @@ class Editor {
127
126
  place(offset) {
128
127
  this.wantCol = null;
129
128
  this.anchor = null;
130
- this.cursor = Math.max(0, Math.min(offset, this.text.length));
129
+ this.cursor = clamp(offset, 0, this.text.length);
131
130
  }
132
131
 
133
132
  backspace() {
@@ -145,8 +144,8 @@ class Editor {
145
144
  if (this.removeSpan()) return;
146
145
  const { parts, i, pos } = graphemeIndex(this.text, this.cursor);
147
146
  if (i >= parts.length) return;
148
- const next =
149
- this.text.slice(0, pos) + this.text.slice(pos + parts[i].length);
147
+ const size = parts[i].length;
148
+ const next = this.text.slice(0, pos) + this.text.slice(pos + size);
150
149
  this.edit(next, this.cursor);
151
150
  }
152
151
 
@@ -206,7 +205,7 @@ class Editor {
206
205
  }
207
206
  const rows = this.text.split('\n');
208
207
  const { line, col } = this.linePos();
209
- const next = Math.min(Math.max(line + delta, 0), rows.length - 1);
208
+ const next = clamp(line + delta, 0, rows.length - 1);
210
209
  if (next === line) return;
211
210
  let cursor = 0;
212
211
  for (let i = 0; i < next; i++) cursor += rows[i].length + 1;
@@ -1,15 +1,8 @@
1
1
  'use strict';
2
2
 
3
- const actions = require('./session/actions.js');
3
+ const actions = require('./actions.js');
4
4
 
5
- const { ACTIONS, ACTION_IDS, BRANCH_ACTIONS, COMMIT_ACTIONS } = actions;
6
- const { DASH_IDS, DASH_HIDDEN } = actions;
7
- const { DIFF_DISABLED, FILES_GIT_DISABLED, FILES_HIDDEN } = actions;
8
- const { TASKS_DISABLED, BRANCHES_DISABLED } = actions;
9
- const { COMMITS_DISABLED, UNIT_DISABLED, NPM_DISABLED } = actions;
10
- const { diffGitDisabled, branchGitDisabled, commitGitDisabled } = actions;
11
- const { actionLetter, buttonWord } = actions;
12
- const { CONFIRM, confirmPrefix, promptFromChoices } = actions;
5
+ const { ACTIONS } = actions;
13
6
 
14
7
  const CSI_KEYS = {
15
8
  A: 'up',
@@ -18,16 +11,38 @@ const CSI_KEYS = {
18
11
  D: 'left',
19
12
  H: 'home',
20
13
  F: 'end',
14
+ Z: 'shift-tab',
15
+ };
16
+
17
+ const SS3_KEYS = {
18
+ ...CSI_KEYS,
19
+ P: 'f1',
20
+ Q: 'f2',
21
+ R: 'f3',
22
+ S: 'f4',
21
23
  };
22
24
 
23
25
  const CSI_TILDE = {
24
26
  1: 'home',
27
+ 2: 'insert',
25
28
  3: 'delete',
26
29
  4: 'end',
27
30
  5: 'pageUp',
28
31
  6: 'pageDown',
29
32
  7: 'home',
30
33
  8: 'end',
34
+ 11: 'f1',
35
+ 12: 'f2',
36
+ 13: 'f3',
37
+ 14: 'f4',
38
+ 15: 'f5',
39
+ 17: 'f6',
40
+ 18: 'f7',
41
+ 19: 'f8',
42
+ 20: 'f9',
43
+ 21: 'f10',
44
+ 23: 'f11',
45
+ 24: 'f12',
31
46
  };
32
47
 
33
48
  const CSI_MAX = 16;
@@ -46,14 +61,16 @@ const MOUSE_WHEEL = {
46
61
  65: 'wheelDown',
47
62
  };
48
63
 
64
+ const ARROW_KEYS = ['left', 'right', 'up', 'down'];
65
+ const EDGE_KEYS = ['home', 'end'];
66
+
49
67
  const NEED_MORE = { needMore: true };
50
68
 
51
69
  const keyAt = (key, end) => ({ event: { type: 'key', key }, end });
52
70
 
53
71
  const modifiedKey = (base, modText) => {
54
- const arrow =
55
- base === 'left' || base === 'right' || base === 'up' || base === 'down';
56
- const end = base === 'home' || base === 'end';
72
+ const arrow = ARROW_KEYS.includes(base);
73
+ const end = EDGE_KEYS.includes(base);
57
74
  if (!arrow && !end) return base;
58
75
  const mod = parseInt(modText, 10);
59
76
  const bits = Number.isFinite(mod) ? mod - 1 : 0;
@@ -121,7 +138,7 @@ const parseEsc = (text, start) => {
121
138
  if (rest.startsWith('\x1b[')) return parseCsi(rest, start);
122
139
  if (rest.startsWith('\x1bO')) {
123
140
  if (rest.length < 3) return NEED_MORE;
124
- const key = CSI_KEYS[rest[2]];
141
+ const key = SS3_KEYS[rest[2]];
125
142
  return key ? keyAt(key, start + 3) : keyAt('escape', start + 1);
126
143
  }
127
144
  return keyAt('escape', start + 1);
@@ -161,6 +178,11 @@ const decodeChunk = (text, carry = '') => {
161
178
  return { events, carry: '' };
162
179
  };
163
180
 
181
+ const isTextKey = (key) => {
182
+ if (!key || key.length !== 1) return false;
183
+ return key.charCodeAt(0) >= 32;
184
+ };
185
+
164
186
  const hitAction = (hits, x) => {
165
187
  for (const hit of hits) {
166
188
  if (x >= hit.x0 && x < hit.x1) return hit.id;
@@ -168,29 +190,4 @@ const hitAction = (hits, x) => {
168
190
  return null;
169
191
  };
170
192
 
171
- module.exports = {
172
- ACTIONS,
173
- ACTION_IDS,
174
- DASH_IDS,
175
- DASH_HIDDEN,
176
- BRANCH_ACTIONS,
177
- COMMIT_ACTIONS,
178
- DIFF_DISABLED,
179
- FILES_HIDDEN,
180
- FILES_GIT_DISABLED,
181
- TASKS_DISABLED,
182
- BRANCHES_DISABLED,
183
- COMMITS_DISABLED,
184
- NPM_DISABLED,
185
- UNIT_DISABLED,
186
- diffGitDisabled,
187
- branchGitDisabled,
188
- commitGitDisabled,
189
- decodeChunk,
190
- actionLetter,
191
- buttonWord,
192
- hitAction,
193
- CONFIRM,
194
- confirmPrefix,
195
- promptFromChoices,
196
- };
193
+ module.exports = { ACTIONS, decodeChunk, hitAction, isTextKey };