/usr/share/gps/plug-ins/block_completion.py is in gnat-gps-common 5.3dfsg-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | """Provides end-of-block completion for the Ada language
This script defines an action named Block_Completion that, based on
GPS block information, ends the current block with the proper ending
statement.
The current implementation handles the if, case, loop (with optional
label), procedure, function, declare block (with optional label), package
spec and body.
Example of use:
in an Ada file, type the following (leave the cursor at the '_' character):
if Foo then
null;
_
and then select the menu /Edit/More Completion/Complete Block
This automatically adds "end if;" on the line following the statement
"""
############################################################################
## No user customization below this line
############################################################################
action_name = "Block Completion"
menu_name = "/Edit/More Completion/Complete _Block"
## Name of the action and the menu defined by this package.
import re, string, GPS
# BLOCKS_DEFS is a dictionary describing the action to be done for each block.
#
# <block_name> : [<ending_pattern>, <completion pattern>]
#
# <block_name> : this is the name used internally by GPS
# <ending_pattern> : the string to use to close the corresponding block.
# this string can contain replacement tag \1 \2, see
# below
# <completion_patttern> : optional, this is a regular expression pattern to
# match against the first line of the block to
# retrieve information for creating the final ending
# pattern.
BLOCKS_DEFS = {
'CAT_IF_STATEMENT' : ['end if;', ''],
'CAT_CASE_STATEMENT' : ['end case;', ''],
'CAT_CASE_INSIDE_RECORD' : ['end case;', ''],
'CAT_LOOP_STATEMENT' : [r'end loop \1;', r'\s*([^ ]+)\s*:\s*loop.*'],
'CAT_RETURN_BLOCK' : [r'end return;', ''],
'CAT_PROCEDURE' : [r'end \2;', r'\s*(overriding\s+)?\s*procedure\s+([^ \n(]+).*'],
'CAT_FUNCTION' : [r'end \2;', r'\s*(overriding\s+)?\s*function\s+([^ \n(]+).*'],
'CAT_DECLARE_BLOCK' : [r'end \1;', r'\s*([^ ]+)\s*:\s*declare.*'],
'CAT_PACKAGE' : [r'end \2;', r'\s*package\s+(body\s+)?([^ \n]+).*'],
'CAT_STRUCTURE' : ['end record;', ''],
'CAT_CLASS' : ['end record;', ''],
'CAT_PROTECTED' : [r'end \2;', r'\s*protected\s+(body\s+)?([^ \n]+).*'],
'CAT_ENTRY' : [r'end \1;', r'\s*entry\s+([^ \n(]+).*']
}
def on_gps_started (hook_name):
"Initializes this module."
global action_name, menu_name
init = "<action name='" + action_name + """' category='Editor'>
<description>End the current Ada block, by providing the appropriate "end" statement</description>
<filter language="ada"
error='""" + action_name + """ requires an Ada file' />
<shell lang="python" output="none">block_completion.block_complete("%F");</shell>
</action>
<menu action='""" + action_name + """' before="Refill">
<title>""" + menu_name + """</title>
</menu>"""
GPS.parse_xml (init)
def block_complete_on_location (buffer, location):
# Check if we need to insert a new-line character
start = GPS.EditorLocation (buffer, location.line(), 1)
end = GPS.EditorLocation (buffer, location.line(), location.column())
# A new-line character is inserted if there is some text on the left
# of the current cursor position.
if buffer.get_chars (start, end).strip() != "":
buffer.insert (location, '\n');
location = location.forward_line()
block = location.block_type();
if not BLOCKS_DEFS.has_key (block):
return;
(term, pattern) = BLOCKS_DEFS [block];
if pattern != '':
# Retreive the line at the start of the block
start = GPS.EditorLocation (buffer, location.block_start_line(), 1);
end = GPS.EditorLocation (buffer, location.block_start_line() + 1, 1);
bs_content = buffer.get_chars (start, end);
re_pattern = re.compile (pattern, re.IGNORECASE | re.DOTALL);
if re_pattern.match (bs_content):
term = re_pattern.sub (term, bs_content);
else:
# The pattern does not macth the content, remove the tags
term = term.replace (r' \1', '');
term = term.replace (r'\1', '');
term = term.replace (r' \2', '');
term = term.replace (r'\2', '');
buffer.start_undo_group();
buffer.insert (location, term);
buffer.indent (location, location);
buffer.finish_undo_group();
def block_complete (filename):
file = GPS.File (filename);
# Only Ada language supported
if file.language().lower() != "ada":
return;
eb = GPS.EditorBuffer.get (file);
ev = eb.current_view();
el = ev.cursor();
block_complete_on_location (eb, el);
GPS.Hook ("gps_started").add (on_gps_started)
|