This file is indexed.

/usr/share/vile/perl/capture.pm is in vile-common 9.8q-1build1.

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
package capture;

use strict;
use Vile::Manual;

use vars qw(@ISA %REGISTRY);

require Vile::Exporter;
@ISA      = 'Vile::Exporter';
%REGISTRY = (
    'async-capture-command' => [
        \&capture_command,
        'run a command, capturing its output in the [Output] buffer', '^A-!',
    ],
    'async-capture-command-help' =>
      [ sub { &manual }, 'manual page for async-capture-command' ]
);

my $last_command = '';

sub capture_command {

    # Fetch user command from the message line
    my $command = Vile::mlreply_shell( "async-!", $last_command );
    return if !defined($command);

    # Remember the command for next time...
    $last_command = $command;

    # Get a handle for or create the [Output] buffer by whatever
    # means necessary
    my $b;
    if ( grep( $_->buffername eq '[Output]', Vile::buffers() ) ) {
        $b = edit Vile::Buffer '[Output]';
    }
    if ( !$b ) {
        $b = new Vile::Buffer;
        $b->buffername('[Output]');
    }

    # Make sure we can write to the buffer
    $b->set( readonly => 0, view => 0 );

    # Output a bold header (just the command name and a bunch of dashes)
    my @startdot = $b->dotq('$$');
    print $b "\n$command\n----------------\n";
    $b->set_region( @startdot, '$', '$$' )->attribute( 'bold', color => 4 );

    # Remember the starting dot for the error finder
    @startdot = $b->dotq('$$');

    # Set [read-only view-only loading] attributes for the mode line
    $b->set( readonly => 1, view => 1, loading => 1 );

    # Find a window corresponding to the buffer
    my $w = undef;
    foreach my $i ( 0 .. Vile::window_count() - 1 ) {
        if ( $b->buffername eq Vile::window_at($i)->buffer->buffername ) {
            $w = Vile::window_at($i);
            last;
        }
    }

    # Pop up a window and set dot if possible
    $w = Vile::Window->new($b) unless $w;
    $w->dot( $b->dot() ) if $w;

    # Clear the [modified] attribute
    $b->unmark;

    # Run the command
    unless ( open CAPTURE, "$command 2>&1 |" ) {
        print STDERR "Can't run command $command";
        return;
    }

    # Have vile watch for output from the command while waiting
    # for user input; when not otherwise busy, vile will call the
    # anonymous subroutine which we pass as the third parameter
    Vile::watchfd(
        fileno(CAPTURE),
        'read',
        sub {
            my $buf = ' ' x 4096;

            # Set "dot" to end of the buffer.  Note that we use
            # dotq which does it quietly.  I.e, the buffer position
            # will not be propagated back to the editor upon return
            $b->dotq('$$');

            # Try to find a window associated with the buffer which
            # also has DOT near the end.
            my $w = undef;
            foreach my $i ( 0 .. Vile::window_count() - 1 ) {
                $w = Vile::window_at($i);
                if (    $b->buffername eq $w->buffer->buffername
                    and $w->dot() >= $b->dot() - 1 )
                {
                    last;
                }
                $w = undef;
            }

            # Fetch data from input stream
            if ( !sysread CAPTURE, $buf, 4096 ) {

                # We're at the end of the stream; stop watching
                # for input on this file handle and close it down
                Vile::unwatchfd( fileno(CAPTURE) );
                close CAPTURE;

                # Clear the [loading] attribute on the mode line
                $b->set( loading => 0 );

                # Reset dot to the beginning of the text that was
                # just loaded for the error finder.  But only do
                # it if the user's dot was positioned at the end
                # of the buffer.  We won't move it on him if he
                # was browsing the buffer.
                $w->dot(@startdot) if $w;

                # Update the screen
                Vile::update();

                return;
            }

            # Nuke ^M characters
            $buf =~ s/\r\n/\n/gs;

            # Make it writable
            $b->set( readonly => 0, view => 0 );

            # Write data to the editor's buffer
            print $b $buf;

            # Restore view-only and read-only attributes
            $b->set( readonly => 1, view => 1 );

            # Nuke the [modified] message
            $b->unmark();

            # Move dot for one of the windows (maybe)
            $w->dot( $b->dot() ) if $w;

            # Update the screen
            Vile::update();
        }
    );

    # Associate the [Output] buffer with the error finder.  When
    # invoked without an argument, this is its default action.
    Vile::command('error-buffer');
}

1;
__DATA__

=head1 NAME

capture - run a shell command, capturing its output in the [Output] buffer

=head1 SYNOPSIS

In .vilerc:

    perl "use capture"

In [x]vile:

    :async-capture-command

or

    ^A-!

and then provide the command to run at the ensuing prompt.

=head1 DESCRIPTION

The B<capture> package provides a drop-in replacement (almost) for
vile's capture-command command.

It provides additional functionality, however.  Rather than waiting
for the command to finish before displaying the buffer, this version
will update the [Output] buffer as the results of the command become
available thus permitting the user to perform other editing tasks while
the command is running.

Also, unlike its builtin cousin, capture.pm will preserve all of the
commands that have been run in the [Output] buffer, setting the
current position to the first line of the new output after the
command has completed.  This allows the error finder to operate
on the newly read in lines.  The error finder may also be used
before the command has completed, but the user must position the
cursor manually for this to work.

When capturing a slow or long running command, capture.pm look at
the cursor position prior to adding new output from the command.
If the position is near the end of the buffer, the cursor will
be repositioned to be at the end of the new text added to the
buffer.  Otherwise, the cursor will be left alone.  This allows
the user to either watch the output or browse the buffer whichever
is desired.

=head1 BUGS

There is no way to interrupt a command once started.

=head1 AUTHOR

Kevin Buettner

=cut