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
|
#!/usr/bin/perl
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright © 2018-2025 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.5';
=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 pkgfile-logged(vim-addon) pkgfile-logged(vim-opt-addon) pkgfile-logged(neovim-addon) pkgfile-logged(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 {
my %tagdirs;
foreach my $package (@_) {
my $tmp = tmpdir($package);
my %substvar;
foreach my $pkgfilebase (sort keys %pkgfiledir) {
my $pkgfile = pkgfile($package, $pkgfilebase);
my $skip_process = process_pkg($package) ? 0 : 1;
next if $skip_process;
if (length($pkgfile) == 0) {
verbose_print("No config found for $pkgfilebase");
next;
}
my @paths;
@paths = filedoublearray($pkgfile) if $pkgfile;
# Verify all the specified directories can be found
my @dirs = grep { -d File::Spec->join($tmp, $_->[0]) } @paths;
my @unknown = map { $_->[0] }
grep { ! -d File::Spec->join($tmp, $_->[0]) } @paths;
error("No directories found matching: @unknown\n") if @unknown;
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($tmp, $basedir, 'doc');
if (-d $docdir) {
verbose_print("$addon_name doc directory: $docdir");
$tagdirs{$docdir} = 1;
} else {
verbose_print("No doc directory for $addon_name");
}
}
if ($pkgfilebase =~ m/neovim/) {
verbose_print("Adding neovim substvar for $pkgfilebase");
# First version with good "packages" support
$substvar{neovim} = '0.2.2-1~';
} else {
verbose_print("Adding vim substvar for $pkgfilebase");
# 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);
}
# Record that the package was handled, even though it only
# generates new content, rather than installing anything from
# the source
log_installed_files($package);
}
if (scalar(%tagdirs)) {
doit('helpztags', sort keys %tagdirs);
}
});
|