@mak-98/dirvi-cli 0.3.2 → 0.4.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 +25 -18
- package/dist/application/dir-buffer-helpers.d.ts +5 -2
- package/dist/application/dir-buffer-helpers.js +17 -17
- package/dist/application/display-rows.d.ts +10 -3
- package/dist/application/display-rows.d.ts.map +1 -1
- package/dist/application/display-rows.js +54 -41
- package/dist/application/effect-to-action.d.ts +7 -4
- package/dist/application/effect-to-action.d.ts.map +1 -1
- package/dist/application/effect-to-action.js +84 -75
- package/dist/application/fold-helpers.d.ts +22 -6
- package/dist/application/fold-helpers.js +36 -32
- package/dist/application/intent-to-effect.d.ts +57 -37
- package/dist/application/intent-to-effect.d.ts.map +1 -1
- package/dist/application/intent-to-effect.js +116 -103
- package/dist/application/reducer-action.d.ts +22 -18
- package/dist/application/reducer.d.ts +1 -1
- package/dist/application/reducer.d.ts.map +1 -1
- package/dist/application/reducer.js +40 -28
- package/dist/application/user-input-to-intent.d.ts +38 -14
- package/dist/application/user-input-to-intent.d.ts.map +1 -1
- package/dist/application/user-input-to-intent.js +103 -49
- package/dist/domain/event-message.d.ts +14 -11
- package/dist/domain/print-message.d.ts +10 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +35 -30
- package/dist/infrastructure/ink-input-to-user-input.d.ts +7 -0
- package/dist/infrastructure/ink-input-to-user-input.d.ts.map +1 -0
- package/dist/infrastructure/ink-input-to-user-input.js +45 -0
- package/dist/infrastructure/input.d.ts +7 -2
- package/dist/infrastructure/input.js +71 -71
- package/dist/infrastructure/load-initial-props.d.ts +1 -1
- package/dist/infrastructure/load-initial-props.d.ts.map +1 -1
- package/dist/infrastructure/load-initial-props.js +32 -25
- package/dist/infrastructure/user-input.d.ts +31 -16
- package/dist/infrastructure/user-input.d.ts.map +1 -1
- package/dist/infrastructure/user-input.js +42 -32
- package/dist/ui/App.d.ts +11 -6
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +127 -89
- package/dist/ui/App2.d.ts +11 -6
- package/dist/ui/App2.js +95 -84
- package/dist/ui/AppShell.d.ts +12 -7
- package/dist/ui/AppShell.js +11 -6
- package/dist/ui/components/DirEntries.d.ts +8 -5
- package/dist/ui/components/DirEntries.js +56 -31
- package/dist/ui/components/StatusBar.d.ts +10 -0
- package/dist/ui/components/StatusBar.d.ts.map +1 -0
- package/dist/ui/components/StatusBar.js +32 -0
- package/dist/ui/components/UnixEntry.d.ts +8 -5
- package/dist/ui/components/UnixEntry.js +17 -10
- package/dist/ui/components/UnixEntryComponent.d.ts +8 -5
- package/dist/ui/components/UnixEntryComponent.js +17 -10
- package/dist/ui/components/ViewRowComponent.d.ts +6 -4
- package/dist/ui/components/ViewRowComponent.js +30 -10
- package/dist/ui/hooks/useView.d.ts +6 -2
- package/dist/ui/hooks/useView.d.ts.map +1 -1
- package/dist/ui/hooks/useView.js +30 -22
- package/dist/ui/view.d.ts +15 -10
- package/dist/ui/view.d.ts.map +1 -1
- package/dist/ui/view.js +63 -59
- package/package.json +3 -2
package/dist/ui/App.js
CHANGED
|
@@ -1,101 +1,139 @@
|
|
|
1
|
-
import { jsx as _jsx } from
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { Box, Text, useApp, useInput } from 'ink';
|
|
3
|
+
import { Box, Text, useApp, useInput, useWindowSize } from 'ink';
|
|
4
4
|
import { useEffect, useMemo, useReducer, useState } from 'react';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
getDirLazyEntries,
|
|
7
|
+
intentToEffect,
|
|
8
|
+
NavigationNode,
|
|
9
|
+
userInputToIntent,
|
|
10
|
+
} from 'dirvi-lib';
|
|
6
11
|
import { useView } from './hooks/useView.js';
|
|
7
12
|
import { reducer } from '../application/reducer.js';
|
|
8
13
|
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
14
|
import { effectToAction } from '../application/effect-to-action.js';
|
|
15
|
+
import { StatusBar } from './components/StatusBar.js';
|
|
16
|
+
import { inkInputToUserInput } from '../infrastructure/ink-input-to-user-input.js';
|
|
13
17
|
export function App({ cwdAddress, initialState, print, onError }) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
const [state, dispatch] = useReducer(reducer, initialState);
|
|
19
|
+
const navigation = useMemo(
|
|
20
|
+
() => NavigationNode.from(state.buffer, state.folds),
|
|
21
|
+
[state.buffer, state.folds],
|
|
22
|
+
);
|
|
23
|
+
const [inputState, setInputState] = useState({
|
|
24
|
+
inputMode: 'normal',
|
|
25
|
+
normalBuffer: '',
|
|
26
|
+
});
|
|
27
|
+
const { rows: terminalRows } = useWindowSize();
|
|
28
|
+
const view = useView(navigation, state, terminalRows);
|
|
29
|
+
const [exitStatus, setExitStatus] = useState();
|
|
30
|
+
// Print view on changes
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
print?.({ type: 'view', view: state });
|
|
33
|
+
const visibleFilesPaths = NavigationNode.visibleFilesPaths(navigation).map(
|
|
34
|
+
(path) => join(...path),
|
|
35
|
+
);
|
|
36
|
+
print?.({
|
|
37
|
+
type: 'displayed-files-paths',
|
|
38
|
+
paths: visibleFilesPaths,
|
|
39
|
+
});
|
|
40
|
+
}, [state, print, navigation, cwdAddress]);
|
|
41
|
+
function executeEffect(effect) {
|
|
42
|
+
if (effect === undefined) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
switch (effect.effectType) {
|
|
46
|
+
case 'dispatchEffectAction':
|
|
47
|
+
const action = effectToAction(effect.action, navigation, state);
|
|
48
|
+
if (action === undefined) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
dispatch(action);
|
|
52
|
+
setInputState({
|
|
53
|
+
inputMode: 'normal',
|
|
54
|
+
normalBuffer: '',
|
|
55
|
+
});
|
|
56
|
+
return;
|
|
57
|
+
case 'setInputState':
|
|
58
|
+
console.log('setInputState', effect.inputState);
|
|
59
|
+
setInputState(effect.inputState);
|
|
60
|
+
return;
|
|
61
|
+
case 'loadDir': {
|
|
62
|
+
const address = join(cwdAddress, ...effect.path);
|
|
63
|
+
void getDirLazyEntries(address)
|
|
64
|
+
.then((entries) => {
|
|
65
|
+
dispatch({
|
|
66
|
+
kind: 'updateDir',
|
|
67
|
+
path: effect.path,
|
|
68
|
+
entries,
|
|
69
|
+
});
|
|
70
|
+
})
|
|
71
|
+
.catch((error) => {
|
|
72
|
+
const appError =
|
|
73
|
+
error instanceof Error ? error : new Error(String(error));
|
|
74
|
+
onError?.(appError);
|
|
75
|
+
setExitStatus(`Unable to open directory: ${appError.message}`);
|
|
76
|
+
});
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
case 'printFile':
|
|
23
80
|
print?.({
|
|
24
|
-
|
|
25
|
-
|
|
81
|
+
type: 'file',
|
|
82
|
+
path: effect.path,
|
|
26
83
|
});
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
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);
|
|
42
|
-
void getDirLazyEntries(address)
|
|
43
|
-
.then((entries) => {
|
|
44
|
-
dispatch({
|
|
45
|
-
kind: 'updateDir',
|
|
46
|
-
path: effect.path,
|
|
47
|
-
entries,
|
|
48
|
-
});
|
|
49
|
-
})
|
|
50
|
-
.catch((error) => {
|
|
51
|
-
const appError = error instanceof Error ? error : new Error(String(error));
|
|
52
|
-
onError?.(appError);
|
|
53
|
-
setExitStatus(`Unable to open directory: ${appError.message}`);
|
|
54
|
-
});
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
case 'printFile':
|
|
58
|
-
print?.({
|
|
59
|
-
type: 'file',
|
|
60
|
-
path: effect.path,
|
|
61
|
-
});
|
|
62
|
-
return;
|
|
63
|
-
case 'exit':
|
|
64
|
-
setExitStatus(effect.exitMessage);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
84
|
+
return;
|
|
85
|
+
case 'quit':
|
|
86
|
+
setExitStatus(effect.exitMessage);
|
|
87
|
+
return;
|
|
67
88
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
exit();
|
|
95
|
-
}, [exitStatus, exit, onError]);
|
|
96
|
-
if (exitStatus !== undefined) {
|
|
97
|
-
return null;
|
|
89
|
+
}
|
|
90
|
+
// --- Input Hook ---
|
|
91
|
+
useInput((input, key) => {
|
|
92
|
+
const userInput = inkInputToUserInput(input, key);
|
|
93
|
+
if (userInput === undefined) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const intent = userInputToIntent(userInput, inputState);
|
|
97
|
+
if (intent === undefined) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const effectResult = intentToEffect(intent, state);
|
|
101
|
+
if (effectResult === undefined) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
executeEffect(effectResult);
|
|
105
|
+
});
|
|
106
|
+
// --- Exit Logic ---
|
|
107
|
+
const { exit } = useApp();
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
if (exitStatus === undefined) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (exitStatus !== '') {
|
|
113
|
+
onError?.(new Error(exitStatus));
|
|
98
114
|
}
|
|
99
|
-
|
|
100
|
-
|
|
115
|
+
exit();
|
|
116
|
+
}, [exitStatus, exit, onError]);
|
|
117
|
+
if (exitStatus !== undefined) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
// --- JSX ---
|
|
121
|
+
return _jsxs(Box, {
|
|
122
|
+
flexDirection: 'column',
|
|
123
|
+
height: terminalRows,
|
|
124
|
+
children: [
|
|
125
|
+
_jsx(Box, {
|
|
126
|
+
flexDirection: 'column',
|
|
127
|
+
flexGrow: 1,
|
|
128
|
+
flexShrink: 1,
|
|
129
|
+
children:
|
|
130
|
+
view.rows.length === 0
|
|
131
|
+
? _jsx(Text, { dimColor: true, children: 'Directory is empty.' })
|
|
132
|
+
: view.rows.map((row) =>
|
|
133
|
+
_jsx(ViewRowComponent, { row: row }, row.id),
|
|
134
|
+
),
|
|
135
|
+
}),
|
|
136
|
+
_jsx(StatusBar, { inputState: inputState }),
|
|
137
|
+
],
|
|
138
|
+
});
|
|
101
139
|
}
|
package/dist/ui/App2.d.ts
CHANGED
|
@@ -2,10 +2,15 @@ import { State } from 'dirvi-lib';
|
|
|
2
2
|
import type { UnixAbsolutePath } from 'dirvi-lib';
|
|
3
3
|
import { EventMessage } from '../domain/event-message.js';
|
|
4
4
|
export type AppProps = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
cwdAddress: UnixAbsolutePath;
|
|
6
|
+
initialState: State;
|
|
7
|
+
print?: (message: EventMessage) => void;
|
|
8
|
+
onError?: (error: Error) => void;
|
|
9
9
|
};
|
|
10
|
-
export declare function App2({
|
|
11
|
-
|
|
10
|
+
export declare function App2({
|
|
11
|
+
cwdAddress,
|
|
12
|
+
initialState,
|
|
13
|
+
print,
|
|
14
|
+
onError,
|
|
15
|
+
}: AppProps): import('react').JSX.Element | null;
|
|
16
|
+
//# sourceMappingURL=App2.d.ts.map
|
package/dist/ui/App2.js
CHANGED
|
@@ -1,96 +1,107 @@
|
|
|
1
|
-
import { jsx as _jsx } from
|
|
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
4
|
import { useEffect, useReducer, useRef, useState } from 'react';
|
|
5
5
|
import { Cursor, getDirLazyEntries } from 'dirvi-lib';
|
|
6
6
|
import { useView } from './hooks/useView.js';
|
|
7
7
|
import { reducer } from '../application/reducer.js';
|
|
8
|
-
import { userInputToInputResult
|
|
8
|
+
import { userInputToInputResult } from '../infrastructure/input.js';
|
|
9
9
|
import { ViewRowComponent } from './components/ViewRowComponent.js';
|
|
10
10
|
export function App2({ cwdAddress, initialState, print, onError }) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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;
|
|
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(
|
|
26
|
+
input,
|
|
27
|
+
key,
|
|
28
|
+
state,
|
|
29
|
+
pendingInput.current,
|
|
30
|
+
);
|
|
31
|
+
if (result === undefined) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (result === 'z') {
|
|
35
|
+
pendingInput.current = result;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
pendingInput.current = undefined;
|
|
39
|
+
const action = result;
|
|
40
|
+
// Contents of `updateDir` change meaning at this boundary:
|
|
41
|
+
if (action.kind === 'updateDir') {
|
|
42
|
+
// If the entry at the path is directory with no entries loaded:
|
|
43
|
+
if (action.entries === undefined) {
|
|
44
|
+
const path = Cursor.getPath(state.cursor);
|
|
45
|
+
if (path === undefined) {
|
|
46
|
+
return undefined;
|
|
67
47
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
48
|
+
const address = join(cwdAddress, ...path);
|
|
49
|
+
void getDirLazyEntries(address)
|
|
50
|
+
.then((entries) => {
|
|
51
|
+
dispatch({
|
|
52
|
+
kind: 'updateDir',
|
|
53
|
+
path: path,
|
|
54
|
+
entries,
|
|
72
55
|
});
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
56
|
+
})
|
|
57
|
+
.catch((error) => {
|
|
58
|
+
const appError =
|
|
59
|
+
error instanceof Error ? error : new Error(String(error));
|
|
60
|
+
onError?.(appError);
|
|
61
|
+
setExitStatus(`Unable to open directory: ${appError.message}`);
|
|
62
|
+
});
|
|
63
|
+
} else {
|
|
64
|
+
// Otherwise need to wipe the entries:
|
|
65
|
+
dispatch({
|
|
66
|
+
kind: 'updateDir',
|
|
67
|
+
path: action.path,
|
|
68
|
+
entries: undefined,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (action.kind === 'printFile') {
|
|
74
|
+
print?.({
|
|
75
|
+
type: 'file',
|
|
76
|
+
path: action.path,
|
|
77
|
+
});
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (action.kind === 'exit') {
|
|
81
|
+
setExitStatus(action.exitMessage);
|
|
82
|
+
}
|
|
83
|
+
dispatch(action);
|
|
84
|
+
});
|
|
85
|
+
// --- Exit Logic ---
|
|
86
|
+
const { exit } = useApp();
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
if (exitStatus === undefined) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (exitStatus !== '') {
|
|
92
|
+
onError?.(new Error(exitStatus));
|
|
93
93
|
}
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
exit();
|
|
95
|
+
}, [exitStatus, exit, onError]);
|
|
96
|
+
if (exitStatus !== undefined) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
// --- JSX ---
|
|
100
|
+
return _jsx(Box, {
|
|
101
|
+
flexDirection: 'column',
|
|
102
|
+
children:
|
|
103
|
+
view.rows.length === 0
|
|
104
|
+
? _jsx(Text, { dimColor: true, children: 'Directory is empty.' })
|
|
105
|
+
: view.rows.map((row) => _jsx(ViewRowComponent, { row: row }, row.id)),
|
|
106
|
+
});
|
|
96
107
|
}
|
package/dist/ui/AppShell.d.ts
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
cwdAddress: UnixAbsolutePath;
|
|
8
|
+
initialState: State | EmptyView;
|
|
9
|
+
print?: (message: EventMessage) => void;
|
|
10
|
+
onError?: (error: Error) => void;
|
|
11
11
|
};
|
|
12
|
-
export declare function AppShell({
|
|
13
|
-
|
|
12
|
+
export declare function AppShell({
|
|
13
|
+
cwdAddress,
|
|
14
|
+
initialState,
|
|
15
|
+
print,
|
|
16
|
+
onError,
|
|
17
|
+
}: ShellAppProps): import('react').JSX.Element;
|
|
18
|
+
//# sourceMappingURL=AppShell.d.ts.map
|
package/dist/ui/AppShell.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { jsx as _jsx } from
|
|
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, initialState, print, onError
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
export function AppShell({ cwdAddress, initialState, print, onError }) {
|
|
5
|
+
if (initialState.cursor === undefined) {
|
|
6
|
+
return _jsx(Text, { dimColor: true, children: 'Directory is empty.' });
|
|
7
|
+
}
|
|
8
|
+
return _jsx(App, {
|
|
9
|
+
cwdAddress: cwdAddress,
|
|
10
|
+
initialState: initialState,
|
|
11
|
+
print: print,
|
|
12
|
+
onError: onError,
|
|
13
|
+
});
|
|
9
14
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { Cursor } from 'dirvi-lib';
|
|
2
2
|
import { DisplayRow } from 'dirvi-lib';
|
|
3
|
-
declare function DirEntries({
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
3
|
+
declare function DirEntries({
|
|
4
|
+
rows,
|
|
5
|
+
cursor,
|
|
6
|
+
}: {
|
|
7
|
+
rows: DisplayRow[];
|
|
8
|
+
cursor: Cursor;
|
|
9
|
+
}): import('react').JSX.Element;
|
|
7
10
|
export default DirEntries;
|
|
8
|
-
//# sourceMappingURL=DirEntries.d.ts.map
|
|
11
|
+
//# sourceMappingURL=DirEntries.d.ts.map
|
|
@@ -1,39 +1,64 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment } from
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { Box, Text, useWindowSize } from 'ink';
|
|
3
3
|
import { Cursor } from 'dirvi-lib';
|
|
4
4
|
import { UnixEntryComponent as UnixEntryComponent } from './UnixEntryComponent.js';
|
|
5
5
|
import { useRef } from 'react';
|
|
6
6
|
function DirEntries({ rows, cursor }) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
7
|
+
const scrollMargin = 3;
|
|
8
|
+
const { rows: terminalRows } = useWindowSize();
|
|
9
|
+
const viewportStartRef = useRef(0);
|
|
10
|
+
const cursorIndex = rows.findIndex((row) =>
|
|
11
|
+
Cursor.matchesDisplayRow(cursor, row),
|
|
12
|
+
);
|
|
13
|
+
const viewportHeight = Math.max(1, terminalRows);
|
|
14
|
+
const maximumViewportStart = Math.max(0, rows.length - viewportHeight);
|
|
15
|
+
let viewportStart = viewportStartRef.current;
|
|
16
|
+
if (cursorIndex >= 0) {
|
|
17
|
+
const firstVisibleCursorIndex = viewportStart + scrollMargin;
|
|
18
|
+
const lastVisibleCursorIndex =
|
|
19
|
+
viewportStart + viewportHeight - 1 - scrollMargin;
|
|
20
|
+
if (cursorIndex < firstVisibleCursorIndex) {
|
|
21
|
+
// Cursor moved above the visible area.
|
|
22
|
+
viewportStart = cursorIndex - scrollMargin;
|
|
23
|
+
} else if (cursorIndex > lastVisibleCursorIndex) {
|
|
24
|
+
// Cursor moved below the visible area.
|
|
25
|
+
viewportStart = cursorIndex - viewportHeight + 1 + scrollMargin;
|
|
25
26
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
27
|
+
}
|
|
28
|
+
viewportStart = Math.max(0, Math.min(viewportStart, maximumViewportStart));
|
|
29
|
+
viewportStartRef.current = viewportStart;
|
|
30
|
+
const visibleRows = rows.slice(viewportStart, viewportStart + viewportHeight);
|
|
31
|
+
return _jsx(_Fragment, {
|
|
32
|
+
children: visibleRows.map((row) => {
|
|
33
|
+
const selected = Cursor.matchesDisplayRow(cursor, row);
|
|
34
|
+
const indent = row.parentPath.length;
|
|
35
|
+
if (row.kind === 'fold') {
|
|
36
|
+
const key = `fold-${row.parentPath.join('/')}-${row.entryNames[0]}`;
|
|
37
|
+
return _jsx(
|
|
38
|
+
Box,
|
|
39
|
+
{
|
|
40
|
+
paddingLeft: indent * 2,
|
|
41
|
+
children: _jsx(Text, {
|
|
42
|
+
inverse: selected,
|
|
43
|
+
dimColor: !selected,
|
|
44
|
+
children: '...',
|
|
45
|
+
}),
|
|
46
|
+
},
|
|
47
|
+
key,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
return _jsx(
|
|
51
|
+
Box,
|
|
52
|
+
{
|
|
53
|
+
paddingLeft: indent * 2,
|
|
54
|
+
children: _jsx(UnixEntryComponent, {
|
|
55
|
+
entry: row.entry,
|
|
56
|
+
selected: selected,
|
|
57
|
+
}),
|
|
58
|
+
},
|
|
59
|
+
[...row.parentPath, row.entry.name].join('/'),
|
|
60
|
+
);
|
|
61
|
+
}),
|
|
62
|
+
});
|
|
38
63
|
}
|
|
39
64
|
export default DirEntries;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { InputState } from 'dirvi-lib';
|
|
2
|
+
export declare const STATUS_BAR_HEIGHT = 1;
|
|
3
|
+
type StatusBarProps = {
|
|
4
|
+
inputState: InputState;
|
|
5
|
+
};
|
|
6
|
+
export declare function StatusBar({
|
|
7
|
+
inputState,
|
|
8
|
+
}: StatusBarProps): import('react').JSX.Element;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=StatusBar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatusBar.d.ts","sourceRoot":"","sources":["../../../src/ui/components/StatusBar.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC,KAAK,cAAc,GAAG;IACpB,UAAU,EAAE,UAAU,CAAA;CACvB,CAAC;AAEF,wBAAgB,SAAS,CAAC,EAAE,UAAU,EAAE,EAAE,cAAc,+BAyBvD"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
export const STATUS_BAR_HEIGHT = 1;
|
|
4
|
+
export function StatusBar({ inputState }) {
|
|
5
|
+
const inputMode = inputState.inputMode;
|
|
6
|
+
return _jsxs(Box, {
|
|
7
|
+
width: '100%',
|
|
8
|
+
height: STATUS_BAR_HEIGHT,
|
|
9
|
+
flexDirection: 'row',
|
|
10
|
+
justifyContent: 'space-between',
|
|
11
|
+
flexShrink: 0,
|
|
12
|
+
backgroundColor: 'gray',
|
|
13
|
+
children: [
|
|
14
|
+
_jsx(Box, {
|
|
15
|
+
flexShrink: 1,
|
|
16
|
+
children: _jsx(Text, {
|
|
17
|
+
color: 'black',
|
|
18
|
+
wrap: 'truncate-end',
|
|
19
|
+
children: inputMode === 'command' ? inputState.commandLine : '',
|
|
20
|
+
}),
|
|
21
|
+
}),
|
|
22
|
+
_jsx(Box, {
|
|
23
|
+
flexShrink: 1,
|
|
24
|
+
children: _jsx(Text, {
|
|
25
|
+
color: 'black',
|
|
26
|
+
wrap: 'truncate-start',
|
|
27
|
+
children: inputMode === 'normal' ? inputState.normalBuffer : '',
|
|
28
|
+
}),
|
|
29
|
+
}),
|
|
30
|
+
],
|
|
31
|
+
});
|
|
32
|
+
}
|