bin/git-ctags

Thu, 03 Oct 2019 01:16:54 -0500

author
Meredith Howard <mhoward@roomag.org>
date
Thu, 03 Oct 2019 01:16:54 -0500
changeset 794
152f0c95cbb0
parent 754
0b6dae901ee5
permissions
-rwxr-xr-x

drop ag.vim; this seems to cover all i do (plus rg)

#!/usr/bin/env ruby
exit if ENV['CTAGS_SKIP']
running_hook = ENV['CTAGS_HOOK'] || false
ctags_cmd    = ENV['CTAGS_CMD']  || 'ctags'

case ARGV[0]
when 'help'
  exec 'perldoc', '-T', $0
when 'hook'
  running_hook = true
end

if (dir = `git rev-parse --show-toplevel 2>/dev/null`.chomp) != ''
  list_cmd = 'git ls-files'
  conf     = "#{dir}/.git/ctags.conf"
elsif (dir = `hg root 2>/dev/null`.chomp) != ''
  list_cmd = 'hg stat -Aqn'
  conf     = "#{dir}/.hg/ctags.conf"
else
  abort 'not an hg or git repository'
end

target = "#{dir}/.tags"
tmp    = "#{dir}/.tags.#{$$}~"
opts   = File.exists?(conf) ? "--options=#{conf}" : ''

if running_hook
  fork and exit
  [STDIN, STDOUT, STDERR].each {|p| p.reopen '/dev/null'}
  sleep 5
end

open(target, File::RDONLY|File::CREAT, 0644) do |f|
  if running_hook
    exit unless f.flock(File::LOCK_EX|File::LOCK_NB)
    exit unless f.size == 0 || (Time.now - f.mtime) > 60
  end

  system(<<-CMD) or exit $?.exitstatus
    #{list_cmd} \
     | #{ctags_cmd} --tag-relative -L - -f"#{tmp}" #{opts} \
    && mv #{tmp} #{target}
  CMD
end

exit 0

__END__
=head1 NAME

git-ctags - run ctags on git tracked files

=head1 SYNOPSIS

 git ctags

 echo 'git ctags hook 2>/dev/null' >> .git/hooks/post-checkout &&
   chmod +x $_

 git checkout some/branch
 CTAGS_SKIP=1 git checkout some/branch

=head1 DESCRIPTION

Create a .tags file (target) using git's list of tracked files.  If
C<.git/ctags.conf> exists in the repo it is passed to the ctags invocation.

When run with the C<hook> argument or C<CTAGS_HOOK> set, additional behavior is
enabled to avoid excess re-runs during multiple VCS operations, and the work is
moved to background as well.

=head2 Mercurial

Mercurial repositories are supported too, with git taking priority when finding
a repo root.  To add a hook, in the repository C<.hg/hgrc>, add:

 [hooks]
 update = git ctags hook

In a Mercurial repo, additional options can be put in C<.hg/ctags.conf>.

=head1 ENVIRONMENT

=head2 CTAGS_SKIP

If defined, exit immediately.

=head2 CTAGS_HOOK

If defined, run as a VCS hook.  This causes git-ctags to fork and exit, wait five
seconds, then try to lock and update the tags file if it hasn't been updated in
the last minute.

=head2 CTAGS_CMD

If defined, use this to invoke ctags rather than assuming C<ctags> can be found in
path.

=cut

mercurial