6922
Comment: ui.prompt does not have pat anymore
|
11352
|
Deletions are marked like this. | Additions are marked like this. |
Line 3: | Line 3: |
<<TableOfContents>> | |
Line 6: | Line 7: |
Extensions allow the creation of new features and using them directly from the main hg command line as if they were builtin commands. The extensions have full access to the MercurialApi. | Extensions allow the creation of new features and using them directly from the main hg command line as if they were built-in commands. The extensions have full access to the MercurialApi. |
Line 9: | Line 10: |
Line 11: | Line 11: |
Line 17: | Line 16: |
==== The `cmdtable` dictionary ==== | ==== The cmdtable dictionary ==== |
Line 20: | Line 19: |
1. the function name to be called when the command is used. | 1. the function to be called when the command is used. |
Line 22: | Line 21: |
1. a help string for the command. | 1. a command line synopsis for the command (the function docstring is used for the full help). |
Line 25: | Line 24: |
Al the command flag options are documented in the mercurial/fancyopts.py sources. | All the command flag options are documented in the [[http://selenic.com/repo/hg/file/tip/mercurial/fancyopts.py|mercurial/fancyopts.py]] sources. |
Line 28: | Line 27: |
1. a flag specifying if the option is of the short or long sort, like {{{-o}}} or {{{--option}}}. 1. an option name. |
1. the short option letter, or {{{''}}} if no short option is available (for example, {{{o}}} for a {{{-o}}} option). 1. the long option name (for example, {{{option}}} for a {{{--option}}} option). |
Line 33: | Line 33: |
==== Example `cmdtable` ==== | ==== Example cmdtable ==== |
Line 43: | Line 43: |
Line 47: | Line 46: |
If there is no repo to be associated with the command and consequently no {{{repo}}} passed then {{{commands}}} should be imported from {{{mercurial}}} and the extension name should be added to {{{commands.norep}}} like this: | If there is no repo to be associated with the command and consequently no {{{repo}}} passed then {{{commands}}} should be imported from {{{mercurial}}} and the extension name should be added to {{{commands.norepo}}} like this: |
Line 51: | Line 51: |
commands.norepo += " mycommand" | commands.norepo += " mycommand" |
Line 55: | Line 55: |
=== Command function docstrings === The docstring of your function is used as the main help text, shown by {{{hg help mycommand}}}. The docstring should be formatted using a simple subset of [[http://docutils.sourceforge.net/docs/user/rst/quickstart.html|reStructuredText]] markup. The supported constructs include: Paragraphs: {{{ This is a paragraph. Paragraphs are separated by blank lines. }}} A verbatim block is introduced with a double colon followed by an indented block. The double colos is turned into a single colon on display: {{{ Some text:: verbatim text !! }}} We have field lists: {{{ :key1: value1 :key2: value2 }}} Bullet lists: {{{ - foo - bar }}} Enumerated lists: {{{ 1. foo 2. bar }}} Inline markup: {{{*bold*}}}, {{{``monospace``}}}. Mark Mercurial commands as {{{:hg:`command`}}} to make a nice link to the corresponding documentation. We'll expand the support if new constructs can be parsed without too much trouble. |
|
Line 56: | Line 96: |
Line 62: | Line 101: |
Extensions are loaded in phases, all extensions are processed in a given phase before the next phase begins. In the first phase all extension modules are loaded and registered with Mercurial. this means that you can find all enabled extensions with `extensions.find` in the following phases. | |
Line 64: | Line 104: |
Extensions can implement an optional callback named `uisetup`. `uisetup` is called when the extension is first loaded and receives a ui object. | Extensions can implement an optional callback named `uisetup`. `uisetup` is called when the extension is first loaded and receives a ui object: {{{ def uisetup(ui): # ... }}} |
Line 67: | Line 111: |
Extensions can implement an optional callback named `extsetup`. It is called after all the extension are loaded, and can be useful in case one extension optionally depends on another extension. Signature: |
Extensions can implement an optional callback named `extsetup`. It is called after all the extension are loaded, and can be useful in case one extension optionally depends on another extension. Signature: |
Line 75: | Line 117: |
Mercurial version 8e6019b16a7d and later (that is post-1.3.1) will pass a `ui` argument to `extsetup`. ==== Command table setup ==== After `extsetup`, the `cmdtable` is copied into the global command table in Mercurial. |
|
Line 79: | Line 125: |
As other command functions it receives an ui object and a repo object (no additional parameters for this, though): | As other command functions it receives an `ui` object and a `repo` object (no additional parameters for this, though): |
Line 85: | Line 131: |
It is important to take into account that the `ui` object that is received by the `reposetup` function is not the same as the one received by the `uisetup` and `extsetup` functions. This is particularly important when setting up hooks as described in the following section, since not all hooks us the same `ui` object and hence different hooks must be configured in different setup functions. === Configuring Hooks === Some extensions must use hooks to do their work. These required hooks can be configured manually by the user by modifying the `[hook]` section of their hgrc, but they can also be configured automatically by calling the `ui.setconfig('hooks', ...)` function in one of the setup functions described above. The main difference between manually modifying the hooks section in the hgrc and using `ui.setconfig()` is that when using `ui.setconfig()` you have access to the actual hook function object, which you can pass directly to `ui.setconfig()`, while when you use the hooks section of the hgrc file you must refer to the hook function by using the "`python:modulename.functioname`" idiom (e.g. "`python:hgext.notify.hook`"). For example: {{{ def myextensionupdatehook(ui, repo, **kwargs): # This hook should be executed when the pre-commit event happens # This must be configured by means of the ui.setconfig() function # in the ui or extension setup functions # Note that the actual name of the hook function is irrelevant. print("Pre-commit hook triggered") def myextensionupdatehook(ui, repo, **kwargs): # This hook should be executed when the update event happens # This must be configured by means of the ui.setconfig() function # in the repository setup function # Note that the actual name of the hook function is irrelevant. print("Update hook triggered") def uisetup(ui): # Automatically configure the notification changegroup hook # Note the use of ui.setconfig. This is similar to having manually # modified the hgrc file by setting the [hooks]/update.mysection key to ui.setconfig("hooks", "pre-commit.myextension", myextensionprecommithook) def reposetup(ui, repo): # Automatically configure the notification changegroup hook ui.setconfig("hooks", "update.myextension", myextensionupdatehook) }}} . Note how different hooks may need to be configured in different setup functions. In the example you can see that the update hook must be configured in the `reposetup` function, while the pre-commit hook must be configured on the `uisetup` or the `extsetup` functions. |
|
Line 88: | Line 168: |
{{{ #!python |
{{{#!python |
Line 106: | Line 184: |
# # For experimenting with Mercurial in the python interpreter: # Getting the repository of the current dir: |
# # For experimenting with Mercurial in the python interpreter: # Getting the repository of the current dir: |
Line 121: | Line 199: |
# the string representation of a context returns a smaller portion of the sha1 ui.write("short %s %s\n" % (parents[0], parents[1])) |
# the string representation of a context returns a smaller portion of the sha1 ui.write("short %s %s\n" % (parents[0], parents[1])) |
Line 124: | Line 202: |
# the hex representation of a context returns the full sha1 ui.write("long %s %s\n" % (parents[0].hex(), parents[1].hex())) |
# the hex representation of a context returns the full sha1 ui.write("long %s %s\n" % (parents[0].hex(), parents[1].hex())) |
Line 127: | Line 205: |
ui.write("default %s %s\n" % (parents[0], parents[1])) | ui.write("default %s %s\n" % (parents[0], parents[1])) |
Line 132: | Line 210: |
# see mercurial/fancyopts.py for all of the command # flag options. |
# see mercurial/fancyopts.py for all of the command # flag options. |
Line 138: | Line 216: |
}}} |
}}} |
Line 144: | Line 220: |
Line 150: | Line 225: |
See CategoryExtension for related pages and [[UsingExtensions]] for a list of readily avaliable extensions bundled with Mercurial or provided by third parties. | See CategoryExtension for related pages and UsingExtensions for a list of readily avaliable extensions bundled with Mercurial or provided by third parties. |
Writing Mercurial extensions
Mercurial features an extension mechanism for adding new commands.
Extensions allow the creation of new features and using them directly from the main hg command line as if they were built-in commands. The extensions have full access to the MercurialApi.
1. Writing your own extension
1.1. File Layout
Extensions are usually written as simple python modules. Larger ones are better split into multiple modules of a single package (see ConvertExtension). The package root module gives its name to the extension and implements the cmdtable and optional callbacks described below.
1.2. Command table
To write your own extension, your python module can provide an optional dict named cmdtable with entries describing each command.
1.2.1. The cmdtable dictionary
The cmdtable dictionary uses as key the new command names, and, as value, a tuple containing:
- the function to be called when the command is used.
- a list of options the command can take.
- a command line synopsis for the command (the function docstring is used for the full help).
1.2.2. List of options
All the command flag options are documented in the mercurial/fancyopts.py sources.
The options list is a list of tuples containing:
the short option letter, or '' if no short option is available (for example, o for a -o option).
the long option name (for example, option for a --option option).
- a default value for the option.
- a help string for the option (it's possible to ommit the "hg newcommand" part and only the options and parameter subsstring is needed).
1.2.3. Example cmdtable
cmdtable = { # "command-name": (function-call, options-list, help-string) "print-parents": (printparents, [('s', 'short', None, 'print short form'), ('l', 'long', None, 'print long form')], "hg print-parents [options] node") }
1.3. Command function signatures
Functions that implement new commands always receive a ui and usually a repo parameter. Please see the MercurialApi for information on how to use these. The rest of parameters are taken from the command line items that don't start with a dash and are passed in the same order they were written. If no default value is given in the parameter list they are required.
If there is no repo to be associated with the command and consequently no repo passed then commands should be imported from mercurial and the extension name should be added to commands.norepo like this:
from mercurial import commands ... commands.norepo += " mycommand"
For examples of norepo see the source code to the RcpathExtension (direct link to RcpathExtension/rcpath.py extension source) or the ConvertExtension (direct link to convert extension source).
1.4. Command function docstrings
The docstring of your function is used as the main help text, shown by hg help mycommand. The docstring should be formatted using a simple subset of reStructuredText markup. The supported constructs include:
Paragraphs:
This is a paragraph. Paragraphs are separated by blank lines.
A verbatim block is introduced with a double colon followed by an indented block. The double colos is turned into a single colon on display:
Some text:: verbatim text !!
We have field lists:
:key1: value1 :key2: value2
Bullet lists:
- foo - bar
Enumerated lists:
1. foo 2. bar
Inline markup: *bold*, ``monospace``. Mark Mercurial commands as :hg:`command` to make a nice link to the corresponding documentation. We'll expand the support if new constructs can be parsed without too much trouble.
1.5. Communicating with the user
Besides the ui methods listed in MercurialApi, like ui.write(*msg) or ui.prompt(msg, default="y"), an extension can add help text for each of its commands and the extension itself.
The module docstring will be used as help string when hg help extensionname is used and, similarly, the help string for a command and the docstring belonging to the function that's wrapped by the command will be shown when hg help command is invoked.
1.6. Setup Callbacks
Extensions are loaded in phases, all extensions are processed in a given phase before the next phase begins. In the first phase all extension modules are loaded and registered with Mercurial. this means that you can find all enabled extensions with extensions.find in the following phases.
1.6.1. ui setup
Extensions can implement an optional callback named uisetup. uisetup is called when the extension is first loaded and receives a ui object:
def uisetup(ui): # ...
1.6.2. Extension setup
Extensions can implement an optional callback named extsetup. It is called after all the extension are loaded, and can be useful in case one extension optionally depends on another extension. Signature:
def extsetup(): # ...
Mercurial version 8e6019b16a7d and later (that is post-1.3.1) will pass a ui argument to extsetup.
1.6.3. Command table setup
After extsetup, the cmdtable is copied into the global command table in Mercurial.
1.6.4. Repository setup
Extensions can implement an optional callback named reposetup. It is called after the main Mercurial repository initialization, and can be used to setup any local state the extension might need.
As other command functions it receives an ui object and a repo object (no additional parameters for this, though):
def reposetup(ui, repo): #do initialization here.
It is important to take into account that the ui object that is received by the reposetup function is not the same as the one received by the uisetup and extsetup functions. This is particularly important when setting up hooks as described in the following section, since not all hooks us the same ui object and hence different hooks must be configured in different setup functions.
1.7. Configuring Hooks
Some extensions must use hooks to do their work. These required hooks can be configured manually by the user by modifying the [hook] section of their hgrc, but they can also be configured automatically by calling the ui.setconfig('hooks', ...) function in one of the setup functions described above.
The main difference between manually modifying the hooks section in the hgrc and using ui.setconfig() is that when using ui.setconfig() you have access to the actual hook function object, which you can pass directly to ui.setconfig(), while when you use the hooks section of the hgrc file you must refer to the hook function by using the "python:modulename.functioname" idiom (e.g. "python:hgext.notify.hook").
For example:
def myextensionupdatehook(ui, repo, **kwargs): # This hook should be executed when the pre-commit event happens # This must be configured by means of the ui.setconfig() function # in the ui or extension setup functions # Note that the actual name of the hook function is irrelevant. print("Pre-commit hook triggered") def myextensionupdatehook(ui, repo, **kwargs): # This hook should be executed when the update event happens # This must be configured by means of the ui.setconfig() function # in the repository setup function # Note that the actual name of the hook function is irrelevant. print("Update hook triggered") def uisetup(ui): # Automatically configure the notification changegroup hook # Note the use of ui.setconfig. This is similar to having manually # modified the hgrc file by setting the [hooks]/update.mysection key to ui.setconfig("hooks", "pre-commit.myextension", myextensionprecommithook) def reposetup(ui, repo): # Automatically configure the notification changegroup hook ui.setconfig("hooks", "update.myextension", myextensionupdatehook)
Note how different hooks may need to be configured in different setup functions. In the example you can see that the update hook must be configured in the reposetup function, while the pre-commit hook must be configured on the uisetup or the extsetup functions.
2. Example extension
1 #!/usr/bin/env python
2
3 '''printparents
4
5 Prints the parents of a given revision.
6 '''
7
8 from mercurial import hg
9
10 # every command must take a ui and and repo as arguments.
11 # opts is a dict where you can find other command line flags
12 #
13 # Other parameters are taken in order from items on the command line that
14 # don't start with a dash. If no default value is given in the parameter list,
15 # they are required.
16 #
17 # For experimenting with Mercurial in the python interpreter:
18 # Getting the repository of the current dir:
19 # >>> from mercurial import hg, ui
20 # >>> repo = hg.repository(ui.ui(), path = ".")
21
22 def printparents(ui, repo, node, **opts):
23 # The doc string below will show up in hg help
24 """Print parent information"""
25
26 # repo can be indexed based on tags, an sha1, or a revision number
27 ctx = repo[node]
28 parents = ctx.parents()
29
30 if opts['short']:
31 # the string representation of a context returns a smaller portion of the sha1
32 ui.write("short %s %s\n" % (parents[0], parents[1]))
33 elif opts['long']:
34 # the hex representation of a context returns the full sha1
35 ui.write("long %s %s\n" % (parents[0].hex(), parents[1].hex()))
36 else:
37 ui.write("default %s %s\n" % (parents[0], parents[1]))
38
39 cmdtable = {
40 # cmd name function call
41 "print-parents": (printparents,
42 # see mercurial/fancyopts.py for all of the command
43 # flag options.
44 [('s', 'short', None, 'print short form'),
45 ('l', 'long', None, 'print long form')],
46 "[options] REV")
47 }
If cmdtable or reposetup is not present, your extension will still work. This means that an extension can work "silently", without making new functionality directly visible through the command line interface.
3. Where to put extensions in the source tree
As of a change shortly after the 0.7 release, the recommended location for installing extensions in the source tree is the hgext directory. If you put a file in there called foo.py, you will need to refer to it in the hgrc file as a qualified package name, hgext.foo.
The contents of the hgext directory will be installed by the top-level setup.py script along with the rest of Mercurial.
See CategoryExtension for related pages and UsingExtensions for a list of readily avaliable extensions bundled with Mercurial or provided by third parties.