This file is indexed.

/usr/share/gps/plug-ins/block_completion.py is in gnat-gps-common 6.1.2016-1ubuntu1.

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
131
"""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"
# Name of the action and the menu defined by this package.

import re
import string
import GPS
logger = GPS.Logger("block_complete")

# 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*:.*?loop.*'],
    'CAT_RETURN_BLOCK': [r'end return;', ''],
    'CAT_PROCEDURE': [r'end \1;', r'.*?procedure\s+([^ \n(]+).*'],
    'CAT_FUNCTION': [r'end \1;', r'.*?function\s+([^ \n(]+).*'],
    'CAT_DECLARE_BLOCK': [r'end \1;', r'\s*([^ ]+)\s*:\s*declare.*'],
    'CAT_SIMPLE_BLOCK': [r'end \1;', r'\s*([^ ]+)\s*:\s*declare.*'],
    'CAT_PACKAGE': [r'end \2;', r'.*?package\s+(body\s+)?([^ \n]+).*'],
    'CAT_STRUCTURE': ['end record;', ''],
    'CAT_CLASS': ['end record;', ''],
    'CAT_PROTECTED': [r'end \3;', r'\s*protected\s+((body|type)\s+)?([^ \n]+).*'],
    'CAT_TASK': [r'end \3;', r'\s*task\s+((body|type)\s+)?([^ \n]+).*'],
    'CAT_ENTRY': [r'end \1;', r'\s*entry\s+([^ \n(]+).*']
}


def on_gps_started(hook_name):
    "Initializes this module."
    init = """<action name='%(action)s' category='Editor'>
     <description>End the current Ada block, by providing the appropriate "end" statement</description>
      <filter language="ada" error='%(action)s requires an Ada file' />
      <shell lang="python" output="none">block_completion.block_complete("%%F");</shell>
   </action>""" % {"action": action_name}
    GPS.parse_xml(init)


def block_complete_on_location(buffer, location):
    # Check if we need to insert a new-line character
    start = buffer.at(location.line(), 1)
    end = buffer.at(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()
    logger.log(str(block))

    if block not in BLOCKS_DEFS:
        return

    (term, pattern) = BLOCKS_DEFS[block]

    if pattern != '':
        # Retrieve the line at the start of the block

        start = buffer.at(location.block_start_line(), 1)
        end = location

        bs_content = buffer.get_chars(start, end)
        logger.log(bs_content)

        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 match 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)