@brimveyn/aimux-config 0.1.0 → 0.2.1
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/package.json +1 -1
- package/src/actions.ts +112 -1
- package/src/defaults.ts +31 -0
- package/src/types.ts +62 -1
package/package.json
CHANGED
package/src/actions.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ActionFn, KeyResult, ModeContext } from './types'
|
|
1
|
+
import type { ActionFn, AppAction, KeyResult, ModeContext } from './types'
|
|
2
2
|
|
|
3
3
|
function r(
|
|
4
4
|
actions: KeyResult['actions'] = [],
|
|
@@ -36,6 +36,7 @@ export const helpModal: KeyResult = r([{ type: 'open-help-modal' }], [], 'modal.
|
|
|
36
36
|
|
|
37
37
|
export const toggleSidebar: KeyResult = r([{ type: 'toggle-sidebar' }])
|
|
38
38
|
export const toggleGitPanel: KeyResult = r([{ type: 'toggle-git-panel' }])
|
|
39
|
+
export const enterGitMode: KeyResult = r([{ type: 'enter-git-mode' }], [], 'git-mode')
|
|
39
40
|
|
|
40
41
|
export const splitVertical: KeyResult = r(
|
|
41
42
|
[{ direction: 'vertical', type: 'open-split-picker' }],
|
|
@@ -366,3 +367,113 @@ export const snippetFilterPasteToGroup: KeyResult = r(
|
|
|
366
367
|
[{ type: 'paste-snippet-to-group' }],
|
|
367
368
|
'navigation'
|
|
368
369
|
)
|
|
370
|
+
|
|
371
|
+
// ---------------------------------------------------------------------------
|
|
372
|
+
// Git mode (src/input/modes/handlers/git-mode.ts replacement)
|
|
373
|
+
// ---------------------------------------------------------------------------
|
|
374
|
+
|
|
375
|
+
function clearPendingDelete(ctx: ModeContext): AppAction[] {
|
|
376
|
+
if (ctx.state.gitMode.pendingDeletePath === null) return []
|
|
377
|
+
return [{ path: null, type: 'git-mode-set-pending-delete' }]
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export const exitGitMode: KeyResult = r([{ type: 'exit-git-mode' }], [], 'navigation')
|
|
381
|
+
|
|
382
|
+
export function selectGitFile(delta: -1 | 1): ActionFn {
|
|
383
|
+
return (ctx: ModeContext) => {
|
|
384
|
+
const total = ctx.state.gitPanel.files.length
|
|
385
|
+
if (total === 0) return r([])
|
|
386
|
+
const current = ctx.state.gitMode.selectedFileIndex
|
|
387
|
+
const next = (current + delta + total) % total
|
|
388
|
+
if (next === current) return r([])
|
|
389
|
+
return r([{ delta, type: 'git-mode-select-file' }])
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export function scrollGitDiff(delta: number): KeyResult {
|
|
394
|
+
return r([], [{ delta, type: 'scroll-git-diff' }])
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export const gitStageSelected: ActionFn = (ctx: ModeContext) => {
|
|
398
|
+
const file = ctx.state.gitPanel.files[ctx.state.gitMode.selectedFileIndex]
|
|
399
|
+
if (!file) return r(clearPendingDelete(ctx))
|
|
400
|
+
const actions = clearPendingDelete(ctx)
|
|
401
|
+
if (file.section === 'staged') return r(actions)
|
|
402
|
+
actions.push({
|
|
403
|
+
fromSection: file.section,
|
|
404
|
+
path: file.path,
|
|
405
|
+
toSection: 'staged',
|
|
406
|
+
type: 'git-mode-optimistic-move',
|
|
407
|
+
})
|
|
408
|
+
return r(actions, [{ path: file.path, type: 'git-stage' }])
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
export const gitDestructiveSelected: ActionFn = (ctx: ModeContext) => {
|
|
412
|
+
const file = ctx.state.gitPanel.files[ctx.state.gitMode.selectedFileIndex]
|
|
413
|
+
if (!file) return r(clearPendingDelete(ctx))
|
|
414
|
+
|
|
415
|
+
if (file.section === 'staged') {
|
|
416
|
+
const actions = clearPendingDelete(ctx)
|
|
417
|
+
const toSection = file.status === 'A' ? 'untracked' : 'unstaged'
|
|
418
|
+
actions.push({
|
|
419
|
+
fromSection: 'staged',
|
|
420
|
+
path: file.path,
|
|
421
|
+
toSection,
|
|
422
|
+
type: 'git-mode-optimistic-move',
|
|
423
|
+
})
|
|
424
|
+
return r(actions, [{ path: file.path, type: 'git-unstage' }])
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const isUntracked = file.section === 'untracked'
|
|
428
|
+
const pending = ctx.state.gitMode.pendingDeletePath
|
|
429
|
+
|
|
430
|
+
if (pending === file.path) {
|
|
431
|
+
const actions: AppAction[] = [
|
|
432
|
+
{ path: null, type: 'git-mode-set-pending-delete' },
|
|
433
|
+
{
|
|
434
|
+
fromSection: file.section,
|
|
435
|
+
path: file.path,
|
|
436
|
+
toSection: null,
|
|
437
|
+
type: 'git-mode-optimistic-move',
|
|
438
|
+
},
|
|
439
|
+
]
|
|
440
|
+
const effectType = isUntracked ? 'git-rm' : 'git-restore'
|
|
441
|
+
return r(actions, [{ path: file.path, type: effectType }])
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return r([{ path: file.path, type: 'git-mode-set-pending-delete' }])
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
export const gitCommitOpen: ActionFn = (ctx: ModeContext) => {
|
|
448
|
+
return r([...clearPendingDelete(ctx), { type: 'open-git-commit-modal' }], [], 'modal.git-commit')
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
export const gitPush: ActionFn = (ctx: ModeContext) => {
|
|
452
|
+
return r(clearPendingDelete(ctx), [{ type: 'git-push' }])
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// ---------------------------------------------------------------------------
|
|
456
|
+
// Modal: git-commit
|
|
457
|
+
// ---------------------------------------------------------------------------
|
|
458
|
+
|
|
459
|
+
export const gitCommitCancel: KeyResult = r([{ type: 'close-modal' }], [], 'git-mode')
|
|
460
|
+
|
|
461
|
+
export const gitCommitSubmit: ActionFn = (ctx: ModeContext) => {
|
|
462
|
+
const modal = ctx.state.modal
|
|
463
|
+
if (modal.type !== 'git-commit') {
|
|
464
|
+
return r([{ type: 'close-modal' }], [], 'git-mode')
|
|
465
|
+
}
|
|
466
|
+
const editBuffer = modal.editBuffer ?? ''
|
|
467
|
+
const activeIsTitle = modal.activeField === 'title'
|
|
468
|
+
const title = (activeIsTitle ? editBuffer : modal.contentBuffer).trim()
|
|
469
|
+
const body = (activeIsTitle ? modal.contentBuffer : editBuffer).trim()
|
|
470
|
+
return r([{ type: 'close-modal' }], [{ body, title, type: 'git-commit' }], 'git-mode')
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
export const gitCommitReturnKey: ActionFn = (ctx: ModeContext) => {
|
|
474
|
+
const modal = ctx.state.modal
|
|
475
|
+
if (modal.type === 'git-commit' && modal.activeField === 'body') {
|
|
476
|
+
return r([{ char: '\n', type: 'update-command-edit' }])
|
|
477
|
+
}
|
|
478
|
+
return r([{ type: 'switch-create-session-field' }])
|
|
479
|
+
}
|
package/src/defaults.ts
CHANGED
|
@@ -28,6 +28,7 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
|
|
|
28
28
|
.map('<C-h>', actions.resizeSidebar(-2))
|
|
29
29
|
.map('<C-l>', actions.resizeSidebar(2))
|
|
30
30
|
.map('G', actions.toggleGitPanel)
|
|
31
|
+
.map('<C-d>', actions.enterGitMode)
|
|
31
32
|
.map('<C-j>', actions.resizeGitPanel(-0.05))
|
|
32
33
|
.map('<C-k>', actions.resizeGitPanel(0.05))
|
|
33
34
|
.map('J', actions.reorderTab(1))
|
|
@@ -72,6 +73,24 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
|
|
|
72
73
|
.map('q', actions.closePane)
|
|
73
74
|
)
|
|
74
75
|
|
|
76
|
+
// -----------------------------------------------------------------------
|
|
77
|
+
// Git mode (src/input/modes/handlers/git-mode.ts)
|
|
78
|
+
// -----------------------------------------------------------------------
|
|
79
|
+
.mode('git-mode', (m) =>
|
|
80
|
+
m
|
|
81
|
+
.map('<Esc>', actions.exitGitMode)
|
|
82
|
+
.map('j', actions.selectGitFile(1))
|
|
83
|
+
.map('k', actions.selectGitFile(-1))
|
|
84
|
+
.map('<C-d>', actions.scrollGitDiff(20))
|
|
85
|
+
.map('<C-u>', actions.scrollGitDiff(-20))
|
|
86
|
+
.map('<Down>', actions.scrollGitDiff(1))
|
|
87
|
+
.map('<Up>', actions.scrollGitDiff(-1))
|
|
88
|
+
.map('a', actions.gitStageSelected)
|
|
89
|
+
.map('d', actions.gitDestructiveSelected)
|
|
90
|
+
.map('c', actions.gitCommitOpen)
|
|
91
|
+
.map('p', actions.gitPush)
|
|
92
|
+
)
|
|
93
|
+
|
|
75
94
|
// -----------------------------------------------------------------------
|
|
76
95
|
// Modal: help (src/input/modes/handlers/modal-help.ts)
|
|
77
96
|
// -----------------------------------------------------------------------
|
|
@@ -240,5 +259,17 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
|
|
|
240
259
|
.map('<CR>', actions.confirmSplit)
|
|
241
260
|
)
|
|
242
261
|
|
|
262
|
+
// -----------------------------------------------------------------------
|
|
263
|
+
// Modal: git-commit (src/input/modes/handlers/modal-git-commit.ts)
|
|
264
|
+
// -----------------------------------------------------------------------
|
|
265
|
+
.mode('modal.git-commit', (m) =>
|
|
266
|
+
m
|
|
267
|
+
.map('<Esc>', actions.gitCommitCancel)
|
|
268
|
+
.map('<C-CR>', actions.gitCommitSubmit)
|
|
269
|
+
.map('<Tab>', actions.switchField)
|
|
270
|
+
.map('<CR>', actions.gitCommitReturnKey)
|
|
271
|
+
.passthrough()
|
|
272
|
+
)
|
|
273
|
+
|
|
243
274
|
return kb._build()
|
|
244
275
|
}
|
package/src/types.ts
CHANGED
|
@@ -12,6 +12,7 @@ export type ModeId =
|
|
|
12
12
|
| 'navigation'
|
|
13
13
|
| 'terminal-input'
|
|
14
14
|
| 'layout'
|
|
15
|
+
| 'git-mode'
|
|
15
16
|
| 'modal.new-tab'
|
|
16
17
|
| 'modal.new-tab.command-edit'
|
|
17
18
|
| 'modal.session-picker'
|
|
@@ -25,6 +26,7 @@ export type ModeId =
|
|
|
25
26
|
| 'modal.theme-picker'
|
|
26
27
|
| 'modal.help'
|
|
27
28
|
| 'modal.split-picker'
|
|
29
|
+
| 'modal.git-commit'
|
|
28
30
|
|
|
29
31
|
// ─── Primitive app types ──────────────────────────────────────────────────────
|
|
30
32
|
|
|
@@ -32,7 +34,13 @@ export type BuiltinAssistantId = 'claude' | 'codex' | 'opencode' | 'terminal'
|
|
|
32
34
|
export type AssistantId = BuiltinAssistantId | (string & {})
|
|
33
35
|
export type TabStatus = 'starting' | 'running' | 'disconnected' | 'exited' | 'error'
|
|
34
36
|
export type TabActivity = 'busy' | 'idle'
|
|
35
|
-
export type FocusMode =
|
|
37
|
+
export type FocusMode =
|
|
38
|
+
| 'navigation'
|
|
39
|
+
| 'terminal-input'
|
|
40
|
+
| 'modal'
|
|
41
|
+
| 'command-edit'
|
|
42
|
+
| 'layout'
|
|
43
|
+
| 'git'
|
|
36
44
|
export type SplitDirection = 'horizontal' | 'vertical'
|
|
37
45
|
|
|
38
46
|
// ─── Terminal data shapes ─────────────────────────────────────────────────────
|
|
@@ -179,10 +187,31 @@ export interface GitPanelState {
|
|
|
179
187
|
error: GitPanelError | null
|
|
180
188
|
}
|
|
181
189
|
|
|
190
|
+
export type DiffFileStatus = 'modified' | 'new' | 'deleted' | 'binary' | 'renamed'
|
|
191
|
+
|
|
192
|
+
export interface DiffData {
|
|
193
|
+
path: string
|
|
194
|
+
status: DiffFileStatus
|
|
195
|
+
oldPath?: string
|
|
196
|
+
rawDiff: string
|
|
197
|
+
binarySizeBefore?: number
|
|
198
|
+
binarySizeAfter?: number
|
|
199
|
+
errorMessage?: string
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export interface GitModeState {
|
|
203
|
+
selectedFileIndex: number
|
|
204
|
+
diffs: Record<string, DiffData>
|
|
205
|
+
loading: Record<string, boolean>
|
|
206
|
+
pendingDeletePath: string | null
|
|
207
|
+
actionMessage: string | null
|
|
208
|
+
}
|
|
209
|
+
|
|
182
210
|
interface ModalBase {
|
|
183
211
|
selectedIndex: number
|
|
184
212
|
editBuffer: string | null
|
|
185
213
|
sessionTargetId: string | null
|
|
214
|
+
cursorPos?: number
|
|
186
215
|
}
|
|
187
216
|
|
|
188
217
|
export interface ModalClosed extends ModalBase {
|
|
@@ -223,6 +252,11 @@ export interface ModalCreateSession extends ModalBase {
|
|
|
223
252
|
activeField: 'directory' | 'name'
|
|
224
253
|
nameBuffer: string
|
|
225
254
|
}
|
|
255
|
+
export interface ModalGitCommit extends ModalBase {
|
|
256
|
+
type: 'git-commit'
|
|
257
|
+
activeField: 'title' | 'body'
|
|
258
|
+
contentBuffer: string
|
|
259
|
+
}
|
|
226
260
|
export interface ModalSnippetEditor extends ModalBase {
|
|
227
261
|
type: 'snippet-editor'
|
|
228
262
|
activeField: 'name' | 'content'
|
|
@@ -241,6 +275,7 @@ export type ModalState =
|
|
|
241
275
|
| ModalSplitPicker
|
|
242
276
|
| ModalCreateSession
|
|
243
277
|
| ModalSnippetEditor
|
|
278
|
+
| ModalGitCommit
|
|
244
279
|
|
|
245
280
|
export interface LayoutState {
|
|
246
281
|
terminalCols: number
|
|
@@ -261,6 +296,7 @@ export interface AppState {
|
|
|
261
296
|
layout: LayoutState
|
|
262
297
|
customCommands: Record<AssistantId, string>
|
|
263
298
|
gitPanel: GitPanelState
|
|
299
|
+
gitMode: GitModeState
|
|
264
300
|
pendingChords: string[] | null
|
|
265
301
|
}
|
|
266
302
|
|
|
@@ -369,6 +405,23 @@ export type GitPanelAction =
|
|
|
369
405
|
| { type: 'git-refresh-error'; kind: GitPanelError }
|
|
370
406
|
| { type: 'git-panel-reset' }
|
|
371
407
|
|
|
408
|
+
export type GitModeAction =
|
|
409
|
+
| { type: 'enter-git-mode' }
|
|
410
|
+
| { type: 'exit-git-mode' }
|
|
411
|
+
| { type: 'git-mode-select-file'; delta: -1 | 1 }
|
|
412
|
+
| { type: 'git-mode-set-diff'; path: string; diff: DiffData }
|
|
413
|
+
| { type: 'git-mode-set-loading'; path: string; loading: boolean }
|
|
414
|
+
| { type: 'git-mode-set-pending-delete'; path: string | null }
|
|
415
|
+
| { type: 'git-mode-clear-diff-cache'; path: string }
|
|
416
|
+
| { type: 'git-mode-set-message'; message: string | null }
|
|
417
|
+
| {
|
|
418
|
+
type: 'git-mode-optimistic-move'
|
|
419
|
+
path: string
|
|
420
|
+
fromSection: GitFileSection
|
|
421
|
+
toSection: GitFileSection | null
|
|
422
|
+
}
|
|
423
|
+
| { type: 'open-git-commit-modal' }
|
|
424
|
+
|
|
372
425
|
export type DataAction =
|
|
373
426
|
| { type: 'set-snippets'; snippets: SnippetRecord[] }
|
|
374
427
|
| { type: 'delete-snippet'; snippetId: string }
|
|
@@ -381,6 +434,7 @@ export type AppAction =
|
|
|
381
434
|
| UIAction
|
|
382
435
|
| DataAction
|
|
383
436
|
| GitPanelAction
|
|
437
|
+
| GitModeAction
|
|
384
438
|
|
|
385
439
|
// ─── Side effects ─────────────────────────────────────────────────────────────
|
|
386
440
|
|
|
@@ -406,6 +460,13 @@ export type SideEffect =
|
|
|
406
460
|
| { type: 'rename-session'; sessionId: string; name: string }
|
|
407
461
|
| { type: 'split-pane'; direction: SplitDirection }
|
|
408
462
|
| { type: 'confirm-split' }
|
|
463
|
+
| { type: 'scroll-git-diff'; delta: number }
|
|
464
|
+
| { type: 'git-stage'; path: string }
|
|
465
|
+
| { type: 'git-unstage'; path: string }
|
|
466
|
+
| { type: 'git-restore'; path: string }
|
|
467
|
+
| { type: 'git-rm'; path: string }
|
|
468
|
+
| { type: 'git-commit'; title: string; body: string }
|
|
469
|
+
| { type: 'git-push' }
|
|
409
470
|
|
|
410
471
|
// ─── Key input / KeyResult / ModeContext ──────────────────────────────────────
|
|
411
472
|
|