19. Useful plugins

19.1. User plugins

GNAT Studio comes with a number of plugins, some of which are activated by default. Control which plugins are activated by using the Edit ‣ Preferences… menu.

This section discusses a few of the many plugins built in to GNAT Studio. The preferences dialog shows their description, so you can decide whether you want them enabled.

19.2. Helper plugins

A number of plugins are useful when you want to create your own plugins.

19.2.1. The gs_utils module

class gs_utils.Chainmap(*maps)

Combine multiple mappings for sequential lookup.

For example, to emulate Python’s normal lookup sequence:

import __builtin__ pylookup = Chainmap(locals(), globals(), vars(__builtin__))

keys() a set-like object providing a view on D's keys
gs_utils.execute_for_all_cursors(ed, mark_fn, extend_selection=False)

Execute the function mark_fn for every cursor in the editor, meaning, the main cursor + every existing multi cursor. mark_fn has the prototype def mark_fn(EditorBuffer, EditorMark)

gs_utils.freeze_prefs()

A context manager that temporarily freezes GPS’ preferences_changed signal from being emitted, and then reactivated it. This is useful when modifying a large number of preferences as a single batch.

This can be used as:

with gs_utils.freeze_prefs():
    GPS.Preference(...).set(...)
    GPS.Preference(...).set(...)
    GPS.Preference(...).set(...)
gs_utils.get_gnat_driver_cmd()

Return the name of the GNAT driver that is suitable for the current project’s target. For instance: “gnat” for native targets or “powerpc-elf-gnat” for cross PowerPC ELF targets.

class gs_utils.hook(hook, last=True)

A decorator that makes it easier to connect to hooks:

@hook("gps_started")
def my_function(*args, **kwargs):
    pass

Note that the function does not receive the hook as the first parameter. The function should however accept any number of parameters, for future extensions, since some hooks might receive extra arguments.

gs_utils.in_ada_file(context)

Returns True if the focus is currently inside an Ada editor

gs_utils.in_c_file(context)

Returns True if the focus is currently inside an c/cpp editor

gs_utils.in_xml_file(context)

Returns True if the focus is in an XML editor

class gs_utils.interactive(*args, **kwargs)

A decorator with the same behavior as make_interactive(). This can be used to easily associate a function with an interactive action, menu or key, so that a user can conveniently call it:

@interactive("Editor", menu="/Edit/Foo")
def my_function():
    pass
gs_utils.is_writable(context)

Returns True if the focus is currently inside a writable editor

gs_utils.make_interactive(callback, category='General', filter='', menu='', key='', contextual='', name='', before='', after='', contextual_ref='', icon='', description='', toolbar='', toolbar_section='', button_label='', static_path='', key_exclusive=True, for_learning=False, contextual_group=10000)

Declare a new GPS action (an interactive function, in Emacs talk), associated with an optional menu and default key.

Parameters:
  • callback

    This is the code that gets executed when the user executes the action. Such an action is executed via a menu, a toolbar button, a key shortcut, or by entering its name in the omnisearch.

    The callback can be one of:
    • a standard function that requires no argument although it can have optional arguments (none will be set when this is called from the menu or the key shortcut).

    • a class: when the user executes the action, a new instance of the class is created, so it is expected that the work is done in the __init__ of the class. This is in particular useful for classes that derive from CommandWindow.

    • a generator function. Those are functions that use the yield keyword to temporarily suspend and give back control to the caller. These are convenient when chaining background tasks. See the workflows/promises.py package for more on generators and workflows

  • menu – The name of a menu to associate with the action. It will be placed within its parent just before the item referenced as before, or after the item referenced as after.

  • icon (str) – Name of the icon to use for this action, for instance in toolbars or in various dialogs. This is the name of a file (minus extension) found in the icons directory of GPS.

  • contextual – Path for the contextual menu This is either a string, for instance ‘/Menu/Submenu’ or ‘/Menu/Submenu %f’, which supports a number of parameter substitution; or a function that receives a GPS.Context as parameter and returns a string.

  • static_path – This is a string that contains the path and name for the contextual menu when ‘contextual’ parameter is function.

  • name (str) – The name for the action. The default is to use the callback’s name.

  • key_exclusive (bool) – Only applies when a key is specified. If true, the key will no longer execute any action it was previously bound to. If false, the key will be bound to multiple actions.

  • description (str) – the description for this action, as visible to the user. If not specified, the callback’s own documentation will be used.

  • toolbar (str) – If specified, inserts a button in the corresponding toolbar (either ‘main’ or the name of the view as found in the /Tools/Views menu)

  • toolbar_section (str) – Where, in the toolbar, to insert the button. See GPS.Action.button()

  • button_label (str) – The label to use for the button (defaults to the name of the action).

  • for_learning (bool) – whether or not this action should be displayed in the Learn view.

