This file is indexed.

/usr/share/gps/library/vi.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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
"""This plug-in provides a basic emulation of the vi editor's command line.

It is not meant as a vi emulation, ie it will not emulate the insertion
and command modes for instance.
Instead, it provides a way to open a command line (the default key
shortcut is control-:, by analogy with vi's ":" prompt.
In this command line, you can type some of vi's command, to modify the
current editor. The format of the command line is

  [from[,to]]cmd[params]

where "from,to" defines a range of lines other that the command should
act on. If none of "from" and "to" are specified, the command only applies
to the current line.  If only "from" is specified, the command applies to
the line specified by "from". If both are specified, the command applies to
the range of lines defined by those, including those two lines.

"from" and "to" can both be one of:
   - ".": indicates the line on which the cursor currently is
   - "$": indicates the last line in the buffer
   - "<": indicates the start of the current selection
   - ">": indicates the end of the current selection
   - a number: indicates a specific line in the buffer
   - "+" and a number: indicates a line relative to the current line, or
     to the line specified by "from"
   - "-" and a number: indicates a line relative to the current line, or
     to the line specified by "from"
In addition, "from,to" can be replaced by "%" to indicate the whole
buffer.

The supported commands are:
   - s/str/repl/
     replaces the first occurrence of the regular expression "str" by
     "repl". The latter can contain \1, \2,... to reference parenthesis
     groups in "str".
     If a range of lines was specified, the replacement is done for all
     occurrences within that range. If a single line was specified (or
     none, which defaults to the current line), only the first occurrence
     on that line is replaced. If an extra "g" is put after the closing "/",
     all occurrences on that line are replaced.
     For convenience, the separator can be any character, not just "/".
     An extra "i" on the command line will make the search case-insensitive.
     You can set the option "ignorecase" below to be in case-insensitive
     mode by default.

   - d
     deletes the lines in the specied range

Here are a few examples:
   %s/foo/bar
      Replaces all instances of "foo" by "bar" in the whole buffer
   .,$s/foo/bar
      Replaces all instances of "foo" by "bar", in all the lines after the
      current one
   67,120s/\d+/DIGIT:\1
      Replaces all numbers from line 67 to 120 inclusive by adding a
      prefix "DIGIT:" to them

The command window that pops up when you press <control-:> has a history: if
you use the <up> and <down> keys, previous commands can be executed again,
or modified and then executed.
In addition, pression <control-.> will execute the previous command without
displaying the command window. This is by analogy with vi's <.> command,
although the scope is less ambitious here.
"""

#############################################################################
# No user customization below this line
#############################################################################

from GPS import *
import re

Preference("Plugins/vi/bgcolor").create(
    "Background color", "color",
    """Color to use for the command line window""",
    "red")

Preference("Plugins/vi/ignorecase").create(
    "Ignore case", "boolean",
    """If enabled, searching will ignore casing by default""",
    False)


def on_gps_started(hook_name):
    parse_xml ("""
  <action name='vi_command_line' category="Editor" output="none">
     <description />
     <filter id="Source editor" />
     <shell lang="python">vi.CmdLine()</shell>
  </action>
  <action name='vi_repeat_cmd' category="Editor" output="none">
     <description />
     <filter id="Source editor" />
     <shell lang="python">vi.CmdLine.repeat_command()</shell>
  </action>
  <menu action='vi_command_line' after="Refill">
    <title>/Edit/Vi command line</title>
  </menu>
  <key action="vi_command_line">control-colon</key>
  <key action="vi_repeat_cmd">control-period</key>
""")


