summaryrefslogtreecommitdiffstats
path: root/debian/extra/debhelper/dh_bash-completion
blob: fabae5837ebd983f8da6c1c811ff0462a8e73d12 (plain)
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
#!/usr/bin/perl -w

=head1 NAME

dh_bash-completion - install bash completions for package

=cut

use strict;
use File::Find;
use Debian::Debhelper::Dh_Lib;

=head1 SYNOPSIS

B<dh_bash-completion> [S<I<debhelper options>>]

=head1 DESCRIPTION

dh_bash-completion is a debhelper program that is responsible for installing
completions for bash, usable installing the "bash-completion" package.

In order to use it, you need to pass "--with bash-completion" to debhelper and
Build-depend on bash-completion.

If a file named debian/package.bash-completion exists, then different actions
are performed, depending on its format.

It can be a proper completion snippet, and in that case it would be installed
in the completion directory, and no other actions would be performed.

It can also be a list of files, with an optionally specified name to call the
completion snippet after. The file format is as follows:

  my/path/to/foo-completion       # this would be installed as "foo-completion"
  my/path/to/bar-completion  baz  # this would be installed as "baz"

=cut

# This helper function tries to determine (using some poor man's
# heuristics) whether $file (its first and only argument) is a
# filelist containing a list of files to be installed by us, or a
# bash-completion script, which should itself be installed.
#
# If we're dealing with a filelist, return 1.  Otherwise, return 0.
sub is_filelist {
	# The file to be checked.
	my ($file) = @_;

	open (DH_FILE, '<', $file) || error("cannot read $file: $!");

	while (<DH_FILE>) {
		# Get rid of lines containing just spaces or comments.
		chomp;
		s/^\s++//;
		next if /^#/;
		s/\s++$//;

		# We always ignore/permit empty lines
		next if $_ eq '';

		# This is the heart of the script.  Here, we check for some
		# well-known idioms on bash scripts, and try to determine if
		# they're present in the file we're examining.  We assume that
		# if they are, then this means the file is a bash-completion
		# script.
		#
		# The regexes check:
		#
		# - If we're calling the bash function "complete", which is a
		#   pretty common thing to do in bash-completion scripts, or
		#
		# - If we're using the $(program) way of executing a program.
		#   We don't take into account multi-line statements.  Or
		#
		# - If we're calling the bash function "compgen", which is
		#   also a pretty common thing that bash-completion scripts
		#   do.  Or
		#
		# - If we see an "if...then" construction in the file.  We
		#   take into account multi-line statements.
		if (/(^|[|&;])\s*complete.*-[A-Za-z].*/
			|| /\$\(.*\)/
			|| /\s*compgen.*-[A-Za-z].*/
			|| /\s*if.*;.*then/s) {
			return 0;
		}
	}

	# If we reached the end, this is not a bash-completion script.
	return 1;
}

init();

my $srcdir = '.';
$srcdir = $dh{SOURCEDIR}."/" if defined $dh{SOURCEDIR};

# PROMISE: DH NOOP WITHOUT bash-completion cli-options()

PKG: foreach my $package (@{$dh{DOPACKAGES}}) {
	next if is_udeb($package);

	my $tmp = tmpdir($package);
	my $bc_dir = "$tmp/usr/share/bash-completion/completions";
	my $completions = pkgfile($package,"bash-completion");

	my @install;
	my $name;

	if ($completions) {
		install_dir($bc_dir);

		# Invoke our heuristic function to try and determine
		# if we're dealing with a filelist or with a
		# bash-completion script.
		if (!is_filelist($completions)) {
			verbose_print "detected $completions as a bash-completion script";
			install_file($completions, "$bc_dir/$package");
			next PKG
		}

		# try parsing a list of files
		@install = filedoublearray($completions);
		foreach my $set (@install) {
			my @filelist;
			my @tmp = @$set;
			if (@$set > 1) {
				$name = pop @$set;
			}
			else {
				$name = basename($tmp[0]);
			}
			verbose_print "installing $tmp[0] as $name";

			my @found;
			foreach my $glob (@$set) {
				@found = glob "$srcdir/$glob";
				if (!compat(6)) {
					# Fall back to looking into debian/tmp
					if (!@found || !-e $found[0]) {
						@found = glob "debian/tmp/$glob";
					}
				}

				if (!@found || !-e $found[0]) {
					warning "file-list parsing failed, installing as proper snippet";

					install_file($completions, "$bc_dir/$package");
					next PKG
				}
				push @filelist, @found;
			}

			if (!@filelist) {
				error("$package missing files (@$set), aborting");
			}

			foreach my $src (@filelist) {
				install_file($src, "$bc_dir/$name");
			}
		}
	}
}

=head1 SEE ALSO

L<debhelper(1)>

This program is a part of bash-completion.

L<bash(1)>

=head1 AUTHOR

David Paleino <d.paleino@gmail.com>

=cut