summaryrefslogtreecommitdiff
path: root/dh_vim-addon
blob: 2cbff8be8d1d54c7c12b2c07d4ac4142e14781e1 (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
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
#!/usr/bin/perl

# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright © 2018 James McCoy <jamessan@debian.org>

=head1 NAME

dh_vim-addon - debhelper addon to help package Vim/Neovim addons

=cut

use strict;
use warnings;
use Debian::Debhelper::Dh_Lib;
use File::Spec;

our $VERSION = '0.1';

=head1 SYNOPSIS

B<dh_vim-addon> [S<I<debhelper options>>]

=head1 DESCRIPTION

B<dh_vim-addon> is a debhelper program that is responsible for installing
addons for Vim/Neovim and generating the help tags file for any documentation.
The addons are installed into directories following Vim's native "package"
hierarchy.

There are two types of addons which are supported.

=over 4

=item automatic

Automatic addons are immediately enabled for users when installed.  The addons
should provide a standard mechansim to let the user disable the addon.  This is
typically done by short-circuiting loading of the addon when the user adds
C<let g:loaded_E<lt>addonE<gt> = 1> in their vimrc.

=item optional

Optional addons are only enabled for users if the explicitly opt-in to the
addon.  The user can do so by adding C<packadd E<lt>addonE<gt>> to their vimrc.

=back

=head1 FILES

=over 4

=item debian/I<package>.vim-addon

=item debian/I<package>.neovim-addon

List of installed directories to be setup as an automatic addon in I<package>.
The format is a set of lines, where each line lists the base directory of an
addon, relative to the package build directory and, optionally, the addon name.

=over 4

    B<path/to/addon/basedir>  I<optional-addon-name>

=back

There should typically only be a single addon, and therefore line, per
package.  If an addon name is not supplied, the last component of the base
directory will be used as the addon name.

If the C<basedir> does not match the addon's name (e.g., because it matches the
Debian package's name), then it is recommended to supply the addon name.  This
ensures that common conventions, like C<packadd addon-name> and C<let
g:loaded_addon = 1> work as the user expects.

The C<${vim-addon:Depends}> substvar will be set with any required dependencies.

=item debian/I<package>.vim-opt-addon

=item debian/I<package>.neovim-opt-addon

This file follows the same format as F<vim-addon>, however the directories will
be installed as optional addons in I<package>.

The C<${vim-addon:Depends}> substvar will be set with any required dependencies.

=back

=head1 EXAMPLES

=head2 Single addon, dh-style

Here is an example of a simple dh(1) style package with a single addon,
compatible with Vim and Neovim.  The F<debian/rules> is:

=over 4

    #!/usr/bin/make -f
    %:
        dh $@ --with vim-addon

=back

The Vim addon is installed under F</usr/share/vim-simple>, but the addon name
is I<simple> (i.e., C<let g:loaded_simple = 1> is the expected way for a user
to disable loading of the addon).  The F<vim-addon> file is:

=over 4

    usr/share/vim-simple simple

=back

F<debian/vim-simple.neovim-addon> is a symlink to
F<debian/vim-simple.vim-addon>.

=head2 Multiple addons, debhelper

Here is an example of a debhelper style package, providing multiple addons,
some of which aren't compatible with Neovim.  The F<debian/rules> contains:

=over 4

    #!/usr/bin/make -f
    ...
        # Install the files to the package build directory
        dh_install
        # Setup the (neo)vim addons
        dh_vim-addon

=back

The addons are installed under F</usr/share/vim-multi-addons>.  Unlike the
single addon example, these addons are all installed into a directory matching
the addon name, so only the base directory is needed in the F<vim-addon> file:

=over 4

    usr/share/vim-multi-addons/addon1
    usr/share/vim-multi-addons/addon2

=back

while the F<neovim-addon> is:

=over 4

    usr/share/vim-multi-addon/addon1
    usr/share/vim-multi-addon/addon3

=back

=head1 SEE ALSO

nvim(1), vim(1)

=head1 AUTHOR

James McCoy <jamessan@debian.org>

=cut

init();

# PROMISE: DH NOOP WITHOUT vim-addon vim-opt-addon neovim-addon neovim-opt-addon

my %pkgfiledir = (
	'vim-addon' => '/usr/share/vim/vimfiles/pack/dist-bundle/start',
	'vim-opt-addon' => '/usr/share/vim/vimfiles/pack/dist-bundle/opt',
	'neovim-addon' => '/usr/share/nvim/site/pack/dist-bundle/start',
	'neovim-opt-addon' => '/usr/share/nvim/site/pack/dist-bundle/opt',
);

my @packages = getpackages();
on_items_in_parallel(\@packages, sub {
	foreach my $package (@_) {
		my $tmp = tmpdir($package);

		my %substvar;
		foreach my $pkgfilebase (keys %pkgfiledir) {
			my $pkgfile = pkgfile($package, $pkgfilebase);
			my $skip_process = process_pkg($package) ? 0 : 1;

			next if $skip_process;

			my @paths;
			# Make all paths relative to the package build directory
			@paths = map { [ File::Spec->join($tmp, shift @$_), @$_ ] }
			         filedoublearray($pkgfile) if $pkgfile;

			# Verify all the specified directories can be found
			my @dirs = grep { -d $_->[0] } @paths;
			my @unknown = map { $_->[0] }
			              grep { ! -d $_->[0] } @paths;
			error("No directories found matching: @unknown\n") if @unknown;

			my %tagdirs;
			my $dest = $pkgfiledir{$pkgfilebase};
			foreach my $pair (@dirs) {
				my ($basedir, $addon_name) = @$pair;
				# Can either be [/path/to/addon  addonname] or [/path/to/addon]
				$addon_name = basename($basedir) unless $addon_name;
				my $destpath = File::Spec->join($dest, $addon_name);
				make_symlink($destpath, $basedir, $tmp);

				my $docdir = File::Spec->join($basedir, 'doc');
				if (-d $docdir) {
					$tagdirs{$docdir} = 1;
				}
			}

			if (scalar(%tagdirs)) {
				doit('helpztags', sort keys %tagdirs);
			}

			if ($pkgfilebase =~ m/neovim/) {
				# First version with good "packages" support
				$substvar{neovim} = '0.2.2-1~';
			} else {
				# First version with $VIM/vimfiles as a directory instead of a symlink to /etc/vim
				$substvar{vim} = '2:8.1.0693-2~';
			}
		}

		if (%substvar) {
			my $depinfo = join '|', map { "$_ (>= $substvar{$_})" }
			              # Put vim first when both vim/neovim are supported
			              reverse sort keys %substvar;
			addsubstvar($package, 'vim-addon:Depends', $depinfo);
		}
	}
});