class CmdLine (CommandWindow):
    history = []

    def __init__(self):
        try:
            self.loc = EditorBuffer.get().current_view().cursor()
            CommandWindow.__init__(self,
                                   prompt=self.prompt(),
                                   on_cancel=self.on_cancel,
                                   on_key=self.on_key,
                                   on_activate=self.on_activate)
            self.set_background(Preference("Plugins/vi/bgcolor").get())

            self.current_in_history = -1
            self.current_cmd_line = ""  # Before moving in the history

        except:
            pass

    def prompt(self):
        """Return the prompt to use for the command window"""
        return "Cmd:"

    def on_key(self, input, key, cursor_pos):
        if key.lower() == "up":
            if self.current_in_history == 0:
                self.current_cmd_line = input
            if self.current_in_history < len(CmdLine.history) - 1:
                self.current_in_history = self.current_in_history + 1
                self.write(CmdLine.history[self.current_in_history])

        elif key.lower() == "down":
            if self.current_in_history > 0:
                self.current_in_history = self.current_in_history - 1
                self.write(CmdLine.history[self.current_in_history])
            elif self.current_cmd_line != "":
                self.current_in_history = -1
                self.write(CmdLine.current_cmd_line)
                self.current_cmd_line = ""

    def on_activate(self, input):
        """The user has pressed enter"""
        if input != "":
            CmdLine.history.insert(0, input)
            CmdLine.repeat_command(self.loc)

    @staticmethod
    def get_loc(cmd, loc, buffer):
        """Parse the first location described in ref, and returns it and
           the remaining of the command. LOC is used when the location is
           "." or relative"""
        if cmd[0] == ".":
            return (loc, cmd[1:])
        elif cmd[0] == "$":
            return (buffer.end_of_buffer(), cmd[1:])
        elif cmd[0] == "<":
            return (buffer.selection_start(), cmd[1:])
        elif cmd[0] == ">":
            return (buffer.selection_end(), cmd[1:])
        else:
            match = re.search("([-+]?\d+)(.*)", cmd)
            if match:
                line = int(match.group(1))
                if cmd[0] == "+" or cmd[0] == "-":
                    return (loc.forward_line(line), match.group(2))
                else:
                    return (buffer.at(line, 1), match.group(2))
            else:
                return (loc, cmd)

    @staticmethod
    def get_scope(cmd, current, buffer):
        """return a tuple: (cmd_to_execute, FROM, TO).
           TO is set to FROM if the command should be executed only once"""
        if cmd[0] == "%":
            return (cmd[1:], buffer.beginning_of_buffer(), buffer.end_of_buffer())

        comma = cmd.find(",")
        if comma < 0:
            l, c = CmdLine.get_loc(cmd, current, buffer)
            return (c, l, l)  # Execute only once
        else:
            l, c = CmdLine.get_loc(cmd[:comma], current, buffer)
            e, c = CmdLine.get_loc(cmd[comma + 1:], l,   buffer)
            return (c, l, e)

    @staticmethod
    def do_replace(arg, loc, maxloc):
        buffer = loc.buffer()
        params = arg[1:].split(arg[0])
        if len(params) == 3:
            pattern, replace, options = params
        elif len(params) == 2:
            pattern, replace = params
            options = ""

        count = 1
        icase = Preference(
            "Plugins/vi/ignorecase").get() or (options.find("i") < 0)
        if loc == maxloc:
            maxloc = loc.end_of_line()  # On whole line by default
        else:
            count = 10000000

        if options.find("g") >= 0:
            count = 100000000  # as many times as needed

        while count > 0:
            result = loc.search \
                (pattern, regexp=True,
                 dialog_on_failure=False, case_sensitive=icase)
            if not result:
                return
            else:
                start, last = result
                if start > maxloc:
                    return

                # Add support for \1,.. in the replacement string
                found = buffer.get_chars(start, last - 1)
                if icase:
                    r = re.compile(pattern)
                else:
                    r = re.compile(pattern, re.IGNORECASE)
                repl = r.sub(replace, found)
                buffer.delete(start, last - 1)
                buffer.insert(start, repl)
                loc = start + len(repl)
                buffer.current_view().goto(loc)

            count = count - 1

    @staticmethod
    def do_delete_line(arg, loc, maxloc):
        loc = loc.beginning_of_line()
        maxloc = maxloc.end_of_line()
        loc.buffer().delete(loc, maxloc)
        loc.buffer().current_view().goto(loc)

    @staticmethod
    def repeat_command(loc=None):
        """Repeat the last command that was executed, in Editor"""
        if not loc:
            loc = EditorBuffer.get().current_view().cursor()
        buffer = loc.buffer()
        (cmd, loc, maxloc) = CmdLine.get_scope(CmdLine.history[0], loc, buffer)

        buffer.start_undo_group()
        if cmd[0] == "s":
            CmdLine.do_replace(cmd[1:], loc, maxloc)
        elif cmd[0] == "d":
            CmdLine.do_delete_line(cmd[1:], loc, maxloc)
        buffer.finish_undo_group()

    def on_cancel(self, input):
        """The user has cancelled the search"""
        pass

Hook("gps_started").add(on_gps_started)