Returns:

a tuple (GPS.Action, GPS.Menu) The menu might be None if you did not request its creation.

gs_utils.save_current_window(f, *args, **kwargs)

Save the window that currently has the focus, executes f, and reset the focus to that window.

gs_utils.save_dir(fn)

Saves the current directory before executing the instrumented function, and restore it on exit. This is a python decorator which should be used as:

@save_dir
def my_function():
    pass
gs_utils.save_excursion(f, args, kwargs, undo_group=True)

Save current buffer, cursor position and selection and execute f. (args and kwargs) are passed as arguments to f. They indicate that any number of parameters (named or unamed) can be passed in the usual way to save_excursion, and they will be transparently passed on to f. If undo_group is True, then all actions performed by f will be grouped so that the user needs perform only one single undo to restore previous start.

Then restore the context as it was before, even in the case of abnormal exit.

Example of use:

def my_subprogram():
   def do_work():
       pass   # do actual work here
   save_excursion(do_work)

See also the with_save_excursion decorator below for cases when you need to apply save_excursion to a whole function.

gs_utils.with_save_current_window(fn)

A decorator with the same behavior as save_current_window.

gs_utils.with_save_excursion(fn)

A decorator with the same behavior as save_excursion. To use it, simply add @with_save_excursion before the definition of the function. This ensures that the current context will be restored when the function terminates:

@with_save_excursion
def my_function():
    pass

19.2.2. The gs_utils.highlighter.py module

This file provides various classes to help highlight patterns in files.

class gs_utils.highlighter.Background_Highlighter(style, initial_timeout=None)

An abstract class that provides facilities for highlighting parts of an editor. If possible, this highlighting is done in the background so that it doesn’t interfer with the user typing. Example of use:

class Example(Background_Highlighter):
   def process(self, start, end):
       ... analyze the given range of lines, and perform highlighting
       ... where necessary.

e = Example()
e.start_highlight(buffer1)   # start highlighting a first buffer
e.start_highlight(buffer2)   # start highlighting a second buffer
Parameters:

style (OverlayStyle) – style to use for highlighting.

on_start_buffer(buffer)

Called before we start processing a new buffer.

process(start, end)

Called to highlight the given range of editor. When this is called, previous highlighting has already been removed in that range.

Parameters:
remove_highlight(buffer=None)

Remove all highlighting done by self in the buffer.

Parameters:

buffer (GPS.EditorBuffer) – defaults to the current buffer

set_style(style)

Change the current highlight style.

Parameters:

style (OverlayStyle) – style to use for highlighting.

start_highlight(buffer=None, line=None, context=None)

Start highlighting the buffer, possibly in the background.

Parameters:
  • buffer (GPS.EditorBuffer) – The buffer to highlight (defaults to the current buffer). This buffer is added to the list of buffers, and will be processed when other buffers are finished.

  • line (integer) – The line the highlighting should start from. By default, this is the current line in the editor, so that the user sees changes immediately. But you could chose to start from the top of the file instead.

  • context (integer) – Number of lines before and after ‘line’ that should be highlighted. By default, the whole buffer is highlighted.

stop_highlight(buffer=None)

Stop the background highlighting of the buffer, but preserves any highlighting that has been done so far.

Parameters:

buffer (GPS.EditorBuffer) – If specified, highlighting is only stopped for a specific buffer.

class gs_utils.highlighter.Location_Highlighter(style, context=2, initial_timeout=None)

An abstract class that can be used to implement highlighter related to the cross-reference engine. As usual, such an highlighter does its job in the background. To find the places to highlight in the editor, this class relies on having a list of entities and their references. This list will in general be computed once when we start processing a new buffer:

class H(Location_Highlighter):
    def recompute_refs(self, buffer):
        return ...computation of references within file ...
Parameters:

context (integer) – The number of lines both before and after a given reference where we should find for possible approximate matches. This is used when the reference returned by the xref engine was outdated.

on_start_buffer(buffer)

Called before we start processing a new buffer.

process(start, end)

Called to highlight the given range of editor. When this is called, previous highlighting has already been removed in that range.

Parameters:
recompute_refs(buffer)

Called before we start processing a new buffer.

Returns:

a list of tuples, each of which contains an (name, GPS.FileLocation). The highlighting is only done if the text at the location is name. Name should be a byte-sequence that encodes a UTF-8 strings, not the unicode string itself (the result of GPS.EditorBuffer.get_chars or GPS.Entity.name can be used).

