Farmbot-Web-App/frontend/folders/climb.ts

55 lines
1.4 KiB
TypeScript
Raw Normal View History

2020-01-03 13:13:49 -07:00
import {
2020-02-28 09:35:32 -07:00
RootFolderNode, FolderUnion, FolderNodeMedial, FolderNodeInitial,
2020-01-03 13:13:49 -07:00
} from "./interfaces";
2019-11-27 06:01:39 -07:00
import { defensiveClone } from "../util";
2019-11-26 14:49:18 -07:00
interface TreeClimberState {
active: boolean;
}
interface VisitorProps {
2019-11-27 06:01:39 -07:00
node: FolderNodeInitial | FolderNodeMedial;
2019-11-26 14:49:18 -07:00
callback: TreeClimber;
halt: Halt;
state: TreeClimberState;
}
2019-12-02 09:07:37 -07:00
type Halt = () => RootFolderNode;
2019-11-27 06:01:39 -07:00
type TreeClimber = (t: FolderUnion,
/** Calling this function stops tree climb from continuing. */
2019-12-02 09:07:37 -07:00
halt: Halt) => void;
2019-11-26 14:49:18 -07:00
function visit(p: VisitorProps) {
const { node, callback, halt } = p;
callback(node, halt);
2019-11-26 15:00:07 -07:00
const children: FolderUnion[] = (node.children);
return p.state.active && children.map(nextNode => {
if (nextNode.kind != "terminal") {
p.state.active && visit({ ...p, node: nextNode });
} else {
p.state.active && callback(nextNode, p.halt);
}
});
2019-11-26 14:49:18 -07:00
}
2019-11-27 06:01:39 -07:00
/** Recursively climb a directory structure. */
2019-11-26 14:49:18 -07:00
export const climb = (t: RootFolderNode, callback: TreeClimber) => {
const state: TreeClimberState = { active: true };
2019-12-02 09:07:37 -07:00
const halt = () => {
state.active = false;
return t;
};
2019-11-26 14:49:18 -07:00
t.folders.map((node) => {
const props = { node, callback, halt, state };
state.active && visit(props);
});
2019-11-27 06:01:39 -07:00
return t;
};
/** TODO: Create strategies for non-destructively
* transforming a RootFolderNode. */
export const cloneAndClimb = (t: RootFolderNode, callback: TreeClimber) => {
return climb(defensiveClone(t), callback);
2019-11-26 14:49:18 -07:00
};