@mak-98/dirvi-cli 0.2.1 → 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.
- package/dist/application/action.d.ts +19 -0
- package/dist/application/action.d.ts.map +1 -0
- package/dist/application/action.js +1 -0
- package/dist/application/display-rows.d.ts +3 -3
- package/dist/application/display-rows.d.ts.map +1 -1
- package/dist/application/display-rows.js +7 -7
- package/dist/application/effect-to-action.d.ts +5 -0
- package/dist/application/effect-to-action.d.ts.map +1 -0
- package/dist/application/effect-to-action.js +79 -0
- package/dist/application/fold-helpers.d.ts +2 -2
- package/dist/application/fold-helpers.d.ts.map +1 -1
- package/dist/application/fold-helpers.js +0 -17
- package/dist/application/intent-to-effect.d.ts +39 -0
- package/dist/application/intent-to-effect.d.ts.map +1 -0
- package/dist/application/intent-to-effect.js +118 -0
- package/dist/application/reducer-action.d.ts +19 -0
- package/dist/application/reducer-action.d.ts.map +1 -0
- package/dist/application/reducer-action.js +1 -0
- package/dist/application/reducer.d.ts +3 -28
- package/dist/application/reducer.d.ts.map +1 -1
- package/dist/application/reducer.js +16 -172
- package/dist/application/user-input-to-intent.d.ts +15 -0
- package/dist/application/user-input-to-intent.d.ts.map +1 -0
- package/dist/application/user-input-to-intent.js +56 -0
- package/dist/domain/event-message.d.ts +3 -3
- package/dist/domain/event-message.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/infrastructure/input.d.ts +3 -3
- package/dist/infrastructure/input.d.ts.map +1 -1
- package/dist/infrastructure/input.js +16 -7
- package/dist/infrastructure/load-initial-props.d.ts.map +1 -1
- package/dist/infrastructure/load-initial-props.js +6 -8
- package/dist/infrastructure/user-input.d.ts +17 -0
- package/dist/infrastructure/user-input.d.ts.map +1 -0
- package/dist/infrastructure/user-input.js +35 -0
- package/dist/ui/App.d.ts +4 -5
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +54 -58
- package/dist/ui/App2.d.ts +11 -0
- package/dist/ui/App2.d.ts.map +1 -0
- package/dist/ui/App2.js +96 -0
- package/dist/ui/AppShell.d.ts +3 -3
- package/dist/ui/AppShell.d.ts.map +1 -1
- package/dist/ui/AppShell.js +3 -3
- package/dist/ui/components/DirEntries.d.ts +2 -1
- package/dist/ui/components/DirEntries.d.ts.map +1 -1
- package/dist/ui/components/DirEntries.js +6 -7
- package/dist/ui/components/UnixEntryComponent.d.ts +6 -0
- package/dist/ui/components/UnixEntryComponent.d.ts.map +1 -0
- package/dist/ui/components/UnixEntryComponent.js +12 -0
- package/dist/ui/components/ViewRowComponent.d.ts +5 -0
- package/dist/ui/components/ViewRowComponent.d.ts.map +1 -0
- package/dist/ui/components/ViewRowComponent.js +13 -0
- package/dist/ui/hooks/useView.d.ts +4 -0
- package/dist/ui/hooks/useView.d.ts.map +1 -0
- package/dist/ui/hooks/useView.js +30 -0
- package/dist/ui/view.d.ts +18 -0
- package/dist/ui/view.d.ts.map +1 -0
- package/dist/ui/view.js +74 -0
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-input-to-intent.d.ts","sourceRoot":"","sources":["../../src/application/user-input-to-intent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAE5D,MAAM,MAAM,MAAM,GACd;IACE,UAAU,EAAE,eAAe,CAAC;CAC7B,GACD;IACE,UAAU,EAAE,cAAc,CAAC;CAC5B,GACD;IACE,UAAU,EAAE,cAAc,CAAC;CAC5B,GACD;IACE,UAAU,EAAE,YAAY,CAAC;CAC1B,GACD;IACE,UAAU,EAAE,qBAAqB,CAAC;IAClC,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CAAC;AAqCN,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,MAAM,GACpB,MAAM,GAAG,SAAS,CAiCpB"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
function characterToIntent(character, commandBuffer) {
|
|
2
|
+
if (commandBuffer === '') {
|
|
3
|
+
switch (character) {
|
|
4
|
+
case 'l':
|
|
5
|
+
return {
|
|
6
|
+
intentType: 'interactRight',
|
|
7
|
+
};
|
|
8
|
+
case 'h':
|
|
9
|
+
return {
|
|
10
|
+
intentType: 'interactLeft',
|
|
11
|
+
};
|
|
12
|
+
case 'j':
|
|
13
|
+
return {
|
|
14
|
+
intentType: 'interactDown',
|
|
15
|
+
};
|
|
16
|
+
case 'k':
|
|
17
|
+
return {
|
|
18
|
+
intentType: 'interactUp',
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
intentType: 'updateCommandBuffer',
|
|
24
|
+
updatedCommandBuffer: commandBuffer + character,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
// Derive the intent from the user input and the commandBuffer.
|
|
28
|
+
export function userInputToIntent(userInput, commandBuffer) {
|
|
29
|
+
if (userInput.userInputType === 'esc') {
|
|
30
|
+
return {
|
|
31
|
+
intentType: 'updateCommandBuffer',
|
|
32
|
+
updatedCommandBuffer: '',
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
if (userInput.userInputType === 'character') {
|
|
36
|
+
return characterToIntent(userInput.string, commandBuffer);
|
|
37
|
+
}
|
|
38
|
+
switch (userInput.userInputType) {
|
|
39
|
+
case 'rightArrow':
|
|
40
|
+
return {
|
|
41
|
+
intentType: 'interactRight',
|
|
42
|
+
};
|
|
43
|
+
case 'leftArrow':
|
|
44
|
+
return {
|
|
45
|
+
intentType: 'interactLeft',
|
|
46
|
+
};
|
|
47
|
+
case 'downArrow':
|
|
48
|
+
return {
|
|
49
|
+
intentType: 'interactDown',
|
|
50
|
+
};
|
|
51
|
+
case 'upArrow':
|
|
52
|
+
return {
|
|
53
|
+
intentType: 'interactUp',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { UnixEntryPath, State } from 'dirvi-lib';
|
|
2
2
|
export type EventMessage = {
|
|
3
3
|
type: 'view';
|
|
4
|
-
view:
|
|
4
|
+
view: State;
|
|
5
5
|
} | {
|
|
6
6
|
type: 'displayed-files-paths';
|
|
7
7
|
paths: string[];
|
|
8
8
|
} | {
|
|
9
9
|
type: 'file';
|
|
10
|
-
path:
|
|
10
|
+
path: UnixEntryPath;
|
|
11
11
|
};
|
|
12
12
|
//# sourceMappingURL=event-message.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-message.d.ts","sourceRoot":"","sources":["../../src/domain/event-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"event-message.d.ts","sourceRoot":"","sources":["../../src/domain/event-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAEjD,MAAM,MAAM,YAAY,GACpB;IACE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,KAAK,CAAC;CACb,GACD;IACE,IAAI,EAAE,uBAAuB,CAAC;IAC9B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,CAAC;CACrB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { render } from 'ink';
|
|
|
5
5
|
import { AppShell } from './ui/AppShell.js';
|
|
6
6
|
import { loadInitialProps } from './infrastructure/load-initial-props.js';
|
|
7
7
|
const program = new Command();
|
|
8
|
-
// ---*--- TERMINAL
|
|
8
|
+
// ---*--- TERMINAL ALTERNATE SCREEN ---*---
|
|
9
9
|
// Restore the terminal during normal cleanup and as a
|
|
10
10
|
// last-resort fallback when Node is exiting.
|
|
11
11
|
// Write UI to stderr
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Key } from 'ink';
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import { State } from 'dirvi-lib';
|
|
3
|
+
import { Action } from '../application/action.js';
|
|
4
4
|
export type PendingInput = 'z';
|
|
5
5
|
export type InputResult = Action | PendingInput | undefined;
|
|
6
|
-
export declare function
|
|
6
|
+
export declare function userInputToInputResult(input: string, key: Key, view: State, pendingInput?: PendingInput): InputResult;
|
|
7
7
|
//# sourceMappingURL=input.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/infrastructure/input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE/B,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/infrastructure/input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE/B,OAAO,EAAU,KAAK,EAAQ,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAElD,MAAM,MAAM,YAAY,GAAG,GAAG,CAAC;AAC/B,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;AAE5D,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,KAAK,EACX,YAAY,CAAC,EAAE,YAAY,GAC1B,WAAW,CA8Fb"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { Cursor, View } from 'dirvi-lib';
|
|
2
|
+
export function userInputToInputResult(input, key, view, pendingInput) {
|
|
2
3
|
// Adding Pending Input
|
|
3
4
|
if (pendingInput === undefined && input === 'z') {
|
|
4
5
|
return 'z';
|
|
@@ -25,18 +26,26 @@ export function inputToInputResult(input, key, view, pendingInput) {
|
|
|
25
26
|
}
|
|
26
27
|
// Not prefixed inputs
|
|
27
28
|
if (input === 'l' || key.rightArrow) {
|
|
28
|
-
|
|
29
|
-
if (
|
|
29
|
+
const currentEntry = View.getEntryAtCursor(view);
|
|
30
|
+
if (currentEntry === undefined) {
|
|
30
31
|
return undefined;
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
if (currentEntry.kind === 'directory') {
|
|
34
|
+
const path = Cursor.getPath(view.cursor);
|
|
35
|
+
if (path === undefined) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
34
38
|
return {
|
|
35
|
-
kind: '
|
|
39
|
+
kind: 'updateDir',
|
|
36
40
|
path,
|
|
41
|
+
entries: currentEntry.entries,
|
|
37
42
|
};
|
|
38
43
|
}
|
|
39
|
-
if (
|
|
44
|
+
if (currentEntry.kind === 'file') {
|
|
45
|
+
const path = Cursor.getPath(view.cursor);
|
|
46
|
+
if (path === undefined) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
40
49
|
return {
|
|
41
50
|
kind: 'printFile',
|
|
42
51
|
path,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-initial-props.d.ts","sourceRoot":"","sources":["../../src/infrastructure/load-initial-props.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"load-initial-props.d.ts","sourceRoot":"","sources":["../../src/infrastructure/load-initial-props.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,aAAa,CAAC,CAiC/D"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { getCwdAbsPath, getDirLazyEntries,
|
|
1
|
+
import { getCwdAbsPath, getDirLazyEntries, FoldNode, DisplayEntry, } from 'dirvi-lib';
|
|
2
2
|
export async function loadInitialProps() {
|
|
3
3
|
const cwdAddress = getCwdAbsPath();
|
|
4
4
|
const lazyEntries = await getDirLazyEntries(cwdAddress);
|
|
5
5
|
if (lazyEntries.length === 0) {
|
|
6
6
|
return {
|
|
7
7
|
cwdAddress,
|
|
8
|
-
|
|
8
|
+
initialState: {
|
|
9
9
|
cursor: undefined,
|
|
10
10
|
},
|
|
11
11
|
};
|
|
@@ -16,16 +16,14 @@ export async function loadInitialProps() {
|
|
|
16
16
|
}
|
|
17
17
|
return {
|
|
18
18
|
cwdAddress,
|
|
19
|
-
|
|
20
|
-
buffer:
|
|
21
|
-
entries: lazyEntries,
|
|
22
|
-
},
|
|
19
|
+
initialState: {
|
|
20
|
+
buffer: lazyEntries,
|
|
23
21
|
cursor: {
|
|
24
22
|
kind: 'entry',
|
|
25
23
|
parentPath: [],
|
|
26
|
-
|
|
24
|
+
entryName: DisplayEntry.fromUnixEntry(firstEntry).name,
|
|
27
25
|
},
|
|
28
|
-
folds:
|
|
26
|
+
folds: FoldNode.createEmpty(),
|
|
29
27
|
},
|
|
30
28
|
};
|
|
31
29
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Key } from 'ink';
|
|
2
|
+
export type UserInput = {
|
|
3
|
+
userInputType: 'character';
|
|
4
|
+
string: string;
|
|
5
|
+
} | {
|
|
6
|
+
userInputType: 'esc';
|
|
7
|
+
} | {
|
|
8
|
+
userInputType: 'rightArrow';
|
|
9
|
+
} | {
|
|
10
|
+
userInputType: 'leftArrow';
|
|
11
|
+
} | {
|
|
12
|
+
userInputType: 'downArrow';
|
|
13
|
+
} | {
|
|
14
|
+
userInputType: 'upArrow';
|
|
15
|
+
};
|
|
16
|
+
export declare function inkInputToUserInput(input: string, key: Key): UserInput | undefined;
|
|
17
|
+
//# sourceMappingURL=user-input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-input.d.ts","sourceRoot":"","sources":["../../src/infrastructure/user-input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE/B,MAAM,MAAM,SAAS,GACjB;IACE,aAAa,EAAE,WAAW,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IACE,aAAa,EAAE,KAAK,CAAC;CACtB,GACD;IACE,aAAa,EAAE,YAAY,CAAC;CAC7B,GACD;IACE,aAAa,EAAE,WAAW,CAAC;CAC5B,GACD;IACE,aAAa,EAAE,WAAW,CAAC;CAC5B,GACD;IACE,aAAa,EAAE,SAAS,CAAC;CAC1B,CAAC;AAGN,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,SAAS,GAAG,SAAS,CAuClF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Interprets raw user input to typed UserInput.
|
|
2
|
+
export function inkInputToUserInput(input, key) {
|
|
3
|
+
if (key.escape) {
|
|
4
|
+
return {
|
|
5
|
+
userInputType: 'esc',
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
if (key.rightArrow) {
|
|
9
|
+
return {
|
|
10
|
+
userInputType: 'rightArrow',
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
if (key.leftArrow) {
|
|
14
|
+
return {
|
|
15
|
+
userInputType: 'leftArrow',
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
if (key.upArrow) {
|
|
19
|
+
return {
|
|
20
|
+
userInputType: 'upArrow',
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
if (key.downArrow) {
|
|
24
|
+
return {
|
|
25
|
+
userInputType: 'downArrow',
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
if (input !== '') {
|
|
29
|
+
return {
|
|
30
|
+
userInputType: 'character',
|
|
31
|
+
string: input,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
package/dist/ui/App.d.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { UnixAbsolutePath
|
|
1
|
+
import { State } from 'dirvi-lib';
|
|
2
|
+
import type { UnixAbsolutePath } from 'dirvi-lib';
|
|
3
3
|
import { EventMessage } from '../domain/event-message.js';
|
|
4
4
|
export type AppProps = {
|
|
5
5
|
cwdAddress: UnixAbsolutePath;
|
|
6
|
-
|
|
6
|
+
initialState: State;
|
|
7
7
|
print?: (message: EventMessage) => void;
|
|
8
8
|
onError?: (error: Error) => void;
|
|
9
9
|
};
|
|
10
|
-
export declare function App({ cwdAddress,
|
|
11
|
-
export declare function displayedFilePaths(rows: readonly DisplayRow[]): string[];
|
|
10
|
+
export declare function App({ cwdAddress, initialState, print, onError }: AppProps): import("react").JSX.Element | null;
|
|
12
11
|
//# sourceMappingURL=App.d.ts.map
|
package/dist/ui/App.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/ui/App.tsx"],"names":[],"mappings":"AAIA,OAAO,
|
|
1
|
+
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/ui/App.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAqC,KAAK,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAIlD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAO1D,MAAM,MAAM,QAAQ,GAAG;IACrB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,YAAY,EAAE,KAAK,CAAC;IACpB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IACxC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF,wBAAgB,GAAG,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,QAAQ,sCAwHzE"}
|
package/dist/ui/App.js
CHANGED
|
@@ -1,52 +1,49 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { Box, Text, useApp, useInput } from 'ink';
|
|
4
|
-
import { useEffect,
|
|
5
|
-
import { getDirLazyEntries } from 'dirvi-lib';
|
|
4
|
+
import { useEffect, useMemo, useReducer, useState } from 'react';
|
|
5
|
+
import { getDirLazyEntries, NavigationNode } from 'dirvi-lib';
|
|
6
|
+
import { useView } from './hooks/useView.js';
|
|
6
7
|
import { reducer } from '../application/reducer.js';
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
export function App({ cwdAddress,
|
|
13
|
-
const [
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
8
|
+
import { ViewRowComponent } from './components/ViewRowComponent.js';
|
|
9
|
+
import { inkInputToUserInput } from '../infrastructure/user-input.js';
|
|
10
|
+
import { userInputToIntent } from '../application/user-input-to-intent.js';
|
|
11
|
+
import { intentToEffect } from '../application/intent-to-effect.js';
|
|
12
|
+
import { effectToAction } from '../application/effect-to-action.js';
|
|
13
|
+
export function App({ cwdAddress, initialState, print, onError }) {
|
|
14
|
+
const [state, dispatch] = useReducer(reducer, initialState);
|
|
15
|
+
const navigation = useMemo(() => NavigationNode.from(state.buffer, state.folds), [state.buffer, state.folds]);
|
|
16
|
+
const [commandBuffer, setCommandBuffer] = useState('');
|
|
17
|
+
const view = useView(navigation, state);
|
|
17
18
|
const [exitStatus, setExitStatus] = useState();
|
|
18
19
|
// Print view on changes
|
|
19
20
|
useEffect(() => {
|
|
20
|
-
print?.({ type: 'view', view:
|
|
21
|
+
print?.({ type: 'view', view: state });
|
|
22
|
+
const visibleFilesPaths = NavigationNode.visibleFilesPaths(navigation).map((path) => join(cwdAddress, ...path));
|
|
21
23
|
print?.({
|
|
22
24
|
type: 'displayed-files-paths',
|
|
23
|
-
paths:
|
|
25
|
+
paths: visibleFilesPaths,
|
|
24
26
|
});
|
|
25
|
-
}, [
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const result = inputToInputResult(input, key, view, pendingInput.current);
|
|
29
|
-
if (result === undefined) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
if (result === 'z') {
|
|
33
|
-
pendingInput.current = result;
|
|
27
|
+
}, [state, print, navigation, cwdAddress]);
|
|
28
|
+
function executeEffect(effect) {
|
|
29
|
+
if (effect === undefined) {
|
|
34
30
|
return;
|
|
35
31
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
32
|
+
switch (effect.effectType) {
|
|
33
|
+
case 'dispatchEffectAsAction':
|
|
34
|
+
const action = effectToAction(effect.action, navigation, state);
|
|
35
|
+
if (action === undefined) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
dispatch(action);
|
|
39
|
+
return;
|
|
40
|
+
case 'loadDir': {
|
|
41
|
+
const address = join(cwdAddress, ...effect.path);
|
|
45
42
|
void getDirLazyEntries(address)
|
|
46
43
|
.then((entries) => {
|
|
47
44
|
dispatch({
|
|
48
|
-
kind: '
|
|
49
|
-
path:
|
|
45
|
+
kind: 'updateDir',
|
|
46
|
+
path: effect.path,
|
|
50
47
|
entries,
|
|
51
48
|
});
|
|
52
49
|
})
|
|
@@ -55,26 +52,35 @@ export function App({ cwdAddress, initialView, print, onError }) {
|
|
|
55
52
|
onError?.(appError);
|
|
56
53
|
setExitStatus(`Unable to open directory: ${appError.message}`);
|
|
57
54
|
});
|
|
55
|
+
return;
|
|
58
56
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
path:
|
|
57
|
+
case 'printFile':
|
|
58
|
+
print?.({
|
|
59
|
+
type: 'file',
|
|
60
|
+
path: effect.path,
|
|
63
61
|
});
|
|
64
|
-
|
|
62
|
+
return;
|
|
63
|
+
case 'exit':
|
|
64
|
+
setExitStatus(effect.exitMessage);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// --- Input Hook ---
|
|
69
|
+
useInput((input, key) => {
|
|
70
|
+
const userInput = inkInputToUserInput(input, key);
|
|
71
|
+
if (userInput === undefined) {
|
|
65
72
|
return;
|
|
66
73
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
type: 'file',
|
|
70
|
-
path: action.path,
|
|
71
|
-
});
|
|
74
|
+
const intent = userInputToIntent(userInput, commandBuffer);
|
|
75
|
+
if (intent === undefined) {
|
|
72
76
|
return;
|
|
73
77
|
}
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
const effectResult = intentToEffect(intent, state);
|
|
79
|
+
if (effectResult === undefined) {
|
|
80
|
+
return;
|
|
76
81
|
}
|
|
77
|
-
|
|
82
|
+
setCommandBuffer(effectResult.commandBuffer);
|
|
83
|
+
executeEffect(effectResult.effect);
|
|
78
84
|
});
|
|
79
85
|
// --- Exit Logic ---
|
|
80
86
|
const { exit } = useApp();
|
|
@@ -91,15 +97,5 @@ export function App({ cwdAddress, initialView, print, onError }) {
|
|
|
91
97
|
return null;
|
|
92
98
|
}
|
|
93
99
|
// --- JSX ---
|
|
94
|
-
return (_jsx(Box, { flexDirection: "column", children:
|
|
95
|
-
}
|
|
96
|
-
export function displayedFilePaths(rows) {
|
|
97
|
-
return rows.flatMap((row) => {
|
|
98
|
-
if ((row.kind !== 'entry') || (row.entry.kind !== 'file')) {
|
|
99
|
-
return [];
|
|
100
|
-
}
|
|
101
|
-
return [
|
|
102
|
-
path.posix.join(...row.parentPath.map(String), String(row.entry.name)),
|
|
103
|
-
];
|
|
104
|
-
});
|
|
100
|
+
return (_jsx(Box, { flexDirection: "column", children: view.rows.length === 0 ? (_jsx(Text, { dimColor: true, children: "Directory is empty." })) : (view.rows.map((row) => (_jsx(ViewRowComponent, { row: row }, row.id)))) }));
|
|
105
101
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { State } from 'dirvi-lib';
|
|
2
|
+
import type { UnixAbsolutePath } from 'dirvi-lib';
|
|
3
|
+
import { EventMessage } from '../domain/event-message.js';
|
|
4
|
+
export type AppProps = {
|
|
5
|
+
cwdAddress: UnixAbsolutePath;
|
|
6
|
+
initialState: State;
|
|
7
|
+
print?: (message: EventMessage) => void;
|
|
8
|
+
onError?: (error: Error) => void;
|
|
9
|
+
};
|
|
10
|
+
export declare function App2({ cwdAddress, initialState, print, onError }: AppProps): import("react").JSX.Element | null;
|
|
11
|
+
//# sourceMappingURL=App2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"App2.d.ts","sourceRoot":"","sources":["../../src/ui/App2.tsx"],"names":[],"mappings":"AAIA,OAAO,EAA6B,KAAK,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAQlD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG1D,MAAM,MAAM,QAAQ,GAAG;IACrB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,YAAY,EAAE,KAAK,CAAC;IACpB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IACxC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF,wBAAgB,IAAI,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,QAAQ,sCAsH1E"}
|
package/dist/ui/App2.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { Box, Text, useApp, useInput } from 'ink';
|
|
4
|
+
import { useEffect, useReducer, useRef, useState } from 'react';
|
|
5
|
+
import { Cursor, getDirLazyEntries } from 'dirvi-lib';
|
|
6
|
+
import { useView } from './hooks/useView.js';
|
|
7
|
+
import { reducer } from '../application/reducer.js';
|
|
8
|
+
import { userInputToInputResult, } from '../infrastructure/input.js';
|
|
9
|
+
import { ViewRowComponent } from './components/ViewRowComponent.js';
|
|
10
|
+
export function App2({ cwdAddress, initialState, print, onError }) {
|
|
11
|
+
const [state, dispatch] = useReducer(reducer, initialState);
|
|
12
|
+
const view = useView(state);
|
|
13
|
+
const pendingInput = useRef(undefined);
|
|
14
|
+
const [exitStatus, setExitStatus] = useState();
|
|
15
|
+
// Print view on changes
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
print?.({ type: 'view', view: state });
|
|
18
|
+
// print?.({
|
|
19
|
+
// type: 'displayed-files-paths',
|
|
20
|
+
// paths: displayedFilePaths(displayRows),
|
|
21
|
+
// });
|
|
22
|
+
}, [state, print]);
|
|
23
|
+
// --- Input ---
|
|
24
|
+
useInput((input, key) => {
|
|
25
|
+
const result = userInputToInputResult(input, key, state, pendingInput.current);
|
|
26
|
+
if (result === undefined) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (result === 'z') {
|
|
30
|
+
pendingInput.current = result;
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
pendingInput.current = undefined;
|
|
34
|
+
const action = result;
|
|
35
|
+
// Contents of `updateDir` change meaning at this boundary:
|
|
36
|
+
if (action.kind === 'updateDir') {
|
|
37
|
+
// If the entry at the path is directory with no entries loaded:
|
|
38
|
+
if (action.entries === undefined) {
|
|
39
|
+
const path = Cursor.getPath(state.cursor);
|
|
40
|
+
if (path === undefined) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
const address = join(cwdAddress, ...path);
|
|
44
|
+
void getDirLazyEntries(address)
|
|
45
|
+
.then((entries) => {
|
|
46
|
+
dispatch({
|
|
47
|
+
kind: 'updateDir',
|
|
48
|
+
path: path,
|
|
49
|
+
entries,
|
|
50
|
+
});
|
|
51
|
+
})
|
|
52
|
+
.catch((error) => {
|
|
53
|
+
const appError = error instanceof Error ? error : new Error(String(error));
|
|
54
|
+
onError?.(appError);
|
|
55
|
+
setExitStatus(`Unable to open directory: ${appError.message}`);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// Otherwise need to wipe the entries:
|
|
60
|
+
dispatch({
|
|
61
|
+
kind: 'updateDir',
|
|
62
|
+
path: action.path,
|
|
63
|
+
entries: undefined,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (action.kind === 'printFile') {
|
|
69
|
+
print?.({
|
|
70
|
+
type: 'file',
|
|
71
|
+
path: action.path,
|
|
72
|
+
});
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (action.kind === 'exit') {
|
|
76
|
+
setExitStatus(action.exitMessage);
|
|
77
|
+
}
|
|
78
|
+
dispatch(action);
|
|
79
|
+
});
|
|
80
|
+
// --- Exit Logic ---
|
|
81
|
+
const { exit } = useApp();
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (exitStatus === undefined) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (exitStatus !== '') {
|
|
87
|
+
onError?.(new Error(exitStatus));
|
|
88
|
+
}
|
|
89
|
+
exit();
|
|
90
|
+
}, [exitStatus, exit, onError]);
|
|
91
|
+
if (exitStatus !== undefined) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
// --- JSX ---
|
|
95
|
+
return (_jsx(Box, { flexDirection: "column", children: view.rows.length === 0 ? (_jsx(Text, { dimColor: true, children: "Directory is empty." })) : (view.rows.map((row) => (_jsx(ViewRowComponent, { row: row }, row.id)))) }));
|
|
96
|
+
}
|
package/dist/ui/AppShell.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { UnixAbsolutePath,
|
|
1
|
+
import { UnixAbsolutePath, State } from 'dirvi-lib';
|
|
2
2
|
import { EventMessage } from '../domain/event-message.js';
|
|
3
3
|
export type EmptyView = {
|
|
4
4
|
cursor: undefined;
|
|
5
5
|
};
|
|
6
6
|
export type ShellAppProps = {
|
|
7
7
|
cwdAddress: UnixAbsolutePath;
|
|
8
|
-
|
|
8
|
+
initialState: State | EmptyView;
|
|
9
9
|
print?: (message: EventMessage) => void;
|
|
10
10
|
onError?: (error: Error) => void;
|
|
11
11
|
};
|
|
12
|
-
export declare function AppShell({ cwdAddress,
|
|
12
|
+
export declare function AppShell({ cwdAddress, initialState, print, onError, }: ShellAppProps): import("react").JSX.Element;
|
|
13
13
|
//# sourceMappingURL=AppShell.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppShell.d.ts","sourceRoot":"","sources":["../../src/ui/AppShell.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"AppShell.d.ts","sourceRoot":"","sources":["../../src/ui/AppShell.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAEpD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAI1D,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,EAAE,SAAS,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,EAAE,gBAAgB,CAAC;IAC7B,YAAY,EAAE,KAAK,GAAG,SAAS,CAAC;IAChC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IACxC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF,wBAAgB,QAAQ,CAAC,EACvB,UAAU,EACV,YAAY,EACZ,KAAK,EACL,OAAO,GACR,EAAE,aAAa,+BAaf"}
|
package/dist/ui/AppShell.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Text } from 'ink';
|
|
3
3
|
import { App } from './App.js';
|
|
4
|
-
export function AppShell({ cwdAddress,
|
|
5
|
-
if (
|
|
4
|
+
export function AppShell({ cwdAddress, initialState, print, onError, }) {
|
|
5
|
+
if (initialState.cursor === undefined) {
|
|
6
6
|
return _jsx(Text, { dimColor: true, children: "Directory is empty." });
|
|
7
7
|
}
|
|
8
|
-
return (_jsx(App, { cwdAddress: cwdAddress,
|
|
8
|
+
return (_jsx(App, { cwdAddress: cwdAddress, initialState: initialState, print: print, onError: onError }));
|
|
9
9
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DirEntries.d.ts","sourceRoot":"","sources":["../../../src/ui/components/DirEntries.tsx"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"DirEntries.d.ts","sourceRoot":"","sources":["../../../src/ui/components/DirEntries.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAKvC,iBAAS,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;IAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,+BA2D3E;AAED,eAAe,UAAU,CAAC"}
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text, useWindowSize } from 'ink';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { Cursor } from 'dirvi-lib';
|
|
4
|
+
import { UnixEntryComponent as UnixEntryComponent } from './UnixEntryComponent.js';
|
|
5
5
|
import { useRef } from 'react';
|
|
6
|
-
// Display column of entries in directory, indented, and optional
|
|
7
|
-
// cursor in position.
|
|
8
6
|
function DirEntries({ rows, cursor }) {
|
|
9
7
|
const scrollMargin = 3;
|
|
10
8
|
const { rows: terminalRows } = useWindowSize();
|
|
11
9
|
const viewportStartRef = useRef(0);
|
|
12
|
-
const cursorIndex = rows.findIndex((row) =>
|
|
10
|
+
const cursorIndex = rows.findIndex((row) => Cursor.matchesDisplayRow(cursor, row));
|
|
13
11
|
const viewportHeight = Math.max(1, terminalRows);
|
|
14
12
|
const maximumViewportStart = Math.max(0, rows.length - viewportHeight);
|
|
15
13
|
let viewportStart = viewportStartRef.current;
|
|
@@ -29,10 +27,11 @@ function DirEntries({ rows, cursor }) {
|
|
|
29
27
|
viewportStartRef.current = viewportStart;
|
|
30
28
|
const visibleRows = rows.slice(viewportStart, viewportStart + viewportHeight);
|
|
31
29
|
return (_jsx(_Fragment, { children: visibleRows.map((row) => {
|
|
32
|
-
const selected =
|
|
30
|
+
const selected = Cursor.matchesDisplayRow(cursor, row);
|
|
33
31
|
const indent = row.parentPath.length;
|
|
34
32
|
if (row.kind === 'fold') {
|
|
35
|
-
|
|
33
|
+
const key = `fold-${row.parentPath.join('/')}-${row.entryNames[0]}`;
|
|
34
|
+
return (_jsx(Box, { paddingLeft: indent * 2, children: _jsx(Text, { inverse: selected, dimColor: !selected, children: "..." }) }, key));
|
|
36
35
|
}
|
|
37
36
|
return (_jsx(Box, { paddingLeft: indent * 2, children: _jsx(UnixEntryComponent, { entry: row.entry, selected: selected }) }, [...row.parentPath, row.entry.name].join('/')));
|
|
38
37
|
}) }));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UnixEntryComponent.d.ts","sourceRoot":"","sources":["../../../src/ui/components/UnixEntryComponent.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB,+BAmBA"}
|