@brimveyn/aimux-config 0.8.6 → 0.10.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.
- package/README.md +77 -6
- package/package.json +1 -1
- package/src/actions.ts +239 -150
- package/src/defaults.ts +107 -49
- package/src/index.ts +2 -5
- package/src/resolver.ts +6 -5
- package/src/status-bar-runtime.ts +1 -1
- package/src/types.ts +280 -201
package/src/actions.ts
CHANGED
|
@@ -20,16 +20,17 @@ function r(
|
|
|
20
20
|
export const nextTab: KeyResult = r([{ delta: 1, type: 'move-active-tab' }])
|
|
21
21
|
export const prevTab: KeyResult = r([{ delta: -1, type: 'move-active-tab' }])
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Routed through an effect rather than opening the modal directly: tabs only
|
|
25
|
+
* exist inside a workspace, and whether the project has one is the app's
|
|
26
|
+
* business, not the keymap's. The effect opens the picker or explains why not.
|
|
27
|
+
*/
|
|
28
|
+
export const newTab: KeyResult = r([], [{ type: 'open-new-tab' }])
|
|
28
29
|
export const renameTab: KeyResult = r([{ type: 'open-rename-tab-modal' }], [], 'modal.rename-tab')
|
|
29
|
-
export const
|
|
30
|
-
[{ type: 'open-
|
|
30
|
+
export const projectPicker: KeyResult = r(
|
|
31
|
+
[{ type: 'open-project-picker' }],
|
|
31
32
|
[],
|
|
32
|
-
'modal.
|
|
33
|
+
'modal.project-picker.filtering'
|
|
33
34
|
)
|
|
34
35
|
export const snippetPicker: KeyResult = r(
|
|
35
36
|
[{ type: 'open-snippet-picker' }],
|
|
@@ -59,7 +60,7 @@ export function toggleWidget(widgetId: string): KeyResult {
|
|
|
59
60
|
return r([{ type: 'toggle-widget', widgetId }])
|
|
60
61
|
}
|
|
61
62
|
export const toggleGitPane: KeyResult = toggleWidget('git')
|
|
62
|
-
export const
|
|
63
|
+
export const toggleProjectBar: KeyResult = r([{ type: 'toggle-project-bar' }])
|
|
63
64
|
export const toggleAIUsage: ActionFn = (ctx: ModeContext) => {
|
|
64
65
|
if (ctx.state.modal.type === 'ai-usage') {
|
|
65
66
|
return r([{ type: 'close-modal' }], [], 'navigation')
|
|
@@ -69,8 +70,8 @@ export const toggleAIUsage: ActionFn = (ctx: ModeContext) => {
|
|
|
69
70
|
|
|
70
71
|
export const enterGitMode: KeyResult = r([{ type: 'enter-git-mode' }], [], 'git-mode')
|
|
71
72
|
|
|
72
|
-
export function
|
|
73
|
-
return r([], [{ index, type: 'switch-
|
|
73
|
+
export function switchProjectByIndex(index: number): KeyResult {
|
|
74
|
+
return r([], [{ index, type: 'switch-project-by-index' }])
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
export function switchTabByIndex(index: number): KeyResult {
|
|
@@ -134,8 +135,8 @@ export function reorderTab(delta: number): KeyResult {
|
|
|
134
135
|
return r([{ delta, type: 'reorder-active-tab' }])
|
|
135
136
|
}
|
|
136
137
|
|
|
137
|
-
export function
|
|
138
|
-
return r([{ delta, type: 'reorder-active-
|
|
138
|
+
export function reorderProject(delta: number): KeyResult {
|
|
139
|
+
return r([{ delta, type: 'reorder-active-project' }])
|
|
139
140
|
}
|
|
140
141
|
|
|
141
142
|
export function resizeBar(side: 'left' | 'right', delta: number): KeyResult {
|
|
@@ -199,70 +200,20 @@ export function moveModalSelectionWithPreview(
|
|
|
199
200
|
// Modal-specific actions
|
|
200
201
|
// ---------------------------------------------------------------------------
|
|
201
202
|
|
|
202
|
-
export const launchSelectedAssistant:
|
|
203
|
-
if (ctx.state.modal.type === 'new-tab' && ctx.state.modal.step === 'assistant') {
|
|
204
|
-
return r([{ type: 'select-new-tab-assistant' }])
|
|
205
|
-
}
|
|
206
|
-
if (
|
|
207
|
-
ctx.state.modal.type === 'new-tab' &&
|
|
208
|
-
ctx.state.modal.step === 'worktree' &&
|
|
209
|
-
ctx.state.modal.createWorktree
|
|
210
|
-
) {
|
|
211
|
-
return r([{ type: 'enter-new-tab-worktree-create' }], [{ type: 'load-new-tab-base-branches' }])
|
|
212
|
-
}
|
|
213
|
-
return r([], [{ type: 'launch-selected-assistant' }])
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
export const toggleNewTabWorktree: KeyResult = r([{ type: 'toggle-new-tab-worktree' }])
|
|
203
|
+
export const launchSelectedAssistant: KeyResult = r([], [{ type: 'launch-selected-assistant' }])
|
|
217
204
|
|
|
218
|
-
export const
|
|
205
|
+
export const confirmWorkspaceDeleteModal: ActionFn = (ctx: ModeContext) => {
|
|
219
206
|
const modal = ctx.state.modal
|
|
220
|
-
|
|
221
|
-
if (modal.type !== 'new-tab' || modal.step !== 'worktree' || modal.createWorktree) return null
|
|
222
|
-
if (!(sessionId != null && sessionId !== '')) return null
|
|
223
|
-
const session = ctx.state.sessions.find((entry) => entry.id === sessionId)
|
|
224
|
-
const worktree = session?.worktrees?.[modal.selectedIndex]
|
|
225
|
-
if (!worktree) return null
|
|
226
|
-
// First attempt is never forced — a recoverable failure opens the confirm
|
|
227
|
-
// dialog (see set-new-tab-worktree-delete-prompt), where confirmDeleteWorktree
|
|
228
|
-
// retries with force.
|
|
229
|
-
return r(
|
|
230
|
-
[{ index: modal.selectedIndex, type: 'set-modal-selection-index' }],
|
|
231
|
-
[{ force: false, sessionId, type: 'delete-worktree', worktreeId: worktree.id }]
|
|
232
|
-
)
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
export const confirmDeleteWorktree: ActionFn = (ctx: ModeContext) => {
|
|
236
|
-
const modal = ctx.state.modal
|
|
237
|
-
const sessionId = ctx.state.currentSessionId
|
|
238
|
-
if (modal.type !== 'new-tab' || modal.worktreeDeletePrompt == null) return null
|
|
239
|
-
if (!(sessionId != null && sessionId !== '')) return null
|
|
240
|
-
const { worktreeId } = modal.worktreeDeletePrompt
|
|
241
|
-
return r(
|
|
242
|
-
[{ prompt: null, type: 'set-new-tab-worktree-delete-prompt' }],
|
|
243
|
-
[{ force: true, sessionId, type: 'delete-worktree', worktreeId }],
|
|
244
|
-
'modal.new-tab.command-edit'
|
|
245
|
-
)
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
export const cancelDeleteWorktree: KeyResult = r(
|
|
249
|
-
[{ prompt: null, type: 'set-new-tab-worktree-delete-prompt' }],
|
|
250
|
-
[],
|
|
251
|
-
'modal.new-tab.command-edit'
|
|
252
|
-
)
|
|
253
|
-
|
|
254
|
-
export const confirmWorktreeDeleteModal: ActionFn = (ctx: ModeContext) => {
|
|
255
|
-
const modal = ctx.state.modal
|
|
256
|
-
if (modal.type !== 'worktree-delete-confirm') return null
|
|
207
|
+
if (modal.type !== 'workspace-delete-confirm') return null
|
|
257
208
|
return r(
|
|
258
209
|
[{ type: 'close-modal' }],
|
|
259
210
|
[
|
|
260
211
|
{
|
|
261
212
|
closeTabs: modal.closeTabs,
|
|
262
213
|
force: modal.force,
|
|
263
|
-
|
|
264
|
-
type: 'delete-
|
|
265
|
-
|
|
214
|
+
projectId: modal.projectId,
|
|
215
|
+
type: 'delete-workspace',
|
|
216
|
+
workspaceId: modal.workspaceId,
|
|
266
217
|
},
|
|
267
218
|
],
|
|
268
219
|
'navigation'
|
|
@@ -272,20 +223,52 @@ export const confirmWorktreeDeleteModal: ActionFn = (ctx: ModeContext) => {
|
|
|
272
223
|
export const cancelCommandEdit = (returnTo: KeyResult['transition']): KeyResult =>
|
|
273
224
|
r([{ type: 'cancel-command-edit' }], [], returnTo)
|
|
274
225
|
|
|
275
|
-
export const
|
|
226
|
+
export const confirmSelectedProject: KeyResult = r([], [{ type: 'confirm-selected-project' }])
|
|
276
227
|
|
|
277
|
-
export const
|
|
278
|
-
[{
|
|
228
|
+
export const openCreateProjectModal: KeyResult = r(
|
|
229
|
+
[{ returnToProjectPicker: true, type: 'open-create-project-modal' }],
|
|
279
230
|
[],
|
|
280
|
-
'modal.create-
|
|
231
|
+
'modal.create-project'
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
export const createWorkspaceModal: KeyResult = r(
|
|
235
|
+
[{ type: 'open-create-workspace-modal' }],
|
|
236
|
+
[{ type: 'load-create-workspace-base-branches' }],
|
|
237
|
+
'modal.create-workspace'
|
|
281
238
|
)
|
|
282
239
|
|
|
283
|
-
export const
|
|
240
|
+
export const switchCreateWorkspaceField: KeyResult = r([{ type: 'switch-create-workspace-field' }])
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* An empty prompt is not a workspace: it names nothing, branches nothing and
|
|
244
|
+
* gives the assistant nothing to do, so Enter is simply inert until it is typed.
|
|
245
|
+
*/
|
|
246
|
+
export const confirmCreateWorkspace: ActionFn = (ctx: ModeContext) => {
|
|
247
|
+
const { modal } = ctx.state
|
|
248
|
+
if (modal.type === 'create-workspace' && modal.prompt.trim() === '') return r([])
|
|
249
|
+
return r([], [{ type: 'create-workspace' }])
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* `Enter` creates, so the prompt needs another way to break a line. Inverted
|
|
254
|
+
* from the commit modal on purpose: there the body is the whole point, here
|
|
255
|
+
* most prompts are one line and creating must stay the cheapest keystroke.
|
|
256
|
+
*/
|
|
257
|
+
export const createWorkspaceNewline: ActionFn = (ctx: ModeContext) => {
|
|
258
|
+
const { modal } = ctx.state
|
|
259
|
+
if (modal.type !== 'create-workspace') return r([])
|
|
260
|
+
if (modal.activeField !== 'prompt') return r([])
|
|
261
|
+
return r([{ char: '\n', type: 'update-command-edit' }])
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export const createWorkspaceEscape: KeyResult = r([{ type: 'close-modal' }], [], 'navigation')
|
|
265
|
+
|
|
266
|
+
export const openRenameSelectedProject: KeyResult = r(
|
|
284
267
|
[],
|
|
285
|
-
[{ type: 'open-rename-selected-
|
|
268
|
+
[{ type: 'open-rename-selected-project' }]
|
|
286
269
|
)
|
|
287
270
|
|
|
288
|
-
export const
|
|
271
|
+
export const deleteSelectedProject: KeyResult = r([], [{ type: 'delete-selected-project' }])
|
|
289
272
|
|
|
290
273
|
export const openSnippetEditor: KeyResult = r(
|
|
291
274
|
[{ type: 'open-snippet-editor' }],
|
|
@@ -336,20 +319,20 @@ export function previewTheme(delta: 1 | -1): KeyResult {
|
|
|
336
319
|
export const toggleTransparent: KeyResult = r([], [{ type: 'toggle-transparent' }])
|
|
337
320
|
export const toggleMode: KeyResult = r([], [{ type: 'toggle-mode' }])
|
|
338
321
|
|
|
339
|
-
export const switchField: KeyResult = r([{ type: 'switch-create-
|
|
322
|
+
export const switchField: KeyResult = r([{ type: 'switch-create-project-field' }])
|
|
340
323
|
export const selectDirectory: KeyResult = r([{ type: 'select-directory' }])
|
|
341
324
|
|
|
342
|
-
export const
|
|
343
|
-
[{ type: 'open-
|
|
325
|
+
export const backToProjectPicker: KeyResult = r(
|
|
326
|
+
[{ type: 'open-project-picker' }],
|
|
344
327
|
[],
|
|
345
|
-
'modal.
|
|
328
|
+
'modal.project-picker.filtering'
|
|
346
329
|
)
|
|
347
330
|
|
|
348
|
-
export const
|
|
349
|
-
if (ctx.state.modal.type === 'create-
|
|
331
|
+
export const createProjectEscape: ActionFn = (ctx: ModeContext) => {
|
|
332
|
+
if (ctx.state.modal.type === 'create-project' && !ctx.state.modal.returnToProjectPicker) {
|
|
350
333
|
return r([{ type: 'close-modal' }], [], 'navigation')
|
|
351
334
|
}
|
|
352
|
-
return r([{ type: 'open-
|
|
335
|
+
return r([{ type: 'open-project-picker' }], [], 'modal.project-picker.filtering')
|
|
353
336
|
}
|
|
354
337
|
|
|
355
338
|
export const backToSnippetPicker: KeyResult = r(
|
|
@@ -393,10 +376,10 @@ export const confirmUpdateSelection: KeyResult = r(
|
|
|
393
376
|
)
|
|
394
377
|
|
|
395
378
|
// ---------------------------------------------------------------------------
|
|
396
|
-
//
|
|
379
|
+
// Workspace-move modal
|
|
397
380
|
// ---------------------------------------------------------------------------
|
|
398
381
|
|
|
399
|
-
export const
|
|
382
|
+
export const openWorkspaceMove: ActionFn = (ctx: ModeContext) => {
|
|
400
383
|
if (ctx.state.gitMode.headOffset > 0) {
|
|
401
384
|
return r([
|
|
402
385
|
{
|
|
@@ -405,35 +388,35 @@ export const openWorktreeMove: ActionFn = (ctx: ModeContext) => {
|
|
|
405
388
|
},
|
|
406
389
|
])
|
|
407
390
|
}
|
|
408
|
-
const
|
|
409
|
-
const
|
|
410
|
-
// From git mode, the source is the active
|
|
411
|
-
const source =
|
|
391
|
+
const project = ctx.state.projects.find((entry) => entry.id === ctx.state.currentProjectId)
|
|
392
|
+
const workspaces = project?.workspaces ?? []
|
|
393
|
+
// From git mode, the source is the active workspace (the one being reviewed).
|
|
394
|
+
const source = workspaces.find((w) => w.id === project?.activeWorkspaceId) ?? workspaces[0]
|
|
412
395
|
const hasBranch = source != null && source.branch != null && source.branch !== ''
|
|
413
|
-
const others =
|
|
396
|
+
const others = workspaces.filter((w) => w.id !== source?.id)
|
|
414
397
|
if (!hasBranch || source == null || others.length < 1) {
|
|
415
|
-
return r([{ message: 'no other
|
|
398
|
+
return r([{ message: 'no other workspace to move into', type: 'git-mode-set-message' }])
|
|
416
399
|
}
|
|
417
400
|
// Overlay: no mode transition — deriveModeId routes input to the picker and
|
|
418
401
|
// focusMode stays 'git' so the git view remains mounted underneath.
|
|
419
402
|
return r(
|
|
420
|
-
[{
|
|
421
|
-
[{ type: 'load-
|
|
403
|
+
[{ sourceWorkspaceId: source.id, type: 'open-workspace-move-modal' }],
|
|
404
|
+
[{ type: 'load-workspace-move-stats' }]
|
|
422
405
|
)
|
|
423
406
|
}
|
|
424
407
|
|
|
425
|
-
export const
|
|
408
|
+
export const toggleWorkspaceMoveDelete: KeyResult = r([{ type: 'toggle-workspace-move-delete' }])
|
|
426
409
|
|
|
427
|
-
export const
|
|
410
|
+
export const confirmWorkspaceMove: ActionFn = (ctx: ModeContext) => {
|
|
428
411
|
const modal = ctx.state.modal
|
|
429
|
-
const
|
|
430
|
-
const
|
|
431
|
-
const sourceId = modal.type === '
|
|
432
|
-
const source =
|
|
433
|
-
const targets =
|
|
434
|
-
const selectedIndex = modal.type === '
|
|
412
|
+
const project = ctx.state.projects.find((entry) => entry.id === ctx.state.currentProjectId)
|
|
413
|
+
const workspaces = project?.workspaces ?? []
|
|
414
|
+
const sourceId = modal.type === 'workspace-move' ? modal.sourceWorkspaceId : undefined
|
|
415
|
+
const source = workspaces.find((w) => w.id === sourceId)
|
|
416
|
+
const targets = workspaces.filter((w) => w.id !== sourceId)
|
|
417
|
+
const selectedIndex = modal.type === 'workspace-move' ? modal.selectedIndex : 0
|
|
435
418
|
const target = targets[selectedIndex]
|
|
436
|
-
if (!target || !
|
|
419
|
+
if (!target || !project || !source || modal.type !== 'workspace-move') {
|
|
437
420
|
return r([{ type: 'close-modal' }])
|
|
438
421
|
}
|
|
439
422
|
// Overlay close keeps focusMode 'git' (see close-modal reducer), so the move
|
|
@@ -443,10 +426,10 @@ export const confirmWorktreeMove: ActionFn = (ctx: ModeContext) => {
|
|
|
443
426
|
[
|
|
444
427
|
{
|
|
445
428
|
deleteSource: modal.deleteSource,
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
type: 'move-
|
|
429
|
+
projectId: project.id,
|
|
430
|
+
sourceWorkspaceId: source.id,
|
|
431
|
+
targetWorkspaceId: target.id,
|
|
432
|
+
type: 'move-workspace',
|
|
450
433
|
},
|
|
451
434
|
]
|
|
452
435
|
)
|
|
@@ -454,18 +437,18 @@ export const confirmWorktreeMove: ActionFn = (ctx: ModeContext) => {
|
|
|
454
437
|
|
|
455
438
|
// Confirms the dialog opened after a recoverable move failure: re-runs the
|
|
456
439
|
// move with the flag matching the failure (stash the target / keep conflicts).
|
|
457
|
-
export const
|
|
440
|
+
export const confirmWorkspaceMoveRetry: ActionFn = (ctx: ModeContext) => {
|
|
458
441
|
const modal = ctx.state.modal
|
|
459
|
-
if (modal.type !== '
|
|
442
|
+
if (modal.type !== 'workspace-move-confirm') return null
|
|
460
443
|
return r(
|
|
461
444
|
[{ type: 'close-modal' }],
|
|
462
445
|
[
|
|
463
446
|
{
|
|
464
447
|
deleteSource: modal.deleteSource,
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
type: 'move-
|
|
448
|
+
projectId: modal.projectId,
|
|
449
|
+
sourceWorkspaceId: modal.sourceWorkspaceId,
|
|
450
|
+
targetWorkspaceId: modal.targetWorkspaceId,
|
|
451
|
+
type: 'move-workspace',
|
|
469
452
|
...(modal.variant === 'stash-target' ? { stashTarget: true } : { keepConflicts: true }),
|
|
470
453
|
},
|
|
471
454
|
],
|
|
@@ -487,9 +470,9 @@ export const closePane: ActionFn = (ctx: ModeContext) => {
|
|
|
487
470
|
}
|
|
488
471
|
|
|
489
472
|
// Navigation-specific dynamic actions
|
|
490
|
-
// Reveals whichever bar hosts the
|
|
473
|
+
// Reveals whichever bar hosts the project list — it is not pinned to the left.
|
|
491
474
|
export const ctrlZSidebar: ActionFn = (ctx: ModeContext) => {
|
|
492
|
-
const side = ctx.state.bars.left.widgets.some((w) => w.id === '
|
|
475
|
+
const side = ctx.state.bars.left.widgets.some((w) => w.id === 'projects') ? 'left' : 'right'
|
|
493
476
|
if (!ctx.state.bars[side].visible) {
|
|
494
477
|
return r([{ side, type: 'toggle-bar' }])
|
|
495
478
|
}
|
|
@@ -509,21 +492,21 @@ export const leaveTerminalInput: KeyResult = r(
|
|
|
509
492
|
|
|
510
493
|
export const toggleSidebarFromInput: KeyResult = toggleBar('left')
|
|
511
494
|
|
|
512
|
-
//
|
|
513
|
-
export const
|
|
495
|
+
// Project name modal
|
|
496
|
+
export const confirmProjectRename: ActionFn = (ctx: ModeContext) => {
|
|
514
497
|
const trimmed = (ctx.state.modal.editBuffer ?? '').trim()
|
|
515
|
-
const
|
|
498
|
+
const projectId = ctx.state.modal.projectTargetId
|
|
516
499
|
const returnToPicker =
|
|
517
|
-
ctx.state.modal.type === '
|
|
500
|
+
ctx.state.modal.type === 'project-name' ? ctx.state.modal.returnToProjectPicker : true
|
|
518
501
|
const closeAction: AppAction = returnToPicker
|
|
519
|
-
? { type: 'open-
|
|
502
|
+
? { type: 'open-project-picker' }
|
|
520
503
|
: { type: 'close-modal' }
|
|
521
504
|
const transition: KeyResult['transition'] = returnToPicker
|
|
522
|
-
? 'modal.
|
|
505
|
+
? 'modal.project-picker.filtering'
|
|
523
506
|
: 'navigation'
|
|
524
507
|
const effects: KeyResult['effects'] =
|
|
525
|
-
trimmed &&
|
|
526
|
-
? [{ name: trimmed,
|
|
508
|
+
trimmed && projectId != null && projectId !== ''
|
|
509
|
+
? [{ name: trimmed, projectId, type: 'rename-project' }]
|
|
527
510
|
: []
|
|
528
511
|
return r([closeAction], effects, transition)
|
|
529
512
|
}
|
|
@@ -531,7 +514,7 @@ export const confirmSessionRename: ActionFn = (ctx: ModeContext) => {
|
|
|
531
514
|
// Rename tab modal
|
|
532
515
|
export const confirmRenameTab: ActionFn = (ctx: ModeContext) => {
|
|
533
516
|
const trimmed = (ctx.state.modal.editBuffer ?? '').trim()
|
|
534
|
-
const tabId = ctx.state.modal.
|
|
517
|
+
const tabId = ctx.state.modal.projectTargetId
|
|
535
518
|
const actions: KeyResult['actions'] = []
|
|
536
519
|
const effects: KeyResult['effects'] = []
|
|
537
520
|
if (trimmed && tabId != null && tabId !== '') {
|
|
@@ -541,27 +524,33 @@ export const confirmRenameTab: ActionFn = (ctx: ModeContext) => {
|
|
|
541
524
|
return r(actions, effects, 'navigation')
|
|
542
525
|
}
|
|
543
526
|
|
|
544
|
-
// Rename
|
|
545
|
-
export const
|
|
527
|
+
// Rename workspace modal
|
|
528
|
+
export const confirmRenameWorkspace: ActionFn = (ctx: ModeContext) => {
|
|
546
529
|
const { modal } = ctx.state
|
|
547
530
|
const trimmed = (modal.editBuffer ?? '').trim()
|
|
548
|
-
const
|
|
549
|
-
const
|
|
531
|
+
const workspaceId = modal.projectTargetId
|
|
532
|
+
const projectId = modal.type === 'rename-workspace' ? modal.workspaceProjectId : null
|
|
550
533
|
const actions: KeyResult['actions'] = []
|
|
551
|
-
if (
|
|
534
|
+
if (
|
|
535
|
+
trimmed &&
|
|
536
|
+
workspaceId != null &&
|
|
537
|
+
workspaceId !== '' &&
|
|
538
|
+
projectId != null &&
|
|
539
|
+
projectId !== ''
|
|
540
|
+
) {
|
|
552
541
|
actions.push({
|
|
553
542
|
patch: { name: trimmed },
|
|
554
|
-
|
|
555
|
-
type: 'update-
|
|
556
|
-
|
|
543
|
+
projectId,
|
|
544
|
+
type: 'update-workspace-record',
|
|
545
|
+
workspaceId,
|
|
557
546
|
})
|
|
558
547
|
}
|
|
559
548
|
actions.push({ type: 'close-modal' })
|
|
560
549
|
return r(actions, [], 'navigation')
|
|
561
550
|
}
|
|
562
551
|
|
|
563
|
-
// Create
|
|
564
|
-
export const
|
|
552
|
+
// Create project modal
|
|
553
|
+
export const confirmCreateProject: ActionFn = (ctx: ModeContext) => {
|
|
565
554
|
const modal = ctx.state.modal as {
|
|
566
555
|
activeField?: string
|
|
567
556
|
editBuffer?: string
|
|
@@ -574,26 +563,26 @@ export const confirmCreateSession: ActionFn = (ctx: ModeContext) => {
|
|
|
574
563
|
|
|
575
564
|
const trimmed = (modal.editBuffer ?? '').trim()
|
|
576
565
|
const projectPath = modal.pendingProjectPath ?? undefined
|
|
577
|
-
const
|
|
578
|
-
if (
|
|
566
|
+
const projectName = trimmed || getDefaultProjectName(projectPath)
|
|
567
|
+
if (projectName) {
|
|
579
568
|
return r(
|
|
580
569
|
[{ type: 'close-modal' }],
|
|
581
|
-
[{ name:
|
|
570
|
+
[{ name: projectName, projectPath, type: 'create-project' }],
|
|
582
571
|
'navigation'
|
|
583
572
|
)
|
|
584
573
|
}
|
|
585
574
|
return r([{ type: 'close-modal' }], [], 'navigation')
|
|
586
575
|
}
|
|
587
576
|
|
|
588
|
-
function
|
|
577
|
+
function getDefaultProjectName(projectPath?: string): string {
|
|
589
578
|
if (!(projectPath != null && projectPath !== '')) return ''
|
|
590
579
|
const segments = projectPath.split('/').filter(Boolean)
|
|
591
580
|
return segments.at(-1) ?? ''
|
|
592
581
|
}
|
|
593
582
|
|
|
594
|
-
//
|
|
595
|
-
export const
|
|
596
|
-
if (!(ctx.state.
|
|
583
|
+
// Project picker escape (conditional)
|
|
584
|
+
export const projectPickerEscape: ActionFn = (ctx: ModeContext) => {
|
|
585
|
+
if (!(ctx.state.currentProjectId != null && ctx.state.currentProjectId !== '')) return null
|
|
597
586
|
return r([{ type: 'close-modal' }], [], 'navigation')
|
|
598
587
|
}
|
|
599
588
|
|
|
@@ -833,9 +822,9 @@ export const gitCommitOpen: ActionFn = (ctx: ModeContext) => {
|
|
|
833
822
|
},
|
|
834
823
|
])
|
|
835
824
|
}
|
|
836
|
-
const
|
|
825
|
+
const projectId = ctx.state.currentProjectId ?? undefined
|
|
837
826
|
return r(
|
|
838
|
-
[...clearPendingDelete(ctx), {
|
|
827
|
+
[...clearPendingDelete(ctx), { projectId, type: 'open-git-commit-modal' }],
|
|
839
828
|
[],
|
|
840
829
|
'modal.git-commit'
|
|
841
830
|
)
|
|
@@ -894,13 +883,13 @@ export const gitCommitEnterConfirm: ActionFn = (ctx: ModeContext) => {
|
|
|
894
883
|
if (hasTitle) {
|
|
895
884
|
return r([{ type: 'git-commit-enter-confirm' }], [], 'modal.git-commit.confirm')
|
|
896
885
|
}
|
|
897
|
-
const
|
|
898
|
-
if (!(
|
|
886
|
+
const projectId = ctx.state.currentProjectId
|
|
887
|
+
if (!(projectId != null && projectId !== '')) {
|
|
899
888
|
return r([{ type: 'git-commit-enter-confirm' }], [], 'modal.git-commit.confirm')
|
|
900
889
|
}
|
|
901
890
|
return r(
|
|
902
|
-
[{
|
|
903
|
-
[{
|
|
891
|
+
[{ projectId, type: 'git-commit-enter-generating' }],
|
|
892
|
+
[{ projectId, type: 'generate-auto-commit-now' }],
|
|
904
893
|
'modal.git-commit.generating'
|
|
905
894
|
)
|
|
906
895
|
}
|
|
@@ -912,10 +901,10 @@ export const gitCommitLeaveConfirm: KeyResult = r(
|
|
|
912
901
|
)
|
|
913
902
|
|
|
914
903
|
export const gitCommitLeaveGenerating: ActionFn = (ctx: ModeContext) => {
|
|
915
|
-
const
|
|
904
|
+
const projectId = ctx.state.currentProjectId
|
|
916
905
|
const actionsList: AppAction[] = [{ type: 'git-commit-leave-generating' }]
|
|
917
|
-
if (
|
|
918
|
-
actionsList.push({
|
|
906
|
+
if (projectId != null && projectId !== '') {
|
|
907
|
+
actionsList.push({ projectId, type: 'auto-commit-clear' })
|
|
919
908
|
}
|
|
920
909
|
return r(actionsList, [], 'modal.git-commit')
|
|
921
910
|
}
|
|
@@ -952,5 +941,105 @@ export const gitCommitReturnKey: ActionFn = (ctx: ModeContext) => {
|
|
|
952
941
|
if (modal.type === 'git-commit' && modal.activeField === 'body') {
|
|
953
942
|
return r([{ char: '\n', type: 'update-command-edit' }])
|
|
954
943
|
}
|
|
955
|
-
return r([{ type: 'switch-create-
|
|
944
|
+
return r([{ type: 'switch-create-project-field' }])
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
// ---------------------------------------------------------------------------
|
|
948
|
+
// Settings screen
|
|
949
|
+
// ---------------------------------------------------------------------------
|
|
950
|
+
|
|
951
|
+
export const enterSettings: KeyResult = r([{ type: 'enter-settings' }], [], 'settings')
|
|
952
|
+
export const exitSettings: KeyResult = r([{ type: 'exit-settings' }], [], 'navigation')
|
|
953
|
+
|
|
954
|
+
export function focusSettingsPane(pane: 'nav' | 'rows'): KeyResult {
|
|
955
|
+
return r([{ pane, type: 'settings-focus-pane' }])
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
export function moveSettingsSelection(delta: -1 | 1): KeyResult {
|
|
959
|
+
return r([{ delta, type: 'settings-move-selection' }])
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
/**
|
|
963
|
+
* One key for every kind of row: it toggles a checkbox, advances an enum, or runs
|
|
964
|
+
* whatever the row does. Which one is the row's business, not the keymap's — so
|
|
965
|
+
* there is no per-kind binding to keep in sync with the schema.
|
|
966
|
+
*/
|
|
967
|
+
export const activateSettingsRow: ActionFn = (ctx: ModeContext) => {
|
|
968
|
+
if (ctx.state.settings.pane !== 'rows') return r([{ pane: 'rows', type: 'settings-focus-pane' }])
|
|
969
|
+
return r([], [{ type: 'activate-settings-row' }])
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
export function adjustSettingsRow(delta: 1 | -1): KeyResult {
|
|
973
|
+
return r([], [{ delta, type: 'adjust-settings-row' }])
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
export const resetSettingsRow: KeyResult = r([], [{ type: 'reset-settings-row' }])
|
|
977
|
+
|
|
978
|
+
/**
|
|
979
|
+
* Closing a modal the settings screen opened. `closeModal` declares `navigation`,
|
|
980
|
+
* which is where every other modal goes and is not where these go — the screen is
|
|
981
|
+
* still drawn behind them, and `returnTo` puts the focus back on it.
|
|
982
|
+
*/
|
|
983
|
+
export const closeSettingsModal: KeyResult = r([{ type: 'close-modal' }], [], 'settings')
|
|
984
|
+
|
|
985
|
+
export const openSettingsSearch: KeyResult = r(
|
|
986
|
+
[{ type: 'open-settings-search' }],
|
|
987
|
+
[],
|
|
988
|
+
'modal.settings-search.filtering'
|
|
989
|
+
)
|
|
990
|
+
|
|
991
|
+
/** Jumps the screen to the highlighted setting, wherever it lives. */
|
|
992
|
+
export const confirmSettingsSearch: KeyResult = r(
|
|
993
|
+
[],
|
|
994
|
+
[{ type: 'confirm-settings-search' }],
|
|
995
|
+
'settings'
|
|
996
|
+
)
|
|
997
|
+
|
|
998
|
+
/**
|
|
999
|
+
* The value is carried in the effect rather than read from the store by it: the
|
|
1000
|
+
* `close-modal` action runs first and clears the buffer it would have read.
|
|
1001
|
+
*/
|
|
1002
|
+
export const confirmSettingText: ActionFn = (ctx: ModeContext) => {
|
|
1003
|
+
const modal = ctx.state.modal
|
|
1004
|
+
if (modal.type !== 'setting-text') return r([{ type: 'close-modal' }], [], 'settings')
|
|
1005
|
+
return r(
|
|
1006
|
+
[{ type: 'close-modal' }],
|
|
1007
|
+
[{ settingId: modal.settingId, type: 'commit-setting-text', value: modal.editBuffer ?? '' }],
|
|
1008
|
+
'settings'
|
|
1009
|
+
)
|
|
956
1010
|
}
|
|
1011
|
+
|
|
1012
|
+
// ---------------------------------------------------------------------------
|
|
1013
|
+
// Deprecated aliases — 0.8.x names kept working for one release.
|
|
1014
|
+
//
|
|
1015
|
+
// The project/workspace/worktree rename moved every one of these. Aliases only
|
|
1016
|
+
// exist where the old name still has a target: `toggleNewTabWorktree`,
|
|
1017
|
+
// `deleteSelectedWorktree` and `confirmDeleteWorktree` were deleted outright
|
|
1018
|
+
// when <C-n> stopped creating worktrees, so a config referencing them is a
|
|
1019
|
+
// compile error on purpose.
|
|
1020
|
+
//
|
|
1021
|
+
// ponytail: drop these with the other rename shims.
|
|
1022
|
+
// ---------------------------------------------------------------------------
|
|
1023
|
+
|
|
1024
|
+
/** @deprecated renamed to `projectPicker`. */
|
|
1025
|
+
export const sessionPicker = projectPicker
|
|
1026
|
+
/** @deprecated renamed to `openCreateProjectModal`. */
|
|
1027
|
+
export const openCreateSessionModal = openCreateProjectModal
|
|
1028
|
+
/** @deprecated renamed to `createProjectEscape`. */
|
|
1029
|
+
export const createSessionEscape = createProjectEscape
|
|
1030
|
+
/** @deprecated renamed to `confirmCreateProject`. */
|
|
1031
|
+
export const confirmCreateSession = confirmCreateProject
|
|
1032
|
+
/** @deprecated renamed to `reorderProject`. */
|
|
1033
|
+
export const reorderSession = reorderProject
|
|
1034
|
+
/** @deprecated renamed to `switchProjectByIndex`. */
|
|
1035
|
+
export const switchSessionByIndex = switchProjectByIndex
|
|
1036
|
+
/** @deprecated renamed to `toggleProjectBar`. */
|
|
1037
|
+
export const toggleSessionBar = toggleProjectBar
|
|
1038
|
+
/** @deprecated renamed to `openWorkspaceMove`. */
|
|
1039
|
+
export const openWorktreeMove = openWorkspaceMove
|
|
1040
|
+
/** @deprecated renamed to `toggleWorkspaceMoveDelete`. */
|
|
1041
|
+
export const toggleWorktreeMoveDelete = toggleWorkspaceMoveDelete
|
|
1042
|
+
/** @deprecated renamed to `confirmWorkspaceMove`. */
|
|
1043
|
+
export const confirmWorktreeMove = confirmWorkspaceMove
|
|
1044
|
+
/** @deprecated renamed to `confirmWorkspaceDeleteModal`. */
|
|
1045
|
+
export const confirmWorktreeDeleteModal = confirmWorkspaceDeleteModal
|