#!/usr/bin/perl

use v5.36;
use warnings;
use strict;
use File::Spec;
use Debian::Debhelper::Dh_Lib;

my %SHELLS = (
	bash => '/usr/share/bash-completion/completions',
	fish => '/usr/share/fish/vendor_completions.d',
	zsh => '/usr/share/zsh/vendor-completions',
);

=head1 NAME

dh_shell_completions - install shell completions for package

=head1 SYNOPSIS

B<dh_shell_completions> [S<I<debhelper options>>]

=head1 DESCRIPTION

dh_shell_completions is a debhelper addon for installing shell completion
scripts, respecting conventions of each supported shell.

It currently supports bash, fish, and zsh.

To use it, Build-Depends on it, and pass "--with shell_completions" to
debhelper.

If a file named debian/[$package.]$shell-completions exists, then one of the
two actions are taken, depending on its content.

If it's of the following format:

	path/to/completion/foo       # installed as foo
	path/to/completion/bar  baz  # installed as baz

then the referenced file(s) will be installed as completion(s) for $shell,
named as the comments above suggest.

Otherwise, it's taken as a full completion script, and installed as completion
for $shell, named $package.

If the file is named debian/$shell-completion, the completion script will be
named after the first binary package defined in debian/control.

=cut

# It uses a simple, probably naive heuristic: if no line in the file has more
# than 1 whitespace, it's considered a file list. Shell scripts, especially
# completions scripts, should have at least 2 whitespaces in at least 1 line.
sub is_file_list($path) {
	open(FILE, '<', $path) || error("cannot read $path $!");
	while(<FILE>) {
		chomp;
		s/^\s+//;
		next if /^#/;
		s/^\s+$//;
		next if $_ eq '';
		
		my @split = split(/\s+/, $_, 3);
		if(defined($split[2])) {
			close(FILE);
			return 0;
		}
	}
	close(FILE);
	return 1;
}

sub install_completion($name, $shell, $compdir, $compfile) {
	$name = "$name.fish" if $shell eq 'fish' and $name !~ /\.fish$/;
	$name = "_$name" if $shell eq 'zsh' and $name =~ /^[^_]/;
	install_file($compfile, File::Spec->catfile($compdir, $name));
}

sub process_completion_list($pkg, $shell, $complist) {
	my $compdir = File::Spec->catdir(tmpdir($pkg), $SHELLS{$shell});
	install_dir($compdir);
	return install_completion($pkg, $shell, $compdir, $complist)
		if(!is_file_list($complist));
	open(FILE, '<', $complist) || error("cannot read $complist: $!");
	while (<FILE>) {
		chomp;
		s/^\s+//;
		next if /^#/;
		my @split = split(/\s+/, $_, 2);
		install_completion($split[1] || $pkg, $shell, $compdir, $split[0]);
	}
	close(FILE);
}

sub main {
	my $pkg0 = $dh{DOPACKAGES}[0];

	foreach my $pkg (@{$dh{DOPACKAGES}}) {
		next if is_udeb($pkg);

		foreach my $shell (keys %SHELLS) {
			my $comp_list = pkgfile($pkg, "$shell-completions");
			next if ! -f $comp_list;
			process_completion_list($pkg, $shell, $comp_list);
		}
	}
}

init();
main();

=head1 SEE ALSO

L<debhelper(1)>

=head1 AUTHOR

Blair Noctis <ncts@debian.org>

=cut
