~skiqqy/bin

bin/tagd -rwxr-xr-x 2.8 KiB
e187890dStephen Cochrane Changed echo to no op a day ago
                                                                                
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
#!/bin/bash
# tagd is a simple script that will rebuild ctag files when files are edited.
# This script also acts as a wrapper for ctags.
# Author: Skiqqy

set -B
files=( )

usage ()
{
	cat << EOF
tagd ~ The ctags daemon.

Usage: tagd [options]

Options
-------
-h    Shows this message.
-o    Specify where the tags file should be put (default is curr directory).
-s    Specify the source directory that ctags must generate tags for (default is crr directory).
-g    Generate ctags and then exit.
-r    How often to refresh the tags file (in seconds).
-R    Recursively the directory (identical to ctags -R).
-d    Daemonize.
EOF
}

# set ${files[@]} to contain files in src with thier edited times.
set_files ()
{
	files=( )
	res=$(stat -c "%y|%n" "$src"/{*.c,*.h} | sort -r) # The sort is so when looping over the array if a time is found less than the last $iter the loop may exit (this is an optimization).

	IFS=$'\n'
	for file in $res # I want splitting.
	do
		files+=( "$file" )
	done
	IFS=" " # Reset IFS
}

# Usage: build <options> <output dir> <source dir>
build ()
{
	echo "Building tags file."

	ctags $1 "$3/"* # I want splitting
	if [ ! "$2" = "$(pwd)" ]
	then
		mv tags "$2"
	fi
}

# Convert a date.
# Usage: conv_date <date>
conv_date() {
	date --date="$1" +"%Y-%m-%d %H:%M:%S"
}

# Usage: comp_date <date1> <date2>
# Returns 0 if date1 < date 2, 1 date2 < date1
comp_date ()
{
	[[ $(conv_date "$1") < $(conv_date "$2") ]]
}

main ()
{
	# Vars
	tags=$(pwd)
	src=.
	daemonize=false # TODO: Implement daemonize feature.
	gen=false
	iter=$(date)
	refresh=60
	copts=

	while getopts "ho:s:dgr:R" opt
	do
		case $opt in
			h)
				usage
				exit
				;;
			o)
				tags=$(realpath "$OPTARG")
				if [ ! -d "$OPTARG" ]
				then
					echo "-o must specify a valid directory."
					exit 1
				fi
				;;
			s)
				src=$(realpath "$OPTARG")
				if [ ! -d "$OPTARG" ]
				then
					echo "-s must specify a valid directory."
					exit 1
				fi
				;;
			d)
				daemonize=true
				;;
			g)
				gen=true
				;;
			r)
				if [[ ! "$OPTARG" =~ ^[0-9]+(\.[0-9]+)?$ ]] || [[ "$OPTARG" =~ ^0(\.0*)?$ ]]
				then
					echo "-r must be a non zero real."
					exit 1
				fi
				refresh="$OPTARG"
				;;
			R)
				copts="-R"
				;;
			*)
				usage
				exit 1
				;;
		esac
	done

	# Build tags file before starting main loop.
	build "$copts" "$tags" "$src"

	if "$gen"
	then
		exit
	fi

	# Start
	for ((;;))
	do
		sleep "$refresh"
		set_files
		for file in "${files[@]}"
		do
			time=$(echo "$file" | cut -d "|" -f 1 | cut -d\. -f 1)
			file=$(echo "$file" | cut -d "|" -f 2)
			
			if comp_date "$iter" "$time"
			then
				echo "Change detected!"
				iter=$(date)
				build "$copts" "$tags" "$src"
				break # Yes I know that techinically we only have to look at the first item, but this loop is to allow for the script to be extended.
			fi
		done
	done
}

main "$@"