Commands
As explained in the User Guide, a lot of Pragtical's functionalities are implemented as commands.
Each command has a predicate — a condition to check if Pragtical should run the command. The predicate will return a boolean and other values to be consumed by the command function.
The simplest command is a class.
This tells Pragtical to check whether the current view is an instance of
a class.
For instance, one can pass DocView
as a predicate so that the command
only runs if the user is editing a document.
A simpler form of the predicate above is a string that specifies the
module to import.
Pragtical will import the module and checks whether the current view
is an instance of the module.
To simplify our previous example, we can simply pass core.docview
as a predicate to avoid importing DocView
ourselves.
The string predicate also supports strict checking —
when the module name ends with !
, Pragtical will check whether the
current view is an instance of the class and not it's child classes.
For instance, passing core.view
will match DocView
as well as CommandView
,
but passing core.view!
will only match View
and not DocView
.
The class and string predicates returns a boolean, the current view and other values passed into the predicate.
Lastly, the predicate could also be a function.
This function accepts a variable number of arguments, pass
through command.add()
and returns a boolean and other values.
If the function returns true, the command will be executed.
Other values are passed into the command function as arguments.
For instance, we can create a predicate like this instead of passing
DocView
as a predicate:
local function predicate()
return core.current_view:is(DocView)
end
Adding commands
To add a command, use command.add()
.
local type function Predicate(any...): boolean
function command.add(predicate: Predicate | string | Object,
commands: {string, Predicate}): () end
The first argument to command.add()
is the predicate.
This predicate is set for each command passed to command.add()
.
If no predicates are required, nil
can be passed.
The second parameter is a table of functions mapped to each command.
Example:
local command = require "core.command"
local DocView = require "core.docview"
-- add "test:print-message" which prints a message to stdout
-- this command will be available at all times
command.add(nil, { ["test:print-message"] = function() core.log("Hello world!") end })
-- a predicate function
local function docview_predicate(custom_msg)
return core.active_view:is(DocView), core.active_view, true, custom_msg
end
local function print_doc_name(dv, custom_predicate, custom_msg)
if not custom_msg then
custom_msg = custom_predicate and "custom predicate used!: %s" or "name: %s"
end
core.log(custom_msg, dv.doc.filename)
end
-- add "test:print-doc-name" which prints the name of currently opened file
-- This command will only be available if the user is editing a document.
-- this will log "custom predicate used!: <filename>"
command.add(docview_predicate, { ["test:print-doc-name"] = print_doc_name })
-- the line above can be simplified into this
-- this will log "name: <filename>"
command.add(DocView, { ["test:print-doc-name"] = print_doc_name })
-- the line above can be simplified into this, removing a require
-- this will log "name: <filename>"
command.add("core.docview", { ["test:print-doc-name"] = print_doc_name })
-- if you have subclasses of DocView and don't want to match them,
-- append a exclamation mark at the end.
-- this will log "name: <filename>"
command.add("core.docview!", { ["test:print-doc-name"] = print_doc_name })
Running commands
Users can run these commands via the command palette while
plugins can run these commands programmatically via command.perform()
.
If you want to check whether a command can run without running the command,
(the command exists and the predicate passed),
you can use command.is_valid()
.
function command.perform(cmd: string, ...: any): boolean end
function command.is_valid(cmd: string, ...: any): boolean end
command.perform()
accepts a command as the first parameter.
If the command requires other parameters, it can be passed into
command.perform()
.
If a command is found and executed successfully, the function
returns true
.
Example:
local command = require "core.command"
-- open the command prompt
command.perform "core:find-command"
-- assuming we've run the code in the section above,
-- we can try passing a custom message via command:perform!
command.perform("test:print-doc-name", "custom message! %s")
-- command palette should be accessible all the time
-- prints true
print(command.is_valid "core:find-command")
Utility functions
To get a prettified name of a command, shown in the command palette,
use command.prettify_name()
.
function command.prettify_name(name: string): string end
The function accepts a command-like string and returns a prettified command string. All the dashes are replaced with spaces and the first letter of all words are capitalized.