-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpwb_git_log
executable file
·361 lines (293 loc) · 9.02 KB
/
pwb_git_log
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
#!/usr/bin/env bash
enable ate
enable pwb
source <( pwb_sources \
ate_exit_on_error \
pwb_exit_on_error \
pwb_get_regions \
pwb_print_array \
pwb_printf_limited \
pwb_display_ate_table \
pwb_get_scroll_bar \
)
declare PWB_NAME="gl_display"
declare PWB_MARGIN_COLOR=$'\e[48;2;64;64;64m'
goto_newline() { pwb_newline_indent "$PWB_NAME"; }
clear_comrec() { comrec=( "" "" "" "" "" "" "" ); }
declare ROW_SIZE=7
declare -n commit_hash="comrec[0]"
declare -n commit_decoration="comrec[1]"
declare -n commit_author="comrec[2]"
declare -n commit_date="comrec[3]"
declare -n commit_title="comrec[4]"
declare -n commit_message="comrec[5]"
declare -n commit_merge="comrec[6]"
declare -a commit_fields=(
hash decoration author date title message merge
)
# longest field name, 'decoration', is 10 characters
declare -i max_field_len=10
# Test to confirm clear_comrec makes the expected (ROW_SIZE) length array:
clear_comrec
if [ "${#comrec[*]}" -ne "$ROW_SIZE" ]; then
echo "Comrec array size must match ROW_SIZE constant."
exit
fi
declare -a re_commit_array=(
^
commit
[[:space:]]
\( # capture group #1 for commit hash value
[[:xdigit:]]+
\)
\( # conditional group #2 of optional decoration
[[:space:]]*
\\\( # match opening raw parenthesis
\( # capture group #3 for contents of decoration
[^)]+ # capture to close raw parentesis
\)
\\\)
\)? # end of conditional group #2
$
)
declare OIFS="$IFS"
IFS=''
declare re_commit="${re_commit_array[*]}"
IFS="$OIFS"
unset OIFS
scan_git_log()
{
local tname="$1"
# Confirm appropriate configuration
ate get_row_size "$tname" -v row_size
ate_exit_on_error
if [ "$row_size" -lt "$ROW_SIZE" ]; then
echo "Invalid row size of $row_size should be $ROW_SIZE"
exit
fi
local -a git_log_args=(
--no-pager
log
--date=iso-strict
--pretty=medium
--decorate=full
)
if [ "$#" -gt 1 ]; then
git_log_args+=( --follow -- "$2" )
fi
local OIFS="$IFS"
local IFS=$' '
# Directly use hosted array
ate get_array_name "$tname" -v aname
ate_exit_on_error
local -n sgl_array="$aname"
local -i text_state=0
local curline
local -a text_block=()
local -i commit_count=0
local -i commit_count_predicted=$( git rev-list --count --all )
local -a comrec
clear_comrec
while IFS= read -r curline; do
if [[ "$curline" =~ ^[[:space:]]+([^[:space:]].*) ]]; then
text_block+=( "${BASH_REMATCH[1]}" )
elif [[ "$curline" =~ $re_commit ]]; then
# If currec has contents, save and clear it:
if [ -n "$commit_hash" ]; then
if [ "${#text_block[*]}" -ne 0 ]; then
commit_message="${text_block[*]}"
fi
if (( ++commit_count % 100 == 0 )); then
printf $'\e[2K\e[1G%4d commits out of %4d expected, (%d%%)' \
"$commit_count" \
"$commit_count_predicted" \
$(( (commit_count * 100) / commit_count_predicted ))
fi
sgl_array+=( "${comrec[@]}" )
text_state=0
clear_comrec
fi
text_block=()
text_state=0
# Start next commit record
commit_hash="${BASH_REMATCH[1]}"
commit_decoration="${BASH_REMATCH[3]}"
elif [[ "$curline" =~ ^Author:\ +([^\)]+)$ ]]; then
commit_author="${BASH_REMATCH[1]}"
elif [[ "$curline" =~ ^Date:\ *([^\)]+)$ ]]; then
commit_date="${BASH_REMATCH[1]}"
elif [[ "$curline" =~ ^Merge:\ +([^\)]+)$ ]]; then
commit_merge="${BASH_REMATCH[1]}"
elif [[ "$curline" =~ ^[[:space:]]*$ ]]; then
(( ++text_state ))
if (( text_state == 2 )); then
commit_title="${text_block[*]}"
text_block=()
elif (( text_state > 2 )); then
text_block+=( $'\nBOO\n' )
fi
fi
done < <( git "${git_log_args[@]}" )
# Save final commit record, not followed by a "commit" line
if [ -n "$commit_hash" ]; then
if [ "${#text_block[*]}" -ne 0 ]; then
if [ "$text_state" -lt 2 ]; then
commit_title="${text_block[*]}"
else
commit_message="${text_block[*]}"
fi
fi
sgl_array+=( "${comrec[@]}" )
clear_comrec
fi
printf $'\e[2K\e[1G'
ate index_rows "$tname"
ate_exit_on_error
}
get_constrained_line()
{
local -n gcl_line="$1"
local -i constraint="$2"
local -n gcl_text="$3"
local -n gcl_progress="$4"
return 1
}
gl_print_formatted_rec()
{
local -a comrec="$1"
local -i screen_cols="$2"
printf $'\e[2J'
declare -i line_width="80"
declare -i left_margin=$(( (screen_cols - line_width) / 2 ))
declare -i data_margin=$(( max_field_len + left_margin + 2 ))
declare -i text_len=$(( line_width - max_field_len - 2 ))
declare format_field
printf -v format_field $'\e[1B\e[%dG%%s: ' "$left_margin"
declare format_text_cont
printf -v format_text_cont $'%%s\e[1B\e[%dG' "$data_margin"
local -i index max_index="${#commit_fields[*]}"
for (( index=0; index<max_index; ++index )); do
local value="${comrec[$index]}"
if [ -n "$value" ]; then
printf "$format_field" "${commit_fields[$index]}"
local line
local -i progress=0
while get_constrained_line line "$value" progress; do
printf "$format_text_cont" "$line"
done
fi
done
read -n1 -p "Press any key to return"
}
gl_show_commit()
{
local -i index="$2"
local dsource="$3"
local pwb_handle="$4"
local -a comrec
ate get_row "$dsource" "$index" -a comrec
ate_exit_on_error
local termapp="$TERM"
x-terminal-emulator -e git -p show "$commit_hash" | less -R
# printf $'\e[2J'
# printf $'\e[1;1H'
# git -p show "$commit_hash" | less -R
# printf $'\e[2J'
pwb print_all "$pwb_handle"
pwb_exit_on_error
return 0
}
###########################
### PWB Print Functions ###
###########################
gl_print_line()
{
local -i index="$1"
local tname="$2"
local -i char_count="$3"
local -a comrec
ate get_row "$tname" "$index" -a comrec
ate_exit_on_error
if [ -n "$commit_decoration" ]; then
printf $'\e[35;1m'
fi
pwb_printf_limited "$char_count" \
"%s (%s): %-s" \
"${commit_date:0:10}" \
"${commit_hash:0:8}" \
"${commit_title}"
if [ -n "$commit_decoration" ]; then
printf $'\e[39m'
fi
}
gl_print_top()
{
local -i index="$1"
local tname="$2"
local -i char_count="$3"
local pwb_handle="$5"
local -a comrec
ate get_row "$tname" "$index" -a comrec
ate_exit_on_error
local -i dindex=0
local -a dlines
printf -v dlines[$(( dindex++ ))] "%s %s" "${commit_data:1:10}" "$commit_hash"
printf -v dlines[$(( dindex++ ))] " Title: %s" "$commit_title"
printf -v dlines[$(( dindex++ ))] " Author: %s" "$commit_author"
if [ -n "$commit_merge" ]; then
printf -v dlines[$(( dindex++ ))]" Merge: %s" "$commit_merge"
fi
if [ -n "$commit_decoration" ]; then
printf -v dlines[$(( dindex++ ))] "Decoration: %s" "$commit_decoration"
fi
printf "$PWB_MARGIN_COLOR"
pwb_print_array dlines \
-t "${GL_REGIONS[TM_TOP]}" \
-l "${GL_REGIONS[TM_LEFT]}" \
-w "${GL_REGIONS[TM_WIDE]}" \
-c "${GL_REGIONS[TM_LINES]}"
printf $'\e[m'
}
exit_trap() { pwb restore; }
#######################
### BEGIN EXECUTION ###
#######################
# Exit quickly if we detect that git not initiated
if ! git status >/dev/null 2>&1; then
echo "Git not configured here, '$PWD'"
exit
fi
declare GL_TABLE
ate declare GL_TABLE "$ROW_SIZE"
ate_exit_on_error
# Built conditional argument list
declare -a scan_log_args=(
GL_TABLE
)
# If provided, add a path to the arguments list:
if [ "$#" -gt 0 ]; then
scan_log_args+=( "$1" )
fi
scan_git_log "${scan_log_args[@]}"
ate get_row_count GL_TABLE -v row_count
ate_exit_on_error
declare -a disp_args=(
GL_TABLE
"$row_count"
gl_print_line
-e gl_show_commit
-t gl_print_top
)
declare PWB_HANDLE
pwb declare PWB_HANDLE "${disp_args[@]}"
pwb_exit_on_error
pwb set_margins PWB_HANDLE 5 4 2
pwb_exit_on_error
# After margins are set, the region dimensions can be calculated
declare -A GL_REGIONS
pwb_get_regions GL_REGIONS PWB_HANDLE
trap exit_trap EXIT SIGINT SIGABRT
pwb init
# pwb_display_ate_table gl_table
pwb start PWB_HANDLE
pwb_exit_on_error