xaizek / vifm (License: GPLv2+) (since 2018-12-07)
Vifm is a file manager with curses interface, which provides Vi[m]-like environment for managing objects within file systems, extended with some useful ideas from mutt.
<root> / src / helpztags (d5f42361f412fada7c161ab78e1cdd366a4bb616) (2,278B) (mode 100755) [raw]
#!/usr/bin/env perl
#
# helpztags generates tags for Vim helpfiles, for both .txt and .txt.gz files
# Author: Jakub Turski <yacoob@chruptak.plukwa.net>
#         Artur R. Czechowski <arturcz@hell.pl>
# Version: 0.4
#
# xaizek: disallow bar symbol (|) in tags as Vim does
# xaizek: warn about duplicated tags

# Please use following command for generate a manual file:
# pod2man -c "User Commands" -s 1 -q none -r "vim 6.2" -d "September 2003" helpztags helpztags.1

=head1 NAME

helpztags - generate the help tags file for directory

=head1 SYNOPSIS

helpztags F<DIRS>...

=head1 DESCRIPTION

F<helpztags> scans given directories for F<*.txt> and F<*.txt.gz> files.
Each file is scanned for tags used in F<vim> help files. For each directory
proper F<tags> file is generated.

There should be at least one directory given. In other case program exits
with error.

=head1 AUTHORS

Written by Jakub Turski and Artur R. Czechowski based on idea
contained in C<vim> sources for its C<:helptags command>.

=head1 REPORTING BUGS

Please use a Debian C<reportbug> command or procedure described at
C<http://bugs.debian.org/>.

=head1 SEE ALSO

Read C<:help helptags> in F<vim> for detailed information about helptags.

=cut

use File::Glob ':globally';
use POSIX qw(getcwd);

($#ARGV==-1)&& die "Error: no directories given. Check manpage for details.\n";

$startdir=getcwd();

foreach $dir (@ARGV) {
  chdir $dir || die "Error: $dir: no such directory\n";
  print "Processing ".$dir."\n";
  open(TAGSFILE,">tags") || die "Error: Cannot open $dir/tags for writing.\n";
  foreach $file (<*.{gz,txt}>) {
    do { open(GZ, "zcat $file|") if ($file =~ /\.gz$/) } or open(GZ,$file);
    while (<GZ>) {
        # From vim61/src/ex_cmds.c, lines 5034-5036
        #
        # Only accept a *tag* when it consists of valid
        # characters, there is no '-' before it and is followed
        # by a white character or end-of-line.
      while (/(?<!-)\*([^*|\s]+?)\*\s+?/g) {
        if (exists($tags{$+})) {
          die "Error: duplicated tag in $dir/$file at $.: $+\n";
        }
        $tags{$+}=$file;
      }
    }
    close(GZ);
  }
  map { print TAGSFILE "$_\t$tags{$_}\t/*"; s'\\'\\\\'g; s'/'\/'g; print TAGSFILE "$_*\n" } sort keys %tags;
  close TAGSFILE;
  chdir $startdir;
}
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/vifm

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/vifm

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master