class gs_utils.highlighter.On_The_Fly_Highlighter(style, context_lines=0)

This abstract class provides a way to easily highlight text in an editor. When possible, the highlighting is done in the background, in which case it is also done on the fly every time the file is modified. If pygobject is not available, the highlighting is only done when the file is opened or saved

As for Background_Highlight, you need to override the process() function to perform actual work.

Parameters:
  • style (OverlayStyle) – the style to apply.

  • context_lines (integer) – The number of lines (plus or minus) around the current location that get refreshed when a local highlighting is requested.

must_highlight(buffer)
Parameters:

buffer (GPS.EditorBuffer) – The buffer to test.

Returns:

whether to highlight this buffer. The default is to higlight all buffers, but some highlightings might apply only to specific languages for instance

Return type:

boolean

start()

Start highlighting. This is automatically called from __init__, and only needs to be called when you have called stop() first. Do not call this function multiple times.

stop()

Stop highlighting through self

class gs_utils.highlighter.OverlayStyle(name, foreground='', background='', weight=None, slant=None, editable=None, whole_line=False, speedbar=False, style=None, **kwargs)

Description for a style to apply to a section of an editor. In practice, this could be implemented as an editor overlay, or a message, depending on whether highlighting should be done on the whole line or not.

Parameters:
  • name (string) – name of the overlay so that we can remove it later.

  • foreground (string) – foreground color

  • background (string) – background color

  • weight (string) – one of “bold”, “normal”, “light”

  • slant (string) – one of “normal”, “oblique”, “italic”

  • editable (boolean) – whether the text is editable by the user interactively.

  • whole_line (boolean) – whether to highlight the whole line, up to the right margin

  • speedbar (boolean) – whether to show a mark in the speedbar to the left of editors.

  • style (GPS.Style) – the style to apply to the overlay.

  • kwargs – other properties supported by EditorOverlay

apply(start, end)

Apply the highlighting to part of the buffer.

Parameters:
remove(start, end=None)

Remove the highlighting in whole or part of the buffer. :param GPS.EditorLocation start: start of region. :param GPS.EditorLocation end: end of region. If unspecified, the highlighting for the whole buffer is removed.

use_messages()
Returns:

Whether this style will use a GPS.Message or a GPS.EditorOverlay to highlight.

Return type:

boolean

class gs_utils.highlighter.Regexp_Highlighter(regexp, style, context_lines=0)

The Regexp_Highlighter is a concrete implementation to highlight editors based on regular expressions. One example is for instance to highlight tabs or trailing spaces on lines, when this is considered improper style:

Regexp_Highlighter(
    regexp="    +|\s+$",
    style=OverlayStyle(
       name="tabs style",
       strikethrough=True,
       background="#FF7979"))

Another example is to highlight TODO lines. Various conventions exist to mark these in the sources, but the following should catch some of these:

Regexp_Highlighter(
    regexp="TODO.*|\?\?\?.*",
    style=OverlayStyle(
       name="todo",
       background="#FF7979"))

Another example is a class to highlight Spark comments. This should only be applied when the language is spark:

class Spark_Highlighter(Regexp_Highlighter):
    def must_highlight(self, buffer):
        return buffer.file().language().lower() == "spark"

Spark_Highlighter(
    regexp="--#.*$",
    style=OverlayStyle(
        name="spark", foreground="red"))
Parameters:
  • regexp (string) – the regular expression to search for. It should preferrably apply to a single line, since highlighting is done on small sections of the editor at a time, and it might not detect cases where the regular expression would match across sections.

  • style (OverlayStyle) – the style to apply.

process(start, end)

Called to highlight the given range of editor. When this is called, previous highlighting has already been removed in that range.

Parameters:
class gs_utils.highlighter.Text_Highlighter(text, style, whole_word=False, context_lines=0)

Similar to Regexp_Highlighter, but highlights constant text instead of a regular expression. By default, highlighting is done in all buffer, override the function must_highlight to reduce the scope.

Parameters:
  • text (string) – the text to search for. It should preferrably apply to a single line, since highlighting is done on small sections of the editor at a time, and it might not detect cases where the text would match across sections.

  • style (OverlayStyle) – the style to apply.

process(start, end)

Called to highlight the given range of editor. When this is called, previous highlighting has already been removed in that range.

Parameters:

19.2.3. The gs_utils.console_process.py module

class gs_utils.console_process.ANSI_Console_Process(command)

This class has a purpose similar to Console_Process. However, this class does not attempt to do any of the high-level processing of prompt and input that Console_Process does, and instead forward immediately any of the key strokes within the console directly to the external process. It also provides an ANSI terminal to the external process. The latter can thus send escape sequences to change colors, cursor position,…

