hd0013's picture
Upload folder using huggingface_hub
8fdc036 verified
raw
history blame contribute delete
No virus
4.02 kB
import { writable, type Writable } from "svelte/store";
/**
* Base command interface that is added to the command_managers history
*/
export interface Command {
/**
* Optionally called when the command is first executed for multi-step commands
* @param args arguments to pass to the command
*/
start?: (...args: any) => any | Promise<any>;
/**
* Optionally called when the command is continued for multi-step commands
* @param args arguments to pass to the command
*/
continue?: (...args: any) => any | Promise<any>;
/**
* Optionally called when the command is stopped for multi-step commands
* @param args arguments to pass to the command
*/
stop?: (...args: any) => any | Promise<any>;
/**
* Called by the command manager to execute the command, can act as a no-op if the work has already been done
* This function must be able to recreate the command if the command is undone and redone (`stop`/`start`/`continue` will not be called again)
*/
execute(): any | Promise<any>;
/**
* Called by the command manager to undo the command
* This function must be able to undo the work done by the execute function
*/
undo(): any | Promise<any>;
}
/**
* Command manager interface that handles the undo/redo history
*/
export interface CommandManager {
/**
* Undo the last command
*/
undo(): void;
/**
* Redo the last undone command
*/
redo(): void;
/**
* Execute a command and add it to the history
* @param command command to execute
*/
execute(command: Command): void;
/**
* Whether or not there are commands that can be undone
* Observable store that you can subscribe to for updates
*/
readonly can_undo: Writable<boolean>;
/**
* Whether or not there are commands that can be redone
* Observable store that you can subscribe to for updates
*/
readonly can_redo: Writable<boolean>;
/**
* Resets the history
*/
reset(): void;
/**
* The current history node
* Observable store that you can subscribe to for updates
*/
readonly current_history: Writable<CommandNode>;
}
/**
* Command node interface that is used to create the undo/redo history
*/
interface CommandNode {
/**
* Command that the node holds
*/
command: Command | null;
/**
* Next command in the history
*/
next: CommandNode | null;
/**
* Previous command in the history
*/
previous: CommandNode | null;
/**
* Push a command onto the history
* @param command command to push onto the history
*/
push(command: Command): void;
}
/**
* Creates a command node
* @param command command to add to the node
* @returns a command node
*/
function command_node(command?: Command): CommandNode {
return {
command: command || null,
next: null,
previous: null,
push: function (command: Command) {
const node = command_node(command);
node.previous = this;
this.next = node;
}
};
}
/**
* Creates a command manager
* @returns a command manager
*/
export function command_manager(): CommandManager {
let history: CommandNode = command_node();
const can_undo = writable(false);
const can_redo = writable(false);
const current_history = writable(history);
return {
undo: function () {
if (history.previous) {
history.command?.undo();
history = history.previous;
}
can_undo.set(!!history.previous);
can_redo.set(!!history.next);
current_history.set(history);
},
redo: function () {
if (history.next) {
history.next.command?.execute();
history = history.next;
}
can_undo.set(!!history.previous);
can_redo.set(!!history.next);
current_history.set(history);
},
execute: function (command: Command) {
command.execute();
history.push(command);
history = history.next!;
can_undo.set(!!history.previous);
can_redo.set(!!history.next);
current_history.set(history);
},
can_undo,
can_redo,
current_history,
reset: function () {
history = command_node();
can_undo.set(false);
can_redo.set(false);
current_history.set(history);
}
};
}