[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
retags 1.1
From: |
Tom Tromey |
Subject: |
retags 1.1 |
Date: |
Sun, 09 Mar 2008 10:59:08 -0600 |
User-agent: |
Gnus/5.11 (Gnus v5.11) Emacs/22.1 (gnu/linux) |
Here's a new version of the 'retags' script.
This version adds the ability to ignore patterns, using a line like
this in the .retags file:
testsuite/* ignore
It also changes retags to run recursively by default.
Finally, it tries to be smarter at startup time, so that the --force
option is no longer needed.
Tom
#! /bin/bash
# retags [--verbose] [--kill] DIR
# Run in background and watch for changes in DIR.
# Re-run etags whenever something changes.
# --kill means stop a running retags in DIR.
# --verbose turns on debug output
# Reads DIR/.retags to see how to run etags.
# Each line of .retags is a glob matching a file name, followed
# by etags arguments (don't use -o or the like).
# Instead of arguments, the word "ignore" means to ignore the file.
# Comments (with '#') or blank lines are ok.
# For instance, a typical, simple one is:
# *.[chyl]
# A more complicated one:
# *.def --language=none --regex='/DEFTREECODE [(]\([A-Z_]+\)/\1/'
# testsuite/* ignore
# By Tom Tromey <address@hidden>
# Licensed under the GPL.
# Version 1.1.
kill=
verbose=
function usage ()
{
echo "usage: retags [--verbose] [--kill] DIR" 1>&2
exit 1
}
while [[ $# -ne 1 ]]; do
case "$1" in
(--kill) kill=yes ;;
# We used to support --force, so keep doing that.
(--force) ;;
(--verbose) verbose=yes ;;
(*) break
esac
shift
done
if test $# -ne 1; then
usage
fi
dir=$1
if test -n "$kill"; then
rm -f $dir/.retags.pid
exit 0
fi
if ! test -f $dir/.retags; then
echo "retags: no such file $dir/.retags" 1>&2
exit 1
fi
dir=$(cd $dir && pwd)
cd $dir
if test -f .retags.pid; then
# Kill the running retags.
rm .retags.pid
fi
mkdir -p .retags.d
declare -a file_contents
function verbose ()
{
if test -n "$verbose"; then
echo "$@"
fi
}
function run ()
{
verbose "$@"
"$@"
}
function read_retags ()
{
local -i idx=0
file_contents=()
while read line; do
line=$(echo "$line" | sed -e 's, *#.*$,,')
if test "$line" != ""; then
verbose "Adding $line"
file_contents[$idx]=$line
idx=idx+1
fi
done < .retags
}
function finish ()
{
if test "$(cat .retags.pid 2> /dev/null)" = "$$"; then
rm -f .retags.pid
fi
exit 0
}
function update_etags ()
{
local args
local files=$(echo .retags.d/*)
if test "$files" != '.retags.d/*'; then
# We could use etags -i, but having a large number of includes
# makes emacs freak out.
cat $files > TAGS
fi
}
function handle_file ()
{
local event=$1
local file=$2
local -i idx=0
if test -e $file && ! test -f $file; then
return
fi
case $file in
# Backups and other uninteresting files.
(*~ | .#* | \#* | .retags.d* | TAGS)
return
;;
# Source control stuff.
(*.git* | *CVS* | *.svn* | *.hg*)
return
;;
(.retags.pid | */.retags.pid)
finish
return
;;
(.retags | */.retags)
if test $event = DELETE; then
finish
elif test $event = CLOSE_WRITE; then
read_retags
fi
return
esac
# We may get these even without listening for them explicitly
if test "$event" = DELETE_SELF || test $event = UNMOUNT; then
finish
fi
# See if the file matches any pattern the user provided.
local found pattern args
while [[ $idx -lt address@hidden ]]; do
pattern=$(echo "${file_contents[$idx]}" | sed -e 's, .*$,,')
case $file in
($pattern)
found=yes
args=$(echo "${file_contents[$idx]}" | sed -e 's,^[^ ]*\(
\|$\),,')
break
;;
esac
idx=idx+1
done
if test -z "$found"; then
return
fi
# A silly way to generate a variable name from the file name. Why
# did I write this in sh again? Note the leading 't'.
local md5=t$(echo "$file" | md5sum | sed 's/ *.*$//')
local tfile=.retags.d/$md5
local update=
local run_etags=
if test "$args" = ignore; then
if test $event = MODIFY_IF && test -f $tfile; then
# Was created, but is now ignored.
rm -f $tfile
fi
return
fi
case $event in
# This is a fake event used at startup only.
(MODIFY_IF)
# Note this does the right thing if tfile doesn't exist.
if test $file -nt $tfile; then
run_etags=yes
fi
;;
(MODIFY)
eval $md5=modified
;;
(CREATE)
eval $md5=modified
update=yes
;;
(DELETE)
if test -f $tfile; then
rm -f $tfile
update=yes
fi
;;
(CLOSE_WRITE)
if test "$(eval echo \$$md5)" = modified; then
run_etags=yes
fi
;;
esac
if test -n "$run_etags"; then
# Update the tags file for this source file. We have to
# play games here to prevent relativization, so we can
# cat the files into TAGS. If we ever use -i instead,
# fix this.
run eval "etags $args -o .retags.tmp $file"
mv .retags.tmp $tfile
eval $md5=
if test $event != MODIFY_IF; then
# See comment in update_etags.
update=yes
fi
fi
if test -n "$update"; then
update_etags
fi
}
# Make the TAGS file when it is missing.
function start_up ()
{
local file
echo -n "Updating tags files..."
find . -type f -print | sed -e 's,^[.]/,,' | while read file; do
handle_file MODIFY_IF $file
done
update_etags
echo "done"
}
# Read the config file and make the tags file the first time, if
# needed.
read_retags
start_up
(
absdir=$(pwd)/
# FIXME: handle moved_to and moved_from
inotifywait -mqr -e modify -e close_write -e delete -e create . |
while read edir events file; do
# Only bother with the first event.
event=$(echo "$events" | sed -e 's/,.*$//')
# Strip the base off the directory.
edir=$(echo "$edir" | sed -e "s,$absdir,,")
if test -n "$edir"; then
file="$edir$file"
fi
handle_file $event $file
done
) &
echo $! > .retags.pid
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- retags 1.1,
Tom Tromey <=