on_completion(input)

The user has pressed <tab> in the console. The default is just to insert the character, but if you are driving a process that knows about completion, such as an OS shell for instance, you could have a different implementation. input is the full input till, but not including, the tab character

on_input(input)

This method is called when the user has pressed <enter> in the console. The corresponding command is then sent to the process

on_key(keycode, key, modifier)

The user has pressed a key in the console (any key). This is called before any of the higher level on_completion or on_input callbacks. If this subprogram returns True, GPS will consider that the key has already been handled and will not do its standard processing with it. By default, we simply let the key through and let GPS handle it.

Parameters:

key – the unicode character (numeric value) that was entered by the user. _modifier_ is a mask of the control and shift keys that were pressed at the same time. See the Mask constants above. keycode is the code of the key, which is useful for non-printable characters. It is set to 0 in some cases if the input is simulated after the user has copied some text into the console

This function is also called for each character pasted by the user in the console. If it returns True, then the selection will not be inserted in the console.

class gs_utils.console_process.Console_Process(command, close_on_exit=True, force=False, ansi=False, manage_prompt=True, task_manager=False)

This class provides a way to spawn an interactive process and do its input/output in a dedicated console in GPS. The process is created so that it does not appear in the task manager, and therefore the user can exit GPS without being asked whether or not to kill the process.

You can of course derive from this class easily. Things are slightly more complicated if you want in fact to derive from a child of GPS.Console (for instance a class that would handle ANSI escape sequences). The code would then look like:

class ANSI_Console (GPS.Console):
   def write (self, txt): ...

class My_Process (ANSI_Console, Console_Process):
   def __init__ (self, command):
     Console_Process.__init__ (self, command)

In the list of base classes for My_Process, you must put ANSI_Console before Console_Process. This is because python resolves overridden methods by looking depth-first search from left to right. This way, it will see ANSI_Console.write before Console_Process.write and therefore use the former.

However, because of that the __init__ method that would be called when calling My_Process (…) is also that of ANSI_Console. Therefore you must define your own __init__ method locally.

See also the class ANSI_Console_Process if you need your process to execute within a terminal that understands ANSI escape sequences.

Parameters:
  • force (boolean) – If True, a new console is opened, otherwise an existing one will be reused (although you should take care in this case if you have multiple processes attached to the same console).

  • manage_prompt (boolean) – If True, then GPS will do some higher level handling of prompts: when some output is done by the process, GPS will temporarily hide what the user was typing, insert the output, and append what the user was typing. This is in general suitable but might interfer with external programs that do their own screen management through ANSI commands (like a Unix shell for instance).

  • task_manager (boolean) – If True, the process will be visible in the GPS tasks view and can be interrupted or paused by users. Otherwise, it is running in the background and never visible to the user.

on_completion(input)

The user has pressed <tab> in the console. The default is just to insert the character, but if you are driving a process that knows about completion, such as an OS shell for instance, you could have a different implementation. input is the full input till, but not including, the tab character

on_destroy()

This method is called when the console is being closed. As a result, we terminate the process (this also results in a call to on_exit

on_exit(status, remaining_output)

This method is called when the process terminates. As a result, we close the console automatically, although we could decide to keep it open as well

on_input(input)

This method is called when the user has pressed <enter> in the console. The corresponding command is then sent to the process

on_interrupt()

This method is called when the user presses control-c in the console. This interrupts the command we are currently processing

on_key(keycode, key, modifier)

The user has pressed a key in the console (any key). This is called before any of the higher level on_completion or on_input callbacks. If this subprogram returns True, GPS will consider that the key has already been handled and will not do its standard processing with it. By default, we simply let the key through and let GPS handle it.

Parameters:

key – the unicode character (numeric value) that was entered by the user. _modifier_ is a mask of the control and shift keys that were pressed at the same time. See the Mask constants above. keycode is the code of the key, which is useful for non-printable characters. It is set to 0 in some cases if the input is simulated after the user has copied some text into the console

This function is also called for each character pasted by the user in the console. If it returns True, then the selection will not be inserted in the console.

on_output(matched, unmatched)

This method is called when the process has emitted some output. The output is then printed to the console

on_resize(console, rows, columns=None)

This method is called when the console is being resized. We then let the process know about the size of its terminal, so that it can adapt its output accordingly. This is especially useful with processes like gdb or unix shells

gs_utils.console_process.has_paste_clipboard(context)

A fliter to check if focus in a console

19.3. Plugins for external tools

19.3.1. QGen

The QGen Debugger manual can be found within the QGen User guide.