User defined commands¶
Defining commands¶
VPE provides the vpe.define_command
function as a way to create commands that
invoke Python functions or methods. In other words, you can define commands
that are implemented using Python functions (implementation functions). It maps
fairly closely to Vim’s :command. Here is a very trival example:
import vpe
def echo_command(info: vpe.CommandInfo, *args):
vpe.echo_msg(f'Echoing {args}')
vpe.define_command('Echo', echo_command, nargs='*')
This creates a command call ‘Echo’, which takes an arbitrary number of
arguments. The ‘echo_command’ function receives these as positional parameters
following the initial vpe.CommandInfo
argument. The command:
Echo 1 2 three
will print:
Echoing ('1', '2', 'Three')
The vpe.define_command
function takes a number of keyword arguments that are
analogues of the :command options with the same names.
- nargs
May be 0, 1, ‘*’, ‘?’ or ‘+’ (‘0’ and ‘1’ as strings also work).
- complete
A string. Any value accepted by :command, except for ‘custom’ and ‘customlist’.
- range
Set to
True
to simply allow the command to take a range. Use ‘%’ to set a default range of the whole file and a number (may be as a string) to set a default count.- count
The same as for :command, except that you can use integers or strings ‘N’.
- addr
How special characters in a range are interpreted by Vim.
- bang, bar, register, buffer
Boolean values that act like the corresponding :command options.
The implementation of vpe.define_command
invokes :command! ...
so that any
previous command of the same name is replaced. The argument replace=False
makes VPE invoke :command ...
.
CommandInfo¶
The vpe.CommandInfo
argument makes it easy for the called function to determine
the details of how the command was invoked. It provides the following
attributes.
- line1, line2
The start line and end line of the command range.
- range
The number of items in the command range: 0, 1 or 2. This requires at least vim 8.0.1089; for earlier versions it is fixed as -1.
- count
Any count value supplied (see command-count).
- bang
True if the command was invoked with a ‘!’.
- mods
The command modifiers (see :command-modifiers). This is a space separated string.
- reg
The optional register, if provided.
Functions arguments¶
Additional arguments can be passed to the command callback function. These are
defined using args
and kwargs
.
def echo_command(info: vpe.CommandInfo, mode, *args, level=0):
vpe.echo_msg(f'{mode}[{level}]: {args}')
vpe.define_command(
'Echo',
echo_command,
nargs='*',
args=('info',),
kwargs={'level': 2})
The command:
Echo 20 30
Will print:
info[2]: ('20', '30')
Notice that args
preset using vpe.define_command
are passed to the
implementation function before those of the Echo
command.
The vpe.CommandInfo
parameter can be suppressed if desired using the
pass_info
argument.
def echo_command(mode, *args, level=0):
vpe.echo_msg(f'{mode}[{level}]: {args}')
vpe.define_command(
'Echo',
echo_command,
nargs='*',
args=('info',),
kwargs={'level': 2},
pass_info=False)
Using decorators¶
Note
This feature should be considered experimental at the moment. It will not be removed, but detailed behaviour, argument names, etc. may change in the next release.
In a similar way to key mapping, VPE provides a decorator approach to define
command implementation functions. The vpe.CommandHandler
mixin class is used for
this.
class MessageGenerator(vpe.CommandHandler):
command = vpe.CommandHandler.command
def __init__(self):
self.auto_define_commands()
@command('Echo', nargs='*', args=('info',), kwargs={'level': 2})
def echo_command(self, mode, *args, level=0):
vpe.echo_msg(f'{mode}[{level}]: {args}')
message_gen = MessageGenerator()
This can make code easier to read and maintain in some circumstances,
but it is not as flexible as vpe.define_command
.
Note that the mappings are only created when the self.auto_define_commands()
method is invoked. Also note that, by default, the methods do not receive a
vpe.CommandInfo
object as the first argument. Give the vpe.CommandHandler.command
decorator a
pass_info=True
argument to change this behaviour.
The vpe.CommandHandler.command
decorator accepts all the arguments of vpe.define_command
except
for func
.