dirvi-lib 0.10.0 → 0.11.0-beta.12
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/app/app-methods.d.ts +53 -0
- package/dist/app/app-methods.d.ts.map +1 -0
- package/dist/app/index.d.ts +1 -1
- package/dist/app/index.d.ts.map +1 -1
- package/dist/app/index.js +1 -1
- package/dist/app/reducer/effect-to-action.d.ts +2 -2
- package/dist/app/reducer/effect-to-action.d.ts.map +1 -1
- package/dist/app/reducer/effect-to-action.js +87 -32
- package/dist/app/reducer/reducer-action.d.ts +12 -6
- package/dist/app/reducer/reducer-action.d.ts.map +1 -1
- package/dist/app/reducer/reducer.d.ts +4 -2
- package/dist/app/reducer/reducer.d.ts.map +1 -1
- package/dist/app/reducer/reducer.js +106 -72
- package/dist/feedback/feedback.impl.d.ts.map +1 -1
- package/dist/feedback/feedback.types.d.ts +1 -1
- package/dist/feedback/feedback.types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/input/application/intent-to-effect.d.ts +2 -2
- package/dist/input/application/intent-to-effect.d.ts.map +1 -1
- package/dist/input/application/intent-to-effect.js +10 -11
- package/dist/input/application/parse-ex-command.d.ts +17 -0
- package/dist/input/application/parse-ex-command.d.ts.map +1 -0
- package/dist/input/application/{parse-command.js → parse-ex-command.js} +84 -54
- package/dist/input/application/parse-normal-command.d.ts +1 -1
- package/dist/input/application/parse-normal-command.d.ts.map +1 -1
- package/dist/input/domain/effect.d.ts +20 -9
- package/dist/input/domain/effect.d.ts.map +1 -1
- package/dist/state-and-nav/cursor.d.ts +89 -0
- package/dist/state-and-nav/cursor.d.ts.map +1 -0
- package/dist/state-and-nav/cursor.js +84 -0
- package/dist/{trees → state-and-nav}/fold-node/deprecated/fold-node.impl.d.ts +1 -1
- package/dist/state-and-nav/fold-node/deprecated/fold-node.impl.d.ts.map +1 -0
- package/dist/state-and-nav/fold-node/deprecated/fold-node.test.d.ts.map +1 -0
- package/dist/{trees → state-and-nav}/fold-node/deprecated/fold-node.test.js +2 -2
- package/dist/{trees → state-and-nav}/fold-node/deprecated/fold-node.types.d.ts +2 -2
- package/dist/state-and-nav/fold-node/deprecated/fold-node.types.d.ts.map +1 -0
- package/dist/{trees → state-and-nav}/fold-node/fold-node.impl.d.ts +3 -3
- package/dist/state-and-nav/fold-node/fold-node.impl.d.ts.map +1 -0
- package/dist/{trees → state-and-nav}/fold-node/fold-node.impl.js +2 -2
- package/dist/{trees → state-and-nav}/fold-node/fold-node.model.d.ts +1 -1
- package/dist/state-and-nav/fold-node/fold-node.model.d.ts.map +1 -0
- package/dist/{trees → state-and-nav}/fold-node/fold-node.types.d.ts +2 -2
- package/dist/state-and-nav/fold-node/fold-node.types.d.ts.map +1 -0
- package/dist/state-and-nav/fold-node/index.d.ts.map +1 -0
- package/dist/state-and-nav/index.d.ts +16 -0
- package/dist/state-and-nav/index.d.ts.map +1 -0
- package/dist/state-and-nav/index.js +6 -0
- package/dist/state-and-nav/nav/nav.ordered.impl.d.ts +12 -0
- package/dist/state-and-nav/nav/nav.ordered.impl.d.ts.map +1 -0
- package/dist/state-and-nav/nav/nav.ordered.impl.js +77 -0
- package/dist/state-and-nav/nav/nav.traversal.d.ts +11 -0
- package/dist/state-and-nav/nav/nav.traversal.d.ts.map +1 -0
- package/dist/state-and-nav/nav/nav.traversal.js +204 -0
- package/dist/{trees/nav-node/nav-node.types.d.ts → state-and-nav/nav/nav.types.d.ts} +37 -23
- package/dist/state-and-nav/nav/nav.types.d.ts.map +1 -0
- package/dist/state-and-nav/nav/nav.unordered.impl.d.ts +13 -0
- package/dist/state-and-nav/nav/nav.unordered.impl.d.ts.map +1 -0
- package/dist/state-and-nav/nav/nav.unordered.impl.js +77 -0
- package/dist/state-and-nav/state/state.impl.d.ts +9 -0
- package/dist/state-and-nav/state/state.impl.d.ts.map +1 -0
- package/dist/{trees → state-and-nav}/state/state.impl.js +62 -9
- package/dist/state-and-nav/state/state.schemas.d.ts +2 -0
- package/dist/state-and-nav/state/state.schemas.d.ts.map +1 -0
- package/dist/state-and-nav/state/state.schemas.js +39 -0
- package/dist/state-and-nav/state/state.types.d.ts +72 -0
- package/dist/state-and-nav/state/state.types.d.ts.map +1 -0
- package/dist/state-and-nav/tree/deprecated/tree-node.arb.d.ts.map +1 -0
- package/dist/state-and-nav/tree/deprecated/tree-node.arb.debug.test.d.ts.map +1 -0
- package/dist/state-and-nav/tree/deprecated/tree-node.impl.d.ts.map +1 -0
- package/dist/state-and-nav/tree/deprecated/tree-node.schemas.d.ts.map +1 -0
- package/dist/state-and-nav/tree/deprecated/tree-node.test.d.ts.map +1 -0
- package/dist/state-and-nav/tree/deprecated/tree-node.types.d.ts.map +1 -0
- package/dist/state-and-nav/tree/index.d.ts +7 -0
- package/dist/state-and-nav/tree/index.d.ts.map +1 -0
- package/dist/state-and-nav/tree/index.js +1 -0
- package/dist/state-and-nav/tree/tree-node.arb.d.ts +94 -0
- package/dist/state-and-nav/tree/tree-node.arb.d.ts.map +1 -0
- package/dist/state-and-nav/tree/tree-node.arb.debug.test.d.ts +2 -0
- package/dist/state-and-nav/tree/tree-node.arb.debug.test.d.ts.map +1 -0
- package/dist/state-and-nav/tree/tree-node.arb.debug.test.js +54 -0
- package/dist/state-and-nav/tree/tree-node.arb.js +188 -0
- package/dist/state-and-nav/tree/tree-node.model.d.ts +194 -0
- package/dist/state-and-nav/tree/tree-node.model.d.ts.map +1 -0
- package/dist/state-and-nav/tree/tree-node.model.js +110 -0
- package/dist/state-and-nav/tree/tree-node.test.d.ts +2 -0
- package/dist/state-and-nav/tree/tree-node.test.d.ts.map +1 -0
- package/dist/state-and-nav/tree/tree-node.test.js +234 -0
- package/dist/{trees/tree-node/tree-node.impl.d.ts → state-and-nav/tree/tree.impl.d.ts} +3 -3
- package/dist/state-and-nav/tree/tree.impl.d.ts.map +1 -0
- package/dist/{trees/tree-node/tree-node.impl.js → state-and-nav/tree/tree.impl.js} +20 -17
- package/dist/{trees/tree-node/tree-node.types.d.ts → state-and-nav/tree/tree.types.d.ts} +67 -47
- package/dist/state-and-nav/tree/tree.types.d.ts.map +1 -0
- package/dist/state-and-nav/tree/tree.types.js +1 -0
- package/package.json +4 -3
- package/dist/app/app-api.d.ts +0 -74
- package/dist/app/app-api.d.ts.map +0 -1
- package/dist/app/app-api.js +0 -11
- package/dist/input/application/parse-command.d.ts +0 -14
- package/dist/input/application/parse-command.d.ts.map +0 -1
- package/dist/trees/cursor.d.ts +0 -59
- package/dist/trees/cursor.d.ts.map +0 -1
- package/dist/trees/cursor.js +0 -55
- package/dist/trees/fold-node/deprecated/fold-node.impl.d.ts.map +0 -1
- package/dist/trees/fold-node/deprecated/fold-node.test.d.ts.map +0 -1
- package/dist/trees/fold-node/deprecated/fold-node.types.d.ts.map +0 -1
- package/dist/trees/fold-node/fold-node.impl.d.ts.map +0 -1
- package/dist/trees/fold-node/fold-node.model.d.ts.map +0 -1
- package/dist/trees/fold-node/fold-node.types.d.ts.map +0 -1
- package/dist/trees/fold-node/index.d.ts.map +0 -1
- package/dist/trees/index.d.ts +0 -9
- package/dist/trees/index.d.ts.map +0 -1
- package/dist/trees/index.js +0 -8
- package/dist/trees/nav-node/nav-node.impl.d.ts +0 -29
- package/dist/trees/nav-node/nav-node.impl.d.ts.map +0 -1
- package/dist/trees/nav-node/nav-node.impl.js +0 -223
- package/dist/trees/nav-node/nav-node.types.d.ts.map +0 -1
- package/dist/trees/state/state.impl.d.ts +0 -8
- package/dist/trees/state/state.impl.d.ts.map +0 -1
- package/dist/trees/state/state.schemas.d.ts +0 -25
- package/dist/trees/state/state.schemas.d.ts.map +0 -1
- package/dist/trees/state/state.schemas.js +0 -17
- package/dist/trees/state/state.types.d.ts +0 -36
- package/dist/trees/state/state.types.d.ts.map +0 -1
- package/dist/trees/tree-node/deprecated/tree-node.arb.d.ts.map +0 -1
- package/dist/trees/tree-node/deprecated/tree-node.arb.debug.test.d.ts.map +0 -1
- package/dist/trees/tree-node/deprecated/tree-node.impl.d.ts.map +0 -1
- package/dist/trees/tree-node/deprecated/tree-node.schemas.d.ts.map +0 -1
- package/dist/trees/tree-node/deprecated/tree-node.test.d.ts.map +0 -1
- package/dist/trees/tree-node/deprecated/tree-node.types.d.ts.map +0 -1
- package/dist/trees/tree-node/index.d.ts +0 -5
- package/dist/trees/tree-node/index.d.ts.map +0 -1
- package/dist/trees/tree-node/index.js +0 -2
- package/dist/trees/tree-node/tree-node.arb.d.ts +0 -104
- package/dist/trees/tree-node/tree-node.arb.d.ts.map +0 -1
- package/dist/trees/tree-node/tree-node.arb.js +0 -188
- package/dist/trees/tree-node/tree-node.impl.d.ts.map +0 -1
- package/dist/trees/tree-node/tree-node.model.d.ts +0 -78
- package/dist/trees/tree-node/tree-node.model.d.ts.map +0 -1
- package/dist/trees/tree-node/tree-node.model.js +0 -37
- package/dist/trees/tree-node/tree-node.types.d.ts.map +0 -1
- /package/dist/{trees/fold-node/deprecated/fold-node.types.js → app/app-methods.js} +0 -0
- /package/dist/{trees → state-and-nav}/fold-node/deprecated/fold-node.impl.js +0 -0
- /package/dist/{trees → state-and-nav}/fold-node/deprecated/fold-node.test.d.ts +0 -0
- /package/dist/{trees/fold-node → state-and-nav/fold-node/deprecated}/fold-node.types.js +0 -0
- /package/dist/{trees → state-and-nav}/fold-node/fold-node.model.js +0 -0
- /package/dist/{trees/nav-node/nav-node.types.js → state-and-nav/fold-node/fold-node.types.js} +0 -0
- /package/dist/{trees → state-and-nav}/fold-node/index.d.ts +0 -0
- /package/dist/{trees → state-and-nav}/fold-node/index.js +0 -0
- /package/dist/{trees/state/state.types.js → state-and-nav/nav/nav.types.js} +0 -0
- /package/dist/{trees/tree-node/deprecated/tree-node.types.js → state-and-nav/state/state.types.js} +0 -0
- /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.arb.d.ts +0 -0
- /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.arb.debug.test.d.ts +0 -0
- /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.arb.debug.test.js +0 -0
- /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.arb.js +0 -0
- /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.impl.d.ts +0 -0
- /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.impl.js +0 -0
- /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.schemas.d.ts +0 -0
- /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.schemas.js +0 -0
- /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.test.d.ts +0 -0
- /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.test.js +0 -0
- /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.types.d.ts +0 -0
- /package/dist/{trees/tree-node → state-and-nav/tree/deprecated}/tree-node.types.js +0 -0
|
@@ -1,53 +1,100 @@
|
|
|
1
|
-
function firstAvailableAdditionalFoldIndex(foldsApi,
|
|
1
|
+
function firstAvailableAdditionalFoldIndex(foldsApi, folds) {
|
|
2
2
|
let index = 1;
|
|
3
|
-
while (foldsApi.hasAtIndex(
|
|
3
|
+
while (foldsApi.hasAtIndex(folds, index)) {
|
|
4
4
|
index += 1;
|
|
5
5
|
}
|
|
6
6
|
return index;
|
|
7
7
|
}
|
|
8
|
-
export function createReducer(
|
|
8
|
+
export function createReducer(stateApi, navNodeApi) {
|
|
9
|
+
const { treeMethods, foldMethods, cursorMethods } = stateApi;
|
|
10
|
+
/**
|
|
11
|
+
* Preserve the cursor if its position remains navigable. Otherwise, move it
|
|
12
|
+
* to a fold marker containing its representative entry, or to the nearest
|
|
13
|
+
* visible ancestor.
|
|
14
|
+
*/
|
|
15
|
+
function reconcileCursor(state) {
|
|
16
|
+
const navigation = navNodeApi.from(stateApi.getRoot(state), stateApi.getFolds(state));
|
|
17
|
+
if (navigation === undefined || navigation.children === null) {
|
|
18
|
+
// StateApi guarantees that the root is a loaded branch.
|
|
19
|
+
throw new Error('Cannot navigate state: root is not a loaded branch.');
|
|
20
|
+
}
|
|
21
|
+
const cursor = stateApi.getCursor(state);
|
|
22
|
+
const positions = [
|
|
23
|
+
{ path: [] },
|
|
24
|
+
...navNodeApi.cursors(navigation.children),
|
|
25
|
+
];
|
|
26
|
+
if (positions.some((position) => cursorMethods.equal(position, cursor))) {
|
|
27
|
+
return state;
|
|
28
|
+
}
|
|
29
|
+
const path = cursorMethods.getPath(cursor);
|
|
30
|
+
while (path.length > 0) {
|
|
31
|
+
const entryId = path.at(-1);
|
|
32
|
+
if (entryId !== undefined) {
|
|
33
|
+
const parentPath = path.slice(0, -1);
|
|
34
|
+
const parent = navNodeApi.getNodeAtPath(navigation.children, parentPath);
|
|
35
|
+
const foldEntry = parent?.entries.find((entry) => navNodeApi.entryIsFold(entry) &&
|
|
36
|
+
entry.folded.some((foldedEntry) => !navNodeApi.entryIsFold(foldedEntry) &&
|
|
37
|
+
foldedEntry.id === entryId));
|
|
38
|
+
if (foldEntry !== undefined && navNodeApi.entryIsFold(foldEntry)) {
|
|
39
|
+
const firstEntry = foldEntry.folded.find((entry) => !navNodeApi.entryIsFold(entry));
|
|
40
|
+
if (firstEntry !== undefined && !navNodeApi.entryIsFold(firstEntry)) {
|
|
41
|
+
const foldCursor = {
|
|
42
|
+
parentPath,
|
|
43
|
+
firstId: firstEntry.id,
|
|
44
|
+
};
|
|
45
|
+
if (positions.some((position) => cursorMethods.equal(position, foldCursor))) {
|
|
46
|
+
return stateApi.update(state, { cursor: foldCursor }) ?? state;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const nodeCursor = { path: [...path] };
|
|
51
|
+
if (positions.some((position) => cursorMethods.equal(position, nodeCursor))) {
|
|
52
|
+
return stateApi.update(state, { cursor: nodeCursor }) ?? state;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
path.pop();
|
|
56
|
+
}
|
|
57
|
+
// The root cursor is always included in `positions`.
|
|
58
|
+
return stateApi.update(state, { cursor: { path: [] } }) ?? state;
|
|
59
|
+
}
|
|
60
|
+
function update(state, changes) {
|
|
61
|
+
const nextState = stateApi.update(state, changes);
|
|
62
|
+
return nextState === undefined ? state : reconcileCursor(nextState);
|
|
63
|
+
}
|
|
9
64
|
return (state, action) => {
|
|
10
65
|
switch (action.kind) {
|
|
11
66
|
case 'changeCursor':
|
|
12
|
-
return {
|
|
13
|
-
...state,
|
|
14
|
-
cursor: action.cursor,
|
|
15
|
-
};
|
|
67
|
+
return update(state, { cursor: action.cursor });
|
|
16
68
|
case 'updateBranch': {
|
|
17
|
-
const root =
|
|
69
|
+
const root = treeMethods.updateAtPath(stateApi.getRoot(state), action.path, (node) => {
|
|
18
70
|
/*
|
|
19
|
-
* Loading/unloading is a branch-only operation.
|
|
20
|
-
* structurally convert any node, but the
|
|
21
|
-
*
|
|
71
|
+
* Loading/unloading is a branch-only operation. TreeMethods can
|
|
72
|
+
* structurally convert any node, but the reducer must not turn a
|
|
73
|
+
* leaf into a branch.
|
|
22
74
|
*/
|
|
23
|
-
if (
|
|
75
|
+
if (treeMethods.kind(node) === 'leaf') {
|
|
24
76
|
return undefined;
|
|
25
77
|
}
|
|
26
78
|
if (action.entries === null) {
|
|
27
|
-
return
|
|
79
|
+
return treeMethods.toUnloadedBranch(node);
|
|
28
80
|
}
|
|
29
|
-
return
|
|
81
|
+
return treeMethods.withLoadedChildren(node, action.entries);
|
|
30
82
|
});
|
|
31
83
|
/*
|
|
32
84
|
* State requires its root to remain a loaded branch. In particular,
|
|
33
85
|
* refuse an accidental updateBranch with path [] and entries null.
|
|
34
86
|
*/
|
|
35
|
-
if (root === undefined ||
|
|
87
|
+
if (root === undefined || treeMethods.kind(root) !== 'loaded-branch') {
|
|
36
88
|
return state;
|
|
37
89
|
}
|
|
38
|
-
return {
|
|
39
|
-
...state,
|
|
40
|
-
root,
|
|
41
|
-
};
|
|
90
|
+
return update(state, { root });
|
|
42
91
|
}
|
|
43
92
|
case 'setState': {
|
|
44
93
|
// A newer update has already been applied.
|
|
45
94
|
if (state !== action.oldState) {
|
|
46
95
|
return state;
|
|
47
96
|
}
|
|
48
|
-
return
|
|
49
|
-
...action.newState,
|
|
50
|
-
};
|
|
97
|
+
return reconcileCursor(action.newState);
|
|
51
98
|
}
|
|
52
99
|
case 'addToFoldTree': {
|
|
53
100
|
const entryId = action.path.at(-1);
|
|
@@ -55,82 +102,69 @@ export function createReducer(treeNodeApi, foldsApi) {
|
|
|
55
102
|
return state;
|
|
56
103
|
}
|
|
57
104
|
const parentPath = action.path.slice(0, -1);
|
|
58
|
-
const folds =
|
|
105
|
+
const folds = foldMethods.hideEntryAtPath(stateApi.getFolds(state), action.foldTreeIndex, parentPath, entryId);
|
|
59
106
|
if (folds === undefined) {
|
|
60
107
|
return state;
|
|
61
108
|
}
|
|
62
|
-
return {
|
|
63
|
-
...state,
|
|
109
|
+
return update(state, {
|
|
64
110
|
folds,
|
|
65
111
|
cursor: action.cursor,
|
|
66
|
-
};
|
|
112
|
+
});
|
|
67
113
|
}
|
|
68
114
|
case 'removeFromFoldTree': {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
115
|
+
let folds = stateApi.getFolds(state);
|
|
116
|
+
if (action.entryIds === null) {
|
|
117
|
+
const nextFolds = foldMethods.showAllHiddenEntriesAtPath(folds, action.foldTreeIndex, action.path);
|
|
118
|
+
if (nextFolds === undefined) {
|
|
119
|
+
return state;
|
|
120
|
+
}
|
|
121
|
+
folds = nextFolds;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
for (const entryId of action.entryIds) {
|
|
125
|
+
const nextFolds = foldMethods.showEntryAtPath(folds, action.foldTreeIndex, action.path, entryId);
|
|
126
|
+
if (nextFolds === undefined) {
|
|
127
|
+
return state;
|
|
128
|
+
}
|
|
129
|
+
folds = nextFolds;
|
|
130
|
+
}
|
|
73
131
|
}
|
|
74
|
-
return {
|
|
75
|
-
...state,
|
|
132
|
+
return update(state, {
|
|
76
133
|
folds,
|
|
77
134
|
cursor: action.cursor,
|
|
78
|
-
};
|
|
135
|
+
});
|
|
79
136
|
}
|
|
80
137
|
case 'fold': {
|
|
81
|
-
const folds =
|
|
82
|
-
return folds === undefined
|
|
83
|
-
? state
|
|
84
|
-
: {
|
|
85
|
-
...state,
|
|
86
|
-
folds,
|
|
87
|
-
};
|
|
138
|
+
const folds = foldMethods.activateAtIndex(stateApi.getFolds(state), action.foldTreeIndex);
|
|
139
|
+
return folds === undefined ? state : update(state, { folds });
|
|
88
140
|
}
|
|
89
141
|
case 'unfold': {
|
|
90
|
-
const folds =
|
|
91
|
-
return folds === undefined
|
|
92
|
-
? state
|
|
93
|
-
: {
|
|
94
|
-
...state,
|
|
95
|
-
folds,
|
|
96
|
-
};
|
|
142
|
+
const folds = foldMethods.deactivateAtIndex(stateApi.getFolds(state), action.foldTreeIndex);
|
|
143
|
+
return folds === undefined ? state : update(state, { folds });
|
|
97
144
|
}
|
|
98
145
|
case 'toggleFold': {
|
|
99
|
-
const folds =
|
|
100
|
-
return folds === undefined
|
|
101
|
-
? state
|
|
102
|
-
: {
|
|
103
|
-
...state,
|
|
104
|
-
folds,
|
|
105
|
-
};
|
|
146
|
+
const folds = foldMethods.toggleActiveAtIndex(stateApi.getFolds(state), action.foldTreeIndex);
|
|
147
|
+
return folds === undefined ? state : update(state, { folds });
|
|
106
148
|
}
|
|
107
149
|
case 'createFoldTree': {
|
|
108
|
-
const
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
150
|
+
const currentFolds = stateApi.getFolds(state);
|
|
151
|
+
const index = firstAvailableAdditionalFoldIndex(foldMethods, currentFolds);
|
|
152
|
+
const folds = foldMethods.setAdditionalFoldAtIndex(currentFolds, index,
|
|
153
|
+
// Obtain this through the actual TreeMethods root-ID operation.
|
|
154
|
+
treeMethods.id(stateApi.getRoot(state)), {
|
|
112
155
|
name: action.name,
|
|
113
156
|
description: null,
|
|
114
157
|
});
|
|
115
|
-
return folds === undefined
|
|
116
|
-
? state
|
|
117
|
-
: {
|
|
118
|
-
...state,
|
|
119
|
-
folds,
|
|
120
|
-
};
|
|
158
|
+
return folds === undefined ? state : update(state, { folds });
|
|
121
159
|
}
|
|
122
160
|
case 'deleteFoldTree': {
|
|
123
|
-
const
|
|
161
|
+
const currentFolds = stateApi.getFolds(state);
|
|
162
|
+
const index = foldMethods.getIndexByName(currentFolds, action.name);
|
|
124
163
|
if (index === undefined || index === 0) {
|
|
125
164
|
return state;
|
|
126
165
|
}
|
|
127
|
-
const folds =
|
|
128
|
-
return folds === undefined
|
|
129
|
-
? state
|
|
130
|
-
: {
|
|
131
|
-
...state,
|
|
132
|
-
folds,
|
|
133
|
-
};
|
|
166
|
+
const folds = foldMethods.removeAdditionalFoldAtIndex(currentFolds, index);
|
|
167
|
+
return folds === undefined ? state : update(state, { folds });
|
|
134
168
|
}
|
|
135
169
|
default: {
|
|
136
170
|
const _exhaustive = action;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feedback.impl.d.ts","sourceRoot":"","sources":["../../src/feedback/feedback.impl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"feedback.impl.d.ts","sourceRoot":"","sources":["../../src/feedback/feedback.impl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AA4BjE;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GAC7D,WAAW,CAkBb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feedback.types.d.ts","sourceRoot":"","sources":["../../src/feedback/feedback.types.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"feedback.types.d.ts","sourceRoot":"","sources":["../../src/feedback/feedback.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,CAAC,MAAM,aAAa,EAAE,OAAO,MAAM,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC;IAC9B,QAAQ,CAAC,CAAC,aAAa,CAAC,EAAE,OAAO,aAAa,CAAC;CAChD,CAAC,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;IACjC;;;OAGG;IACH,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY,KAAK,QAAQ,CAAC;IAE/D,mDAAmD;IACnD,UAAU,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,MAAM,CAAC;IAE3C,wDAAwD;IACxD,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,YAAY,CAAC;CAC/C,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AAEzC,cAAc,qBAAqB,CAAC;AAEpC,cAAc,gBAAgB,CAAC;AAE/B,cAAc,8BAA8B,CAAC;AAE7C,cAAc,yBAAyB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SerializableKey, State, StateMethods } from '../../state-and-nav/index.js';
|
|
2
2
|
import type { Effect, Intent } from '../domain/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* Converts a user intent and the current tree state into an effect.
|
|
@@ -10,5 +10,5 @@ import type { Effect, Intent } from '../domain/index.js';
|
|
|
10
10
|
* @typeParam Value - Application-owned data stored in each tree node.
|
|
11
11
|
*/
|
|
12
12
|
export type IntentToEffect<Id extends SerializableKey, Value> = (intent: Intent, state: State<Id, Value>) => Effect<Id, Value> | undefined;
|
|
13
|
-
export declare function createIntentToEffect<Id extends SerializableKey, Value>(
|
|
13
|
+
export declare function createIntentToEffect<Id extends SerializableKey, Value>(registeredCommands: ReadonlySet<string>, stateApi: StateMethods<Id, Value>): IntentToEffect<Id, Value>;
|
|
14
14
|
//# sourceMappingURL=intent-to-effect.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent-to-effect.d.ts","sourceRoot":"","sources":["../../../src/input/application/intent-to-effect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"intent-to-effect.d.ts","sourceRoot":"","sources":["../../../src/input/application/intent-to-effect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,KAAK,EACL,YAAY,EACb,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,EAAgB,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAKvE;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,IAAI,CAC9D,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,KACpB,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,SAAS,CAAC;AAEnC,wBAAgB,oBAAoB,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,EACpE,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,EACvC,QAAQ,EAAE,YAAY,CAAC,EAAE,EAAE,KAAK,CAAC,GAChC,cAAc,CAAC,EAAE,EAAE,KAAK,CAAC,CAgE3B"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseExCommand } from './parse-ex-command.js';
|
|
2
2
|
import { parseNormalCommand } from './parse-normal-command.js';
|
|
3
|
-
export function createIntentToEffect(
|
|
3
|
+
export function createIntentToEffect(registeredCommands, stateApi) {
|
|
4
4
|
return (intent, state) => {
|
|
5
5
|
switch (intent.intentType) {
|
|
6
6
|
case 'setNormalBuffer':
|
|
7
7
|
return normalBufferToEffectResult(intent.normalBuffer);
|
|
8
8
|
case 'normalRight':
|
|
9
|
-
return normalInteractRightToEffect(state, stateApi
|
|
9
|
+
return normalInteractRightToEffect(state, stateApi);
|
|
10
10
|
case 'normalLeft':
|
|
11
|
-
return normalInteractLeftToEffect(state,
|
|
11
|
+
return normalInteractLeftToEffect(state, stateApi);
|
|
12
12
|
case 'normalDown':
|
|
13
13
|
return dispatchAction({
|
|
14
14
|
effectActionType: 'nextEntry',
|
|
@@ -42,7 +42,7 @@ export function createIntentToEffect(stateApi, cursorApi, treeNodeApi) {
|
|
|
42
42
|
},
|
|
43
43
|
};
|
|
44
44
|
case 'executeCommandLine':
|
|
45
|
-
return (
|
|
45
|
+
return (parseExCommand(intent.commandLine, registeredCommands) ?? {
|
|
46
46
|
effectType: 'setInputState',
|
|
47
47
|
inputState: {
|
|
48
48
|
inputMode: 'normal',
|
|
@@ -106,16 +106,16 @@ function normalBufferToEffectResult(updatedNormalBuffer) {
|
|
|
106
106
|
* - An open branch dispatches an action that closes/unloads its children.
|
|
107
107
|
* - A leaf has no right-interaction effect.
|
|
108
108
|
*/
|
|
109
|
-
function normalInteractRightToEffect(state, stateApi
|
|
109
|
+
function normalInteractRightToEffect(state, stateApi) {
|
|
110
110
|
const currentEntry = stateApi.getNodeAtCursor(state);
|
|
111
111
|
if (currentEntry === undefined) {
|
|
112
112
|
return undefined;
|
|
113
113
|
}
|
|
114
|
-
const path =
|
|
114
|
+
const path = stateApi.cursorPath(state);
|
|
115
115
|
if (path === undefined) {
|
|
116
116
|
return undefined;
|
|
117
117
|
}
|
|
118
|
-
switch (
|
|
118
|
+
switch (stateApi.treeMethods.kind(currentEntry)) {
|
|
119
119
|
case 'unloaded-branch':
|
|
120
120
|
return {
|
|
121
121
|
effectType: 'loadBranchEntries',
|
|
@@ -137,9 +137,8 @@ function normalInteractRightToEffect(state, stateApi, cursorApi, treeNodeApi) {
|
|
|
137
137
|
* Left from the root has no effect. Otherwise dispatch navigation to the
|
|
138
138
|
* parent entry.
|
|
139
139
|
*/
|
|
140
|
-
function normalInteractLeftToEffect(state,
|
|
141
|
-
|
|
142
|
-
if (path === undefined || path.length === 0) {
|
|
140
|
+
function normalInteractLeftToEffect(state, stateApi) {
|
|
141
|
+
if (stateApi.isCursorRoot(state)) {
|
|
143
142
|
return undefined;
|
|
144
143
|
}
|
|
145
144
|
return dispatchAction({
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { SerializableKey } from 'dirvi-apis';
|
|
2
|
+
import type { Effect } from '../domain/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Parses a Vim-style Ex command into an application effect.
|
|
5
|
+
*
|
|
6
|
+
* Leading `:` characters are optional. Arguments are split on whitespace;
|
|
7
|
+
* quoting and escaping are not supported.
|
|
8
|
+
*
|
|
9
|
+
* Registered commands take precedence over built-ins and receive their
|
|
10
|
+
* arguments without validation. This function does not execute them.
|
|
11
|
+
*
|
|
12
|
+
* @param commandLine - The raw command line.
|
|
13
|
+
* @param registeredCommands - User-command names that override built-ins.
|
|
14
|
+
* @returns An effect, or `undefined` for an empty command.
|
|
15
|
+
*/
|
|
16
|
+
export declare function parseExCommand<Id extends SerializableKey, Value>(commandLine: string, registeredCommands: ReadonlySet<string>): Effect<Id, Value> | undefined;
|
|
17
|
+
//# sourceMappingURL=parse-ex-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-ex-command.d.ts","sourceRoot":"","sources":["../../../src/input/application/parse-ex-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AA6IjD;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,EAC9D,WAAW,EAAE,MAAM,EACnB,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,GACtC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,SAAS,CA+D/B"}
|
|
@@ -1,23 +1,59 @@
|
|
|
1
|
-
const DEFAULT_VIEW_NAME = 'default';
|
|
1
|
+
// const DEFAULT_VIEW_NAME = 'default';
|
|
2
2
|
const DEFAULT_FOLD_TREE_NAME = 'default';
|
|
3
|
+
function parseAppCommand(commandArgs) {
|
|
4
|
+
const [firstArgument, ...remainingArguments] = commandArgs;
|
|
5
|
+
const badArgs = {
|
|
6
|
+
effectType: 'emitError',
|
|
7
|
+
message: `Unrecognized command arguments: app ${commandArgs.join(' ')}`,
|
|
8
|
+
};
|
|
9
|
+
switch (firstArgument) {
|
|
10
|
+
case 'list':
|
|
11
|
+
return commandArgs.length === 1
|
|
12
|
+
? {
|
|
13
|
+
effectType: 'listApps',
|
|
14
|
+
}
|
|
15
|
+
: badArgs;
|
|
16
|
+
case 'open':
|
|
17
|
+
case 'switch': {
|
|
18
|
+
const [appId, input] = remainingArguments;
|
|
19
|
+
if (appId === undefined || remainingArguments.length > 2) {
|
|
20
|
+
return badArgs;
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
effectType: 'switchApp',
|
|
24
|
+
appId,
|
|
25
|
+
input,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
default: {
|
|
29
|
+
if (firstArgument === undefined || remainingArguments.length > 1) {
|
|
30
|
+
return badArgs;
|
|
31
|
+
}
|
|
32
|
+
const input = remainingArguments[0];
|
|
33
|
+
return {
|
|
34
|
+
effectType: 'switchApp',
|
|
35
|
+
appId: firstArgument,
|
|
36
|
+
input,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
3
41
|
function parseFoldCommand(commandArgs) {
|
|
4
42
|
const [subcommand, name] = commandArgs;
|
|
43
|
+
const badArgs = {
|
|
44
|
+
effectType: 'emitError',
|
|
45
|
+
message: `Unrecognized command arguments: fold ${commandArgs.join(' ')}`,
|
|
46
|
+
};
|
|
5
47
|
switch (subcommand) {
|
|
6
48
|
case 'list':
|
|
7
49
|
return commandArgs.length === 1
|
|
8
50
|
? {
|
|
9
51
|
effectType: 'listFolds',
|
|
10
52
|
}
|
|
11
|
-
:
|
|
12
|
-
effectType: 'unrecognizedCommand',
|
|
13
|
-
commandLine: `fold ${commandArgs.join(' ')}`,
|
|
14
|
-
};
|
|
53
|
+
: badArgs;
|
|
15
54
|
case 'create':
|
|
16
55
|
return name === undefined || commandArgs.length !== 2
|
|
17
|
-
?
|
|
18
|
-
effectType: 'unrecognizedCommand',
|
|
19
|
-
commandLine: `fold ${commandArgs.join(' ')}`,
|
|
20
|
-
}
|
|
56
|
+
? badArgs
|
|
21
57
|
: {
|
|
22
58
|
effectType: 'dispatchEffectAction',
|
|
23
59
|
action: {
|
|
@@ -27,10 +63,7 @@ function parseFoldCommand(commandArgs) {
|
|
|
27
63
|
};
|
|
28
64
|
case 'delete':
|
|
29
65
|
return name === undefined || commandArgs.length !== 2
|
|
30
|
-
?
|
|
31
|
-
effectType: 'unrecognizedCommand',
|
|
32
|
-
commandLine: `fold ${commandArgs.join(' ')}`,
|
|
33
|
-
}
|
|
66
|
+
? badArgs
|
|
34
67
|
: {
|
|
35
68
|
effectType: 'dispatchEffectAction',
|
|
36
69
|
action: {
|
|
@@ -41,10 +74,7 @@ function parseFoldCommand(commandArgs) {
|
|
|
41
74
|
case 'enable':
|
|
42
75
|
case 'close':
|
|
43
76
|
return commandArgs.length > 2
|
|
44
|
-
?
|
|
45
|
-
effectType: 'unrecognizedCommand',
|
|
46
|
-
commandLine: `fold ${commandArgs.join(' ')}`,
|
|
47
|
-
}
|
|
77
|
+
? badArgs
|
|
48
78
|
: {
|
|
49
79
|
effectType: 'dispatchEffectAction',
|
|
50
80
|
action: {
|
|
@@ -58,10 +88,7 @@ function parseFoldCommand(commandArgs) {
|
|
|
58
88
|
case 'disable':
|
|
59
89
|
case 'open':
|
|
60
90
|
return commandArgs.length > 2
|
|
61
|
-
?
|
|
62
|
-
effectType: 'unrecognizedCommand',
|
|
63
|
-
commandLine: `fold ${commandArgs.join(' ')}`,
|
|
64
|
-
}
|
|
91
|
+
? badArgs
|
|
65
92
|
: {
|
|
66
93
|
effectType: 'dispatchEffectAction',
|
|
67
94
|
action: {
|
|
@@ -74,10 +101,7 @@ function parseFoldCommand(commandArgs) {
|
|
|
74
101
|
};
|
|
75
102
|
case 'toggle':
|
|
76
103
|
return commandArgs.length > 2
|
|
77
|
-
?
|
|
78
|
-
effectType: 'unrecognizedCommand',
|
|
79
|
-
commandLine: `fold ${commandArgs.join(' ')}`,
|
|
80
|
-
}
|
|
104
|
+
? badArgs
|
|
81
105
|
: {
|
|
82
106
|
effectType: 'dispatchEffectAction',
|
|
83
107
|
action: {
|
|
@@ -89,55 +113,61 @@ function parseFoldCommand(commandArgs) {
|
|
|
89
113
|
},
|
|
90
114
|
};
|
|
91
115
|
default:
|
|
92
|
-
return
|
|
93
|
-
effectType: 'unrecognizedCommand',
|
|
94
|
-
commandLine: `fold ${commandArgs.join(' ')}`,
|
|
95
|
-
};
|
|
116
|
+
return badArgs;
|
|
96
117
|
}
|
|
97
118
|
}
|
|
98
119
|
/**
|
|
99
|
-
* Parses a
|
|
120
|
+
* Parses a Vim-style Ex command into an application effect.
|
|
100
121
|
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* Effect<Id, Value> pipeline.
|
|
122
|
+
* Leading `:` characters are optional. Arguments are split on whitespace;
|
|
123
|
+
* quoting and escaping are not supported.
|
|
104
124
|
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
125
|
+
* Registered commands take precedence over built-ins and receive their
|
|
126
|
+
* arguments without validation. This function does not execute them.
|
|
127
|
+
*
|
|
128
|
+
* @param commandLine - The raw command line.
|
|
129
|
+
* @param registeredCommands - User-command names that override built-ins.
|
|
130
|
+
* @returns An effect, or `undefined` for an empty command.
|
|
107
131
|
*/
|
|
108
|
-
export function
|
|
109
|
-
const command = commandLine.trim().replace(
|
|
132
|
+
export function parseExCommand(commandLine, registeredCommands) {
|
|
133
|
+
const command = commandLine.trim().replace(/^:+/, '');
|
|
110
134
|
if (command === '') {
|
|
111
135
|
return undefined;
|
|
112
136
|
}
|
|
113
137
|
const [commandName, ...commandArgs] = command.split(/\s+/);
|
|
138
|
+
if (commandName !== undefined && registeredCommands.has(commandName)) {
|
|
139
|
+
return {
|
|
140
|
+
effectType: 'userExCommand',
|
|
141
|
+
name: commandName,
|
|
142
|
+
args: commandArgs,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
114
145
|
switch (commandName) {
|
|
115
146
|
case 'q':
|
|
116
147
|
return {
|
|
117
148
|
effectType: 'quit',
|
|
118
149
|
exitMessage: '',
|
|
119
150
|
};
|
|
151
|
+
case 'app':
|
|
152
|
+
return parseAppCommand(commandArgs);
|
|
120
153
|
case 'fold':
|
|
121
154
|
return parseFoldCommand(commandArgs);
|
|
122
|
-
case '
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
effectType: 'loadView',
|
|
135
|
-
name: commandArgs[0] || DEFAULT_VIEW_NAME,
|
|
136
|
-
};
|
|
155
|
+
// case 'mkview!':
|
|
156
|
+
// return {
|
|
157
|
+
// effectType: 'saveView',
|
|
158
|
+
// name: commandArgs[0] || DEFAULT_VIEW_NAME,
|
|
159
|
+
// overwrite: true,
|
|
160
|
+
// };
|
|
161
|
+
//
|
|
162
|
+
// case 'loadview':
|
|
163
|
+
// return {
|
|
164
|
+
// effectType: 'loadView',
|
|
165
|
+
// name: commandArgs[0] || DEFAULT_VIEW_NAME,
|
|
166
|
+
// };
|
|
137
167
|
default:
|
|
138
168
|
return {
|
|
139
|
-
effectType: '
|
|
140
|
-
commandLine
|
|
169
|
+
effectType: 'emitError',
|
|
170
|
+
message: `Unrecognized command: "${commandLine}"`,
|
|
141
171
|
};
|
|
142
172
|
}
|
|
143
173
|
/*
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SerializableKey } from '../../
|
|
1
|
+
import type { SerializableKey } from '../../state-and-nav/index.js';
|
|
2
2
|
import type { EffectAction } from '../domain/index.js';
|
|
3
3
|
export type ParseNormalCommandResult<Id extends SerializableKey, Value> = {
|
|
4
4
|
kind: 'incomplete';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-normal-command.d.ts","sourceRoot":"","sources":["../../../src/input/application/parse-normal-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"parse-normal-command.d.ts","sourceRoot":"","sources":["../../../src/input/application/parse-normal-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAOvD,MAAM,MAAM,wBAAwB,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,IAClE;IACE,IAAI,EAAE,YAAY,CAAC;CACpB,GACD;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,YAAY,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;CACjC,GACD;IACE,IAAI,EAAE,SAAS,CAAC;CACjB,CAAC;AAEN,wBAAgB,kBAAkB,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,EAClE,YAAY,EAAE,MAAM,GACnB,wBAAwB,CAAC,EAAE,EAAE,KAAK,CAAC,CAwCrC"}
|