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/select.js CHANGED
@@ -1,10 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  const ansi = require('./ansi.js');
4
-
5
- const { ESC, RESET, THEME, seq, stripAnsi, graphemes, graphemeWidth } = ansi;
4
+ const { ESC, RESET, THEME, seq, fg, bg, stripAnsi, visibleWidth } = ansi;
5
+ const { graphemes, graphemeWidth, firstGrapheme } = ansi;
6
6
 
7
7
  const CSI_FINAL = /[@-~]/;
8
+ const TRUECOLOR = 2;
8
9
 
9
10
  const isRange = (sel) => {
10
11
  if (!sel || !sel.start || !sel.end) return false;
@@ -12,21 +13,16 @@ const isRange = (sel) => {
12
13
  };
13
14
 
14
15
  const ordered = (sel) => {
15
- const start = sel.start;
16
- const end = sel.end;
17
- if (start.y < end.y) return { first: start, last: end };
18
- if (start.y > end.y) return { first: end, last: start };
19
- if (start.x <= end.x) return { first: start, last: end };
20
- return { first: end, last: start };
16
+ const { start, end } = sel;
17
+ const forward = start.y < end.y || (start.y === end.y && start.x <= end.x);
18
+ return forward ? { first: start, last: end } : { first: end, last: start };
21
19
  };
22
20
 
23
21
  const slicePlain = (plain, fromCol, toCol) => {
24
- const parts = graphemes(plain);
25
22
  let col = 0;
26
23
  let out = '';
27
- for (const ch of parts) {
28
- const w = graphemeWidth(ch, col);
29
- const next = col + w;
24
+ for (const ch of graphemes(plain)) {
25
+ const next = col + graphemeWidth(ch, col);
30
26
  if (next > fromCol && col < toCol) out += ch;
31
27
  col = next;
32
28
  if (col >= toCol) break;
@@ -38,10 +34,8 @@ const lineRange = (rowIndex, sel) => {
38
34
  const { first, last } = ordered(sel);
39
35
  const y = rowIndex + 1;
40
36
  if (y < first.y || y > last.y) return null;
41
- let from = 0;
42
- let to = Infinity;
43
- if (y === first.y) from = first.x - 1;
44
- if (y === last.y) to = last.x;
37
+ const from = y === first.y ? first.x - 1 : 0;
38
+ const to = y === last.y ? last.x : Infinity;
45
39
  if (to <= from) return null;
46
40
  return { from, to };
47
41
  };
@@ -60,11 +54,10 @@ const extractText = (rows, sel) => {
60
54
  return lines.join('\n');
61
55
  };
62
56
 
63
- const consumeCsi = (line, i) => {
57
+ const csiEnd = (line, i) => {
64
58
  let j = i + 2;
65
59
  while (j < line.length && !CSI_FINAL.test(line[j])) j += 1;
66
- if (j < line.length) j += 1;
67
- return j;
60
+ return j < line.length ? j + 1 : j;
68
61
  };
69
62
 
70
63
  const parseParams = (body) => {
@@ -73,45 +66,30 @@ const parseParams = (body) => {
73
66
  };
74
67
 
75
68
  const applyRgb = (state, field, params, i) => {
76
- const TRUECOLOR = 2;
77
69
  const isTruecolor = params[i + 1] === TRUECOLOR;
78
- const hasRgb = isTruecolor && i + 4 < params.length;
79
- if (!hasRgb) return 1;
70
+ if (!isTruecolor || i + 4 >= params.length) return 1;
80
71
  state[field] = [params[i + 2], params[i + 3], params[i + 4]];
81
72
  return 5;
82
73
  };
83
74
 
84
- const SGR = {
85
- 0: (state) => {
86
- state.fg = null;
87
- state.bg = null;
88
- return 1;
89
- },
90
- 38: (state, params, i) => applyRgb(state, 'fg', params, i),
91
- 48: (state, params, i) => applyRgb(state, 'bg', params, i),
92
- 39: (state) => {
93
- state.fg = null;
94
- return 1;
95
- },
96
- 49: (state) => {
97
- state.bg = null;
98
- return 1;
99
- },
100
- };
101
-
102
75
  const applySgr = (params, state) => {
103
76
  let i = 0;
104
77
  while (i < params.length) {
105
- const apply = SGR[params[i]];
106
- i += apply ? apply(state, params, i) : 1;
78
+ const code = params[i];
79
+ if (code === 38) {
80
+ i += applyRgb(state, 'fg', params, i);
81
+ continue;
82
+ }
83
+ if (code === 48) {
84
+ i += applyRgb(state, 'bg', params, i);
85
+ continue;
86
+ }
87
+ if (code === 0 || code === 39) state.fg = null;
88
+ if (code === 0 || code === 49) state.bg = null;
89
+ i += 1;
107
90
  }
108
91
  };
109
92
 
110
- const nextGrapheme = (line, index) => {
111
- const parts = graphemes(line.slice(index));
112
- return parts[0] ?? '';
113
- };
114
-
115
93
  const parseCells = (line) => {
116
94
  const cells = [];
117
95
  const state = { fg: null, bg: null };
@@ -119,24 +97,21 @@ const parseCells = (line) => {
119
97
  let i = 0;
120
98
  while (i < line.length) {
121
99
  if (line[i] === ESC && line[i + 1] === '[') {
122
- const n = consumeCsi(line, i);
123
- if (line[n - 1] === 'm') {
124
- const body = line.slice(i + 2, n - 1);
125
- applySgr(parseParams(body), state);
100
+ const end = csiEnd(line, i);
101
+ if (line[end - 1] === 'm') {
102
+ applySgr(parseParams(line.slice(i + 2, end - 1)), state);
126
103
  }
127
- i = n;
104
+ i = end;
128
105
  continue;
129
106
  }
130
107
  if (line[i] === ESC) {
131
108
  i += 1;
132
109
  continue;
133
110
  }
134
- const ch = nextGrapheme(line, i);
111
+ const ch = firstGrapheme(line.slice(i));
135
112
  if (!ch) break;
136
113
  const width = graphemeWidth(ch, col);
137
- const fg = state.fg;
138
- const bg = state.bg;
139
- cells.push({ ch, fg, bg, col, width });
114
+ cells.push({ ch, fg: state.fg, bg: state.bg, col, width });
140
115
  col += width;
141
116
  i += ch.length;
142
117
  }
@@ -145,10 +120,10 @@ const parseCells = (line) => {
145
120
 
146
121
  const rgbKey = (rgb) => (rgb ? `${rgb[0]},${rgb[1]},${rgb[2]}` : '');
147
122
 
148
- const styleSeq = (fg, bg) => {
149
- if (fg && bg) return RESET + seq(fg, bg);
150
- if (fg) return RESET + ansi.fg(fg);
151
- if (bg) return RESET + ansi.bg(bg);
123
+ const styleSeq = (fgRgb, bgRgb) => {
124
+ if (fgRgb && bgRgb) return RESET + seq(fgRgb, bgRgb);
125
+ if (fgRgb) return RESET + fg(fgRgb);
126
+ if (bgRgb) return RESET + bg(bgRgb);
152
127
  return RESET;
153
128
  };
154
129
 
@@ -159,17 +134,15 @@ const overlayRange = (line, fromCol, toCol) => {
159
134
  let out = '';
160
135
  let last = null;
161
136
  for (const cell of cells) {
162
- const next = cell.col + cell.width;
163
- const hit = next > fromCol && cell.col < toCol;
164
- let fg = cell.fg;
165
- let bg = cell.bg;
166
- if (hit) {
167
- fg = cell.bg ?? THEME.ctxBg;
168
- bg = cell.fg ?? THEME.ctxFg;
137
+ let cellFg = cell.fg;
138
+ let cellBg = cell.bg;
139
+ if (cell.col + cell.width > fromCol && cell.col < toCol) {
140
+ cellFg = cell.bg ?? THEME.ctxBg;
141
+ cellBg = cell.fg ?? THEME.ctxFg;
169
142
  }
170
- const key = `${rgbKey(fg)}|${rgbKey(bg)}`;
143
+ const key = `${rgbKey(cellFg)}|${rgbKey(cellBg)}`;
171
144
  if (key !== last) {
172
- out += styleSeq(fg, bg);
145
+ out += styleSeq(cellFg, cellBg);
173
146
  last = key;
174
147
  }
175
148
  out += cell.ch;
@@ -177,15 +150,55 @@ const overlayRange = (line, fromCol, toCol) => {
177
150
  return out;
178
151
  };
179
152
 
153
+ const editorSelection = (view) => {
154
+ const source = view?.compose || view?.codeOverlay;
155
+ if (!source || typeof source.anchor !== 'number') return null;
156
+ const cursor = source.cursor ?? 0;
157
+ if (source.anchor === cursor) return null;
158
+ return { anchor: source.anchor, cursor };
159
+ };
160
+
161
+ const spanCols = (hit, lo, hi) => {
162
+ const start = hit.start ?? 0;
163
+ const from = Math.max(lo, start);
164
+ const to = Math.min(hi, hit.limit ?? start);
165
+ if (to <= from) return null;
166
+ const text = hit.text ?? '';
167
+ const c0 = visibleWidth(text.slice(0, Math.max(0, from - start)));
168
+ const c1 = visibleWidth(text.slice(0, Math.max(0, to - start)));
169
+ const scroll = hit.scroll ?? 0;
170
+ const textX = hit.textX ?? 1;
171
+ const room = Math.max(0, (hit.x1 ?? textX) - textX);
172
+ const vis0 = Math.max(c0, scroll);
173
+ const vis1 = Math.min(c1, scroll + room);
174
+ if (vis1 <= vis0) return null;
175
+ const origin = textX - 1;
176
+ return { from: origin + vis0 - scroll, to: origin + vis1 - scroll };
177
+ };
178
+
179
+ const markEditorSelection = (rows, view, hits, color) => {
180
+ if (!color || !hits) return rows;
181
+ const sel = editorSelection(view);
182
+ if (!sel) return rows;
183
+ const lo = Math.min(sel.anchor, sel.cursor);
184
+ const hi = Math.max(sel.anchor, sel.cursor);
185
+ const next = rows.slice();
186
+ for (const hit of hits) {
187
+ if (!hit.live || !hit.y) continue;
188
+ const range = spanCols(hit, lo, hi);
189
+ const i = hit.y - 1;
190
+ if (!range || i < 0 || i >= next.length) continue;
191
+ next[i] = overlayRange(next[i], range.from, range.to);
192
+ }
193
+ return next;
194
+ };
195
+
180
196
  const overlayRows = (rows, sel) => {
181
197
  if (!isRange(sel)) return rows;
182
- const { length } = rows;
183
- const next = new Array(length);
184
- for (let i = 0; i < length; i++) {
198
+ return rows.map((row, i) => {
185
199
  const range = lineRange(i, sel);
186
- next[i] = range ? overlayRange(rows[i], range.from, range.to) : rows[i];
187
- }
188
- return next;
200
+ return range ? overlayRange(row, range.from, range.to) : row;
201
+ });
189
202
  };
190
203
 
191
204
  module.exports = {
@@ -193,4 +206,5 @@ module.exports = {
193
206
  extractText,
194
207
  overlayRange,
195
208
  overlayRows,
209
+ markEditorSelection,
196
210
  };
@@ -1,33 +1,26 @@
1
1
  'use strict';
2
2
 
3
- const bindAlias = (target, name, get, set) => {
4
- const desc = { configurable: true, enumerable: true, get };
5
- if (set) desc.set = set;
6
- Object.defineProperty(target, name, desc);
7
- };
8
-
9
3
  const bindAccessors = (target, owner, names) => {
10
4
  for (const name of names) {
11
- const get = () => owner[name];
12
- const set = (value) => {
13
- owner[name] = value;
14
- };
15
- bindAlias(target, name, get, set);
5
+ Object.defineProperty(target, name, {
6
+ configurable: true,
7
+ enumerable: true,
8
+ get: () => owner[name],
9
+ set: (value) => {
10
+ owner[name] = value;
11
+ },
12
+ });
16
13
  }
17
14
  };
18
15
 
19
16
  const bindGetters = (target, owner, names) => {
20
17
  for (const name of names) {
21
- bindAlias(target, name, () => owner[name]);
18
+ Object.defineProperty(target, name, {
19
+ configurable: true,
20
+ enumerable: true,
21
+ get: () => owner[name],
22
+ });
22
23
  }
23
24
  };
24
25
 
25
- const stateView = (state, methods, writable = [], readonly = []) => {
26
- const descriptors = Object.getOwnPropertyDescriptors(methods);
27
- const view = Object.defineProperties({}, descriptors);
28
- bindAccessors(view, state, writable);
29
- bindGetters(view, state, readonly);
30
- return view;
31
- };
32
-
33
- module.exports = { bindAccessors, bindGetters, bindAlias, stateView };
26
+ module.exports = { bindAccessors, bindGetters };
@@ -6,13 +6,14 @@ const ACTIONS = {
6
6
  add: ['a'],
7
7
  unstage: ['u'],
8
8
  revert: ['d'],
9
+ ignore: ['i'],
9
10
  commit: ['c'],
10
11
  prev: ['left', 'p', 'k'],
11
12
  next: ['right', 'n', 'j'],
12
13
  check: ['x', ' '],
13
14
  layout: ['m'],
14
15
  feedback: ['f'],
15
- todo: ['t'],
16
+ tasks: ['t'],
16
17
  code: ['e'],
17
18
  branch: ['b'],
18
19
  file: ['f'],
@@ -23,51 +24,79 @@ const ACTION_IDS = Object.keys(ACTIONS);
23
24
 
24
25
  const BRANCH_ACTIONS = {
25
26
  newBranch: ['n'],
26
- rebase: ['r'],
27
- drop: ['d'],
27
+ rebase: ['e'],
28
+ drop: ['delete'],
28
29
  pull: ['p'],
29
30
  push: ['s'],
30
31
  };
31
32
 
32
33
  const COMMIT_ACTIONS = {
33
34
  amend: ['a'],
34
- apply: ['a'],
35
- reword: ['r'],
36
- fixup: ['f'],
37
- drop: ['d'],
35
+ apply: ['p'],
36
+ reword: ['e'],
37
+ fixup: ['x'],
38
+ drop: ['delete'],
38
39
  view: ['v'],
39
- pull: ['p'],
40
- push: ['s'],
41
40
  };
42
41
 
43
42
  const NPM_ACTIONS = {
44
43
  npm: ['n'],
45
44
  npmEdit: ['e'],
46
- npmNew: ['n'],
47
- npmDrop: ['d'],
48
- npmLogs: ['c'],
45
+ npmNew: ['i'],
46
+ npmDrop: ['delete'],
47
+ npmLogs: ['l'],
49
48
  npmStop: ['escape'],
49
+ npmVerbose: ['v'],
50
50
  npmRerun: ['r'],
51
51
  };
52
52
 
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'],
61
+ };
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',
71
+ };
72
+ const DASH_ALLOWED = [...DASH_IDS, 'quit', 'theme'];
73
+ const DASH_HIDDEN = ACTION_IDS.filter((id) => id !== 'quit');
74
+
53
75
  const ACTION_HOT = {
54
76
  prev: '←',
55
77
  next: '→',
78
+ drop: 'del',
79
+ npmDrop: 'del',
56
80
  npmStop: 'esc',
57
81
  };
58
82
 
59
83
  const ACTION_LABEL = {
84
+ ...DASH_BLOCKS,
60
85
  revert: 'drop',
61
86
  check: 'x',
62
87
  layout: 'mode',
88
+ tasks: 'tasks',
63
89
  view: 'view',
64
90
  code: 'edit',
91
+ reword: 'edit',
92
+ drop: 'delete',
65
93
  newBranch: 'new',
66
94
  npmEdit: 'edit',
67
- npmNew: 'new',
95
+ npmNew: 'insert',
68
96
  npmDrop: 'delete',
69
97
  npmLogs: 'cleanup',
70
98
  npmStop: 'esc',
99
+ npmVerbose: 'verbose',
71
100
  npmRerun: 're-run',
72
101
  quit: 'q',
73
102
  prev: '←',
@@ -83,7 +112,7 @@ const DIFF_DISABLED = [
83
112
  'file',
84
113
  'diff',
85
114
  ];
86
- const UNIT_DISABLED = [...DIFF_DISABLED, 'layout'];
115
+ const UNIT_DISABLED = [...DIFF_DISABLED, 'layout', 'ignore'];
87
116
  const FILES_DISABLED = ['layout', 'feedback', 'code'];
88
117
  const FILES_HIDDEN = [
89
118
  ...FILES_DISABLED,
@@ -93,17 +122,20 @@ const FILES_HIDDEN = [
93
122
  'commit',
94
123
  'file',
95
124
  'diff',
125
+ 'tasks',
126
+ 'branch',
96
127
  ];
97
- const FILES_GIT_DISABLED = ['add', 'unstage', 'revert'];
98
- const FILES_TODO_DISABLED = [...FILES_GIT_DISABLED, ...FILES_DISABLED];
99
- const TODO_DISABLED = [
128
+ const FILES_GIT_DISABLED = ['add', 'unstage', 'revert', 'ignore'];
129
+ const FILES_TASKS_DISABLED = [...FILES_GIT_DISABLED, ...FILES_DISABLED];
130
+ const TASKS_DISABLED = [
100
131
  'add',
101
132
  'unstage',
102
133
  'revert',
134
+ 'ignore',
103
135
  'commit',
104
136
  'layout',
105
137
  'feedback',
106
- 'todo',
138
+ 'tasks',
107
139
  'code',
108
140
  'branch',
109
141
  'file',
@@ -115,10 +147,11 @@ const BRANCHES_DISABLED = [
115
147
  'add',
116
148
  'unstage',
117
149
  'revert',
150
+ 'ignore',
118
151
  'commit',
119
152
  'layout',
120
153
  'feedback',
121
- 'todo',
154
+ 'tasks',
122
155
  'code',
123
156
  'check',
124
157
  'branch',
@@ -130,11 +163,11 @@ const BRANCHES_DISABLED = [
130
163
  const COMMITS_DISABLED = BRANCHES_DISABLED.filter((id) => id !== 'commit');
131
164
  const NPM_DISABLED = [...BRANCHES_DISABLED, 'pull', 'push'];
132
165
 
133
- const isTodosTarget = (item) =>
134
- !!(item && (item.kind === 'todos' || item.origin === 'todo'));
166
+ const isTasksTarget = (item) =>
167
+ !!(item && (item.kind === 'tasks' || item.origin === 'task'));
135
168
 
136
169
  const diffGitDisabled = (item) => {
137
- if (!item || isTodosTarget(item)) return [];
170
+ if (!item || isTasksTarget(item)) return [];
138
171
  if (item.origin === 'staged') return ['add'];
139
172
  return ['unstage'];
140
173
  };
@@ -171,8 +204,8 @@ const commitGitDisabled = (item) => {
171
204
  };
172
205
 
173
206
  const disabledActions = (pane, item) => {
174
- const onTodos = isTodosTarget(item);
175
- if (pane === 'files') return onTodos ? FILES_TODO_DISABLED : FILES_DISABLED;
207
+ const onTodos = isTasksTarget(item);
208
+ if (pane === 'files') return onTodos ? FILES_TASKS_DISABLED : FILES_DISABLED;
176
209
  if (pane === 'unit') return [...UNIT_DISABLED, ...diffGitDisabled(item)];
177
210
  if (pane === 'branches') {
178
211
  return [...BRANCHES_DISABLED, ...branchGitDisabled(item)];
@@ -181,7 +214,7 @@ const disabledActions = (pane, item) => {
181
214
  return [...COMMITS_DISABLED, ...commitWriteDisabled(item)];
182
215
  }
183
216
  if (pane === 'npm') return NPM_DISABLED;
184
- if (onTodos) return TODO_DISABLED;
217
+ if (pane === 'tasks' || onTodos) return TASKS_DISABLED;
185
218
  return [...DIFF_DISABLED, ...diffGitDisabled(item)];
186
219
  };
187
220
 
@@ -203,8 +236,8 @@ const SCROLL = {
203
236
  home: 'home',
204
237
  end: 'end',
205
238
  enter: 'open',
206
- backspace: 'removeTodo',
207
- delete: 'removeTodo',
239
+ backspace: 'removeTask',
240
+ delete: 'removeTask',
208
241
  };
209
242
 
210
243
  const keysForActions = (actions) => {
@@ -216,25 +249,26 @@ const keysForActions = (actions) => {
216
249
  };
217
250
 
218
251
  const PANE_ONLY = ['branch', 'file', 'diff'];
219
- const FILES_KEYS = keysForActions({
220
- branch: ACTIONS.branch,
221
- pull: BRANCH_ACTIONS.pull,
222
- push: BRANCH_ACTIONS.push,
223
- npm: NPM_ACTIONS.npm,
224
- });
252
+ const REVIEW_DROP = { d: 'revert' };
225
253
  const BRANCH_KEYS = keysForActions(BRANCH_ACTIONS);
226
- const COMMIT_KEYS = keysForActions(COMMIT_ACTIONS);
254
+ const COMMIT_KEYS = { ...keysForActions(COMMIT_ACTIONS), c: 'commit' };
227
255
  const NPM_KEYS = {
228
256
  e: 'npmEdit',
229
- n: 'npmNew',
230
- d: 'npmDrop',
231
- c: 'npmLogs',
257
+ i: 'npmNew',
258
+ delete: 'npmDrop',
259
+ l: 'npmLogs',
232
260
  };
261
+ const DASH_KEYS = keysForActions(DASH_ACTIONS);
262
+ const SCREEN_KEYS = DASH_KEYS;
233
263
  const PANE_KEYS = {
234
- files: FILES_KEYS,
264
+ dashboard: DASH_KEYS,
265
+ files: REVIEW_DROP,
266
+ diff: REVIEW_DROP,
267
+ unit: REVIEW_DROP,
235
268
  branches: BRANCH_KEYS,
236
269
  commits: COMMIT_KEYS,
237
270
  npm: NPM_KEYS,
271
+ tasks: { delete: 'drop' },
238
272
  };
239
273
 
240
274
  const KEY_TO_ACTION = {
@@ -247,16 +281,13 @@ const KEY_TO_ACTION = {
247
281
  ...HIDDEN_KEYS,
248
282
  };
249
283
 
250
- const actionFromKey = (key, pane, fileScope) => {
284
+ const actionFromKey = (key, pane) => {
251
285
  if (LIST_PANES.includes(pane) && (key === 'left' || key === 'right')) {
252
286
  return null;
253
287
  }
254
288
  const paneKeys = PANE_KEYS[pane];
255
289
  if (paneKeys && paneKeys[key]) return paneKeys[key];
256
- if (pane === 'files') {
257
- if (key === 'f' && fileScope !== 'file') return 'file';
258
- if (key === 'd' && fileScope === 'file') return 'diff';
259
- }
290
+ if (pane && SCREEN_KEYS[key]) return SCREEN_KEYS[key];
260
291
  return KEY_TO_ACTION[key] ?? null;
261
292
  };
262
293
 
@@ -265,11 +296,10 @@ const actionKeys = (id) =>
265
296
  BRANCH_ACTIONS[id] ??
266
297
  COMMIT_ACTIONS[id] ??
267
298
  NPM_ACTIONS[id] ??
299
+ DASH_ACTIONS[id] ??
268
300
  [];
269
301
 
270
- const actionHot = (id) => ACTION_HOT[id] ?? actionKeys(id)[0];
271
-
272
- const actionLetter = actionHot;
302
+ const actionLetter = (id) => ACTION_HOT[id] ?? actionKeys(id)[0];
273
303
 
274
304
  const buttonWord = (id) => {
275
305
  const word = ACTION_LABEL[id] ?? ACTION_HOT[id] ?? id;
@@ -337,13 +367,6 @@ const confirmKey = (mode, key) => {
337
367
  return spec.keys[norm] ?? null;
338
368
  };
339
369
 
340
- const applyConfirm = (mode, key, handlers) => {
341
- const action = confirmKey(mode, key);
342
- if (!action) return;
343
- const handler = handlers[action];
344
- if (handler) handler();
345
- };
346
-
347
370
  const confirmPrefix = (spec, view) => {
348
371
  if (typeof spec.prefix === 'function') return spec.prefix(view);
349
372
  return spec.prefix ?? '';
@@ -354,39 +377,35 @@ const promptFromChoices = (choices) =>
354
377
 
355
378
  module.exports = {
356
379
  LIST_PANES,
380
+ DASH_IDS,
381
+ DASH_BLOCKS,
382
+ DASH_ALLOWED,
383
+ DASH_HIDDEN,
357
384
  ACTIONS,
358
385
  ACTION_IDS,
359
386
  BRANCH_ACTIONS,
360
387
  COMMIT_ACTIONS,
361
- NPM_ACTIONS,
362
- ACTION_HOT,
363
- ACTION_LABEL,
364
388
  DIFF_DISABLED,
365
389
  UNIT_DISABLED,
366
390
  FILES_DISABLED,
367
391
  FILES_HIDDEN,
368
392
  FILES_GIT_DISABLED,
369
- FILES_TODO_DISABLED,
370
- TODO_DISABLED,
393
+ FILES_TASKS_DISABLED,
394
+ TASKS_DISABLED,
371
395
  BRANCHES_DISABLED,
372
396
  COMMITS_DISABLED,
373
397
  NPM_DISABLED,
374
- SCROLL,
375
- PANE_ONLY,
376
398
  disabledActions,
377
399
  diffGitDisabled,
378
400
  branchGitDisabled,
379
401
  commitGitDisabled,
380
402
  isFixupCommit,
381
403
  actionFromKey,
382
- actionKeys,
383
- actionHot,
384
404
  actionLetter,
385
405
  buttonWord,
386
406
  CONFIRM,
387
407
  CONFIRM_MODE,
388
408
  confirmKey,
389
- applyConfirm,
390
409
  confirmPrefix,
391
410
  promptFromChoices,
392
411
  };