Add New Command

This goes over adding a new command with lookup. To see an example, see this command and this commit: cc8a02b4.

Lifecycle

sequenceDiagram participant user participant lookupCommand participant lookupController participant lookupProvider user ->> lookupCommand: user issues command Note left of user: 1. cmd.gatherInput() rect rgb(150, 170, 150) lookupCommand ->> lookupController: creates controller lookupCommand ->> lookupProvider: creates provider lookupCommand ->> lookupController: call show(provider) lookupCommand ->> lookupProvider: subscribe to provider lookupController ->> user: shows quickinput end user ->> user: chooses a selection lookupProvider ->> lookupCommand: notify(selection) lookupCommand ->> lookupCommand: calls command.execute()

The execution in pseudocode

run(args) {
	sanityCheckResp = @sanityCheck
	if sanityCheckResp {
		// throw error
	}

	inputs = gatherInputs(args)
	if !inputs return

	opts = @enrichInputs(inputs)
	if !opts return

	@execute(merge(opts, args))
	@showResponse(resp)
}

Steps

Decide on a name

  1. Dendron commands follow a VERB + NOUN convention (eg. Go to Note)

Add new command

Add constant key

  1. Add command to DENDRON_COMMANDS under plugin-core/src/constants.ts
  2. Update the plugin config

    1. Open the command prompt, enter Run Task, and run gen:config
      • this will add the command to package.json

Create new command

  1. Create the new command in plugin-core/src/commands/{COMMAND_NAME}.ts
    • you can copy the contents of an existing command (eg. src/commands/ShowHelp.ts) to help you get started
  2. Write command logic
  3. Add command to ../packages/plugin-core/src/commands/index.ts (Private)
  4. Test your command manually, see Manual Testing

Some other notes:

  • If it makes sense, add a keyboard shortcut for the command. Make sure it doesn't conflict with an generic VSCode command or existing Dendron commands. You can detect existing keybindings by using the guide here
  • If your command requires an active workspace to function, make sure that requireActiveWorkspace = true
    export class CreateDailyJournalCommand extends CreateNoteWithTraitCommand {
     // THIS needs to be set to tell Dendron to NOT activate this command unless dendron is active
     static requireActiveWorkspace: boolean = true;
     ...
    }
    
  • If your command needs to manually clean up resources, make sure that any places where your command is constructed that it gets properly cleaned up when out of scope. An example of this is with the NoteLookupCommand. The preferred way to do this is by implementing the vscode Disposable interface (although NoteLookupCommand doesn't do this yet).
  • If your command involves opening a note, also return it in the CommandOutput signature. this makes it easy to compose the command as well as test it

Add Tests

  1. Write tests

    • tests are in plugin-core/src/test/suite-integ/{COMMAND}
    • testing instructions are here

Update package.json

This goes over updating the package.json in plugin-core. This needs to be done when a command is added or modified

Steps

  1. Inside of vscode, use > Run Task
  2. Execute gen:config to update package.json`

Submit a pull request

  1. Submit pull request. See process here

Gotchas

If the command needs to accept input objects from VSCode, for example ShowPreview (Private), then base your command on InputArgCommand (Private) and avoid adding gatherInputs and enrichInputs. Otherwise Dendron can convert the input object into a plain javascript object.

Keyboard Shortcut

  1. To add a keyboard binding to a command, add the keybindings property to the command.
keybindings: {
    key: "ctrl+shift+i",
    mac: "cmd+shift+i",
    // use the `when` clause to enable the command only when the dendron plugin is active
    // generally advisable for most commands
    when: DendronContext.PLUGIN_ACTIVE,
}

Example: https://github.com/dendronhq/dendron/blob/master/packages/plugin-core/src/constants.ts#L267:L267

Input Validation

Reference


Backlinks