Command API ​
Commands are the actions that can be triggered by the user. With the command API, you can define chainable commands and execute them.
Command Chain ​
Commands are executed in a chain, and each command can decide whether to continue the chain or not.
std.command.pipe().command1().command2().command3().run();std.command.pipe().command1().command2().command3().run();You will need to call pipe() to start a new chain. Then, you can call any command defined in the Commands interface. And finally, call run() to execute the chain.
Try ​
If a command fails, the chain will be interrupted. However, you can use try() to call a list of commands until one of them succeeds.
std.command
.pipe()
.try(cmd => [cmd.command1(), cmd.command2()])
.command3()
.run();std.command
.pipe()
.try(cmd => [cmd.command1(), cmd.command2()])
.command3()
.run();In this chain, command3 will be executed only if command1 or command2 succeeds.
Writing Commands ​
Commands are defined as pure functions.
import type { Command } from '@blocksuite/block-std';
export const myCommand: Command = (ctx, next) => {
if (fail) {
return;
}
return next();
};
declare global {
namespace BlockSuite {
interface Commands {
my: typeof myCommand;
}
}
}
// Add the command to the std command list
std.command.add('my', myCommand);
// You can call it with
std.command.pipe().my().run();import type { Command } from '@blocksuite/block-std';
export const myCommand: Command = (ctx, next) => {
if (fail) {
return;
}
return next();
};
declare global {
namespace BlockSuite {
interface Commands {
my: typeof myCommand;
}
}
}
// Add the command to the std command list
std.command.add('my', myCommand);
// You can call it with
std.command.pipe().my().run();Only when the command calls next(), the next command in the chain will be executed.
Command Context ​
When a list of commands are executed, they share a context object. This object is standalone for each command execution, and you can use it to store temporary data.
import type { Command } from '@blocksuite/block-std';
export const myCommand: Command<never, 'myCommandData'> = (ctx, next) => {
if (fail) {
return;
}
return next({ myCommandData: 'hello' });
};
declare global {
namespace BlockSuite {
interface CommandData {
myCommandData: string;
}
interface Commands {
myCommand: typeof myCommand;
}
}
}import type { Command } from '@blocksuite/block-std';
export const myCommand: Command<never, 'myCommandData'> = (ctx, next) => {
if (fail) {
return;
}
return next({ myCommandData: 'hello' });
};
declare global {
namespace BlockSuite {
interface CommandData {
myCommandData: string;
}
interface Commands {
myCommand: typeof myCommand;
}
}
}Then, commands executed after myCommand can access the data:
export const myCommand: Command<'myCommandData'> = (ctx, next) => {
const data = ctx.myCommandData;
console.log(data);
};export const myCommand: Command<'myCommandData'> = (ctx, next) => {
const data = ctx.myCommandData;
console.log(data);
};Command Options ​
You can pass options to a command when calling it:
import type { Command } from '@blocksuite/block-std';
type MyCommandOptions = {
configA: number;
configB: string;
};
export const myCommand: Command<never, never, MyCommandOptions> = (
ctx,
next
) => {
const { configA, configB } = ctx;
if (fail) {
return;
}
return next();
};
// You can call it with
std.command.pipe().my({ configA: 0, configB: 'hello' }).run();import type { Command } from '@blocksuite/block-std';
type MyCommandOptions = {
configA: number;
configB: string;
};
export const myCommand: Command<never, never, MyCommandOptions> = (
ctx,
next
) => {
const { configA, configB } = ctx;
if (fail) {
return;
}
return next();
};
// You can call it with
std.command.pipe().my({ configA: 0, configB: 'hello' }).run();Please notice that commands take only one argument, so you need to wrap the options in an object if you want to pass multiple options.
Inline Command ​
You can also use inline command for some temporary commands.
std.command
.pipe()
.inline((ctx, next) => {
// ...
return next();
})
.run();std.command
.pipe()
.inline((ctx, next) => {
// ...
return next();
})
.run();