forked from doekman/osagitfilter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
osagitfilter.sh
executable file
·187 lines (169 loc) · 5.55 KB
/
osagitfilter.sh
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/usr/bin/env bash
# Unofficial Bash Strict Mode <http://redsymbol.net/articles/unofficial-bash-strict-mode/>
set -euo pipefail
IFS=$'\n\t'
SCRIPT_VER=0.7.1
SCRIPT_NAME=$(basename $0 .sh)
CALLED_WITH="$0 $@"
LOG_PATH=~/Library/Logs/Catsdeep/
OSA_GET_LANG_CMD=osagetlang
DEFAULT_OSA_LANG=AppleScript
OSA_LANG=$DEFAULT_OSA_LANG
FORBIDDEN_TEXT="AppleScript Debugger" #colon seperated list
FORBIDDEN=()
DO_LOG=0
FILE=
SCRATCH=
function finish {
#SCRATCH is initialized to a temp directory only at the moment it's needed
if [[ $SCRATCH ]]; then
if [[ $DO_LOG = 0 ]]; then
rm -Rf "$SCRATCH"
else #leave the temporary files when in debug or logging mode
log_line "stopped: $(date '+%Y-%m-%d %H:%M:%S') (temporary files have been left for inspection)"
#make the log operation "atomic"
cat $SCRATCH/tmp.log >> $LOG_PATH/$SCRIPT_NAME.log
fi
fi
}
trap finish EXIT
################
function usage {
show_version
echo
echo "usage: $SCRIPT_NAME command [options] [FILE]"
echo
echo "command (use one):"
echo " clean Translates OSA script to text, to be put into git"
echo " smudge Translates text stored in git to OSA script"
echo
echo "arguments (all optional):"
echo " -f, --forbidden Provide (colon-seperated) forbidden languages. Use '-' for empty list; defaults to 'AppleScript Debugger'"
echo " -l, --log Write debug info to '$LOG_PATH/$SCRIPT_NAME.log'"
echo " -h, -?, --help Show this help message and exit"
echo " -v, --version Show program's version number and exit"
echo " FILE Filename of current stream; not actually used but comes in handy when debugging"
echo
echo "This script translates input from stdin to stdout only. The option '--forbidden' "
echo "are only used with the 'clean' command."
if [[ $# > 0 ]]; then
ERROR 1 "$@"
fi
exit 0
}
function show_version {
echo "$SCRIPT_NAME v$SCRIPT_VER"
}
function log_line {
if [[ $DO_LOG = 1 ]]; then
printf "%s\n" "$@">>$SCRATCH/tmp.log
fi
}
function ERROR {
ERR_NR=$1
shift
>&2 echo "ERROR: $@"
log_line "ERROR($ERR_NR): $@"
exit $ERR_NR
}
if [[ $# > 0 ]]; then
case $1 in
clean | smudge) CMD=$1;;
-h | -\? | --help) usage;;
-v | --version) show_version;exit 0;;
*) usage "unknown command '$1'";;
esac
shift
else
usage "missing command"
fi
while (( $# > 0 )) ; do
case $1 in
-f | --forbidden) [[ $# > 1 ]] || usage "FORBIDDEN argument expected after $1"; FORBIDDEN_TEXT=$2; shift;;
-l | --log) DO_LOG=1;;
-h | -\? | --help) usage;;
-v | --version) show_version;exit 0;;
-*) usage "Unrecognized switch '$1'";;
*) FILE=$1;;
esac
shift
done
IFS=:
if [[ $FORBIDDEN_TEXT = "-" ]]; then
FORBIDDEN=()
else
FORBIDDEN=($FORBIDDEN_TEXT)
fi
IFS=$'\n\t'
[[ $CMD ]] || usage "No command supplied"
[[ -d "$LOG_PATH" ]] || mkdir -p "$LOG_PATH"
SCRATCH=$(mktemp -d -t osagitfilter.tmp)
log_line "---=[ $(show_version) ]=----------------------------------------------"
log_line "command: $CMD"
log_line "started: $(date '+%Y-%m-%d %H:%M:%S')"
log_line "sw_vers: $(sw_vers | tr -d '\t' | tr '\n' ';')"
log_line "call: $CALLED_WITH"
log_line "caller: $(ps -o args= $PPID)" #see: https://stackoverflow.com/a/26985984/56
log_line "scratch: $SCRATCH"
log_line "pwd: $(pwd)"
log_line "filename: '$FILE'"
if [[ $CMD = clean ]]; then
#Create a temporary file from the stdin, because osadecompile expects a file, and $FILE might not exist on disk
CLEAN_SCPT_FILE=$SCRATCH/tmp_clean_stdin.scpt
cat - > $CLEAN_SCPT_FILE
#determine osa-language of input file
OSA_LANG=$($OSA_GET_LANG_CMD $CLEAN_SCPT_FILE)
log_line "OSA lang: $OSA_LANG"
if [[ $OSA_LANG = "-" ]]; then
#Not an OSA file, just let it pass through
cat $CLEAN_SCPT_FILE
else
#check if the osa-lang is forbidden
log_line "forbidden langs: ${FORBIDDEN[@]:-}"
for BL in "${FORBIDDEN[@]:-}"; do
if [[ $BL = $OSA_LANG ]]; then
ERROR 1 "OSA language '$BL' is forbidden by $SCRIPT_NAME"
fi
done
#write header
if [[ $OSA_LANG = "JavaScript" ]]; then
comment="//"
else
comment="#"
fi
# Possible lines that can be written (22-31 bytes, excluding newline):
# "#@osa-lang:AppleScript"
# "#@osa-lang:AppleScript Debugger"
# "//@osa-lang:JavaScript"
echo "$comment@osa-lang:$OSA_LANG"
#decompile to text, and strip tailing whitespace and finally remove last line if it's empty
log_line "Starting osadecompile, strip trailing whitespace and remove last line if it's empty (which is added by osacompile)"
osadecompile $CLEAN_SCPT_FILE | sed -E 's/[[:space:]]*$//' | perl -pe 'chomp if eof'
fi
elif [[ $CMD = smudge ]]; then
#Create a temporary file, for "random access" of stdin
SMUDGE_TXT_FILE=$SCRATCH/tmp_smudge_stdin.txt
cat - > $SMUDGE_TXT_FILE
# First get first 42 bytes (more than the max osa header) to make fail safe for binary files
# then take the first line (if there are more) and only return the header value
FIRST_LINE=$(head -c 42 < $SMUDGE_TXT_FILE | head -n 1)
OSA_HDR_RX=$'^(//|#)@osa-lang:(.+)$'
if [[ $FIRST_LINE =~ $OSA_HDR_RX ]]; then
OSA_LANG=${BASH_REMATCH[2]}
log_line "osa-lang header: '$OSA_LANG'"
#Create a temporary file, for storing output of osacompile
SMUDGE_SCPT_FILE=$SCRATCH/tmp_smudge_stdout.scpt
# Remove header (first line) and perform the compilation
log_line "Starting osacompilation"
# perl -pe'1..1and$_=""'
# sed '1d'
perl -pe'1..1and$_=""' < $SMUDGE_TXT_FILE | osacompile -l "$OSA_LANG" -o $SMUDGE_SCPT_FILE
# Osacompile always outputs to file puts the output on a file, so cat that file...
cat $SMUDGE_SCPT_FILE
else
# no header, so not an OSA file, just let it pass through
cat $SMUDGE_TXT_FILE
fi
else
usage "unexpected command (SHOULD NOT HAPPEN)"
fi