[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
GPS provides several levels of customization, from simple preferences dialog
to powerful scripting capability through the python
language.
This chapters describes each of these capabilities.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Edit->Preferences
, allows you to
modify the global preferences of GPS.
To enable the new preferences, you simply need to confirm by pressing
the OK
button. To test your changes, you can use the Apply
button. Pressing the Cancel
button will undo all your changes.
Each preference is composed of a label displaying the name of the preference, and an editing area to modify its value. If you leave to mouse over the label, a tool tip will be displayed giving an on-line help on the preference.
The preferences dialog is composed of several areas, accessible through the tabs at the left of the dialog. Each page corresponds to a set of preferences.
This page allows you to quickly change the current settings for GPS, including preferences, key bindings, menus.... See 15.2 GPS Themes for more information on themes. It is only displayed when there are themes registered.
When this preference is enabled, you can navigate through the menus, and type the key binding you want to associate to a particular item. To remove a key binding, use the Backspace key. Your changes will be saved when GPS exits, in a file called `$HOME/.gps/custom_keys'. In particular, this means that if for some reason you need to edit the file manually, you need to do it outside of GPS, or save the file under a different name, and rename it after exiting GPS.
By default, GPS will call gnatmake to build projects containing Ada sources,
meaning that non Ada sources won't be built. By enabling this preference,
a multi-language build tool, called gprmake
will be called.
Note that this tool is still under development, so this option should
only be activated with caution.
This section specifies preferences that apply to the Multiple Document Interface described in 4. Multiple Document Interface.
If False, the title bar is not displayed, to save space on the screen. The tabs of the notebooks will then be highlighted.
{}[]()
Each modified file is saved under a file called .#filename#
, which is
removed on the next explicit save operation.
Never
Automatic
Always
xterm -geo 80x50 -exe vi +%l %f |
The following substitutions are provided:
%l
%c
%f
%e
%p
%%
variable1, variable2, variable3 : Integer; |
case Value is when others => null; end case; |
If this preference is set to Non_Rm_Style
, this would be indented as:
case Value is when others => null; end case; |
By default (Automatic
), GPS will choose to indent with an extra
level or not based on the first when
construct: if the first
when
is indented by an extra level, the whole case statement will
be indented following the RM style.
Unchanged
will keep the casing as-is;
Upper
will change the casing of all reserved words to upper case;
Lower
will change the casing to lower case;
Mixed
will change the casing to mixed case (all characters to
lower case except first character and characters after an underscore
which are set to upper case);
Smart_Mixed
As above but do not force upper case characters to
lower case.
<=
, :=
, =>
, ...)
Consider the following code:
Variable : constant String := "a string"; |
If this preference is enabled, it will be indented as follows:
Variable : constant String := "a string"; |
Note that in this mode under Windows, the Debug->Interrupt
menu
will not interrupt the debugged program. Instead, you need to hit
Ctrl-C in the separate execution window to interrupt it while it is
running. On Windows this separate execution window uses the default
system-wide console properties (the size of the window, the
colors...). It is possible to change those properties using the
default console menu (top-left of the console) on Windows XP or using
the control panel on Windows NT.
If false, no execution window will be created. The debugger assumes that the program being debugged does not require input, or that if it does, input is handled outside GPS. For example, when you attach to a running process, this process already has a separate associated terminal.
rsh -l user
rcp -l user
This program is required under Unix systems in order to print, and is set to
a2ps
by default.
If a2ps
is not installed on your system, you can download it
from www.inf.enst.fr/~demaille/a2ps
Under Windows systems, this program is optional and is empty by default, since a built-in printing is provided. An external tool will be used if specified, such as the PrintFile freeware utility available from www.lerup.com/printfile/descr.html
Note that in order to perform visual comparison between files, GPS
needs to call external tool (not distributed with GPS) such as diff
or patch
. These tools are usually found on most unix systems, and
may not be available by default on other OSes. Under Windows, you can
download them from one of the unix toolsets
available, such as msys (http://www.mingw.org/msys.shtml) or
cygwin (http://www.cygwin.com).
-c
nor -u
switch).
Arguments of interest may include (this will depend on the version of diff
used):
This command should be compatible with the GNU patch
utility.
GPS assumes that the following restricitions are true when the preference is activated. If this isn't the case, no error is reported, and only minor drawacks will be visible in GPS (no detection that two files are the same if one of them is a symbolic link for instance, although GPS will still warn you if you are trying to overwrite a file modified on the disk).
The restrictions are the following:
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
15.2.1 The Emacs Theme
GPS provides an extensive support for themes. Themes are predefined set of value for the preferences, for the key bindings, or any other configurable aspect of GPS.
For instance, color themes are a convenient way to change all colors in GPS at once, according to predefined choices (strongly contrasted colors, monochrome,...). It is also possible to have key themes, defining a set of key bindings to emulate e.g. other editors.
Any number of themes can be activated at the same time through the
preferences dialog (Edit->Preferences
). This dialog contains a list
of all themes that GPS knows about, organized into categories for convenient
handling. Just click on the buttons on the left of each theme name to activate
that theme.
Note that this will immediately change the current preferences settings. For
instance, if the theme you just selected changes the colors in the editor,
these are changed immediately in the Editor->Fonts & Colors
. You can
of course still press Cancel
to keep your previous settings
If multiple themes are active at the same time and try to override the same preferences, the last theme which is loaded by GPS will override all previously loaded themes. However, there is no predefined order in which the themes are loaded.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The Emacs Theme, which is provided by default with GPS, defines a number of key bindings similar to Emacs.
control-c n
control-k
control-d
control-t
control-x control-s
control-a
control-e
alt-less
control-c control-d
control-c o
control-y
alt-w
control-w
shift-control-underscore
control-x k
control-x control-c
control-s
control-x 3
control-x 2
control-x o
control-l
alt-backspace
alt-right
alt-left
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The key manager is accessible through the menu Edit->Key Shortcuts
.
This dialog provides an easy way to associate key shortcuts with actions.
These actions are either predefined in GPS, or defined in your own
customization files, as documented in 15.4 Customizing through XML files.
It also provides an easy way to redefine the menu shortcuts.
Actions are referenced by their name, and are grouped into categories. These
categories indicate when the action applies. For instance, the indentation
command only applies in source editors, whereas the command to change the
current window applies anywhere in GPS. The categories correspond in fact to
filters that indicate when the action can be executed. You can create your own
new categories by using the <filter>
tag in the customization files
(see section 15.4 Customizing through XML files).
Through the key manager, you can define key bindings similar to what Emacs
uses (control-x followed by control-k for instance). To register
such key bindings, you need to press the Grab
button as usual, and then
type the shortcut. The recording of the key binding will stop a short while
after the last key stroke.
If you define complex shortcuts for menus, they will not appear next to the menu name when you select it with the mouse. This is expected, and is due to technical limitations in the graphical toolkit that GPS uses.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
You can customize lots of capabilities in GPS using XML files that are loaded by GPS at start up.
For example, you can add items in the menu and tool bars, as well as defining new key bindings, new languages, new tools, ...
XML files are found through three mechanisms, described here in the order in
which they are searched. Files with the `.xml' extension found through
GPS_CUSTOM_PATH
or the user's directory can override any setup found in
the system directory. Likewise, files found in the user's directory can
override any file found in the GPS_CUSTOM_PATH
directories.
Note that only files with the `.xml' extension are considered, other files are ignored.
The `INSTALL/share/gps/customize' directory, where `INSTALL' is the name of the GPS installation directory, should contain the files that will always be loaded whenever GPS is started, by any user on the system.
GPS_CUSTOM_PATH
This environment variable can be set before launching GPS. It should contain a list of directories, separated by semicolons (';') on Windows systems and colons (':') on Unix systems. All the files found in these directories will be searched for customization files.
This is a convenient way to have project-specific customization files. You can for instance create scripts, or icons, that set the appropriate value for the variable and then start GPS. Depending on your project, this allows you to load specific aliases which do not make sense for other projects.
The directory `$HOME/.gps/customize' on Unix
systems, and `%HOME%\.gps\customize' on Windows systems, can also contain
customization files which are parsed at startup. This is a convenient way for
users to define their own customization, that they want to load no matter which
project they are working on. Note that you can use the environment variable
GPS_HOME
to override the value of the HOME
variable.
Alternatively, if none of HOME
and GPS_HOME
are defined,
USERPROFILE
is also considered.
XML files must be utf8-encoded by default. In addition, you can specify any
specific encoding through the standard <?xml encoding="..." ?>
declaration, as in the following example:
<?xml version="1.0" encoding="iso-8859-1"?> <submenu> <title>encoded text/title> </submenu> |
Any given XML file can contain customization for various aspects of GPS, mixing aliases, new languages or menus,... in a single file. This is a convenient way to distribute your customization to other users.
These files must be valid XML files, i.e. must start with the
<?xml?>
tag, and contain a single root XML node, the name of which is
left to your consideration. The general format is therefore
<?xml version="1.0" ?> <root_node> ... </root_node> |
The list of valid XML child nodes that can be specified under <root> is described in later sections. It includes:
<action>
<key>
<submenu>
<pref>
<preference>
<alias>
<language>
<button>
<entry>
<vsearch-pattern>
<tool>
<filter>
<contextual>
<case_exceptions>
<documentation_file>
<stock>
<project_attribute>
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This facility distinguishes the actions from their associated menus or key bindings. Actions can take several forms: external commands, shell commands and predefined commands, as will be explained in more details below.
The general form to define new actions is to use the <action>
tag.
This tag accepts the following attributes:
name (mandatory)
output (optional)
<shell>
and <external>
tags,
See section 15.5.4.5 Redirecting the command output.
show-command (optional)
This attribute can be overridden for each command.
If you are defining the same action multiple times, the last definition will be kept. However, existing menus, buttons,... that already reference that action will keep their existing semantic. The new definition will only be used for all new menus created from that point on.
The <action>
can have one or
several children, all of which define a particular command to execute. All
of these commands are executed one after the other, unless one of them
fails in which case the following commands are not executed.
The following XML tags are valid children for <action>
.
<external>
Note for Windows users: like under UNIX, scripts can be called
from custom menu. In order to do that, you must write your script in a
`.bat' or `.cmd' file, and call this file using cmd /c
.
Thus, the external
tag would look like:
<?xml version="1.0" ?> <external_example> <action name="my_command"> <external>cmd /c c:\.gps\my_scripts\my_cmd.cmd</external> </action> </external_example> |
This tag accepts the following attributes:
show-command (optional)
<action>
tag.
output (optional)
<action>
tag.
progress-regexp (optional)
The name of the action is printed in the progress bar while the action is executing.
<?xml version="1.0" ?> <progress_action> <action name="progress" > <external progress-regexp="(\d+) out of (\d+).*$" progress-current="1" progress-final="2" progress-hide="true">gnatmake foo.adb </external> </action> </progress_action> |
progress-current (optional)
progress-regexp
that contains the current step.
progress-final (optional)
progress-regexp
that contains the current last step. This last index can grow as
needed. For example, gnatmake will output the number of
the file it is currently examining, and the total number of files to be
examined. However, that last number may grow up, since parsing a new file
might generate a list of additional files to parse later on.
progress-hide (optional)
progress-regexp
and are used to compute the progress will
not be displayed in the output console. For any other value of this
attribute, these lines are displayed along will the rest of the output.
<on-failure>
This tag specifies a group of command to be executed if the previous external command fails. Typically, this is used to parse the output of the command and fill the location window appropriately (see section 15.5.4.6 Processing the tool output).
For instance, the following action spawn an external tool, and parses its output to the location window and the automatic fixing tool if the external tool happens to fail.
In this group of commands the %... and $... macros can be used.
<?xml version="1.0" ?> <action_launch_to_location> <action name="launch tool to location" > <external>tool-path</external> <on-failure> <shell>Locations.parse "%1" category<shell> <external>echo the error message is "%2"</external> </on-failure> <external>echo the tool succeeded with message %1</external> </action> </action_launch_to_location> |
<shell>
shell
tag. These are command written in one of the
shell scripts supported by GPS.
This tag supports the same show-command
and output
attributes
as the <action>
tag.
The following example shows how to
create two actions to invoke the help
interactive command and to open
the file `main.c'.
<?xml version="1.0" ?> <help> <action name="help"> <shell>help</shell> </action> <action name="edit"> <shell>edit main.c</shell> </action> </help> |
By default, commands are expected to be written in the GPS shell language.
However, you can specify the language through the lang
attribute. Its
default value is "shell"
.
The value of this attribute could also be "python".
When programming with the GPS shell, you can execute multiple commands by separating them with semicolons. Therefore, the following example adds a menu which lists all the files used by the current file, in a project browser.
<?xml version="1.0" ?> <current_file_uses> <action name="current file uses"> <shell lang="shell">File %f</shell> <shell lang="shell">File.uses %1</shell> </action> </current_file_uses> |
<description>
<filter>, <filter_and>, <filter_or>
It is possible to mix both shell commands and external commands. For instance, the following command opens an xterm (on Unix systems only) in the current directory, which depends on the context.
<?xml version="1.0" ?> <xterm_directory> <action "xterm in current directory"> <shell lang="shell">cd %d</shell> <external>xterm</external> </action> </xterm_directory> |
As seen in some of the examples above, some special strings are expanded by GPS just prior to executing the command. These are the "%f", "%d",.. See below for a full list.
More information on chaining commands is provided in See section 15.5.4.1 Chaining commands.
Some actions are also predefined in GPS itself. This include for instance
aliases expansion, manipulating MDI windows,... All known actions (predefined
and the ones you have defined in your own customization files) can be
discovered by opening the key shortcut editor (Edit->Key shortcuts
menu).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When an action is defined, you can use macro arguments to pass to your shell or external commands. Macro arguments are special parameters that are transformed every time the command is executed. The following macro arguments are provided.
The equivalent python command is given for all tests. These commands are useful when you are writing a full python script, and want to test for yourself whether the context is properly defined.
%f
Python equivalent:
import os.path os.path.basename (GPS.current_context().file().name()) |
%F
Python equivalent:
GPS.current_context().file().name() |
%d
Python equivalent:
GPS.current_context().directory() |
%p
Python equivalent:
GPS.current_context().project().name() |
%P
Python equivalent:
GPS.Project.root().name() |
%pp
Python equivalent:
GPS.current_context().project().file().name() |
%PP
Python equivalent:
GPS.Project.root().file().name() |
%pps
%pp
, except it returns the project name prepended
with -P
, or an empty string if there is no project file selected and the
current source file doesn't belong to any project. This is mostly for use with
the GNAT command line tools.
Python equivalent:
if GPS.current_context().project(): return "-P" & GPS.current_context().project().path() |
%PPs
%PP
, except it returns the project name prepended
with -P
, or an empty string if the root project is the default project.
This is mostly for use with the GNAT command line tools.
%(p|P)[r](d|s)[f]
P
p
r
d
Python equivalent:
GPS.current_context().project().source_dirs() |
s
Python equivalent:
GPS.current_context().project().sources() |
f
%Ps
%prs
%prdf
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
By default, an action will execute in any context in GPS. The user just selects the menu or key, and GPS tries to execute the action.
It is possible to restrict when an action should be considered as valid. If the current context is incorrect for the action, GPS will not attempt to run anything, and will display an error message for the user.
Actions can be restricted in several ways:
For instance, if you have specified %F
as a parameter to one of the
commands, GPS will check prior to running the action that there is a current
file. This can be either a currently selected file editor, or for instance that
the project explorer is selected, and a file node inside it is also selected.
You do not have to specify anything else, this filtering is automatic
<filter>
, <filter_and>
and <filter_or>
tags, see below.
These tags can be used to further restrict when the command is valid. For instance, you can use them to specify that the command only applies to Ada files, or only if a source editor is currently selected.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Such filters can be defined in one of two places in the customization files:
<action>
, <menu>
or
<button>
tags, you can define named filters. These are general filters,
that can be referenced elsewhere without requiring code duplication. They
also appear explicitly in the key shortcuts editor if at least one action is
depending on them.
<action>
tag
Such filters are anonymous, although they provide exactly the same capabilities
as the ones above. These are mostly meant for simple filters, or filters that
you use only once, or don't want to appear in the key shortcuts manager.
There are three different kinds of tags:
<filter>
<filter_and>
<filter>
, <filter_and>
and <filter_or>
.
<filter_or>
<filter>
,
<filter_and>
and <filter_or>
.
If several such tags are found following one another under an <action>
tag, they are combined through "or", i.e. any of the filters may match for the
action to be executed.
The <filter>
, <filter_and>
and <filter_or>
tags accept the
following set of common attributes:
name (optional)
id
attribute. The name can
take any form. This is also the name that appears in the context of the
key shortcuts editor.
error (optional)
<filter_and>
and <filter_or>
, only the error message of
the top-level filter will be printed.
In addition, the <filter>
has the following specific attributes:
id (optional)
<?xml version="1.0" ?> <test_filter> <filter name="Test filter" language="ada" /> <action name="Test action" > <filter id="Test filter" /> <shell>pwd</shell> </action> </test_filter> |
A number of filters are predefined by GPS itself. The full list appears in the key shortcut editor, and is listed here:
Source editor
language (optional)
ada
,
you must have an Ada file selected, or the action won't execute. The language
for a file is found by GPS following several algorithms (file extensions, and
via the naming scheme defined in the project files).
shell_cmd (optional)
Note that currently no expansion of macro arguments (%f, %p,...) is done in this command.
shell_lang (optional)
module (optional)
The list of module names can be obtained by typing lsmod
in the shell
console at the bottom of the GPS window.
This attribute is mostly useful when creating new contextual menus.
When several attributes are specified for a <filter>
node (which is not
possible with id
), they must all match for the action to be executed.
<?xml version="1.0" ?> <!-- The following filter will only match if the currently selected window is a text editor editing an Ada source file --> <ada_editor> <filter_and name="Source editor in Ada" > <filter language="ada" /> <filter id="Source editor" /> </filter_and> <!-- The following action will only be executed for such an editor --> <action name="Test Ada action" > <filter id="Source editor in Ada" /> <shell>pwd</shell> </action> <!-- An action with an anonymous filter. It will be executed if the selected file is in Ada, even if the file was selected through the project explorer --> <action name="Test for Ada files" > <filter language="ada" /> <shell>pwd</shell> </action> </ada_editor> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
These commands can be associated with menus, tool bar buttons and keys. All of these use similar syntax.
Binding a menu to an action is done through the <menu>
and
<submenu>
tags.
The <menu>
tag takes the following attributes:
action (mandatory)
This attribute can be omitted only when no title is specified for the menu to make it a separator (see below).
before (optional)
after (optional)
before
, but has a lower priority. If it
is specified, and there is no before
attribute, it specifies a reference
menu after which the new menu should be inserted.
It should also have one XML child called <title>
which specifies the
label of the menu. This is really a path to a menu, and thus you can define
submenus by specifying something like "/Parent1/Parent2/Menu" in the title
to automatically create the parent menus if they don't exist yet.
You can define the accelerator keys for your menus, using underscores
in the titles. Thus, if you want an accelerator on the first letter in
a menu named File
, set its title as _File
.
The tag <submenu>
accepts the following attributes:
before (optional)
<menu>
after (optional)
<menu>
It accepts several children, among <title>
(which must be specified
at most once), <submenu>
(for nested menus), and <menu>
.
Since <submenu>
doesn't accept the action
attribute, you should
use <menu>
for clickable items that should result in an action, and
<submenu>
if you want to define several menus with the same path.
You can specify which menu the new item is added to in one of two ways:
title
attribute of <menu>
<menu>
as a child of a <submenu>
node
This requires slightly more typing, but it allows you to specify the exact
location, at each level, of the parent menu (before or after an existing
menu).
For example, this adds an item named mymenu
to the standard
Edit
menu.
<?xml version="1.0" ?> <test> <submenu> <title>Edit</title> <menu action="current file uses"> <title>mymenu</title> </menu> </submenu> </test> |
The following has exactly the same effect:
<?xml version="1.0" ?> <test> <menu action="current file uses"> <title>Edit/mymenu</title> </menu> </test> |
The following adds a new item "stats" to the "unit testing" submenu in "my_tools".
<?xml version="1.0" ?> <test> <menu action="execute my stats"> <title>/My_Tools/unit testing/stats</title> </menu> </test> |
The previous syntax is shorter, but less flexible than the following,
where we also force the My_Tools menu, if it doesn't exist yet, to
appear after the File menu. This is not doable by using only <menu>
tags. We also insert several items in that new menu
<?xml version="1.0" ?> <test> <submenu after="File"> <title>My_Tools</title> <menu action="execute my stats"> <title>unit testing/stats</title> </menu> <menu action="execute my stats2"> <title>unit testing/stats2</title> </menu> </submenu> </test> |
Adding an item with an empty title or no title at all inserts a menu separator. For instance, the following example will insert a separator followed by a File/Custom menu:
<?xml version="1.0" ?> <menus> <action name="execute my stats" /> <submenu> <title>File</title> <menu><title/></menu> <menu action="execute my stats"> <title>Custom</title> </menu> </submenu> </menus> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The actions can also be used to contribute new entries in the contextual menus everywhere in GPS. These menus are displayed when the user presses the right mouse button, and should only show actions relevant to the current context.
Such contributions are done through the <contextual>
tag, which takes
one mandatory attribute action
, which is the name of the action to
execute, and must be defined elsewhere in one of the customization files.
It accepts one child tag, <Title>
which specifies the name of the
menu entry. If this child is not specified, the menu entry will use the name
of the action itself. The title is in fact the full path to the new menu entry.
Therefore, you can create submenus by using a title of the form
"Parent1/Parent2/Menu".
The new contextual menu will only be shown if the filters associated with the action match the current context.
For instance, the following example inserts a new contextual menu which prints the name of the current file in the GPS console. This contextual menu is only displayed in source editors.
<?xml version="1.0" ?> <print> <action name="print current file name" > <filter module="Source_Editor" /> <shell>echo %f</shell> </action> <contextual action="print current file name" > <Title>Print Current File Name</Title> </contextual> </print> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
As an alternative to creating new menu items, you can create new
buttons on the tool bar, with a similar syntax, by using
the <button>
tag. As for the <menu>
tag, it requires an
action
attribute which specifies what should be done when the button
is pressed. The button is not created if no such action was created.
Within this tag, the tag <pixmap>
can be used to indicate
the location of an image file (of the type jpeg, png, gif
or xpm
) to be used as icon for the button. An empty
<button>
tag indicates a separator in the tool bar.
A title can also be specified with <title>
. This will be visible only
if the user choses to see both text and icons in the tool bar.
The following example defines a new button:
<?xml version="1.0" ?> <stats> <button action="execute my stats"> <title>stats</title> <pixmap>/my_pixmaps/button.jpg</pixmap> </button> </stats> |
The <button>
tag allows you to create a simple button that the user
can press to start an action. GPS also supports another type of button,
a combo box, from which the user can choose among a list of choices. Such
a combo box can be created with the <entry>
tag.
This tag accepts the following arguments:
id (mandatory)
This should be a unique id for this combo box, and will be used later on to refer it, in particular from the scripting languages. It can be any string
label (default is "")
The text of a label to display on the left of the combo box. If this isn't specified, no text will be displayed
on-changed (default is "")
The name of a GPS action to execute whenever the user selects a new value in the combo box. This action is called with two parameters, the unique id of the combo box and the newly selected text respectively.
It also accepts any number of <choice>
tags, each of which defines
one of the values the user can choose from. These tags accepts one optional
attribute, "on-selected", which is the name of a GPS action to call when
that particular value is selected.
<action name="animal_changed"> <shell>echo A new animal was selected in combo $1: animal is $2"</shell> </action> <action name="gnu-selected"> <shell>echo Congratulations on choosing a Gnu</shell> </action> <entry id="foo" label="Animal" on-changed="animal_changed"> <choice>Elephant</choice> <choice on-selected="gnu-selected">Gnu</choice> </entry> |
A more convenient interface exists for Python, the GPS.Toolbar class, which gives you the same flexibility as above, but also gives you dynamic control over the entry. See the python documentation.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
All the actions defined above can be bound to specific key shortcuts through
the <key>
attribute. As usual, it requires one <action>
attribute to specify what to do when the key is pressed. The name of the
action can start with a '/' to indicate that a menu should be executed
instead of a user-defined action.
This tag doesn't contain any child tag. Instead, its text contents specified
the keyboard shortcut. The name
of the key can be prefixed by control-
, alt-
, shift-
or
any combination of these to specify the key modifiers to apply.
You can also define multiple key bindings similar to Emacs's by separating them
by a space. For instance, control-x control-k
means that the user should
press control-x, followed by a control-k to activate the
corresponding action.
Use an empty string to describe the key binding if you wish to deactivate a preexisting binding. The second example below deactivates the standard binding.
<?xml version="1.0" ?> <keys> <key action="expand alias">control-o</key> <key action="Jump to matching delimiter" /> <!-- Bind a key to a menu --> <key action="/Window/Close">control-x control-w</key> </key> |
Multiple actions can be bound to the same key binding. The first one with a filter valid for the current context is executed. If no action with a filter can be executed, then the first action with no filter will be executed.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
GPS has a number of predefined preferences to configure its behavior and its appearance. They are all customizable through the Edit->Preferences menu.
However, you might wish to add your own kind of preferences for your extension modules. This can easily be done through the usual GPS customization files. Preferences are different from project attributes (see section 15.4.14 Defining project attributes), in that the latter will vary depending on which project is loaded by the user, whereas preferences are always set to the same value no matter what project is loaded.
Such preferences are created with the <preference>
tag, which takes
a number of attributes.
name (mandatory)
This is the name of the preference, used when the preference is saved by
GPS in the `$HOME/.gps/preferences' file, and to query the value of
a preference interactively through the GPS.Preference
class in the
GPS shell or python. There are a few limitation to the form of these names:
they cannot contain space or underscore characters. You should replace the
latter with minus signs for instance.
page (optional, default is "General")
The name of the page in the preferences editor where the preference can be edited. If this is the name of a non-existing page, GPS will automatically create it. If this is the empty string (""), the preference will not be editable interactively. This could be used to save a value from one session of GPS to the next, without allowing the user to alter it.
Subpages are references by separating pages name with colons (':').
default (optional, default depends on the type of the preference)
The default value of the preference, when not set by the user. This is 0 for integer preferences, the empty string for string preferences, True for boolean values, and the first possible choice for choice preferences.
tip (optional, default is "")
This is the text of the tooltip that appears in the preferences editor dialog.
label (mandatory)
This is the name of the preference as it appears in the preferences editor dialog
type (mandatory)
This is the type of the preference, and should be one of:
The preference can be True or False.
The preference is an integer. Two optional attributes can be specified for
<preference>
, "minimum" and "maximum", which define the range of
valid values for that integer. Default values are 0 and 10 respectively.
The preference is a string, which might contain any value
The preference is a color name, in the format of a named color such as "yellow", or a string similar to "#RRGGBB", where RR is the red component, GG is the green component, and BB is the blue component
The preference is a font
The preference is a string, whose value is chosen among a static list of
possible values. Each possible value is defined in a <choice>
child
of the <preference>
node.
Here is an example that defines a few new preferences:
<?xml version="1.0"?> <custom> <preference name="my-int" page="Editor" label="My Integer" default="30" minimum="20" maximum="35" page="Manu" type="integer" /> <preference name="my-enum" page="Editor:Fonts & Colors" label="My Enum" default="1" type="choices" > <choice>Choice1</choice> <choice>Choice2</choice> <!-- The default choice --> <choice>Choice3</choice> </preference> </custom> |
The values of the above preferences can be queries in the scripting languages:
Preference "my-enum" Preference.get %1 |
val = GPS.Preference ("my-enum").get () val2 = GPS.Preference ("my-int").get () |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
You can force specific default values for the preferences in the customization
files through the <pref>
tag. This is the same tag that is used by
GPS itself when it saves the preferences edited through the preferences
dialog.
This tag requires on attribute:
name
It accepts no child tag, but the value of the <pref>
tag defines the
default value of the preference, which will be used unless the user has
overridden it in his own preferences file.
Any setting that you have defined in the customization files will be overridden by the user's preferences file itself, unless the user was still using the default value of that preference.
This <pref>
tag is mostly intended for use through the themes
(see section 15.4.9 Creating themes).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In addition to the predefined themes that come with GPS, you can create your own themes and share them between users. You can then selectively chose which themes they want to activate through the preferences dialog (see section 15.2 GPS Themes).
Creating new themes is done in the customization files through
the <theme>
tag.
This tag accepts a number of attributes:
name (mandatory)
description (optional)
category (optional, default is General)
This tag accepts any other customization tag that can be put in the
customization files. This includes setting preferences (<pref>
,
defining key bindings (<key
), defining menus (<menu>
),...
If the same theme is defined in multiple locations (multiple times in the same customization file or in different files), their effects will be cumulated. The first definition of the theme seen by GPS will set the description and category for this theme.
All the children tags of the theme will be executed when the theme is activated
through the preferences dialog. Although there is no strict ordering in which
order the children will be executed, the global order is the same as for the
customization files themselves: first the predefined themes of GPS, then the
ones defined in customization files found through the GPS_CUSTOM_PATH
directories, and finally the ones defined in files found in the user's
own GPS directory.
<?xml version="1.0" ?> <customize> <theme name="my theme" description="Create a new menu"> <menu action="my action"><title>/Edit/My Theme Menu</title></menu> </theme> </customize> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The search dialog contains a number of predefined search patterns for Ada, C and C++. These are generally complex regular expressions, presented in the dialog with a more descriptive name. This includes for instance "Ada assignment", which will match all such assignments.
You can define your own search patterns in the customization files. This is
done through the <vsearch-pattern>
tag. This tag can have a number of
children tags:
<name>
This tag is the string that is displayed in the search dialog to represent the new pattern. This is the text that the user will effectively see, instead of the often hard to understand regular expression.
<regexp>
This tag provides the regular expression to use when the pattern has been selected by the user. Be careful that you must protect reserved XML characters such as '<' and replace them by their equivalent expansion ("<" for this character).
This accepts one optional attribute, named case-sensitive
. This
attribute accepts one of two possible values ("true" or "false") which
indicates whether the search should distinguish lower case and upper
case letters. Its default value is "false".
<string>
This tag provides a constant string that should be searched.
Only one of <regexp>
and <string>
should be provided. If
both exists, the first <regexp>
child found is used. If there is
none, the first <string>
child is used.
The tag accepts the same optional attribute case-sensitive
as
above
Here is a small example on how the "Ada assignment" pattern was defined.
<?xml version="1.0" ?> <search> <vsearch-pattern> <name>Ada: assignment</name> <regexp case-sensitive="false">\b(\w+)\s*:=</regexp> </vsearch-pattern> </search> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
You can define new languages in a custom file by using the Language
tag. Defining languages gives GPS the ability to highlight the syntax of a
file, explore a file (using e.g. the project explorer), find files
associated with a given language, ...
As described previously for menu items, any file in the `customize' directory will be loaded by GPS at start up. Therefore, you can either define new languages in a separate file, or reuse a file where you already define actions and menus.
The following tags are available in a Language
section:
Name
Parent
Ada
, C++
) or
another custom language, this language will inherit by default all its
properties from this language. Any field explicitly defined for this language
will override the inherited settings.
Spec_Suffix
Extension
tag instead.
This tag must be unique.
Body_Suffix
Spec_Suffix
, so that the user
can choose to easily go from one file to the other.
This tag must be unique.
Extension
Keywords
Keywords
tags can be specified, and will be concatenated
into a single regular expression.
The full grammar of the regular expression can be found in the spec of the file `g-regpat.ads' in the GNAT run time.
Engine
The name can be a full pathname, or a short name. E.g. under most Unix systems
if you specify custom
, GPS will look for libcustom.so
in
the LD_LIBRARY_PATH
run time search path. You can also specify
explicitly e.g. libcustom.so
or /usr/lib/libcustom.so
.
For each of the following five items, GPS will look for the corresponding
symbol in Engine
and if found, will call this symbol when needed.
Otherwise, it will default to the static behavior, as defined by the other
language-related items describing a language.
You will find the required specification for the C and Ada languages
to implement the following functions in the directory
`<prefix>/share/gps/doc/examples/language' of your GPS installation.
`language_custom.ads' is the Ada spec file; `language_custom.h' is
the C spec file; `gpr_custom.ad?' are example files showing a possible Ada
implementation of the function Comment_Line
for the GPS project files (`.gpr' files), or any other Ada-like language;
`gprcustom.c' is the C version of gpr_custom.adb.
Comment_Line
Edit->Un/Comment Lines
).
Parse_Constructs
This procedure is used by GPS to implement several capabilities such as listing constructs in the project explorer, highlighting the current block of code, going to the next or previous procedure, ...
Format_Buffer
This procedure is used to implement the auto indentation when hitting the enter key, or when using the format key on the current selection or the current line.
Parse_Entities
Context
node described below.
Context
Comment_Start
Comment_End
New_Line_Comment_Start
;|#
for comments starting
after a semicolon or after the hash sign.
String_Delimiter
Quote_Character
\
in C).
Constant_Character
Can_Indent
Syntax_Highlighting
Case_Sensitive
Categories
Category
nodes,
each describing the characteristics of a given category, with the following
nodes:
Name
Pattern
Keywords
node, multiple Pattern
tags can be
specified and will be concatenated into a single regular expression.
Index
Here is an example of a language definition for the GPS project files:
<?xml version="1.0"?> <Custom> <Language> <Name>Project File</Name> <Spec_Suffix>.gpr</Spec_Suffix> <Keywords>^(case|e(nd|xte(nds|rnal))|for|is|</Keywords> <Keywords>limited|null|others|</Keywords> <Keywords>p(ackage|roject)|renames|type|use|w(hen|ith))\b</Keywords> <Context> <New_Line_Comment_Start>--</New_Line_Comment_Start> <String_Delimiter>"</String_Delimiter> <Constant_Character>'</Constant_Character> <Can_Indent>True</Can_Indent> <Syntax_Highlighting>True</Syntax_Highlighting> <Case_Sensitive>False</Case_Sensitive> </Context> <Categories> <Category> <Name>package</Name> <Pattern>^[ \t]*package[ \t]+((\w|\.)+)</Pattern> <Index>1</Index> </Category> <Category> <Name>type</Name> <Pattern>^[ \t]*type[ \t]+(\w+)</Pattern> <Index>1</Index> </Category> </Categories> <Engine>gpr</Engine> <Comment_Line>gpr_comment_line</Comment_Line> </Language> </Custom> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
GPS provides a mechanism known as aliases. These are defined
through the menu Edit->Aliases
.
Each alias has a name, which is generally a short string of characters. When you type them in any textual entry in GPS (generally a source editor, but also entry fields for instance in the file selector), and then press the special activation key (by default control-o, controlled by a preference), this name is removed from the source editor, and replaced by the text you have associated with it.
Alias names may be composed of any character except newlines, but must start with a letter. GPS will jump to the start of each word before the current cursor position, and if the characters between this word start and the cursor position is an alias name, this alias is expanded.
The alias editor is divided into three main parts: on the left side, the list of currently defined aliases is shown. Clicking on any of them will display the replacement text for this alias. If you click again the selected alias, GPS displays a text entry which you can use to rename an existing alias. Alias names must start with a letter. A check button at the bottom selects whether the read-only aliases (i.e. system-wide aliases) should be displayed.
The second part is the expansion text for the alias, at the bottom right corner. This replacement text can used multiple lines, and contain some special text that act as a special replacement. These special texts are highlighted in a different color. You can insert these special entities either by typing them, or by right-clicking in the editor, and select the entity in the contextual menu.
The following special entities are currently defined:
%_
%(name)
%D
%H
%l
%c
%f
%d
%p
%P
%O
You cannot expand an alias recursively when already expanding that alias. For instance, if the alias expansion for procedure contains procedure%O, the inner procedure will not be expanded.
The indentation as set in the expansion of the alias is preserved when
the alias is expanded. All the lines will be indented the same amount
to the right as the alias name. You can override this default behavior
by selecting the check button Indent source editor after expansion
.
In this case, GPS will replace the name of the alias by its expansion,
and then automatically recompute the position of each line with its
internal indentation engine, as if the text had been inserted manually.
The third part of the aliases editor, at the top right corner, lists the parameters for the currently selected alias. Any time you insert a %(name) string in the expansion text, GPS automatically detects there is a new parameter reference (or an old reference has changed name or was removed); the list of parameters is automatically updated to show the current list.
Each parameters has three attributes:
When an alias that contains parameters is expanded, GPS will first display a dialog to ask for the value of the parameters. You can interactively enter this value, which replaces all the %(name) entities in the expansion text.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The customization files described earlier can also contain aliases definition. This can be used for instance to create project or system wide aliases. All the customization files will be parsed to look for aliases definition.
All these customization files are considered as read-only by GPS, and therefore cannot be edited through the graphical interface. It is possible to override some of the aliases in your own custom files.
There is one specific files, which must contain only aliases definition. This is the file `$HOME/.gps/aliases'. Whenever you edit aliases graphically, or create new ones, they are stored in this file, which is the only one that GPS will ever modify automatically.
The system files are loaded first, and aliases defined there can be overridden by the user-defined file.
These files are standard XML customization files. The specific XML tag to use is <alias>, one per new alias. The following example contains a standalone customization file, but you might wish to merge the <alias> tag in any other customization file.
The following tags are available:
alias
name
, which the text to type in the source editor
before pressing control-o.
It has one optional attribute, indent
, which, if set to true,
indicate that GPS should recompute the indentation of the newly inserted
paragraph after the expansion.
param
alias
node. There is one per
parameter of the alias. They have one mandatory attribute,
name
, which is the name to type between %(name) in the
alias expansion text.
They have one optional attribute, environment
, which indicates
the default value must be read from the environment variables if it is
set to true.
These tags contain text, which is the default value for the parameter.
text
alias
node, whose value is the
replacement text for the alias.
Here is an example of an alias file:
<?xml version="1.0"?> <Aliases> <alias name="proc" > <param name="p" >Proc1</param> <param environment="true" name="env" /> <text>procedure %(p) is %(env)%_ end %(p);</text> </alias> </Aliases> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The project files are required by GPS, and are used to store various pieces of information related to the current set of source files. This includes how to find the source files, how the files should be compiled, or manipulated through various tools,....
However, the default set of attributes that are usable in a project file is limited to the attributes needed by the tool packaged with GPS or GNAT.
If you are delivering your own tools, you might want to store similar information in the project files themselves, since these are a very convenient place to associate some specific settings with a given set of source files.
GPS lets manipulate the contents of projects through XML customization files and script commands. You can therefore add you own typed attributes into the projects, so that they are saved automatically when the user saves the project, and reloaded automatically the next time GPS is started.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
New project attributes can be declared in two ways: either using the advanced
XML tags below, or using the <tool>
tag (see section 15.5.3 Defining tool switches).
The customization files support the <project_attribute>
tag,
which is used to declare all the new attributes that GPS should expect
in a project. Attributes that have not been declared explictly will
not be accessible through the GPS scripting languagues, and will
generate warnings in the Messages window.
Project attributes are typed: they can either have a single value, or have a set of such values (a list). The values can in turn be a free-form string, a file name, a directory name, or a value extracted from a list of preset values.
Attributes that have been declared in these customization files will also be graphically editable through the project properties dialog, or the project wizard. Therefore, you should specify when an attribute is defined how it should be presented to the GPS user.
The <project_attribute>
tag accepts the following attributes:
package
(a string, default value: "")
This is the package in the project file in which the attribute is stored. Common practice suggests that one such package should be used for each tool. These packages provide namespaces, so that attributes with the same name, but for different tools, do not conflict with each other.
name
(a string, mandatory)
This is the name of the attribute. This should be a string with no space, and that represents a valid Ada identifier (typically, it should start with a letter and be followed by a set of letters, digits or underscore characters). This is an internal name that is used when saving the attribute in a project file.
editor_page
(a string, default value: "General")
This is the name of the page in the Project Properties editor dialog in which the attribute is presented. If no such page already exists, a new one will be created as needed. If the page already exists, the attribute will be appended at its bottom.
editor_section
(a string, default value: "")
This is the name of the section, inside editor page, in which the
attribute is displayed. These sections are surrounded by frames, the
title of which is given by the editor_section
attribute.
If this attribute is not specified, the attribute is put in an
untitled section.
label
(a string, default value: the name of the attribute)
If this attribute is set to a value other than the empty string
""
, a textual label is displayed to the left of the attribute
in the graphical editor. This should be used to identify the
attribute. However, it can be left to the empty string if the
attribute is in a named section of its own, since the title of the
section might be a good enough indication.
description
(a string, default value: "")
This is the help message that describes the role of the attribute. It is displayed in a tooltip if the user leaves the mouse on top of the attribute for a while.
list
(a boolean, default value: "false")
If this is set to "true"
, the project attribute will in fact
contains a list of values, as opposed to a single value. This is used
for instance for the list of source directories in standard projects.
ordered
(a boolean, default value: "false")
This is only relevant if the project attribute contains a list of values. This indicates whether the order of the values is relevant. In most cases, it will not matter. However, for instance, the order of source directories matters, since this also indicates where the source files will be searched, stopping at the first match.
omit_if_default
(a boolean, default value: "true")
This indicates whether the project attribute should be set explicitly
in the project if the user has left it to its default value. This can
be used to keep the project files a simple as possible, if all the
tools that will use this project attribute know about the default
value. If this isn't the case, set omit_if_default
to "false"
to force the generation of the project attribute.
base_name_only
(a boolean, default value: "false")
If the attribute contains a file name or a directory name, this indicates whether the full path should be stored, or only the base name. In most cases, the full path should be used. However, since GPS automatically looks for source files in the list of directories, for instance, the list of source files should only contain base names. This also increases the portability of project files.
case_sensitive_index
(a boolean, default value: "false")
This XML attribute is only relevant for project attributes that are indexed on another one (see below for more information on indexed attributes). It indicates whether two indexes that differ only by their casing should be considered the same. For instance, if the index is the name of one of the languages supported by GPS, the index is case insensitive since "Ada" is the same as "C". However, if the index is the name of a file on Windows, the index is case-insensitive.
hide_in
(a string, default value: "")
This XML attribute defines the various context in which this attribute should not be editable graphically. Currently, GPS provides two such contexts ("wizard" and "properties", corresponding to the project creation wizard and the project properties editor). If any of those context is specified in hide_in, then the widget to edit this attribute will not be shown. The goal is to keep the graphical interface simple.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The type of the project attribute is specified through one or several
child tags of <project_attribute>
. The following tags are
recognized.
<string>
This tag indicates that the attribute is made of one (or more if it is a list) strings. This tag accepts the following XML attributes:
default
(a string, default value: "")
This gives the default value to be used for the string (and therefore the project attribute), in case the user hasn't overridden it.
type
(one of "", "file", "directory", default "")
This indicates what the string represents. In the first case, any value can be used. In the second case, it should represent a file name, although no check is done to make sure the file actually exists on the disk. But GPS will be able to do some special marshalling with the file name. The third case indicates that GPS should expect a directory.
<choice>
This tag can be repeated several times. It indicates one of the valid
values for the attribute, and can be used to provide a static list of
such values. If it is combined with a <string>
tag, this
indicates that the attribute can be any string, although a set of
possible values is provided to the user for ease of use.
This tag accepts one optional attribute, "default"
, which is a
boolean. It indicates whether this value is the default to use for the
project attribute.
If several <choice>
tags are used, it is possible that several
of them are part of the default value if the project attribute is a
list, as opposed to a single value.
<shell>
This tag is a GPS scripting command to execute to get a list of valid
values for the attribute. The command should return a list. As for the
<choice>
tag, the <shell>
tag can be combined with a
<string>
tag to indicate that the list of values returned by
the scripting command is only a set of possible values, but that the
project attribute can in fact take any value.
The <shell>
tag accepts two attributes:
lang
(a string, default value: "shell")
The scripting language in which the command is written. Currently, the only other possible value is "python".
default
(a string, default value: "")
The default value that the project attribute takes if the user hasn't overridden it.
In some cases, the type of the project attribute, or at least its
default value, depends on what the attribute applies to. The project
file support this in the form of indexed project attribute. This is
for instance used to specify what should be the name of the executable
generated when compiling each of the main files in the project (ie the
executable name for gps.adb
should be gps.exe
, the one
for main.c
should be myapp.exe
, and so on).
Such attributes can also be declared through XML files. In such cases,
the <project_attribute>
tag should have one <index>
child, and zero or more <specialized_index>
children.
Each of these two tags in turn take one of the already mentioned
<string>
, <choice>
or <shell>
tag.
The <index>
tag indicates what other project attribute is used
to index the current one. In the example given above for the
executable names, the index is the attribute that contains the list of
main files for the project.
It accepts the following XML attributes:
attribute
(a string, mandatory)
The name of the other attribute. This other attribute must be declared elsewhere in the customization files, and must be a list of values, not a single value.
package
(a string, default value: "")
The package in which the index project attribute is defined. This is used to uniquely identify homonym attributes.
The <specialized_index>
is used to override the default type of
the attribute for specific values of the index. For instance, the
project files contains an attribute that specify what the name of the
compiler is for each language. It is indexed on the project attribute
that list the languages used for the source files of the project. Its
default value depends on the language ("gnatmake" for Ada, "gcc" for
C, and so on). This attribute accepts requires one XML attribute:
value
(a string, mandatory)
This is the value of the attribute for which the type is overriden.
Note that almost all the standard project attributes are defined through an XML file, `projects.xml', which is part of the GPS installation. Check this file to get advanced examples on how to declare project attributes.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The following example declares three attributes, with a single string as their value. This string represents a file or a directory in the last two cases. You can simply copy this into a `.xml' file in your `$HOME/.gps/customize' directory, as usual.
<?xml version="1.0"?> <custom> <project_attribute name="Single1" package="Test" editor_page="Tests single" editor_section="Single" description="Any string"> <string default="Default value" /> </project_attribute> <project_attribute name="File1" package="Test" editor_page="Tests single" editor_section="Single" description="Any file" > <string type="file" default="/my/file" /> </project_attribute> <project_attribute name="Directory1" package="Test" editor_page="Tests single" editor_section="Single" description="Any directory" > <string type="directory" default="/my/directory/" /> </project_attribute> </custom> |
The following example declares an attribute whose value is a
string. However, a list of predefined possible values is also
provided, as an help for interactive edition for the user. If the
<string>
tag wasn't given, the attribute's value would have two
be one of the three possible choices.
<?xml version="1.0" ?> <custom> <project_attribute name="Static2" package="Test" editor_page="Tests single" editor_section="Single" description="Choice from static list (or any string)" > <choice>Choice1</choice> <choice default="true" >Choice2</choice> <choice>Choice3</choice> <string /> </project_attribute> </custom> |
The following example declares an attribute whose value is one of the languages currently supported by GPS. Since this list of languages is only know when GPS is executed, a script command is used to query this list.
<?xml version="1.0" ?> <custom> <project_attribute name="Dynamic1" package="Test" editor_page="Tests single" editor_section="Single" description="Choice from dynamic list" > <shell default="C" >supported_languages</shell> </project_attribute> </custom> |
The following example declares an attribute whose value is a set of file names. The order of files in this list matters to the tools that are using this project attribute.
<?xml version="1.0" ?> <custom> <project_attribute name="File_List1" package="Test" editor_page="Tests list" editor_section="Lists" list="true" ordered="true" description="List of any file" > <string type="file" default="Default file" /> </project_attribute> </custom> |
The following example declares an attribute whose value is a set of predefined possible values. By default, two such values are selected, unless the user overrides this default setting.
<?xml version="1.0" ?> <custom> <project_attribute name="Static_List1" package="Test" editor_page="Tests list" editor_section="Lists" list="true" description="Any set of values from a static list" > <choice>Choice1</choice> <choice default="true">Choice2</choice> <choice default="true">Choice3</choice> </project_attribute> </custom> |
The following example declares an attribute whose value is a string. However, the value is specific to each language (this could for instance be used for the name of the compiler to use for a given language). This is an indexed project attribute. It has two default values, one for Ada, one for C. All other languages have no default value.
<?xml version="1.0" ?> <custom> <project_attribute name="Compiler_Name" package="Test" editor_page="Tests indexed" editor_section="Single" <index attribute="languages" package=""> <string default="" /> </index> <specialized_index value="Ada" > <string default="gnatmake" /> </specialized_index> <specialized_index value="C" > <string default="gcc" /> </specialized_index> </project_attribute> </custom> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The new attributes that were defined are accessible from the GPS scripting languages, like all the standard attributes, see section 15.5.4.3 Querying project switches.
You can for instance access the Compiler_Name attribute we created above with a python command similar to:
GPS.Project.root().get_attribute_as_string ("Compiler_Name", "Test", "Ada") |
You can also access the list of main files for the project, for instance, by calling
GPS.Project.root().get_attribute_as_list ("main") |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A set of case exceptions can be declared in this file. Each case
exception is put inside the tag <word>
or <substring>
. These
exceptions are used by GPS to set identifiers or keywords case when
editing case insensitive languages (except if corresponding case is
set to Unchanged). see section 15.1 The Preferences Dialog.
<?xml version="1.0" ?> <exceptions> <case_exceptions> <word>GNAT</word> <word>OS_Lib</word> <substring>IO</substring> </case_exceptions> </exceptions> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
New documentation can be added in GPS in various ways. This is useful if you want to point to your own project documentation for instance.
The first possibility is to create a new menu, through a <menu>
tag
in an XML file, associated with an action that either spawn an external
web browser or calls the internal GPS.Help.browse()
shell command.
However, this will not show the documentation in the Help->Contents
menu, which you also might want to do.
To have both results, you should use the <documentation_file>
tag
in an XML file. These tags are generally found in the `gps_index.xml'
files, as documented in see section 3.2 Adding New Help Files, but you can in fact
add them in any of your customization files.
The documentation files you display can contain the usual type of html links. In addition, GPS will treat specially links starting with '%', and consider them as script commands to execute instead of file to display. The following example show how to insert a link that will in effect open a file in GPS when clicked by the user
<a href="%shell:Editor.editor g-os_lib.ads">Open runtime file</a> |
The first word after '%' is the name of the language, and the command to execute is found after the ':' character.
The <documentation_file>
tag accepts two attributes.
The name of the menu before which the new entry should be inserted. If the
new menu is inserted in some submenus, this tag controls the deeper nesting.
Parent menus are created as needed, but if you wish to control their specific
order, you should create them first with a <menu>
tag.
The name of the menu after which the new entry should be inserted.
The <documentation_file>
accepts a number of child nodes:
GPS_DOC_PATH
.
If this child is omitted, you must specify a <shell>
child.
This name can contain a reference to a specific anchor in the html file, using the standard HTML syntax.
<name>file#anchor</name> |
"lang"
, which is the name of the
language in which the command is written
Help->Contents
menu to organize all the
documentation files.
"/"
. The last part of the
path is the name of the new menu item. If not set, no menu is
displayed for this file, although it will still appear in the
Help->Contents
menu
The following example shows how to create a new entry "item" in the Help
menu, that will display `file.html'. The latter is searched in the
GPS_DOC_PATH
list of directories.
<?xml version="1.0"?> <index> <documentation_file> <name>file.html</name> <descr>Tooltip text</descr> <category>name</category> <menu>/Help/item</menu> </documentation_file> </index> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
XML files can be used to define "stock icons". Stock icons are pictures that are identified by their label, and which are used through GPS in various places, such as buttons, menus, toolbars, and so on.
The stock icons must be declared using the tag <icon>
, within the global
tag <stock>
. The attribute id
indicates the label used to identify
the stock icon, and the attribute file
points to the file which contains
the actual picture, either in absolute format, or relative to the directory
which contains the XML file.
For a better rendering, icons that are to be used in menus and buttons should have a size of 24x24 pixels, whereas icons used in toolbars should be 48x48 pixels.
Here is an example:
<?xml version="1.0"?> <my_visual_preferences> <stock> <icon id="myproject-my-picture" file="icons/my-picture.png" /> </stock> </my_visual_preferences> |
Note: as shown in the example above, it is a good practice to prefix the label
by a unique name (e.g. myproject-
), in order to make sure that
predefined stock icons will not get overridden by your icons.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
15.5.1 Defining supported languages 15.5.2 Defining default command line 15.5.3 Defining tool switches 15.5.4 Executing external tools
GPS has built-in support for external tools. This feature can be used to support a wide variety of tools (in particular, to specify different compilers). Regular enhancements are done in this area, so if you are planning to use the external tool support in GPS, check for the latest GPS version available.
Typically, the following things need to be achieved to successfully use a tool:
Each of these points is discussed in further sections. In all these cases, most
of the work can be done statically through XML customization files.
These files have the same format as other XML customization files
(see section 15.4 Customizing through XML files), and the tool descriptions are found in
<tool>
tags.
This tag accepts the following attributes:
name (mandatory)
package (Default value is ide)
See also See section 15.4.14 Defining project attributes, for more information on defining your own project attributes. Using the "package", "attribute" or "index" XML attributes of <tool> will implicitly create new project attributes as needed.
If this attribute is set to "ide", then the switches cannot be set for a specific file, only at the project level. Support for file-specific switches currently requires modification of the GPS sources themselves.
attribute (Default value is default_switches)
index (Default value is the tool name)
This tag accepts the following children, described in separate sections:
<switches>
<language>
<default-cmd-line>
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This is the language to which the tool applies. There can be from no to any
number of such nodes for one <tool>
tag.
If no language is specified, the tool applies to all languages. In particular, the switches editor page will be displayed for all languages, no matter what languages they support.
If at least one language is specified, the switches editor page will only be displayed if that language is supported by the project.
<?xml version="1.0" ?> <my_tool> <tool name="My Tool" > <language>Ada</language> <language>C</language> </tool> </my_tool> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
It is possible to define the command line that should be used for a tool when the user is using the default project, or hasn't overridden this command line in the project.
This is done through the <initial-cmd-line>
tag, as a child of the
<tool>
tag. Its value is the command line that would be passed to the
tool. This command line is parsed as usual, e.g. quotes are taken into account
to avoid splitting switches each time a space is encountered.
<?xml version="1.0" ?> <my_tool> <tool name="My tool" > <initial-cmd-line>-a -b -c</initial-cmd-line> </tool> </my_tool> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The user has to be able to specify which switches to use with the tool. If the tool is simply called through custom menus, you might want to hard code some or all of the switches. However, in the general case it is better to use the project properties editor, so that project-specific switches can be specified.
This is what GPS does by default for Ada, C and C++. You can find in the GPS installation directory how the switches for these languages are defined in an XML file. These provide extended examples of the use of customization files.
The switches editor in the project properties editor provides a powerful interface to the command line, where the user can edit the command line both as text and through GUI widgets.
The switches are declared through the <switches>
tag in the
customization file, which must be a child of a <tool>
tag as described
above.
This <switches>
tag accepts the following attributes:
lines (default value is 1)
columns (default value is 1)
separator (default value is "")
" "
rather than " "
,
since XML parser must normalize the latter to the empty string when reading
the XML file.
This <switches>
tag can have any number of child tag, among the
following. They can be repeated multiple times if you need several check boxes.
For consistency, most of these child tags accept attributes among the
following:
line (default value is 1)
lines
above.
column (default value is 1)
columns
above.
label (mandatory)
switch (mandatory)
combo
and spin
below.
This switch shouldn't contain any space.
tip (default value is empty)
min (default value is 1)
<spin>
tags, and indicates the minimum
value authorized for that switch.
max (default value is 1)
<spin>
tags, and indicates the maximum
value authorized for that switch.
default (default value is 1)
<spin>
tags. See the description below.
noswitch (default is empty)
<combo>
tags, and described below.
nodigit (default is empty)
<combo>
tags, and described below.
value (mandatory)
<combo-entry>
tags.
separator (default is the value given to <switches>
<switches>
.
Here are the valid children for <switches>
:
<title>
line
and column
attributes, is used
to give a name to a specific frame.
The value of the tag is the title itself. You do not have to specify
a name, and this can be left to an empty value.
Extra attributes for <title>
are:
line-span (default value is 1)
column-span (default value is 1)
<check>
line
, column
, label
, switch
and tip
attributes. It creates a toggle button. When the latter is
active, the text defined in the switch attribute is added as is
to the command line. This tag doesn't have any value or child tags.
<spin>
line
, column
, label
, switch
,
tip
, min
, max
, separator
and default
attributes.
This switch will add the contents of the switch
attribute followed by
the current numeric value of the widget to the command line. This is typically
used to indicate indentation length for instance.
If the current value of the widget is equal to the default
attribute,
then nothing is added to the command line.
<radio>
line
and column
attributes. It groups any
number of children, each of which is associated with its own switch. However,
only one of the children can be selected at any given time.
The children must have the tag radio-entry
. This tag accepts the
attributes label
, switch
and tip
. As a special case,
the switch attribute can have an empty value ("") to indicate this is the
default switch to use in this group of radio buttons.
<field>
line
, column
, label
, switch
,
separator
and tip
attributes. This tag describes a text edition
field, which can
contain any text the user types. This text will be prefixed by the value of
the switch
attribute, and the separator (by default nothing). If no text
is entered in the field
by the user, nothing is put on the command line.
This tag accepts two extra attributes:
as-directory (optional)
as-file (optional)
as-directory
, but opens a dialog to
select a file instead of a directory. If both attributes are set to "true",
the user will select a file.
<combo>
line
, column
, label
, switch
,
tip
, noswitch
, separator
and nodigit
attributes.
The text inserted in the command line is the text from the switch
attribute, concatenated with the text of the value
attribute for the
currently selected entry. If the value of the current entry is the same
as that of the nodigit
attribute, then only the text of the
switch
attribute is put on the command line. This is in fact necessary
to interpret the gcc switch "-O" as "-O1".
If the value of the current entry is that of the noswitch
attribute,
then nothing is put in the command line.
The tag <combo>
accepts any number of combo-entry
children tags,
each of which accepts the label
and value
attribute.
<popup>
line
, column
, label
, lines
and columns
attributes. This displays a simply button that, when
clicked, displays a dialog with some extra switches. This dialog, just as the
switches editor itself, is organizes into lines and columns of frames, the
number of which is provided by the lines
and columns
attributes.
This tag accepts any number of children, which are the same as the
<switches>
attribute itself.
<dependency>
It has its own set of attributes:
master-page master-switch
<check>
.
slave-page slave-switch
<check>
.
master-status slave-status
<expansion>
It is easier to explain it through an example. Specifying the GNAT switch "-gnaty" is equivalent to specifying "-gnatyabcefhiklmnprst". This is in fact a style check switch, with a number of default values. But it is also equivalent to decomposing it into several switches, as in "-gnatya", "-gnatyb",... With this information, GPS will try to keep the command line length as short as possible, to keep it readable.
Both these aspects are defined in a unique <expansion>
tag, which
accepts two attributes: switch
is mandatory, and alias
is
optional. Alias contains the text "-gnatyabcefhiklmnprst" in our example.
It also accepts any number of <entry>
children, each has a mandatory
switch
access. The set of all these children define the expanded
equivalent of the switch. In our example, we need one <entry>
child
for "-gnatya", one for "-gnatyb",....
The exact algorithm used by GPS is the following:
switch
attribute that matches exactly, then it is replaced
by all the switches given in the <entry>
children).
If we have <expansion switch="-gnatwa"> <entry switch="-gnatwc" /> <entry switch="-gnatwd" /> </expansion> then any occurrence of "-gnatwa" on the command line is expanded to "-gnatwc -gnatwd" |
switch
attribute of an <expansion>
node,
then it is grouped with all other similar switches.
if the XML file contains <expansion switch="-gnatw" /> then the command line "-gnatwc -gnatt -gnatwd" is transformed into "-gnatwcd -gnatt", grouping the switches that start with "-gnatw". |
alias
attributes of the <expansion>
nodes, and
replaced appropriately.
if the XML file contains <expansion switch="-gnatwa" alias="-gnatwcd" /> then the command line generated at the second step is further transformed into "-gnatwa -gnatt". |
This rather complex mechanism allows one to either use the various buttons and GUI widgets to edit the switches, or to manually edit the command line.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The user has now specified the default switches he wants to use for the external tool. Spawning the external tool can be done either from a menu item, or as a result of a key press.
Both cases are described in an XML customization file, as described previously,
and both are setup to execute what GPS calls an action, i.e. a set of commands
defined by the <action>
tag.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This action tag, as described previously, executes one or more commands, which can either be internal GPS commands (written in any of the scripting language supported by GPS), or external commands provided by executables found on the PATH.
The command line for each of these commands can either be hard-coded in the
customization file, or be the result of previous commands executed as part of
the same action. As GPS executes each command from the action in turn, it
saves its output on a stack as needed. If a command line contains a special
construct %1
, %2
... then these constructs will be replaced
by the result of respectively the last command executed, the previous from last
command, and so on. They are replaced by the returned value of the command, not
by any output it might have done to some of the consoles in GPS.
Every time you execute a new command, it pushes the previous %1, %2... parameters one step further on the stack, so that they become respectively %2, %3... and the output of that command becomes %1.
The result value of the previous commands is substituted exactly as is. However, if the output is surrounded by quotes, they are ignored when a substitution takes place, so you need to put them back if they are needed. The reason for this behavior is so that for scripting languages that systematically protect their output with quotes (simple or double), these quotes are sometimes in the way when calling external commands.
<?xml version="1.0" ?> <quotes> <action name="test quotes"> <shell lang="python">'-a -b -c'</shell> <external> echo with quotes: "%1"</external> <external> echo without quotes: %2</external/> </action> </quotes> |
If one of the commands in the action raises an error, the execution of the action is stopped immediately, and no further command is performed.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Before launching the external tool, you might want to force GPS to save all
open files, the project.... This is done using the same command GPS itself
uses before starting a compilation. This command is called MDI.save_all
,
and takes one optional boolean argument which specifies whether an interactive
dialog should be displayed for the user.
Since this command aborts when the user presses cancel, you can
simply put it in its own <shell>
command, as in:
<?xml version="1.0" ?> <save_children> <action name="test save children"> <shell>MDI.save_all 0</shell> <external>echo Run unless Cancel was pressed</external> </action> </save_children> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Some GPS shell commands can be used to query the default switches set by the
user in the project file. These are get_tool_switches_as_string
,
get_tool_switches_as_list
, or, more generally,
get_attribute_as_string
and get_attribute_as_list
. The first
two require a unique parameter which is the name of the tool as specified in
the <tool>
tag. This name is case-sensitive. The last two commands are
more general and can be used to query the status of any attribute from the
project. See their description by typing the following in the GPS shell
console window:
help Project.get_attribute_as_string help Project.get_attribute_as_list |
The following is a short example on how to query the switches for the tool
"Find" from the project, See section 15.6.2 Tool example. It first creates an object
representing the current project, then passes this object as the first
argument of the get_tool_switches_as_string
command. The last external
command is a simple output of these switches
<?xml version="1.0" ?> <find_switches> <action name="Get switches for Find"> <shell>Project %p</shell> <shell>Project.get_tool_switches_as_string %1 Find </shell> <external>echo %1</external> </action> </find_switches> |
The following example shows how something similar can be done from Python, in a simpler manner. For a change, this function queries the Ada compiler switches for the current project, and prints them out in the messages window. The
<?xml version="1.0" ?> <query_switches> <action name="Query compiler switches"> <shell lang="python">GPS.Project("%p").get_attribute_as_list (package="compiler", attribute="default_switches", index="ada")</shell> <external>echo compiler switches= %1</external> </action> </query_switches> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Another solution to query the arguments for the tool is to ask the user interactively. The scripting languages provides a number of solutions for these.
They generally have their own native way to read input, possibly by creating a dialog.
In addition, the simplest solution is to use the predefined GPS commands for this. These are the two functions:
yes_no_dialog
input_dialog
From the GPS shell, it is only convenient to query one value at a time, since it doesn't have support for lists, and would return a concatenation of the values. However, this function is especially useful with other scripting languages.
The following is a short example that queries the name of a directory and a file name, and displays each in the Messages window.
<?xml version="1.0" ?> <query_file> <action name="query file and dir"> <shell lang="python">list=GPS.MDI.input_dialog \ ("Please enter directory and file name", "Directory", "File")</shell> <shell lang="python">print ("Dir=" + list[0], "File=" + list[1])</shell> </shell> </action> </query_file> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The output of external commands is send by default to the GPS console window.
In addition, finer control can be exercised using the output
attribute
of the <external>
and <shell>
tags.
This attribute is a string that may take any value. Two values have specific meanings:
"none"
""
other values
This attribute can also be specified at the <action>
tag level, in which
case it defines the default value for all <shell>
and <external>
tags underneath. If it isn't specified for the action itself, its default value
will always be the empty string, i.e. output is sent to the GPS console.
<?xml version="1.0" ?> <ls> <action name="ls current directory" output="default output" > <shell output="Current directory" >pwd</shell> <external output="Current directory contents" >/bin/ls</external> </action> </ls> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The output of the tool has now either been hidden or made visible to the user in one or more windows.
There are several additional things that can be done with this output, for further integration of the tool in GPS.
External tools can usually display error messages for the user that
are associated with specific files and locations in these files. This is for
instance the way the GPS builder itself analyzes the output of make
.
This can be done for your own tools using the shell command
Locations.parse
. This command takes several arguments, so that you
can specify your own regular expression to find the file name, line number and
so on in the error message. By default, it is configured to work
seamlessly with error message of the forms:
file:line: message file:line:column: message |
Please refer to the online help for this command to get more information
(by e.g. typing help Locations.parse
in the GPS Shell).
Here is a small example on how to run a make command and send the errors to the location window afterward.
For languages that support it, it is also recommended that you quote the argument with triple quotes, so that any special character (newlines, quotes, ...) in the output of the tool are not specially interpreted by GPS. Note also that you should leave a space at the end, in case the output itself ends with a quote.
<?xml version="1.0" ?> <make> <action name="make example" > <external>make</external> <on-failure> <shell>Locations.parse """%1 """ make_example</shell> </on-failure> </action> </make> |
GPS has support for automatically correcting errors for some of the languages.
You can get access to this auto-fixing feature through the Codefix.parse
shell command, which takes the same arguments as for Locations.parse
.
This will automatically add pixmaps to the relevant entries in the location
window, and therefore Locations.parse
should be called first prior to
calling this command.
Errors can also be fixed automatically by calling the methods of the
Codefix
class. Several codefix sessions can be active at the same time,
each of which is associated with a specific category. The list of currently
active sessions can be retrieved through the Codefix.sessions()
command.
If support for python is enabled, you can also manipulate the fixable errors
for a given session.
To do so, you must first get a handle on that section, as shown in the example
below. You can then get the list of fixable errors through the errors
command.
Each error is of the class CodefixError
, which has one important
method fix
which allows you to perform an automatic fixing for that
error. The list of possible fixes is retrieved through possible_fixes
.
print GPS.Codefix.sessions () session = GPS.Codefix ("category") errors = session.errors () print errors [0].possible_fixes () errors [0].fix () |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
15.6.1 Menu example 15.6.2 Tool example
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This section provides a full example of a customization file.
It creates a top-level menu named custom menu
.
This menu contains a menu item named item 1
, which is associated to the
external command external-command 1
, a sub menu named other menu
,
etc...
<?xml version="1.0"?> <menu-example> <action name="action1"> <external>external-command 1</external> </action> <action name="action2"> <shell>edit %f</shell> </action> <submenu> <title>custom menu</title> <menu action="action1"> <title>item 1</title> </menu> <submenu> <title>other menu</title> <menu action="action2"> <title>item 2</title> </menu> </submenu> </submenu> </menu-example> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This section provides an example that defines a new tool. This is only a short example, since Ada, C and C++ support themselves are provided through such a file, available in the GPS installation.
This example adds support for the "find" Unix utility, with a few switches. All these switches are editable through the project properties editor.
It also adds a new action and menu. The action associated with this menu gets the default switches from the currently selected project, and then ask the user interactively for the name of the file to search.
<?xml version="1.0" ?> <toolexample> <tool name="Find" > <switches columns="2" > <title column="1" >Filters</title> <title column="2" >Actions</title> <spin label="Modified less than n days ago" switch="-mtime-" min="0" max="365" default="0" /> <check label="Follow symbolic links" switch="-follow" /> <check label="Print matching files" switch="-print" column="2" /> </switches> </tool> <action name="action find"> <shell>Project %p</shell> <shell>Project.get_tool_switches_as_string %1 Find </shell> <shell>input_dialog "Name of file to search" Filename</shell> <external>find . -name %1 %2</external> </action> <Submenu> <Title>External</Title> <menu action="action find"> <Title>Launch find</Title> </menu> </Submenu> </toolexample> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
15.7.1 Scripts 15.7.2 Scripts and GPS actions 15.7.3 The GPS Shell 15.7.4 The Python Interpreter 15.7.6 Subprogram parameters 15.7.7 Python FAQ 15.7.8 Hooks
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Scripts are small programs that interact with GPS and allow you to perform complex tasks repetitively and easily. GPS includes support for two scripting languages currently, although additional languages might be added in the future. These two languages are described in the following section.
Support for scripting is currently work in progress in GPS. As a result, not many commands are currently exported by GPS, although their number is increasing daily. These commands are similar to what is available to people who extend GPS directly in Ada, but with a strong advantage: they do not require any recompilation of the GPS core, and can be tested and executed interactively.
The goal of such scripts is to be able to help automate processes such as builds, automatic generation of graphs,...
These languages all have a separate console associated with them,
which you can open from the Tools
menu. In each of these
console, GPS will display a prompt, at which you can type interactive
commands. These console provide completion of the command names
through the tab key.
For instance, in the GPS shell console you can start typing
GPS> File |
then press the tab key, which will list all the functions whose name starts with "File".
A similar feature is available in the python console, which also provides completion for all the standard python commands and modules.
All the scripting languages share the same set of commands exported by GPS, thanks to a abstract interface defined in the GPS core. As a result, GPS modules do not have to be modified when new scripting languages are added.
Scripts can be executed immediately upon startup of GPS by using the
command line switch --load
. Specifying the following command
line:
gps --load=shell:mytest.gps |
will force the gps script `mytest.gps' to be executed immediately, before GPS starts reacting to user's requests. This is useful if you want to do some special initializations of the environment. It can also be used as a command line interface to GPS, if you script's last command is to exit GPS.
In-line commands can also be given directly on the command line through
--eval
command line switch.
For instance, if you want to analyze an entity in the entity browser from the command line, you would pass the following command switches:
gps --eval=shell:'Entity entity_name file_name; Entity.show %1' |
See the section 15.4 Customizing through XML files on how to bind key shortcuts to shell commands.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
There is a strong relationship between GPS actions, as defined in the customization files (see section 15.4.1 Defining Actions), and scripting languages
Actions can be bound to menus and keys through the customization files or
the Edit->Key shortcuts
dialog.
These actions can execute any script command, See section 15.4.1 Defining Actions. This is
done through the <shell>
XML tag.
But the opposite is also true. From a script, you can execute any action registered in GPS. This can for instance be used to split windows, highlight lines in the editor,... when no equivalent shell function exists. This can also be used to execute external commands, if the scripting language doesn't support this in an easy manner.
Such calls are made through a call to execute_action
, as in the
following example:
execute_action "Split horizontally" |
GPS.execute_action (action="Split horizontally") |
The list of actions known to GPS can be found through the
Edit->Key shortcuts
dialog. Action names are case sensitive.
Some of the shell commands take subprograms as parameters. If you are using the GPS shell, this means you have to pass the name of a GPS action. If you are using Python, this means that you pass a subprogram, See section 15.7.6 Subprogram parameters.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The GPS shell is a very simple-minded, line-oriented language. It is
accessible through the Shell
window at the bottom of the GPS
window. It is similar to a Unix shell, or a command window on Windows
systems.
Type help
at the prompt to get the list of available commands,
or help
followed by the name of a command to get more
information on that specific command.
The following example shows how to get some information on a source entity, and find all references to this entity in the application. It searches for the entity "entity_name", which has at least one reference anywhere in the file "file_name.adb". After the first command, GPS returns an identifier for this entity, which can be used for all commands that need an entity as a parameter, as is the case for the second command. When run, the second command will automatically display all matching references in the location window.
GPS> Entity my_entity file_name.adb <Entity_0x09055790> GPS> Entity.find_all_refs <Entity_0x09055790> |
Since the GPS shell is very simple, it doesn't provide any reference
counting for the result types. As a result, all the values returned by
a command, such as <Entity_0x09055790>
in the example above,
are kept in memory.
The GPS shell provides the command clear_cache
which removes
all such values from the memory. After this command is run, you can no
longer use references obtained from previous commands, although of
course you can run these commands again to get a new reference.
The return value of the 9 previous commands can easily be recalled by
passing %1
, %2
,... on the command line. For instance,
the previous example could be rewritten as
GPS> Entity my_entity file_name.adb <Entity_0x09055790> GPS> Entity.find_all_refs %1 |
These return values will be modified also for internal commands sent
by GPS, so you should really only use this when you emit multiple
commands at the same time, and don't do any other action in GPS. This
is mostly useful when used for command-line scripts (see --eval
and --load
), or for custom files, See section 15.4 Customizing through XML files.
Arguments to commands can, but need not, be quoted. If they don't contain any space, double-quote ('"') or newline characters, you do not need to quote them. Otherwise, you should surround them with double-quotes, and protect any double-quote part of the argument by preceding it with a backslash.
There is another way to quote a command: use three double-quotes characters in a row. Any character loses its special meaning until the next three double-quotes characters set. This is useful if you do not know in advance the contents of the string you are quoting.
Locations.parse """%1 """ category_name |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Python is an interpreted object-oriented language, created by Guido Van Rossum. It is similar in its capabilities to languages such as Perl, Tcl or Lisp. This section is not a tutorial on python programming. See http://www.python.org/doc/current/ to access the documentation for the current version of python.
If python support has been enabled, the python shell is accessible through the
Python
window at the bottom of the GPS window. You can also
display it by using the menu `Tools->Python Console'.
You can type help(GPS)
in the python console to see the list of
functions exported by GPS to python. If you want to save the output of
this (or any) command to a file, you can do:
>>> e=file("/tmp/gps-help.txt", "w") >>> sys.stdout=e >>> help(GPS) >>> e.flush() >>> sys.stdout=sys.__stdout__ |
The same example that was used to show the GPS shell follows, now using python. As you can notice, the name of the commands is similar, although they are not run exactly in the same way. Specifically, GPS benefits from the object-oriented aspects of python to create classes and instances of these classes.
In the first line, a new instance of the class Entity is created
through the create_entity
function. Various methods can then be
applied to that instance, including find_all_refs
, which lists
all references to that entity in the location window:
>>> e=GPS.Entity ("entity_name", "file_name.adb") >>> e.find_all_refs() |
The screen representation of the classes exported by GPS to python has been modified, so that most GPS functions will return an instance of a class, but still display their output in a user-readable manner.
Python has extensive introspection capabilities. Continuing the
previous example, you can find what class e
is an instance of
with the following command:
>>> help(e) Help on instance of Entity: <GPS.Entity instance> |
It is also possible to find all attributes and methods that can be
applied to e
, as in the following example:
>>> dir (e) ['__doc__', '__gps_data__', '__module__', 'called_by', 'calls', 'find_all_refs'] |
Note that the list of methods may vary depending on what modules were loaded in GPS, since each module can add its own methods to any class.
In addition, the list of all existing modules and objects currently known in the interpreter can be found with the following command:
>>> dir () ['GPS', 'GPSStdout', '__builtins__', '__doc__', '__name__', 'e', 'sys'] |
You can also load and execute python scripts with the execfile
command,
as in the following example:
>>> execfile ("test.py") |
Python supports named parameters. Most functions exported by GPS define names for their parameters, so that you can use this Python feature, and make your scripts more readable. A notable exception to this rule are the functions that take a variable number of parameters. Using named parameters allows you to specify the parameters in any order you wish, e.g:
>>> e=GPS.Entity (name="foo", file="file.adb") |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
On startup, GPS will automatically import (with python's import
command) all the files with the extension `.py' found in the directory
`$HOME/.gps/python_startup'. These files are loaded only after all
standard GPS modules have been loaded, as well as the custom files, but
before the script file or batch commands specified on the command lines
with the --eval
or --load
switches.
As a result, one can use the usual GPS functions exported to python in these startup scripts. Likewise, the script run from the command line can use functions defined in the startup files.
Since the import
command is used, the functions defined in this
modules will only be accessible by prefixing their name by the name of the
file in which they are defined. For instance if a file `mystartup.py'
is copied to the startup directory, and defines the function func
,
then the latter will be accessible in GPS through mystartup.func
.
The standard python mechanism for loading scripts on startup is still
available. As usual, python can automatically load a script on startup.
You can do this by setting an environment variable named
PYTHONSTARTUP
to the name of a file containing your start-up commands.
If you are writing a set of python scripts that other people will use, you need to provide several things:
<action>
tag, exported to the user. This allows him
to either create menus to execute these commands or to bind them to special
key shortcuts
Alternatively, your python script can call the command GPS.parse_xml
to specify some inline XML tags to interpret. These tags can directly create
the new menus or key bindings associated with your command.
The following example defines a python command that inserts a line full of dashes ('-') at the current cursor location. This command is associated with the key binding control-c n, and can be distributed as a single XML file.
# This code must be stored in a file test.py in $HOME/.gps/python_startup from GPS import * def add_dashes_line(): replace_text (current_context().file().name(), current_context().location().line(), current_context().location().column(), "--------------------------------", 0, 0) parse_xml (""" <action name="dashes line"> <shell lang="python">test.add_dashes_line()</shell> <context>Source editor</context> </action> <key action="dashes line">control-c n</key> """) |
Several complex examples are provided in the GPS distribution, in the directory `examples/python'. These are modules that you might want to use for your own GPS, but more important that will show how GPS can be extended from Python.
If your script doesn't do what you expect it to do, there are several ways to debug it, among which the easiest is probably to add some "print" statements. Since some output of the scripts is sometimes hidden by GPS (for instance for interactive commands), you might not see this output.
In this case, you can reuse the tracing facility embedded in GPS itself. Modify the file `$HOME/.gps/traces.cfg', and add the following line:
PYTHON.OUT=yes |
This will include the python traces as part of the general traces available in the file `$HOME/.gps/log'. Note that it may slow down GPS if there is a lot of output to process.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A few of the functions exported by GPS in the GPS shell or in python expect a subprogram as a parameter.
This is handled in different ways depending on what language your are using:
It isn't possible to define new functions in the GPS shell. However, this concept is similar to the GPS actions (see section 15.4.1 Defining Actions), which allow you to execute a set of commands and launch external processes.
Therefore, a subprogram parameter in the GPS shell is a string, which is the name of the action to execute.
For instance, the following code defines the action "on_edition", which is called every time a new file is edited. The action is defined in the shell itself, although this could be more conveniently done in a separate customization file.
parse_xml """ |
Python of course has its own notion of subprogram, and GPS is fully compatible with it. As a result, the syntax is much more natural than in the GPS shell. The following example has the same result as above:
import GPS def on_edition(self, *arg): print "File edited" GPS.Hook ("file_edited").add (on_edition) |
Things are in fact slightly more complex if you want to pass methods are arguments. Python has basically three notions of callable subprograms, detailed below. The following examples all create a combo box in the toolbar, which calls a subprogram whenever its value is changed. The documentation for the combo box indicates that the callback in this case takes two parameters:
The first parameter is the instance of the combo box associated with the toolbar widget, and, as always in python, you can store your own data in the instance, as shown in the examples below.
Here is the description of the various subprograms:
These are standard subprograms, found outside class definitions. There is no implicit parameter in this case. However, if you need to pass data to such a subprogram, you need to use global variables
import GPS my_var = "global data" def on_changed (combo, choice): global my_var print "on_changed called: " + \ my_var + " " + combo.data + " " + choice combo = GPS.Combo \ ("name", label="name", on_changed=on_changed) GPS.Toolbar().append (combo) combo.data = "My own data" |
These are methods of a class. You do not specify, when you pass the method in parameter to the combo box, what instance should be passed as its first parameter. Therefore, there is no extra parameter either.
Note however than whatever class the method is defined in, the first parameter is always an instance of the class documented in the GPS documentation (in this case a GPS.Combo instance), not an instance of the current class.
In this first example, since we do not have access to the instance of MyClass, we also need to store the global data as a class component. This is a problem if multiple instances of the class can be created.
import GPS class MyClass: my_var = "global data" def __init__ (self): self.combo = GPS.Combo \ ("name", label="name", on_changed=MyClass.on_changed) GPS.Toolbar().append (self.combo) self.combo.data = "My own data" def on_changed (combo, choice): ## No direct access to the instance of MyClass. print "on_changed called: " + \ MyClass.my_var + " " + combo.data + " " + choice MyClass() |
As the example above explains, there is no direct access to MyClass when executing on_changed. An easy workaround is the following, in which the global data can be stored in the instance of MyClass, and thus be different for each instance of MyClass.
import GPS class MyClass: def __init__ (self): self.combo = GPS.Combo \ ("name", label="name", on_changed=MyClass.on_changed) GPS.Toolbar().append (self.combo) self.combo.data = "My own data" self.combo.myclass = self ## Save the instance self.my_var = "global data" def on_changed (combo, choice): print "on_changed called: " + \ combo.myclass.my_var + " " + combo.data + " " + choice MyClass() |
The last example works as expected, but is not convenient to use. The solution here is to use a bound method, which is a method for a specific instance of a class. Such a method always has an extra first parameter, set implicitly by Python or GPS, which is the instance of the class the method is defined in.
Notice the way we pass the method in parameter to append(), and the extra third argument to on_changed in the example below.
import GPS class MyClass: def __init__ (self): self.combo = GPS.Combo \ ("name", label="name", on_changed=self.on_changed) GPS.Toolbar().append (self.combo) self.combo.data = "My own data" self.my_var = "global data" def on_changed (self, combo, choice): # self is the instance of MyClass specified in call to append() print "on_changed called: " + \ self.my_var + " " + combo.data + " " + choice MyClass() |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This section lists some of the problems that have been encountered while using Python inside GPS. This is not a general Python discussion.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
There exist various solutions to spawn external processes from a script:
GPS.Process
class
GPS.execute_action
.
This action should have an <external>
XML node indicating how to
launch the process
os.popen()
calls
This solution doesn't provide a full interaction with the process, though.
The use of an expect library may be a good solution. There are various python expect libraries that already exist.
These libraries generally try to copy the parameters of the standard file
class. They may fail doing so, as GPS's consoles do not fully emulate all
the primitive functions of that class (there is no file descriptor for
instance).
When possible, it is recommended to use one of the methods above instead.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In general, it is possible to redirect the output of any Python script to
any GPS window (either an already existing one, or creating one automatically),
through the "output"
attribute of XML configuration files.
However, there is a limitation in python that the output of processes spawned through os.exec() or os.spawn() is redirected to the standard output, and not to the usual python output that GPS has overriden.
There are two solutions for this:
The output of the pipe is then redirected to Python's output, as in:
import os, sys def my_external(): f = os.popen ('ls') console = GPS.Console ("ls") for l in f.readlines(): console.write (' ' + l) |
This solution allows you, at the same time, to modify the output, for instance to indent it as in the example above.
You can go through the process of defining an XML customization string for GPS, and execute your process this way, as in:
GPS.parse_xml (""" <action name="ls"> <external output="output of ls">ls</external> </action>""") def my_external(): GPS.execute_action ("ls") |
This solution also allows you to send the output to a different window than the rest of your script. But you cannot filter or modify the output as in the first solution.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The following filter can be used for actions that can only execute in the Project View, and only when the user clicks on an object directory. The contextual menu entry will not be visible in other contexts
<?xml version="1.0" ?> <root> <filter name="object directory" shell_cmd="import os.path; os.path.samefile (GPS.current_context().project().object_dirs()[0],GPS.current_context().directory())" shell_lang="python" module="Explorer" /> <action name="Test on object directory"> <filter id="object directory" /> <shell>echo "Success"</shell> </action> <contextual action="Test on object directory" > <Title>Test on object directory</Title> </contextual> </root> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
By default, the output of all python commands is displayed in the Python console. However, you might want in some cases to create other windows in GPS for this output. This can be done in one of two ways:
If the whole output of your script should be redirected to the same window, or if the script will only be used interactively through a menu or a key binding, the easiest way is to create a new XML action, and redirect the output, as in
<?xml version="1.0" ?> <root> <action name="redirect output" output="New Window"> <shell lang="python">print "a"</shell> </action> </root> |
All the various shell commands in your action can be output in a different window, and this also applies for the output of external commands.
If, however, you want to control in your script where the output should be sent, for instance if you can't know that statically when you write your commands, you can use the following code:
sys.stdin = sys.stdout = GPS.Console ("New window") print "foo" print (sys.stdin.read ()) sys.stdin = sys.stdout = GPS.Console ("Python") |
The first line redirect all input and output to a new window, which is
created if it doesn't exist yet. Note however that the output of stderr
is not redirected, and you need to explicitely do it for sys.stderr
.
The last line restore the default Python console. You must do this at the end of your script, or all scripts will continue to use the new consoles.
You can alternatively create separate objects for the output, and use them in turn:
my_out = GPS.Console ("New Window") my_out2 = GPS.Console ("New Window2") sys.stdout=my_out print "a" sys.stdout=my_out2 print "b" sys.stdout=GPS.Console ("Python") |
The parameter to the constructor GPS.Console
indicates whether any
output sent to that console should be saved by GPS, and reused for the
%1
, %2
,... parameters if the command is executed in a
GPS action. That should generally be 1, except for stderr where it should
be 0.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
After you have made modification to a python file, you might want to reload it in GPS. This requires careful use of python commands.
Here is an example. Lets assume you have a python file (`"mymod.py"') which contains the following:
GPS.parse_xml (""" <action name="my_action"> <shell lang="python">mymod.myfunc()</shell> </action>""") def myfunc(): print "In myfunc\n" |
As you can guess from this file, it defines an action "my_action", that you can for instance associate with a keybinding through the Edit->Key shortcuts menu.
If this file has been copied in the `$HOME/.gps/python_startup/' directory, it will be automatically loaded at startup.
Notice that the function myfunc
is thus found in a separate namespace,
with the name mymod
, same as the file.
If you decide, during your GPS session, to edit this file and have the function print "In myfunc2" instead, you then have to reload the file by typing the following command in the Python console:
> execfile ("HOME/.gps/python_startup/mymod.py", mymod.__dict__) |
The first parameter is the full path to the file that you want to reload.
The second argument is less obvious, but indicates that the file should be
reloaded in the namespace mymod
.
If you omit the optional second parameter, Python will load the file, but
the function myfunc
will be defined in the global namespace, and thus
the new definition is accessible through
> myfunc() |
Thus, the key shortcut you had set, which still executes mymod.myfunc()
will keep executing the old definition.
By default, GPS provides a contextual menu when you are editing a Python file. This contextual menu (Python->Reload module) will take care of all the above details.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The python extension provided by GPS is fully documentation in this manual and a separate manual accessible through the Help menu in GPS.
However, this documentation is provided in HTML, and might not be the best suitable for printing, if you wish to do so.
The following paragraph explains how you can generate your own documentation for any python module, including GPS, and print the result.
import pydoc pydoc.writedoc (GPS) |
In the last comamnd, GPS
is the name of the module that you want
to print the documentation for.
These commands generate a `.html' file in the current directory.
Alternatively, you can generate a simple text file with
e=file("./python_doc", "w") e.write (pydoc.text.document (GPS)) e.flush() |
This text file includes bold characters by default. Such bold characters are correctly interpreted by tools such as `a2ps' which can be used to convert the text file into a postscript document.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
At startup, GPS will automatically load a few python files. This includes the file `autoexec.py' in its installation directory `share/gps/python', as well as all the files that each user has put in his own `$HOME/.gps/python_startup' directory.
In addition, in order to make python files available to a group of users, several approaches are possible:
PYTHONPATH
environment variable. Under unix, you can alternatively modify the small
`gps' wrapper script to do this automatically on startup.
The above steps will make your files available to GPS, but will not execute them automatically (apart for the first solution described above).
If you want to automatically execute a script, there are again a number of possibilities:
import
statement for
each python package to execute.
This will need to be redone after each new installation of GPS
myautoexec.py
) which contains one
import statement for each package to load, as in
import common_package1, common_package2 |
All the methods above require you to modify the installation of GPS somehow. Alternatively, you can also provide a small wrapper script to launch GPS. Here is an example of such a script, assuming your files are in /dir/support and the file to load is support_autoexec.py.
This is a unix-shell syntax. Such shells are also available on Windows, but you can also do the following using a windows `.bat' file
LD_LIBRARY_PATH=/dir/support:$LD_LIBRARY_PATH export LD_LIBRARY_PATH gps --eval=python:'import support_autoexec.py' $* |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A hook is a named set of commands to be executed on particular occasions as a result of user actions in GPS.
GPS and its various modules define a number of standard hooks, which are called for instance when a new project is loaded, when a file is edited, and so on. You can define your own commands to be executed in such cases.
You can find out the list of hooks that GPS currently knows about by calling the Hook.list function, which takes no argument, and returns a list of hook names that you can use. More advanced description for each hook is available through the describe_hook command.
GPS> Hook.list project_changed open_file_action_hook preferences_changed [...] GPS> hook preferences_changed GPS> Hook.describe %1 Hook called when a file needs to be opened or closed This hook is of type "open_file" -- see describe_hook_type |
Python> GPS.Hook ("preferences_changed").describe()
The description of each hooks includes a pointer to the type of the hook, that is what parameters the subprograms in this hook will receive. For instance:
GPS> Hook.describe_type "open_file" Common type for all hooks related to opening files. Arguments are the following: (file, line, column, column_end, enable_navigation, new_file, force_reload) |
The list of all known hook types can be found through the Hook.list_types command. This takes no argument and returns a list of all known types of hooks. As before, you can more information for each of these type through a call to Hook.describe_type.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
You can add your own command to existing hooks through a call to the Hook.add command. Whenever the hook is executed by GPS or another script, your command will also be executed, and will be given the parameters that were specified when the hook is run. The first parameter is always the name of the hook being executed.
This Hook.add applies to an instance of the hook class, and takes one parameter, the command to be executed. This is a subprogram parameter (see section 15.7.6 Subprogram parameters).
The command can be any GPS action (see section 15.4.1 Defining Actions). The arguments for the hook will be passed to the action, and are available as $1, $2,.... In the following example, the message "Just executed the hook: project_changed" will be printed in the Shell console. Note that we are defining the action to be executed inline, but this could in fact be defined in a separate XML customization file for convenience.
GPS> parse_xml """ |
The command must be the name of a subprogram to execute. The arguments for the hook will be passed to this subprogram. In the following example, the message "The hook project_changed was executed by GPS" will be displayed in the Python console whenever the project changes.
def my_callback (name): print "The hook " + name + " was executed by GPS" GPS.Hook ("project_changed").add (my_callback) |
The example above shows the simplest type of hook, which doesn't take any argument. However, most hooks receive several parameters. For instance, the hook "file_edited" receives the file name as a parameter.
The following code will print the name of the hook ("file_edited") and the name of the file in the shell console every time a file is open by GPS.
GPS> parse_xml """ |
The following code prints the name of the file being edited by GPS in the python console whenever a new editor is opened. The second argument is of type GPS.File.
def my_file_callback (name, file): print "Editing " + file.name() GPS.Hook ("file_edited").add (my_file_callback) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Some hooks have a special use in GPS. Their name always ends with "_action_hook".
As opposed to the standard hooks described in the previous section, the execution of the action hooks stops as soon as one of the subprograms returns a True value ("1" or "true"). The subprograms associated with that hook are executed one after the other. If any such subprogram knows how to act for that hook, it should do the appropriate action and return "1".
This mechanism is used extensively by GPS internally. For instance, whenever a file needs to be opened in an editor, GPS executes the "open_file_action_hook" hook to request its editing. Several modules are connected to that hook.
One of the first modules to be executed is the external editor module. If the user has chosen to use an external editor, this module will simply spawn Emacs or the external editor that the user has selected, and return 1. This immediately stops the execution of the "open_file_action_hook".
However, if the user doesn't want to use external editors, this module will return 0. This will keep executing the hook, and in particular will execute the source editor module, which will always act and open an editor internally in GPS.
This is a very flexible mechanism. In your own script, you could choose to have some special handling for files with a ".foo" extension for instance. If the user wants to open such a file, you would spawn for instance an external command (say "my_editor") on this file, instead of opening it in GPS.
This is done with a code similar to the following
from os.path import * import os def my_foo_handler (name, file, line, column, \ column_end, enable_nav, new_file, reload): if splitext (file.name())[1] == ".foo": os.spawnv \ (os.P_NOWAIT, "/usr/bin/emacs", ("emacs", file.name())) return 1 ## Prevent further execution of the hook return 0 ## Let other subprograms in the hook do their job GPS.Hook ("open_file_action_hook").add (my_foo_handler) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Any module in GPS is responsible for running the hooks when appropriate. Most of the time, the subprograms exported by GPS to the scripting languages will properly run the hook. But you might also need to run them in your own scripts.
As usual, this will result in the execution of all the functions bound to that hook, whether they are defined in Ada or in any of the scripting languages.
This is done through the Hook.run command. This applies to an instance of the Hook class, and a variable number of arguments These must be in the right order and of the right type for that specific type of hook.
If you are running an action hook, the execution will stop as usual as soon as one of the subprograms return a True value.
The following example shows how to run a simple hook with no parameter, and a more complex hook with several parameters. The latter will in fact request the opening of an editor for the file in GPS, and thus has an immediately visible effect on the interface. The file is opened at line 100. See the description of the hook for more information on the other parameters.
GPS.Hook ("project_changed").run() GPS.Hook ("open_file_action_hook").run \ (GPS.File ("test.adb"), 100, 1, 0, 1, 1, 1) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The list of hooks known to GPS is fully dynamic. GPS itself declares a number of hooks, mostly for its internal use although of course you can also connect to them.
But you can also create your own hooks to report events happening in your own modules and programs. This way, any other script or GPS module can react to these events.
Such hooks can either be of a type exported by GPS, which constraints the list of parameters for the callbacks, but make such hooks more portable and secure; or they can be of a general type, which allows basically any kind of parameters. In the latter case, checks are done at runtime to ensure that the subprogram that is called as a result of running the hook has the right number of parameters. If this isn't the case, GPS will complain and display error messages.
Creating new hooks is done through a call to Hook.register. This function takes three arguments: the name of the hook you are creating, a description of when the hook is executed for the interactive help, and the type of the hook.
The name of the hook is left to you. Any character is allowed in that name, although using only alphanumerical characters.
The description is displayed when the user calls Hook.describe.
The type of the hook must be one of the following:
This indicates that the hook doesn't take any argument. None should be given to Hook.run, apart of course from the hook name, and none should be expected by the various commands connected to that hook, once again apart from the hook name itself.
This indicates that the hook is of one of the types exported by GPS itself. The advantage of using such explicit types as opposed to "general" is that GPS is able to make more tests for the validity of the parameters.
This indicates that the hook is of the general type that allows any number of parameter, of any type. Other script will be able to connect to it, but will not be executed when the hook is run if they do not expect the same number of parameters that was given to Hook.run
A small trick worth noting: if the command bound to a hook doesn't have the right number of parameters that this hook provide, the command will not be executed and GPS will report an error. You can make sure that your command will always be executed by either giving default values for its parameter, or by using python's syntax to indicate a variable number of arguments.
This is especially useful if you are connecting to a "general" hook, since you do not really know in advance how many parameters the call of Hook.run will provide.
## This callback can be connected to any type of hook def trace (name, *args): print "hook=" + name ## This callback can be connected to hooks with one or two parameters def trace2 (name, arg1, arg2=100): print "hook=" + str (arg1) + str (arg2) Hook.register ("my_custom_hook", "some description", "general") Hook ("my_custom_hook").add (trace2) Hook ("my_custom_hook").run (1, 2) ## Prints 1 2 Hook ("my_custom_hook").run (1) ## Prints 1 100 |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
15.8.1 Custom VCS interfaces 15.8.2 Describing a VCS 15.8.3 Implementing VCS actions
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The Version Control interface in GPS can be customized, either to refine the behavior of the existing system and adapt it to specific needs, or to add support for other Version Control systems.
Custom VCS interfaces are defined entirely through XML files. Those files are read in the same location as all the other XML customizations that GPS offers. See 15.4 Customizing through XML files for a complete description.
There are two steps to follow when creating a custom VCS interface. The first step is to describe the VCS itself, and the second step is to implement actions corresponding to all the operations that this VCS can perform. The following two sections (15.8.2 Describing a VCS and 15.8.3 Implementing VCS actions) describe those steps.
GPS is distributed with XML files describing the interfaces to
ClearCase and CVS. These XML files are located in the directory
share/gps/customize
in the GPS installation, and can be used as a
reference for implementing new custom VCS interfaces.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
15.8.2.1 The VCS node 15.8.2.2 Associating actions to operations 15.8.2.3 Defining status 15.8.2.4 Output parsers
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The vcs
node is the toplevel node which contains the
description of the general behavior expected from the VCS. It has two
attributes.
The attribute name
indicates the identifier of the VCS. The
casing of this name is important, and the same casing must be used in
the project files.
The attribute absolute_name
indicates the behavior of the
VCS relative to file names, and can take the values TRUE
or
FALSE
. If it is set to TRUE
, it means that all
commands in the VCS will work on absolute file names. If it set to
FALSE
, it means that all actions work on base file names, and
that GPS will move to the appropriate directory before executing an
action.
Here is an example, adapted to the use of CVS:
<vcs name="Custom CVS" absolute_names="FALSE"> (... description of action associations ...) (... description of supported status ...) (... description of output parsers ...) </vcs> |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
GPS knows about a certain set of predefined "operations" that a VCS can perform. The user can decide to implement some of them - not necessarily all of them - in this section.
The following node is used to associate a predefined operation to an action:
<OPERATION action="ACTION_LABEL" label="NAME OF OPERATION" /> |
Where:
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
All VCS have the notion of "status" or "state" to describe the
relationship between the local file and the repository. The XML node
status
is used to describe the status that are known to a
custom VCS, and the icons associated to it:
<status label="STATUS_LABEL" stock="STOCK_LABEL" /> |
Where:
Note that the order in which status are defined in the XML file is important: the first status to be displayed must correspond to the status "Up-to-date" or equivalent.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
There are cases in which GPS needs to parse the output of the VCS commands: when querying the status, or when "annotating" a file.
The following parsers can be implemented in the vcs
node.
status_parser
and local_status_parser
They accept the following child nodes:
<regexp>
(mandatory)
<file_index>
regexp
that contains the name
of a file.
<status_index>
regexp
that contains the file
status. This status is passed through the regular expressions defined in the
status_matcher
nodes, see below.
<local_revision_index>
regexp
that contains the name
of the local revision (the version of the file that was checked out).
<repository_revision_index>
regexp
that contains the name
of the repository revision (the latest version of the file in the VCS).
<status_matcher>
label
.
<annotations_parser>
It accepts the following child nodes:
<regexp>
(mandatory)
<repository_revision_index>
regexp
that contains the
repository revision of the line.
<file_index>
regexp
that indicates the
part of the line that belongs to the file.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A number of "standard" VCS operations are known to GPS. Each of these operations can be implemented, using Actions. See 15.4.1 Defining Actions) for a complete description of how to implement actions.
Here is a list of all the defined VCS operations, and their parameters:
status_files
$1 = whether the log files should be cleared when obtaining up-to-date status
$2- = the list of files to query status for.
status_dir
$1 = the directory.
local_status_files
$* = list of files
open
$* = list of files
update
$* = list of files
update_dir
$* = directory
commit
$1 = log file
$2- = list of files
commit_dir
$1 = log
$2 = directory
history
$1 = file
history_revision
$1 = revision
$2 = file
annotate
$1 = file
add
$1 = log
$2 = file or dir
remove
$1 = log
$2 = file or dir
revert
$* = files
diff_head
$1 = file
diff_base_head
$1 = file
diff_working
$1 = file
diff
$1 = rev
$2 = file
diff2
$1 = revision 1
$2 = revision 2
$3 = file
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |