diff options
Diffstat (limited to 'shin')
-rwxr-xr-x | shin | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/shin b/shin new file mode 100755 index 0000000..b966091 --- /dev/null +++ b/shin | |||
@@ -0,0 +1,67 @@ | |||
1 | #!/bin/sh | ||
2 | # SHIN v. 0/1 | ||
3 | # Copyright (C) Case Duckworth <acdw@acdw.net> | ||
4 | # Licensed under the Fair License. See COPYING for details. | ||
5 | |||
6 | _shin() { | ||
7 | awk 'BEGIN { | ||
8 | if (ENVIRON["SHINPATH"]) split(ENVIRON["SHINPATH"], SHINPATH, ":") | ||
9 | else SHINPATH[1] = "." | ||
10 | } | ||
11 | FNR == 1 { outfile = FILENAME; sub(/in$/, "", outfile) } | ||
12 | { print($0) > outfile } | ||
13 | /^#</ { | ||
14 | inclfile = shin_resolve(substr($0, 3)) | ||
15 | while (getline l < inclfile) print(l) > outfile | ||
16 | close(inclfile) | ||
17 | sub(/</, ">", $0) | ||
18 | print > outfile | ||
19 | } | ||
20 | function shin_test(filename) { | ||
21 | if (! system("test -f \"" f "\"")) return filename | ||
22 | print("Cannot find \"" filename "\" in " sp) > (STDERR ? STDERR : "/dev/stderr") | ||
23 | exit 1 | ||
24 | } | ||
25 | function shin_resolve(filename) { | ||
26 | if (match(filename, "^/")) return shin_test(filename) | ||
27 | if (match(filename, "^~")) return shin_test(ENVIRON["HOME"] "/" substr(filename, 2)) | ||
28 | sub(/^[ \t]*/, "", filename) | ||
29 | sub(/[ \t]*$/, "", filename) | ||
30 | sp = "" | ||
31 | for (p in SHINPATH) { | ||
32 | sp = sp (sp ? ", " : "") "\"" SHINPATH[p] "\"" | ||
33 | f = SHINPATH[p] "/" filename | ||
34 | gsub("//", "/", f) | ||
35 | return shin_test(f) | ||
36 | } | ||
37 | }' | ||
38 | } | ||
39 | |||
40 | if [ "x$1" = -h ]; then | ||
41 | cat <<\EOF | ||
42 | SHIN: include shell files in other shell files | ||
43 | USAGE: shin [-h] FILE... | ||
44 | |||
45 | FLAGS: | ||
46 | -h Show this help and exit. | ||
47 | |||
48 | PARAMETERS: | ||
49 | FILE... Input files. FILEs named FILE.shin will be built to | ||
50 | FILE.sh in the same directory. To include files in | ||
51 | shin files, use the following comment syntax: | ||
52 | |||
53 | #< INCLUDE | ||
54 | |||
55 | If INCLUDE begins with / or ~, it's taken as a literal | ||
56 | file name; otherwise SHINPATH will be searched for the | ||
57 | file. SHINPATH is a colon-separated list of paths | ||
58 | like $PATH. If SHINPATH is unset, it defaults to the | ||
59 | current directory. | ||
60 | |||
61 | If INCLUDE is not found, shin will error and quit. | ||
62 | Otherwise, shin will add INCLUDE below that comment, | ||
63 | as well as a comment denoting the end of the INCLUDE. | ||
64 | EOF | ||
65 | else | ||
66 | _shin "$@" | ||
67 | fi | ||