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

55 lines
1.4 KiB
TypeScript

import {
RootFolderNode, FolderUnion, FolderNodeMedial, FolderNodeInitial,
} from "./interfaces";
import { defensiveClone } from "../util";
interface TreeClimberState {
active: boolean;
}
interface VisitorProps {
node: FolderNodeInitial | FolderNodeMedial;
callback: TreeClimber;
halt: Halt;
state: TreeClimberState;
}
type Halt = () => RootFolderNode;
type TreeClimber = (t: FolderUnion,
/** Calling this function stops tree climb from continuing. */
halt: Halt) => void;
function visit(p: VisitorProps) {
const { node, callback, halt } = p;
callback(node, halt);
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);
}
});
}
/** Recursively climb a directory structure. */
export const climb = (t: RootFolderNode, callback: TreeClimber) => {
const state: TreeClimberState = { active: true };
const halt = () => {
state.active = false;
return t;
};
t.folders.map((node) => {
const props = { node, callback, halt, state };
state.active && visit(props);
});
return t;
};
/** TODO: Create strategies for non-destructively
* transforming a RootFolderNode. */
export const cloneAndClimb = (t: RootFolderNode, callback: TreeClimber) => {
return climb(defensiveClone(t), callback);
};