@mak-98/dirvi-cli 0.7.0 → 0.8.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/effect-to-action.d.ts +3 -3
- package/dist/application/effect-to-action.d.ts.map +1 -1
- package/dist/application/effect-to-action.js +14 -25
- package/dist/application/reducer-action.d.ts +2 -3
- package/dist/application/reducer-action.d.ts.map +1 -1
- package/dist/application/reducer.d.ts +1 -1
- package/dist/application/reducer.d.ts.map +1 -1
- package/dist/application/reducer.js +14 -9
- package/dist/domain/app-api.d.ts +15 -11
- package/dist/domain/app-api.d.ts.map +1 -1
- package/dist/domain/app-api.js +4 -8
- package/dist/domain/posix-tree-node.d.ts +5 -5
- package/dist/domain/posix-tree-node.d.ts.map +1 -1
- package/dist/domain/posix-tree-node.js +10 -6
- package/dist/index.js +1 -1
- package/dist/infrastructure/load-posix-app-api.d.ts +8 -7
- package/dist/infrastructure/load-posix-app-api.d.ts.map +1 -1
- package/dist/infrastructure/load-posix-app-api.js +35 -33
- package/dist/ui/App.d.ts +1 -1
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +11 -5
- package/dist/ui/LoadingApp.d.ts.map +1 -1
- package/dist/ui/LoadingApp.js +9 -22
- package/dist/ui/components/StatusBar.d.ts +2 -2
- package/dist/ui/components/StatusBar.d.ts.map +1 -1
- package/dist/ui/components/ViewRowComponent.d.ts.map +1 -1
- package/dist/ui/components/ViewRowComponent.js +3 -6
- package/dist/ui/hooks/useView.d.ts +2 -3
- package/dist/ui/hooks/useView.d.ts.map +1 -1
- package/dist/ui/hooks/useView.js +3 -3
- package/dist/ui/view.d.ts +12 -7
- package/dist/ui/view.d.ts.map +1 -1
- package/dist/ui/view.js +40 -64
- package/package.json +5 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ReducerAction } from './reducer-action.js';
|
|
2
2
|
import { SerializableKey, TreeNode, TreeNodeApi } from 'dirvi-lib/dist/tree-surfer/tree-node/tree-node.types.js';
|
|
3
|
-
import { CursorApi, EffectAction,
|
|
4
|
-
export type EffectToAction<Id extends SerializableKey,
|
|
5
|
-
export declare function createEffectToAction<Id extends SerializableKey,
|
|
3
|
+
import { CursorApi, EffectAction, NavBranch, NavNodeApi, State } from 'dirvi-lib';
|
|
4
|
+
export type EffectToAction<Id extends SerializableKey, Node extends TreeNode<Id, Node>> = (effectAction: EffectAction<Id, Node>, navigation: NavBranch<Id>, state: State<Id, Node>) => ReducerAction<Id, Node> | undefined;
|
|
5
|
+
export declare function createEffectToAction<Id extends SerializableKey, Node extends TreeNode<Id, Node>>(treeNodeApi: TreeNodeApi<Id, Node>, cursorApi: CursorApi<Id>, navNodeApi: NavNodeApi<Id, Node>): EffectToAction<Id, Node>;
|
|
6
6
|
//# sourceMappingURL=effect-to-action.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"effect-to-action.d.ts","sourceRoot":"","sources":["../../src/application/effect-to-action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EACL,eAAe,EACf,QAAQ,EACR,WAAW,EACZ,MAAM,yDAAyD,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"effect-to-action.d.ts","sourceRoot":"","sources":["../../src/application/effect-to-action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EACL,eAAe,EACf,QAAQ,EACR,WAAW,EACZ,MAAM,yDAAyD,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAW,UAAU,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAE3F,MAAM,MAAM,cAAc,CACxB,EAAE,SAAS,eAAe,EAC1B,IAAI,SAAS,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,IAC7B,CACF,YAAY,EAAE,YAAY,CAAC,EAAE,EAAE,IAAI,CAAC,EACpC,UAAU,EAAE,SAAS,CAAC,EAAE,CAAC,EACzB,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,KACnB,aAAa,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC;AAEzC,wBAAgB,oBAAoB,CAClC,EAAE,SAAS,eAAe,EAC1B,IAAI,SAAS,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,EAE/B,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,IAAI,CAAC,EAClC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC,EACxB,UAAU,EAAE,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,GAC/B,cAAc,CAAC,EAAE,EAAE,IAAI,CAAC,CAgG1B"}
|
|
@@ -26,7 +26,11 @@ export function createEffectToAction(treeNodeApi, cursorApi, navNodeApi) {
|
|
|
26
26
|
entries: effectAction.entries,
|
|
27
27
|
};
|
|
28
28
|
case 'navigateToParent': {
|
|
29
|
-
const
|
|
29
|
+
const navNode = navigation.children;
|
|
30
|
+
if (navNode === null) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
const cursor = navNodeApi.parentCursor(navNode, state.cursor);
|
|
30
34
|
return cursor === undefined
|
|
31
35
|
? undefined
|
|
32
36
|
: {
|
|
@@ -35,12 +39,7 @@ export function createEffectToAction(treeNodeApi, cursorApi, navNodeApi) {
|
|
|
35
39
|
};
|
|
36
40
|
}
|
|
37
41
|
case 'fold': {
|
|
38
|
-
if (state.cursor.
|
|
39
|
-
return undefined;
|
|
40
|
-
}
|
|
41
|
-
const path = [...state.cursor.parentPath, state.cursor.entryId];
|
|
42
|
-
const entry = treeNodeApi.getAtPath(state.buffer, path, (node) => node);
|
|
43
|
-
if (entry === undefined) {
|
|
42
|
+
if (state.cursor.length === 0) {
|
|
44
43
|
return undefined;
|
|
45
44
|
}
|
|
46
45
|
const cursor = navNodeApi.cursorAfterFold(navigation, state.cursor);
|
|
@@ -49,36 +48,26 @@ export function createEffectToAction(treeNodeApi, cursorApi, navNodeApi) {
|
|
|
49
48
|
}
|
|
50
49
|
return {
|
|
51
50
|
kind: 'fold',
|
|
52
|
-
|
|
53
|
-
entry,
|
|
51
|
+
path: state.cursor,
|
|
54
52
|
cursor,
|
|
55
53
|
};
|
|
56
54
|
}
|
|
57
55
|
case 'unfold': {
|
|
58
|
-
|
|
56
|
+
const currentPath = cursorApi.getPath(state.cursor);
|
|
57
|
+
const navNode = navigation.children;
|
|
58
|
+
if (navNode === null) {
|
|
59
59
|
return undefined;
|
|
60
60
|
}
|
|
61
|
-
const node = navNodeApi.getNodeAtPath(
|
|
62
|
-
|
|
63
|
-
]);
|
|
64
|
-
if (node === undefined || node.foldedEntries.length === 0) {
|
|
61
|
+
const node = navNodeApi.getNodeAtPath(navNode, currentPath);
|
|
62
|
+
if (node === undefined || node.folded?.entries.length === 0) {
|
|
65
63
|
return undefined;
|
|
66
64
|
}
|
|
67
|
-
const firstFoldedEntry = node.foldedEntries[0];
|
|
68
65
|
return {
|
|
69
66
|
kind: 'unfold',
|
|
70
|
-
|
|
71
|
-
cursor:
|
|
72
|
-
kind: 'entry',
|
|
73
|
-
parentPath: state.cursor.parentPath,
|
|
74
|
-
entryId: firstFoldedEntry.id,
|
|
75
|
-
},
|
|
67
|
+
path: currentPath,
|
|
68
|
+
cursor: state.cursor,
|
|
76
69
|
};
|
|
77
70
|
}
|
|
78
|
-
case 'toggleFold':
|
|
79
|
-
return effectToAction(state.cursor.kind === 'fold'
|
|
80
|
-
? { effectActionType: 'unfold' }
|
|
81
|
-
: { effectActionType: 'fold' }, navigation, state);
|
|
82
71
|
}
|
|
83
72
|
}
|
|
84
73
|
return effectToAction;
|
|
@@ -12,12 +12,11 @@ export type ReducerAction<Id extends SerializableKey, BufferNode extends TreeNod
|
|
|
12
12
|
newState: State<Id, BufferNode>;
|
|
13
13
|
} | {
|
|
14
14
|
kind: 'fold';
|
|
15
|
-
|
|
16
|
-
entry: BufferNode;
|
|
15
|
+
path: readonly Id[];
|
|
17
16
|
cursor: Cursor<Id>;
|
|
18
17
|
} | {
|
|
19
18
|
kind: 'unfold';
|
|
20
|
-
|
|
19
|
+
path: Id[];
|
|
21
20
|
cursor: Cursor<Id>;
|
|
22
21
|
};
|
|
23
22
|
//# sourceMappingURL=reducer-action.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reducer-action.d.ts","sourceRoot":"","sources":["../../src/application/reducer-action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1E,MAAM,MAAM,aAAa,CACvB,EAAE,SAAS,eAAe,EAC1B,UAAU,SAAS,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC,IAEzC;IACE,IAAI,EAAE,cAAc,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;CACpB,GACD;IACE,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,EAAE,EAAE,CAAC;IACX,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;CAC9B,GACD;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IAChC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;CACjC,GACD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,
|
|
1
|
+
{"version":3,"file":"reducer-action.d.ts","sourceRoot":"","sources":["../../src/application/reducer-action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1E,MAAM,MAAM,aAAa,CACvB,EAAE,SAAS,eAAe,EAC1B,UAAU,SAAS,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC,IAEzC;IACE,IAAI,EAAE,cAAc,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;CACpB,GACD;IACE,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,EAAE,EAAE,CAAC;IACX,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;CAC9B,GACD;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IAChC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;CACjC,GACD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;CACpB,GACD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,EAAE,EAAE,CAAC;IACX,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;CACpB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FoldNodeService, SerializableKey, State, TreeNode, TreeNodeApi } from 'dirvi-lib';
|
|
2
2
|
import { ReducerAction } from './reducer-action.js';
|
|
3
3
|
export type Reducer<Id extends SerializableKey, BufferNode extends TreeNode<Id, BufferNode>> = (state: State<Id, BufferNode>, action: ReducerAction<Id, BufferNode>) => State<Id, BufferNode>;
|
|
4
|
-
export declare function createReducer<Id extends SerializableKey,
|
|
4
|
+
export declare function createReducer<Id extends SerializableKey, Node extends TreeNode<Id, Node>>(treeNodeApi: TreeNodeApi<Id, Node>, foldNodeService: FoldNodeService<Id>): Reducer<Id, Node>;
|
|
5
5
|
//# sourceMappingURL=reducer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../../src/application/reducer.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../../src/application/reducer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,eAAe,EACf,KAAK,EACL,QAAQ,EACR,WAAW,EACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,MAAM,OAAO,CACjB,EAAE,SAAS,eAAe,EAC1B,UAAU,SAAS,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC,IACzC,CACF,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,UAAU,CAAC,EAC5B,MAAM,EAAE,aAAa,CAAC,EAAE,EAAE,UAAU,CAAC,KAClC,KAAK,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;AAE3B,wBAAgB,aAAa,CAC3B,EAAE,SAAS,eAAe,EAC1B,IAAI,SAAS,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,EAE/B,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,IAAI,CAAC,EAClC,eAAe,EAAE,eAAe,CAAC,EAAE,CAAC,GACnC,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC,CAkGnB"}
|
|
@@ -7,7 +7,7 @@ export function createReducer(treeNodeApi, foldNodeService) {
|
|
|
7
7
|
cursor: action.cursor,
|
|
8
8
|
};
|
|
9
9
|
case 'updateBranch':
|
|
10
|
-
const
|
|
10
|
+
const root = treeNodeApi.modifyAtPath(state.root, action.path, (node) => {
|
|
11
11
|
// A branch update cannot turn a leaf into a branch.
|
|
12
12
|
if (!treeNodeApi.isBranch(node)) {
|
|
13
13
|
return undefined;
|
|
@@ -17,12 +17,12 @@ export function createReducer(treeNodeApi, foldNodeService) {
|
|
|
17
17
|
children: action.entries,
|
|
18
18
|
};
|
|
19
19
|
});
|
|
20
|
-
if (
|
|
20
|
+
if (root === undefined) {
|
|
21
21
|
return state;
|
|
22
22
|
}
|
|
23
23
|
return {
|
|
24
24
|
...state,
|
|
25
|
-
|
|
25
|
+
root,
|
|
26
26
|
};
|
|
27
27
|
case 'setState': {
|
|
28
28
|
// A newer update has already been applied.
|
|
@@ -34,32 +34,37 @@ export function createReducer(treeNodeApi, foldNodeService) {
|
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
case 'fold': {
|
|
37
|
-
const
|
|
37
|
+
const entryId = action.path.at(-1);
|
|
38
|
+
if (entryId === undefined) {
|
|
39
|
+
return state;
|
|
40
|
+
}
|
|
41
|
+
const parentPath = action.path.slice(0, -1);
|
|
42
|
+
const foldRoot = foldNodeService.addFoldedEntryAtPath(state.foldRoot, parentPath, entryId);
|
|
38
43
|
/*
|
|
39
44
|
* addFoldedEntryAtPath creates missing fold paths, so this should
|
|
40
45
|
* normally never be undefined. Preserve the existing state if it is.
|
|
41
46
|
*/
|
|
42
|
-
if (
|
|
47
|
+
if (foldRoot === undefined) {
|
|
43
48
|
return state;
|
|
44
49
|
}
|
|
45
50
|
return {
|
|
46
51
|
...state,
|
|
47
|
-
|
|
52
|
+
foldRoot,
|
|
48
53
|
cursor: action.cursor,
|
|
49
54
|
};
|
|
50
55
|
}
|
|
51
56
|
case 'unfold': {
|
|
52
|
-
const
|
|
57
|
+
const foldRoot = foldNodeService.clearFoldedEntriesAtPath(state.foldRoot, action.path);
|
|
53
58
|
/*
|
|
54
59
|
* Unlike adding a fold, clearing only operates on an existing path.
|
|
55
60
|
* An undefined result means that the fold path no longer exists.
|
|
56
61
|
*/
|
|
57
|
-
if (
|
|
62
|
+
if (foldRoot === undefined) {
|
|
58
63
|
return state;
|
|
59
64
|
}
|
|
60
65
|
return {
|
|
61
66
|
...state,
|
|
62
|
-
|
|
67
|
+
foldRoot,
|
|
63
68
|
cursor: action.cursor,
|
|
64
69
|
};
|
|
65
70
|
}
|
package/dist/domain/app-api.d.ts
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
|
-
import { CursorApi, FoldNodeApi, FoldNodeService, NavNodeApi, SerializableKey, State, StateApi, TreeNode, TreeNodeApi } from 'dirvi-lib';
|
|
1
|
+
import { BranchTreeNode, CursorApi, FoldNodeApi, FoldNodeService, NavNodeApi, SerializableKey, State, StateApi, TreeNode, TreeNodeApi } from 'dirvi-lib';
|
|
2
2
|
import { ViewApi } from './view-api.js';
|
|
3
|
-
export type AppApi<Id extends SerializableKey,
|
|
3
|
+
export type AppApi<Id extends SerializableKey, Node extends TreeNode<Id, Node>, ViewKey = string> = {
|
|
4
|
+
/**
|
|
5
|
+
* Name used to distinguish the app, e.g. 'posix' for POSIX directory app.
|
|
6
|
+
*/
|
|
4
7
|
appId: string;
|
|
5
8
|
/**
|
|
6
|
-
* Name
|
|
9
|
+
* Name to distinguish app instance.
|
|
7
10
|
*/
|
|
8
11
|
name: string;
|
|
12
|
+
rootId: Id;
|
|
9
13
|
/**
|
|
10
|
-
* Message displayed when
|
|
11
|
-
* to display.
|
|
14
|
+
* Message displayed when there are no root children.
|
|
12
15
|
*/
|
|
13
|
-
|
|
16
|
+
emptyRootMessage: string;
|
|
14
17
|
/**
|
|
15
18
|
* Loads the children of the branch at `path`.
|
|
16
19
|
*
|
|
17
20
|
* The empty path represents the root branch.
|
|
18
21
|
*/
|
|
19
|
-
loadBranches: (path: Id[]) => Promise<
|
|
22
|
+
loadBranches: (path: Id[]) => Promise<Node[]>;
|
|
23
|
+
createRoot: () => Promise<Node & BranchTreeNode<Id, Node>>;
|
|
20
24
|
/**
|
|
21
25
|
* Subscribes to external data changes that require the tree state
|
|
22
26
|
* to be loaded again.
|
|
@@ -24,7 +28,7 @@ export type AppApi<Id extends SerializableKey, BufferNode extends TreeNode<Id, B
|
|
|
24
28
|
* Returns an unsubscribe function.
|
|
25
29
|
*/
|
|
26
30
|
subscribeToResync: (listener: () => void) => () => void;
|
|
27
|
-
treeNodeApi: TreeNodeApi<Id,
|
|
31
|
+
treeNodeApi: TreeNodeApi<Id, Node>;
|
|
28
32
|
/**
|
|
29
33
|
* Structural fold-tree traversal and immutable path updates.
|
|
30
34
|
*/
|
|
@@ -35,10 +39,10 @@ export type AppApi<Id extends SerializableKey, BufferNode extends TreeNode<Id, B
|
|
|
35
39
|
*/
|
|
36
40
|
foldNodeService: FoldNodeService<Id>;
|
|
37
41
|
cursorApi: CursorApi<Id>;
|
|
38
|
-
stateApi: StateApi<Id,
|
|
39
|
-
navNodeApi: NavNodeApi<Id,
|
|
42
|
+
stateApi: StateApi<Id, Node>;
|
|
43
|
+
navNodeApi: NavNodeApi<Id, Node>;
|
|
40
44
|
viewKey: ViewKey;
|
|
41
|
-
viewApi: ViewApi<State<Id,
|
|
45
|
+
viewApi: ViewApi<State<Id, Node>, ViewKey>;
|
|
42
46
|
};
|
|
43
47
|
export declare function createAppApis<Id extends SerializableKey, BufferNode extends TreeNode<Id, BufferNode>>(): {
|
|
44
48
|
treeNodeApi: TreeNodeApi<Id, BufferNode>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-api.d.ts","sourceRoot":"","sources":["../../src/domain/app-api.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"app-api.d.ts","sourceRoot":"","sources":["../../src/domain/app-api.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EAMd,SAAS,EAET,WAAW,EACX,eAAe,EACf,UAAU,EACV,eAAe,EACf,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,WAAW,EACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,MAAM,MAAM,MAAM,CAChB,EAAE,SAAS,eAAe,EAC1B,IAAI,SAAS,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,EAC/B,OAAO,GAAG,MAAM,IACd;IACF;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb,MAAM,EAAE,EAAE,CAAC;IAEX;;OAEG;IACH,gBAAgB,EAAE,MAAM,CAAC;IAEzB;;;;OAIG;IACH,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9C,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,GAAG,cAAc,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;IAE3D;;;;;OAKG;IACH,iBAAiB,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;IAExD,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAEnC;;OAEG;IACH,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;IAE7B;;;OAGG;IACH,eAAe,EAAE,eAAe,CAAC,EAAE,CAAC,CAAC;IAErC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;IAEzB,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAE7B,UAAU,EAAE,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAEjC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;CAC5C,CAAC;AAEF,wBAAgB,aAAa,CAC3B,EAAE,SAAS,eAAe,EAC1B,UAAU,SAAS,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC,KACxC;IACH,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IACzC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;IAC7B,eAAe,EAAE,eAAe,CAAC,EAAE,CAAC,CAAC;IACrC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;IACzB,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IACnC,UAAU,EAAE,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;CACxC,CA4BA"}
|
package/dist/domain/app-api.js
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import { createCursorApi,
|
|
1
|
+
import { createCursorApi, createFoldNodeService, createNavNodeApi, createStateApi, createTreeNodeApi, } from 'dirvi-lib';
|
|
2
2
|
export function createAppApis() {
|
|
3
3
|
const treeNodeApi = createTreeNodeApi();
|
|
4
|
-
const foldNodeApi =
|
|
5
|
-
const foldNodeService = createFoldNodeService(foldNodeApi
|
|
6
|
-
id,
|
|
7
|
-
children: [],
|
|
8
|
-
folds: new Set(),
|
|
9
|
-
}));
|
|
4
|
+
const foldNodeApi = createTreeNodeApi();
|
|
5
|
+
const foldNodeService = createFoldNodeService(foldNodeApi);
|
|
10
6
|
const cursorApi = createCursorApi();
|
|
11
|
-
const navNodeApi = createNavNodeApi(treeNodeApi,
|
|
7
|
+
const navNodeApi = createNavNodeApi(treeNodeApi, foldNodeService, cursorApi);
|
|
12
8
|
const stateApi = createStateApi(treeNodeApi, foldNodeApi, cursorApi, navNodeApi);
|
|
13
9
|
return {
|
|
14
10
|
treeNodeApi,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { UnixPath } from './unix-path.js';
|
|
3
|
-
import { Cursor, FoldNode,
|
|
3
|
+
import { BranchTreeNode, Cursor, FoldNode, NavNode, State } from 'dirvi-lib';
|
|
4
4
|
export declare const PosixNameSchema: z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>, z.ZodString>;
|
|
5
5
|
export type PosixName = z.output<typeof PosixNameSchema>;
|
|
6
6
|
export declare const PosixTreeNodeSchema: z.ZodType<PosixTreeNode>;
|
|
7
|
+
export declare const PosixBranchTreeNodeSchema: z.ZodType<PosixTreeNode & BranchTreeNode<PosixName, PosixTreeNode>>;
|
|
7
8
|
export type PosixTreeNode = {
|
|
8
9
|
kind: 'file';
|
|
9
10
|
id: PosixName;
|
|
@@ -18,14 +19,13 @@ export type PosixTreeNode = {
|
|
|
18
19
|
};
|
|
19
20
|
export declare const PosixTreeNodeApi: import("dirvi-lib").TreeNodeApi<string, PosixTreeNode>;
|
|
20
21
|
export declare const PosixFoldNodeSchema: z.ZodType<PosixFoldNode>;
|
|
21
|
-
export declare const PosixFoldNodeRootSchema: z.ZodType<PosixFoldNodeRoot>;
|
|
22
22
|
export type PosixFoldNode = FoldNode<PosixName>;
|
|
23
|
-
export
|
|
24
|
-
export declare const
|
|
23
|
+
export declare const PosixFoldNodeApi: import("dirvi-lib").TreeNodeApi<string, FoldNode<string>>;
|
|
24
|
+
export declare const PosixFoldNodeService: import("dirvi-lib").FoldNodeService<string>;
|
|
25
25
|
export declare const PosixCursorSchema: z.ZodType<PosixCursor>;
|
|
26
26
|
export type PosixCursor = Cursor<PosixName>;
|
|
27
27
|
export declare const PosixCursorApi: import("dirvi-lib").CursorApi<string>;
|
|
28
|
-
export type PosixNavNode = NavNode<PosixName
|
|
28
|
+
export type PosixNavNode = NavNode<PosixName>;
|
|
29
29
|
export declare const PosixNavApi: import("dirvi-lib").NavNodeApi<string, PosixTreeNode>;
|
|
30
30
|
export declare const PosixStateSchema: z.ZodType<PosixState>;
|
|
31
31
|
export type PosixState = State<PosixName, PosixTreeNode>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"posix-tree-node.d.ts","sourceRoot":"","sources":["../../src/domain/posix-tree-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAkB,MAAM,gBAAgB,CAAC;AAC1D,OAAO,
|
|
1
|
+
{"version":3,"file":"posix-tree-node.d.ts","sourceRoot":"","sources":["../../src/domain/posix-tree-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAkB,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EACL,cAAc,EASd,MAAM,EACN,QAAQ,EACR,OAAO,EAEP,KAAK,EAEN,MAAM,WAAW,CAAC;AAQnB,eAAO,MAAM,eAAe,yEAU3B,CAAC;AAGF,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,eAAe,CAAC,CAAC;AAUzD,eAAO,MAAM,mBAAmB,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAsBvD,CAAC;AAEH,eAAO,MAAM,yBAAyB,EAAE,CAAC,CAAC,OAAO,CAC/C,aAAa,GAAG,cAAc,CAAC,SAAS,EAAE,aAAa,CAAC,CAOzD,CAAC;AAGF,MAAM,MAAM,aAAa,GACrB;IACE,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,SAAS,CAAC;CACf,GACD;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,EAAE,EAAE,SAAS,CAAC;IACd,MAAM,EAAE,QAAQ,CAAC;CAClB,GACD;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,EAAE,EAAE,SAAS,CAAC;IACd,QAAQ,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;CAClC,CAAC;AAQN,eAAO,MAAM,gBAAgB,wDAAgD,CAAC;AAM9E,eAAO,MAAM,mBAAmB,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAAkB,CAAC;AAE5E,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;AAEhD,eAAO,MAAM,gBAAgB,2DAAsD,CAAC;AAEpF,eAAO,MAAM,oBAAoB,6CAAqD,CAAA;AAKtF,eAAO,MAAM,iBAAiB,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAChB,CAAC;AAEtC,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;AAC5C,eAAO,MAAM,cAAc,uCAA+B,CAAC;AAE3D,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAC9C,eAAO,MAAM,WAAW,uDAIvB,CAAC;AAKF,eAAO,MAAM,gBAAgB,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAIlD,CAAC;AAGF,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AAGzD,eAAO,MAAM,aAAa,qDAKzB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { UnixPathSchema } from './unix-path.js';
|
|
3
|
-
import { createCursorApi, createCursorSchema,
|
|
3
|
+
import { createCursorApi, createCursorSchema, createFoldNodeSchemas, createFoldNodeService, createNavNodeApi, createStateApi, createStateSchema, createTreeNodeApi, createTreeNodeSchemas, serializableKeySchema, } from 'dirvi-lib';
|
|
4
4
|
// --- PosixName extends PropertyKey ---
|
|
5
5
|
// Schema
|
|
6
6
|
export const PosixNameSchema = serializableKeySchema.pipe(z
|
|
@@ -32,22 +32,26 @@ export const PosixTreeNodeSchema = z.lazy(() => {
|
|
|
32
32
|
}),
|
|
33
33
|
]);
|
|
34
34
|
});
|
|
35
|
+
export const PosixBranchTreeNodeSchema = PosixTreeNodeSchema.refine((node) => 'children' in node, {
|
|
36
|
+
message: 'The state root must be a branch node.',
|
|
37
|
+
});
|
|
35
38
|
// API
|
|
36
39
|
export const PosixTreeNodeApi = createTreeNodeApi();
|
|
37
40
|
// --- PosixFoldNode ---
|
|
38
41
|
// Schema
|
|
39
|
-
const
|
|
42
|
+
const foldNodeSchema = createFoldNodeSchemas(PosixNameSchema);
|
|
40
43
|
export const PosixFoldNodeSchema = foldNodeSchema;
|
|
41
|
-
export const PosixFoldNodeRootSchema = foldNodeRootSchema;
|
|
42
44
|
// API
|
|
43
|
-
export const PosixFoldNodeApi =
|
|
45
|
+
export const PosixFoldNodeApi = createTreeNodeApi();
|
|
46
|
+
// Service
|
|
47
|
+
export const PosixFoldNodeService = createFoldNodeService(PosixFoldNodeApi);
|
|
44
48
|
// --- PosixCursor ---
|
|
45
49
|
// Schema
|
|
46
50
|
export const PosixCursorSchema = createCursorSchema(PosixNameSchema);
|
|
47
51
|
export const PosixCursorApi = createCursorApi();
|
|
48
|
-
export const PosixNavApi = createNavNodeApi(PosixTreeNodeApi,
|
|
52
|
+
export const PosixNavApi = createNavNodeApi(PosixTreeNodeApi, PosixFoldNodeService, PosixCursorApi);
|
|
49
53
|
// --- PosixState ---
|
|
50
54
|
// Schema
|
|
51
|
-
export const PosixStateSchema = createStateSchema(
|
|
55
|
+
export const PosixStateSchema = createStateSchema(PosixBranchTreeNodeSchema, PosixFoldNodeSchema, PosixCursorSchema);
|
|
52
56
|
// API
|
|
53
57
|
export const PosixStateApi = createStateApi(PosixTreeNodeApi, PosixFoldNodeApi, PosixCursorApi, PosixNavApi);
|
package/dist/index.js
CHANGED
|
@@ -28,7 +28,7 @@ process.on('exit', restoreTerminal);
|
|
|
28
28
|
program
|
|
29
29
|
.name('direx')
|
|
30
30
|
.description('View and manage directories.')
|
|
31
|
-
.version('0.7.
|
|
31
|
+
.version('0.7.1')
|
|
32
32
|
.helpOption('--help')
|
|
33
33
|
.option('-d, --directory <path>', 'Directory to browse')
|
|
34
34
|
.action(async () => {
|
|
@@ -4,14 +4,15 @@ import { UnixAbsolutePath } from '../domain/unix-path.js';
|
|
|
4
4
|
export type StoredPosixFoldNode = {
|
|
5
5
|
id: PosixName;
|
|
6
6
|
children: StoredPosixFoldNode[];
|
|
7
|
-
|
|
7
|
+
foldedChildren: StoredPosixFoldNode[];
|
|
8
8
|
};
|
|
9
|
-
export type
|
|
10
|
-
|
|
11
|
-
folds: PosixName[];
|
|
12
|
-
};
|
|
13
|
-
export type StoredPosixState = Omit<PosixState, 'foldNode'> & {
|
|
14
|
-
foldNode: StoredPosixFoldNodeRoot;
|
|
9
|
+
export type StoredPosixState = Omit<PosixState, 'foldRoot'> & {
|
|
10
|
+
foldRoot: StoredPosixFoldNode;
|
|
15
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* Creates the AppApi for the POSIX app.
|
|
14
|
+
*
|
|
15
|
+
* @param directory - optional directory path for loading the app not at the cwd.
|
|
16
|
+
*/
|
|
16
17
|
export declare function loadPosixAppApi(directory?: string): AppApi<PosixName, PosixTreeNode, UnixAbsolutePath>;
|
|
17
18
|
//# sourceMappingURL=load-posix-app-api.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-posix-app-api.d.ts","sourceRoot":"","sources":["../../src/infrastructure/load-posix-app-api.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAiB,MAAM,sBAAsB,CAAC;AAM7D,OAAO,EAIL,SAAS,EAET,UAAU,EACV,aAAa,EAEd,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"load-posix-app-api.d.ts","sourceRoot":"","sources":["../../src/infrastructure/load-posix-app-api.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAiB,MAAM,sBAAsB,CAAC;AAM7D,OAAO,EAIL,SAAS,EAET,UAAU,EACV,aAAa,EAEd,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAiB1D,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,SAAS,CAAC;IACd,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,cAAc,EAAE,mBAAmB,EAAE,CAAC;CACvC,CAAC;AAoBF,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG;IAC5D,QAAQ,EAAE,mBAAmB,CAAC;CAC/B,CAAC;AA0CF;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAAC,SAAS,EAAE,aAAa,EAAE,gBAAgB,CAAC,CAoCpD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { join } from 'node:path';
|
|
1
|
+
import { basename, join } from 'node:path';
|
|
2
2
|
import { watch } from 'node:fs';
|
|
3
3
|
import { createAppApis } from '../domain/app-api.js';
|
|
4
4
|
import { getUnixAbsPath } from './get-unix-abs-path.js';
|
|
@@ -6,89 +6,91 @@ import { getDirEntries } from './get-dir-entries.js';
|
|
|
6
6
|
import envPaths from 'env-paths';
|
|
7
7
|
import { createFileViewApi } from './create-file-view-api.js';
|
|
8
8
|
import { createHash } from 'node:crypto';
|
|
9
|
-
import { PosixCursorSchema, PosixNameSchema,
|
|
9
|
+
import { PosixBranchTreeNodeSchema, PosixCursorSchema, PosixNameSchema, } from '../domain/posix-tree-node.js';
|
|
10
10
|
import { z } from 'zod';
|
|
11
11
|
// ---*--- App Data ---*---
|
|
12
12
|
// Paths for app data:
|
|
13
|
-
const
|
|
14
|
-
const posixAppDataDirectory = join(
|
|
13
|
+
const environmentPaths = envPaths('dirvi');
|
|
14
|
+
const posixAppDataDirectory = join(environmentPaths.data, 'apps', 'posix');
|
|
15
15
|
const posixAppViewsDirectory = join(posixAppDataDirectory, 'views');
|
|
16
16
|
// Helpers for saving app data:
|
|
17
|
-
// The key for the Posix app instance is just the directory working in.
|
|
18
17
|
function encodeKey(key) {
|
|
19
18
|
return createHash('sha256').update(key).digest('hex');
|
|
20
19
|
}
|
|
21
20
|
const StoredPosixFoldNodeSchema = z.lazy(() => z.object({
|
|
22
21
|
id: PosixNameSchema,
|
|
23
22
|
children: z.array(StoredPosixFoldNodeSchema),
|
|
24
|
-
|
|
23
|
+
foldedChildren: z.array(StoredPosixFoldNodeSchema),
|
|
25
24
|
}));
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const StoredPosixStateSchema = z.object({
|
|
31
|
-
buffer: z.array(PosixTreeNodeSchema),
|
|
32
|
-
foldNode: StoredPosixFoldNodeRootSchema,
|
|
25
|
+
const StoredPosixStateSchema = z
|
|
26
|
+
.object({
|
|
27
|
+
root: PosixBranchTreeNodeSchema,
|
|
28
|
+
foldRoot: StoredPosixFoldNodeSchema,
|
|
33
29
|
cursor: PosixCursorSchema,
|
|
30
|
+
})
|
|
31
|
+
.refine((state) => state.root.id !== state.foldRoot.id, {
|
|
32
|
+
message: 'The fold root ID must match the tree root ID.',
|
|
34
33
|
});
|
|
35
34
|
// ---*--- Codec ---*---
|
|
36
35
|
function encodePosixFoldNode(node) {
|
|
37
36
|
return {
|
|
38
37
|
id: node.id,
|
|
39
38
|
children: node.children.map(encodePosixFoldNode),
|
|
40
|
-
|
|
39
|
+
foldedChildren: [...node.foldedChildren],
|
|
41
40
|
};
|
|
42
41
|
}
|
|
43
42
|
function decodePosixFoldNode(node) {
|
|
44
43
|
return {
|
|
45
44
|
id: node.id,
|
|
46
45
|
children: node.children.map(decodePosixFoldNode),
|
|
47
|
-
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
function encodePosixFoldNodeRoot(root) {
|
|
51
|
-
return {
|
|
52
|
-
children: root.children.map(encodePosixFoldNode),
|
|
53
|
-
folds: [...root.folds],
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
function decodePosixFoldNodeRoot(root) {
|
|
57
|
-
return {
|
|
58
|
-
children: root.children.map(decodePosixFoldNode),
|
|
59
|
-
folds: new Set(root.folds),
|
|
46
|
+
foldedChildren: node.foldedChildren.map(decodePosixFoldNode),
|
|
60
47
|
};
|
|
61
48
|
}
|
|
62
49
|
const posixStateCodec = {
|
|
63
50
|
schema: StoredPosixStateSchema,
|
|
64
51
|
encode(state) {
|
|
65
52
|
return {
|
|
66
|
-
|
|
67
|
-
|
|
53
|
+
root: state.root,
|
|
54
|
+
foldRoot: encodePosixFoldNode(state.foldRoot),
|
|
68
55
|
cursor: state.cursor,
|
|
69
56
|
};
|
|
70
57
|
},
|
|
71
58
|
decode(state) {
|
|
72
59
|
return {
|
|
73
|
-
|
|
74
|
-
|
|
60
|
+
root: state.root,
|
|
61
|
+
foldRoot: decodePosixFoldNode(state.foldRoot),
|
|
75
62
|
cursor: state.cursor,
|
|
76
63
|
};
|
|
77
64
|
},
|
|
78
65
|
};
|
|
79
66
|
// --- Creating Posix App API ---
|
|
67
|
+
/**
|
|
68
|
+
* Creates the AppApi for the POSIX app.
|
|
69
|
+
*
|
|
70
|
+
* @param directory - optional directory path for loading the app not at the cwd.
|
|
71
|
+
*/
|
|
80
72
|
export function loadPosixAppApi(directory) {
|
|
81
73
|
const unixAbsPath = getUnixAbsPath(directory ?? process.cwd());
|
|
74
|
+
const rootId = PosixNameSchema.parse(basename(unixAbsPath));
|
|
82
75
|
const apis = createAppApis();
|
|
83
76
|
return {
|
|
84
77
|
appId: 'posix',
|
|
85
|
-
name:
|
|
86
|
-
|
|
78
|
+
name: unixAbsPath,
|
|
79
|
+
rootId,
|
|
80
|
+
emptyRootMessage: 'The directory is empty.',
|
|
87
81
|
loadBranches: (path) => {
|
|
88
82
|
const address = join(unixAbsPath, ...path);
|
|
89
83
|
return getDirEntries(address);
|
|
90
84
|
},
|
|
85
|
+
createRoot: async () => {
|
|
86
|
+
return {
|
|
87
|
+
id: rootId,
|
|
88
|
+
kind: 'directory',
|
|
89
|
+
children: null
|
|
90
|
+
};
|
|
91
|
+
},
|
|
91
92
|
subscribeToResync: createFsResyncSubscription(join(unixAbsPath)),
|
|
93
|
+
// The key for the Posix app instance is just the directory working in:
|
|
92
94
|
viewKey: unixAbsPath,
|
|
93
95
|
viewApi: createFileViewApi({
|
|
94
96
|
directory: posixAppViewsDirectory,
|
package/dist/ui/App.d.ts
CHANGED
|
@@ -12,6 +12,6 @@ type AppProps<Id extends SerializableKey, BufferNode extends TreeNode<Id, Buffer
|
|
|
12
12
|
clipboard?: (value: string) => void;
|
|
13
13
|
onError?: (error: Error) => void;
|
|
14
14
|
};
|
|
15
|
-
export declare function App<Id extends SerializableKey,
|
|
15
|
+
export declare function App<Id extends SerializableKey, Node extends TreeNode<Id, Node>, ViewKey = string>({ appApi, initialState, reducer, intentToEffect, effectToAction, stdout, clipboard, onError, }: AppProps<Id, Node, ViewKey>): import("react").JSX.Element | null;
|
|
16
16
|
export {};
|
|
17
17
|
//# 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":"AAGA,OAAO,EAGL,cAAc,EACd,eAAe,EACf,KAAK,EACL,QAAQ,EAET,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAGpE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAOpD,KAAK,QAAQ,CACX,EAAE,SAAS,eAAe,EAC1B,UAAU,SAAS,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC,EAC3C,OAAO,GAAG,MAAM,IACd;IACF,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACxC,YAAY,EAAE,KAAK,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IACpC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IACjC,cAAc,EAAE,cAAc,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IAC/C,cAAc,EAAE,cAAc,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IAC/C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF,wBAAgB,GAAG,CACjB,EAAE,SAAS,eAAe,EAC1B,
|
|
1
|
+
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/ui/App.tsx"],"names":[],"mappings":"AAGA,OAAO,EAGL,cAAc,EACd,eAAe,EACf,KAAK,EACL,QAAQ,EAET,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAGpE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAOpD,KAAK,QAAQ,CACX,EAAE,SAAS,eAAe,EAC1B,UAAU,SAAS,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC,EAC3C,OAAO,GAAG,MAAM,IACd;IACF,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACxC,YAAY,EAAE,KAAK,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IACpC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IACjC,cAAc,EAAE,cAAc,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IAC/C,cAAc,EAAE,cAAc,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IAC/C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF,wBAAgB,GAAG,CACjB,EAAE,SAAS,eAAe,EAC1B,IAAI,SAAS,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,EAC/B,OAAO,GAAG,MAAM,EAChB,EACA,MAAM,EACN,YAAY,EACZ,OAAO,EACP,cAAc,EACd,cAAc,EACd,MAAM,EACN,SAAS,EACT,OAAO,GACR,EAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,sCA4O7B"}
|
package/dist/ui/App.js
CHANGED
|
@@ -14,16 +14,15 @@ export function App({ appApi, initialState, reducer, intentToEffect, effectToAct
|
|
|
14
14
|
// Give `subscribeToResync` callback a way to see current state:
|
|
15
15
|
const stateRef = useRef(state);
|
|
16
16
|
stateRef.current = state;
|
|
17
|
-
const
|
|
17
|
+
const navEntry = useMemo(() => appApi.navNodeApi.from(state.root, state.foldRoot), [appApi.navNodeApi, state.root, state.foldRoot]);
|
|
18
18
|
const [inputState, setInputState] = useState({
|
|
19
19
|
inputMode: 'normal',
|
|
20
20
|
normalBuffer: '',
|
|
21
21
|
});
|
|
22
22
|
const { rows: terminalRows } = useWindowSize();
|
|
23
|
-
const view = useView(
|
|
23
|
+
const view = useView(navEntry, state, appApi.navNodeApi, appApi.cursorApi, terminalRows);
|
|
24
24
|
const [exitStatus, setExitStatus] = useState();
|
|
25
|
-
// Subscribe to directory watcher, do not
|
|
26
|
-
// resubscribe on every state change.
|
|
25
|
+
// Subscribe to directory watcher, do not resubscribe on every state change.
|
|
27
26
|
useEffect(() => {
|
|
28
27
|
let active = true;
|
|
29
28
|
const unsubscribe = appApi.subscribeToResync(() => {
|
|
@@ -56,7 +55,7 @@ export function App({ appApi, initialState, reducer, intentToEffect, effectToAct
|
|
|
56
55
|
}
|
|
57
56
|
switch (effect.effectType) {
|
|
58
57
|
case 'dispatchEffectAction':
|
|
59
|
-
const action = effectToAction(effect.action,
|
|
58
|
+
const action = effectToAction(effect.action, navEntry, state);
|
|
60
59
|
if (action === undefined) {
|
|
61
60
|
return;
|
|
62
61
|
}
|
|
@@ -86,7 +85,14 @@ export function App({ appApi, initialState, reducer, intentToEffect, effectToAct
|
|
|
86
85
|
});
|
|
87
86
|
return;
|
|
88
87
|
}
|
|
88
|
+
case 'peekFold':
|
|
89
|
+
// TODO: Need a peek state to know what to display
|
|
90
|
+
return;
|
|
89
91
|
case 'emitVisibleLeavesPaths':
|
|
92
|
+
const navigation = navEntry.children;
|
|
93
|
+
if (navigation === null) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
90
96
|
const visibleLeavesPaths = appApi.navNodeApi.visibleLeavesPaths(navigation);
|
|
91
97
|
stdout?.(JSON.stringify({
|
|
92
98
|
type: 'displayed-leaves-paths',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoadingApp.d.ts","sourceRoot":"","sources":["../../src/ui/LoadingApp.tsx"],"names":[],"mappings":"AAGA,OAAO,EAEL,eAAe,EAEf,QAAQ,EACT,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAI9C,KAAK,eAAe,CAClB,EAAE,SAAS,eAAe,EAC1B,UAAU,SAAS,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC,EAC3C,OAAO,GAAG,MAAM,IACd;IACF,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACxC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC,CAAC;
|
|
1
|
+
{"version":3,"file":"LoadingApp.d.ts","sourceRoot":"","sources":["../../src/ui/LoadingApp.tsx"],"names":[],"mappings":"AAGA,OAAO,EAEL,eAAe,EAEf,QAAQ,EACT,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAI9C,KAAK,eAAe,CAClB,EAAE,SAAS,eAAe,EAC1B,UAAU,SAAS,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC,EAC3C,OAAO,GAAG,MAAM,IACd;IACF,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACxC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF,wBAAgB,UAAU,CACxB,EAAE,SAAS,eAAe,EAC1B,UAAU,SAAS,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC,EAC3C,OAAO,GAAG,MAAM,EAChB,EACA,MAAM,EACN,MAAM,EACN,SAAS,EACT,OAAO,GACR,EAAE,eAAe,CAAC,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,+BA4F1C"}
|
package/dist/ui/LoadingApp.js
CHANGED
|
@@ -5,37 +5,24 @@ import { createIntentToEffect, } from 'dirvi-lib';
|
|
|
5
5
|
import { App } from './App.js';
|
|
6
6
|
import { createReducer } from '../application/reducer.js';
|
|
7
7
|
import { createEffectToAction } from '../application/effect-to-action.js';
|
|
8
|
-
function createInitialState(rootBranches, createEmptyFoldRoot) {
|
|
9
|
-
if (rootBranches.length === 0) {
|
|
10
|
-
throw new Error('createInitialState cannot create a state for an empty forest');
|
|
11
|
-
}
|
|
12
|
-
return {
|
|
13
|
-
buffer: rootBranches,
|
|
14
|
-
foldNode: createEmptyFoldRoot(),
|
|
15
|
-
cursor: {
|
|
16
|
-
kind: 'entry',
|
|
17
|
-
parentPath: [],
|
|
18
|
-
entryId: rootBranches[0].id,
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
8
|
export function LoadingApp({ appApi, stdout, clipboard, onError, }) {
|
|
23
9
|
const [initialState, setInitialState] = useState();
|
|
24
10
|
const [empty, setEmpty] = useState(false);
|
|
25
11
|
const [error, setError] = useState();
|
|
12
|
+
// Loading and setting initial state.
|
|
26
13
|
useEffect(() => {
|
|
27
14
|
let mounted = true;
|
|
28
15
|
appApi
|
|
29
|
-
.
|
|
30
|
-
.then((
|
|
16
|
+
.createRoot()
|
|
17
|
+
.then((root) => {
|
|
31
18
|
if (!mounted) {
|
|
32
19
|
return;
|
|
33
20
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
21
|
+
setInitialState({
|
|
22
|
+
root,
|
|
23
|
+
foldRoot: appApi.foldNodeService.createEmptyNode(appApi.rootId),
|
|
24
|
+
cursor: [],
|
|
25
|
+
});
|
|
39
26
|
})
|
|
40
27
|
.catch((cause) => {
|
|
41
28
|
const nextError = cause instanceof Error ? cause : new Error(String(cause));
|
|
@@ -58,7 +45,7 @@ export function LoadingApp({ appApi, stdout, clipboard, onError, }) {
|
|
|
58
45
|
return _jsx(Text, { color: "red", children: error.message });
|
|
59
46
|
}
|
|
60
47
|
if (empty) {
|
|
61
|
-
return _jsx(Text, { dimColor: true, children: appApi.
|
|
48
|
+
return _jsx(Text, { dimColor: true, children: appApi.emptyRootMessage });
|
|
62
49
|
}
|
|
63
50
|
if (initialState === undefined) {
|
|
64
51
|
return _jsx(Text, { dimColor: true, children: "Loading." });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InputModeState } from 'dirvi-lib';
|
|
2
2
|
export declare const STATUS_BAR_HEIGHT = 1;
|
|
3
3
|
type StatusBarProps = {
|
|
4
|
-
inputState:
|
|
4
|
+
inputState: InputModeState;
|
|
5
5
|
};
|
|
6
6
|
export declare function StatusBar({ inputState }: StatusBarProps): import("react").JSX.Element;
|
|
7
7
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusBar.d.ts","sourceRoot":"","sources":["../../../src/ui/components/StatusBar.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"StatusBar.d.ts","sourceRoot":"","sources":["../../../src/ui/components/StatusBar.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC,KAAK,cAAc,GAAG;IACpB,UAAU,EAAE,cAAc,CAAC;CAC5B,CAAC;AAEF,wBAAgB,SAAS,CAAC,EAAE,UAAU,EAAE,EAAE,cAAc,+BAyBvD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ViewRowComponent.d.ts","sourceRoot":"","sources":["../../../src/ui/components/ViewRowComponent.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,wBAAgB,gBAAgB,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,+
|
|
1
|
+
{"version":3,"file":"ViewRowComponent.d.ts","sourceRoot":"","sources":["../../../src/ui/components/ViewRowComponent.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,wBAAgB,gBAAgB,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,+BAwBzD"}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from 'ink';
|
|
3
3
|
export function ViewRowComponent({ row }) {
|
|
4
|
-
const prefix = '';
|
|
5
4
|
switch (row.type) {
|
|
6
5
|
case 'leaf':
|
|
7
|
-
return (_jsx(Box, { paddingLeft: row.indent * 2, children:
|
|
6
|
+
return (_jsx(Box, { paddingLeft: row.indent * 2, children: _jsx(Text, { inverse: row.cursor, children: row.content }) }));
|
|
8
7
|
case 'branch':
|
|
9
|
-
return (
|
|
10
|
-
case 'fold':
|
|
11
|
-
return (_jsx(Box, { paddingLeft: row.indent * 2, children: _jsxs(Text, { inverse: row.selected, dimColor: true, children: [prefix, row.content] }) }));
|
|
8
|
+
return (_jsxs(Box, { paddingLeft: row.indent * 2, children: [_jsx(Text, { inverse: row.cursor, color: "blue", children: row.content }), row.foldedCount > 0 && (_jsx(Text, { color: "gray", dimColor: true, children: ` … ${row.foldedCount} folded` }))] }));
|
|
12
9
|
}
|
|
13
10
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { CursorApi,
|
|
1
|
+
import { CursorApi, NavBranch, NavNodeApi, SerializableKey, State, TreeNode } from 'dirvi-lib';
|
|
2
2
|
import { View } from '../view.js';
|
|
3
|
-
export
|
|
4
|
-
export declare function useView<Id extends SerializableKey, BufferNode extends TreeNode<Id, BufferNode>>(navigation: NavNode<Id, BufferNode>, state: State<Id, BufferNode>, cursorApi: CursorApi<Id>, terminalRows: number): View;
|
|
3
|
+
export declare function useView<Id extends SerializableKey, Node extends TreeNode<Id, Node>>(navNode: NavBranch<Id>, state: State<Id, Node>, navNodeApi: NavNodeApi<Id, Node>, cursorApi: CursorApi<Id>, terminalRows: number): View;
|
|
5
4
|
//# sourceMappingURL=useView.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useView.d.ts","sourceRoot":"","sources":["../../../src/ui/hooks/useView.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,
|
|
1
|
+
{"version":3,"file":"useView.d.ts","sourceRoot":"","sources":["../../../src/ui/hooks/useView.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EAAE,SAAS,EACX,UAAU,EACnB,eAAe,EACf,KAAK,EACL,QAAQ,EACT,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,IAAI,EAAW,MAAM,YAAY,CAAC;AAM3C,wBAAgB,OAAO,CACrB,EAAE,SAAS,eAAe,EAC1B,IAAI,SAAS,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,EAE/B,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC,EACtB,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,EACtB,UAAU,EAAE,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,EAChC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC,EACxB,YAAY,EAAE,MAAM,GACnB,IAAI,CAyBN"}
|
package/dist/ui/hooks/useView.js
CHANGED
|
@@ -3,12 +3,12 @@ import { useRef } from 'react';
|
|
|
3
3
|
import { STATUS_BAR_HEIGHT } from '../components/StatusBar.js';
|
|
4
4
|
// Hooks that keeps Ref of the viewport's start, and returns View sliced to
|
|
5
5
|
// only the rows that should be visible.
|
|
6
|
-
export function useView(
|
|
6
|
+
export function useView(navNode, state, navNodeApi, cursorApi, terminalRows) {
|
|
7
7
|
const viewportStartRef = useRef(0);
|
|
8
8
|
const viewportHeight = Math.max(1, terminalRows - STATUS_BAR_HEIGHT);
|
|
9
|
-
const rows = View.createRows(
|
|
9
|
+
const rows = View.createRows(navNode, navNodeApi, state.cursor, cursorApi);
|
|
10
10
|
viewportStartRef.current = viewportStart(rows, viewportHeight, viewportStartRef.current);
|
|
11
|
-
return View.create(
|
|
11
|
+
return View.create(navNode, navNodeApi, state.cursor, cursorApi, viewportHeight, viewportStartRef.current);
|
|
12
12
|
}
|
|
13
13
|
function viewportStart(rows, viewportHeight, currentViewportStart) {
|
|
14
14
|
const scrollMargin = 3;
|
package/dist/ui/view.d.ts
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
import { CursorApi, SerializableKey, TreeNode } from 'dirvi-lib';
|
|
2
|
-
import { Cursor
|
|
3
|
-
|
|
4
|
-
export type ViewRow = {
|
|
1
|
+
import { CursorApi, NavBranch, NavNodeApi, SerializableKey, TreeNode } from 'dirvi-lib';
|
|
2
|
+
import { Cursor } from 'dirvi-lib';
|
|
3
|
+
type ViewRowBase = {
|
|
5
4
|
id: string;
|
|
6
5
|
indent: number;
|
|
7
6
|
selected: boolean;
|
|
8
7
|
cursor: boolean;
|
|
9
8
|
content: string;
|
|
10
|
-
type: ViewRowType;
|
|
11
9
|
};
|
|
10
|
+
export type ViewRow = (ViewRowBase & {
|
|
11
|
+
type: 'leaf';
|
|
12
|
+
}) | (ViewRowBase & {
|
|
13
|
+
type: 'branch';
|
|
14
|
+
foldedCount: number;
|
|
15
|
+
});
|
|
12
16
|
export type View = {
|
|
13
17
|
rows: ViewRow[];
|
|
14
18
|
};
|
|
15
19
|
export declare const View: {
|
|
16
|
-
createRows<Id extends SerializableKey,
|
|
17
|
-
create<Id extends SerializableKey,
|
|
20
|
+
createRows<Id extends SerializableKey, Node extends TreeNode<Id, Node>>(rootNode: NavBranch<Id>, navNodeApi: NavNodeApi<Id, Node>, cursor: Cursor<Id>, cursorApi: CursorApi<Id>): ViewRow[];
|
|
21
|
+
create<Id extends SerializableKey, Node extends TreeNode<Id, Node>>(rootNode: NavBranch<Id>, navNodeApi: NavNodeApi<Id, Node>, cursor: Cursor<Id>, cursorApi: CursorApi<Id>, viewportHeight: number, viewportStart: number): View;
|
|
18
22
|
};
|
|
23
|
+
export {};
|
|
19
24
|
//# sourceMappingURL=view.d.ts.map
|
package/dist/ui/view.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/ui/view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/ui/view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACxF,OAAO,EAAE,MAAM,EAAqB,MAAM,WAAW,CAAC;AAEtD,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,OAAO,GACf,CAAC,WAAW,GAAG;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,GACF,CAAC,WAAW,GAAG;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAAC;AAEP,MAAM,MAAM,IAAI,GAAG;IACjB,IAAI,EAAE,OAAO,EAAE,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,IAAI;eAEb,EAAE,SAAS,eAAe,EAC1B,IAAI,SAAS,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,YAErB,SAAS,CAAC,EAAE,CAAC,cACX,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,UACxB,MAAM,CAAC,EAAE,CAAC,aACP,SAAS,CAAC,EAAE,CAAC,GACvB,OAAO,EAAE;WAqBV,EAAE,SAAS,eAAe,EAC1B,IAAI,SAAS,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,YAErB,SAAS,CAAC,EAAE,CAAC,cACX,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,UACxB,MAAM,CAAC,EAAE,CAAC,aACP,SAAS,CAAC,EAAE,CAAC,kBACR,MAAM,iBACP,MAAM,GACpB,IAAI;CAOR,CAAC"}
|
package/dist/ui/view.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
import { isNavBranch } from 'dirvi-lib';
|
|
2
1
|
export const View = {
|
|
3
|
-
createRows(
|
|
4
|
-
|
|
2
|
+
createRows(rootNode, navNodeApi, cursor, cursorApi) {
|
|
3
|
+
const rootCursor = [];
|
|
4
|
+
const rootRow = viewRowForEntry(rootNode, null, cursorApi.equal(cursor, rootCursor), navNodeApi);
|
|
5
|
+
if (rootNode.children === null) {
|
|
6
|
+
return [rootRow];
|
|
7
|
+
}
|
|
8
|
+
return [
|
|
9
|
+
rootRow,
|
|
10
|
+
...viewRowsAtNode(rootNode.children, [], navNodeApi, cursor, cursorApi),
|
|
11
|
+
];
|
|
5
12
|
},
|
|
6
|
-
create(
|
|
7
|
-
const rows = View.createRows(
|
|
13
|
+
create(rootNode, navNodeApi, cursor, cursorApi, viewportHeight, viewportStart) {
|
|
14
|
+
const rows = View.createRows(rootNode, navNodeApi, cursor, cursorApi);
|
|
8
15
|
return {
|
|
9
16
|
rows: rows.slice(viewportStart, viewportStart + viewportHeight),
|
|
10
17
|
};
|
|
@@ -20,79 +27,48 @@ export const View = {
|
|
|
20
27
|
* [] root directory
|
|
21
28
|
* ['src'] root/src
|
|
22
29
|
* ['src', 'lib'] root/src/lib
|
|
23
|
-
*
|
|
24
|
-
* The function uses a depth-first, pre-order traversal:
|
|
25
|
-
*
|
|
26
|
-
* 1. Add an entry's row.
|
|
27
|
-
* 2. If the entry is an opened branch, recursively add its children.
|
|
28
|
-
* 3. After all visible entries, add the directory's fold row.
|
|
29
|
-
*
|
|
30
|
-
* This ordering is what makes the flat row list visually represent a tree.
|
|
31
30
|
*/
|
|
32
|
-
function viewRowsAtNode(node, parentPath, cursor, cursorApi) {
|
|
31
|
+
function viewRowsAtNode(node, parentPath, navNodeApi, cursor, cursorApi) {
|
|
33
32
|
const rows = [];
|
|
34
|
-
/*
|
|
35
|
-
* `node.entries` contains only the entries currently visible in this
|
|
36
|
-
* directory. Folded entries are kept separately in `node.foldedEntries`
|
|
37
|
-
* and are represented by one fold row added below.
|
|
38
|
-
*/
|
|
39
33
|
for (const entry of node.entries) {
|
|
40
|
-
const entryCursor =
|
|
41
|
-
kind: 'entry',
|
|
42
|
-
parentPath,
|
|
43
|
-
entryId: entry.id,
|
|
44
|
-
};
|
|
45
|
-
// If cursor at entry, needs to be rendered differently
|
|
34
|
+
const entryCursor = [...parentPath, entry.id];
|
|
46
35
|
const isCursor = cursorApi.equal(cursor, entryCursor);
|
|
47
|
-
|
|
48
|
-
rows.push(viewRowForEntry(entry, parentPath, isCursor));
|
|
36
|
+
rows.push(viewRowForEntry(entry, parentPath, isCursor, navNodeApi));
|
|
49
37
|
// Case where there's no branches
|
|
50
|
-
if (!
|
|
38
|
+
if (!navNodeApi.entryIsBranch(entry) || entry.children === null) {
|
|
51
39
|
continue;
|
|
52
40
|
}
|
|
53
|
-
rows.push(...viewRowsAtNode(entry.children, [...parentPath, entry.id], cursor, cursorApi));
|
|
54
|
-
}
|
|
55
|
-
/*
|
|
56
|
-
* Folded entries are not rendered individually. They are represented
|
|
57
|
-
* by one synthetic row placed after all visible entries and descendants
|
|
58
|
-
* of this directory.
|
|
59
|
-
*/
|
|
60
|
-
if (node.foldedEntries.length > 0) {
|
|
61
|
-
const foldCursor = {
|
|
62
|
-
kind: 'fold',
|
|
63
|
-
parentPath,
|
|
64
|
-
};
|
|
65
|
-
const isCursor = cursorApi.equal(cursor, foldCursor);
|
|
66
|
-
rows.push({
|
|
67
|
-
id: foldId(parentPath),
|
|
68
|
-
indent: parentPath.length,
|
|
69
|
-
selected: isCursor,
|
|
70
|
-
cursor: isCursor,
|
|
71
|
-
content: `⋯ ${node.foldedEntries.length} folded`,
|
|
72
|
-
type: 'fold',
|
|
73
|
-
});
|
|
41
|
+
rows.push(...viewRowsAtNode(entry.children, [...parentPath, entry.id], navNodeApi, cursor, cursorApi));
|
|
74
42
|
}
|
|
75
43
|
return rows;
|
|
76
44
|
}
|
|
77
|
-
function viewRowForEntry(entry, parentPath, cursor) {
|
|
45
|
+
function viewRowForEntry(entry, parentPath, cursor, navNodeApi) {
|
|
46
|
+
const id = entryId(parentPath ?? [], entry.id);
|
|
47
|
+
const indent = parentPath ? parentPath.length + 1 : 0;
|
|
48
|
+
const selected = false;
|
|
49
|
+
if (navNodeApi.entryIsBranch(entry)) {
|
|
50
|
+
const foldedCount = entry.children === null || entry.children.folded === null
|
|
51
|
+
? 0
|
|
52
|
+
: entry.children.folded.entries.length;
|
|
53
|
+
return {
|
|
54
|
+
id,
|
|
55
|
+
indent,
|
|
56
|
+
selected,
|
|
57
|
+
cursor,
|
|
58
|
+
content: `${String(entry.id)}/`,
|
|
59
|
+
type: 'branch',
|
|
60
|
+
foldedCount,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
78
63
|
return {
|
|
79
|
-
id
|
|
80
|
-
indent
|
|
81
|
-
selected
|
|
64
|
+
id,
|
|
65
|
+
indent,
|
|
66
|
+
selected,
|
|
82
67
|
cursor,
|
|
83
|
-
content:
|
|
84
|
-
type:
|
|
68
|
+
content: String(entry.id),
|
|
69
|
+
type: 'leaf',
|
|
85
70
|
};
|
|
86
71
|
}
|
|
87
72
|
function entryId(parentPath, entryName) {
|
|
88
73
|
return `entry:${JSON.stringify([...parentPath, entryName])}`;
|
|
89
74
|
}
|
|
90
|
-
function foldId(parentPath) {
|
|
91
|
-
return `fold:${JSON.stringify(parentPath)}`;
|
|
92
|
-
}
|
|
93
|
-
function content(entry) {
|
|
94
|
-
return isNavBranch(entry) ? `${String(entry.id)}/` : String(entry.id);
|
|
95
|
-
}
|
|
96
|
-
function type(entry) {
|
|
97
|
-
return isNavBranch(entry) ? 'branch' : 'leaf';
|
|
98
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mak-98/dirvi-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "A Vim-inspired TUI for browsing directories.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
],
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"commander": "^13.0.0",
|
|
16
|
-
"dirvi-lib": "0.
|
|
16
|
+
"dirvi-lib": "0.8.0",
|
|
17
17
|
"env-paths": "^4.0.0",
|
|
18
18
|
"ink": "^7.1.1",
|
|
19
19
|
"react": "^19.0.0",
|
|
@@ -31,6 +31,8 @@
|
|
|
31
31
|
"start": "node dist/index.js",
|
|
32
32
|
"typecheck": "tsc --noEmit",
|
|
33
33
|
"format": "prettier . --write",
|
|
34
|
-
"update-global": "npm install --global @mak-98/dirvi-cli@latest"
|
|
34
|
+
"update-global": "npm install --global @mak-98/dirvi-cli@latest",
|
|
35
|
+
"debug": "node --inspect=9229 --import=tsx src/index.tsx 2>/tmp/dirvi-debug.log",
|
|
36
|
+
"debug:watch": "tail -f /tmp/dirvi-debug.log"
|
|
35
37
|
}
|
|
36
38
|
}
|