-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathate.1
313 lines (278 loc) · 6.98 KB
/
ate.1
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
.TH ate 1 2023-06-26 "" "Loadable Bash Builtin Manual"
.nr include_flag 1
.so ate.1.d/macros.1
.\"
.so ate.1.d/name.1
.so ate.1.d/synopsis.1
.so ate.1.d/description.1
.so ate.1.d/enabling_ate.1
.so ate.1.d/syntax.1
.so ate.1.d/return.1
.SH ATE ACTIONS
.so ate.1.d/list_actions.1
.so ate.1.d/show_action.1
.so ate.1.d/declare.1
.so ate.1.d/append_data.1
.so ate.1.d/index_rows.1
.so ate.1.d/get_row_count.1
.so ate.1.d/get_row_size.1
.so ate.1.d/get_array_name.1
.so ate.1.d/get_field_sizes.1
.so ate.1.d/get_row.1
.so ate.1.d/put_row.1
.so ate.1.d/resize_rows.1
.so ate.1.d/reindex_elements.1
.so ate.1.d/seek_key.1
.SH ACTIONS INVOKING CALLBACK FUNCTIONS
.PP
The following actions call a script function on each table row to
perform an action or to judge one or more records.
.so ate.1.d/walk_rows.1
.so ate.1.d/sort.1
.so ate.1.d/filter.1
.so ate.1.d/make_key.1
.SH EXAMPLES
.PP
A picture is worth a thousand words, likewise, an example may be more
useful than pages of documentation.
.SS DECLARE EXAMPLE
.PP
An
.B ate
handle begins with an array.
There are two methods:
.IP
.EX
declare -a pets=(
dog bark
cat meow
goat bleat
duck quack
cow moo
)
// Method 1, use existing array
ate \fBdeclare\fP pet_handle 2 pets
// Method 2, using anonymous array, filled in second step
ate \fBdeclare\fP pet_handle 2
ate \fBappend_data\fP pet_handle \(dq${pets[@]}\(dq
# Must manually update index after \fBappend_data\fP
ate \fBindex_rows\fP pet_handle
.EE
.SS GET INFO EXAMPLES
.PP
There are some informational actions, as shown:
.IP
.EX
ate \fBget_array_name\fP pet_handle
echo \(dqArray name is $ATE_VALUE\(dq
ate \fBget_row_count\fP pet_handle -v row_count
echo \(dqRow count is $row_count\(dq
ate \fBget_row_size\fP pet_handle -v row_size
echo \(dqRow size is $row_size\(dq
ate \fBget_field_sizes\fP pet_handle -a col_sizes
echo \(dqField sizes are ${col_sizes[*]}\(dq
.EE
.SS GET_ROW EXAMPLE
.PP
Access a table row by 0-based index.
.IP
.EX
ate \fBget_row\fP pet_handle 0
echo \(dqfirst row is ${ATE_ARRAY[*]}\(dq
# Use -a option to override array result name
ate \fBget_row\fP pet_handle 1 -a pet_row
echo \(dqsecond row is ${pet_row[*]}\(dq
.EE
.SS PUT_ROW EXAMPLE
.PP
The script must take care to keep the row and its row number
in sync.
.IP
.EX
ate \fBget_row\fP pet_handle 0 -a pet_row
# change second column and update table
pet_row[1]="bow-wow"
ate \fBput_row\fP pet_handle 0 pet_row
.EE
.SS WALK_ROWS EXAMPLES
.PP
The
.B walk_rows
action invokes a callback function for each row:
.IP
.EX
display_row()
{
local -n dr_row=\(dq$1\(dq
printf \(dq%s makes a %s\(rsn\(dq \(dq${dr_row[@]}\(dq
# Return 0 to continue, non-zero to terminate row walk:
return 0
}
ate \fBwalk_rows\fP pet_handle display_row
.EE
.PP
A
.B walk_rows
procedure might also be used to update the rows of a table.
.IP
.EX
capitalize_name()
{
local -n ur_row=\(dq$1\(dq
local -i row_num=\(dq$2\(dq
local -n ur_handle=\(dq$3\(dq
ur_row[0]=\(dq${ur_row[0]^}\(dq
ate put_row ur_handle \(dq$row_num\(dq ur_row
return 0
}
ate \fBwalk_rows\fP pet_handle capitalize_name
.EE
.SS SORT EXAMPLE
.PP
Like
.BR walk_rows ", the " sort " action"
employes a callback function for flexible ordering:
.IP
.EX
compare_names()
{
local -n cr_result=\(dq$1\(dq
local -n cr_left=\(dq$2\(dq
local -n cr_right=\(dq$3\(dq
\fB# isolate thd column on which we're sorting\fP
local name_left=\(dq${cr_left[0]}\(dq
local name_right=\(dq${cr_right[0]}\(dq
\fB# Use [[ and ]] to compare the lexical order of strings.\fP
if [[ \(dq$left\(dq < \(dq$right\(dq ]]; then
cr_result=-1
elif [[ \(dq$right\(dq < \(dq$left\(dq ]]; then
cr_result=1
else
cr_result=0
fi
return 0
}
.B # Create (and use) sorted handle:
ate \fBsort\fP pet_handle compare_names pets_by_name
ate \fBwalk_rows\fP pets_by_name display_row
.EE
.SS FILTER EXAMPLE
.PP
Another callback function, this time the script provides a function
that decides whether or not a given record should be included in the
filtered group.
.PP
In the following example, the table contained in handle
.B handle_calendar
contains the appointments for everyone in a family.
Chuck want to check on his appointments, so he uses the
.B filter
action to isolate his appointments in the new handle,
.BR handle_chuck_appts .
The resulting filtered table is then printed with the
.B print_formatted_table
function found in the following code example.
.IP
.EX
select_chucks()
{
local -n sc_row=\(dq$1\(dq
local first_name=\(dq${sc_row[1]}\(dq
if [ \(dq${first_name,,}\(dq == \(dqchuck\(dq ]; then
return 0
fi
return 1
}
if ate \fBfilter\fP handle_calendar select_chucks handle_chuck_appts; then
print_formatted_table handle_chuck_appts
fi
.EE
.SS SEEK_KEY EXAMPLE
.PP
Using the
.B pets
array and
.B pet_handle
from the
.B DECLARE EXAMPLE
above, use
.BR MAKE_KEY " and " SEEK_KEY
.IP
.EX
# use lower-case key for case-insensitive matches
assign_key()
{
local -n ak_return=\(dq\(Do1\(dq
local -n ak_row=\(dq\(Do2\(dq
local val=\(dq\(Do{ak_row[0]}\(dq
ak_return=\(dq\(Do{val,,}\(dq
return 0
}
\(sh Make the key table:
ate \fBmake_key\fP pet_handle assign_key pet_key_handle
\(sh Use the key table to find the \(dqdog\(dq row in the
\(sh pet_handle table:
\(sh Find the dog key row index:
ate \fBseek_key\fP pet_key_handle \(dqdog\(dq -v dog_ndx
# Get the key row:
ate \fBget_row\fP pet_key_handle \(dq\(Dodog_ndx\(dq -a key_row
# Get the table row:
ate \fBget_row\fP pet_handle \(dq\(Do{key_row[1]}\(dq -a pet_row
.EE
.PP
Using
.BR make_key " and " seek_key
is overly-complicated for a very small table like our pet table.
They become much more useful when processing very large tables
such as ones that might be derived from a command history list,
.B journalctl
output, or terminfo values.
.SS FORMATTED TABLE EXAMPLE
.PP
Tables with aligned columns are easier to read.
Use
.B ate
actions
.BR get_field_sizes " and " walk_rows
to produce an aligned-column table display by constructing
a custom
.B printf
format string based on the maximum string lengths of each field.
.IP
.EX
print_formatted_table()
{
local -n pft_handle=\(dq$1\(dq
\fB# Make format string\fP
ate \fBget_field_sizes\fP pft_handle
local -a parts=()
local width
local delim=\(aq\(aq
for width in \(dq${ATE_ARRAY[@]}\(dq; do
parts+=( \(dq$delim\(dq \(dq%-${width}s\(dq )
delim=\(aq \(aq
done
\fB# Scrunch array to format string\fP
local IFS=\(aq\(aq
local fmt=\(dq${parts[*]}\(rsn\(dq
\fB# Embedded callback print function\fP
print_row()
{
local -n pr_row=\(dq$1\(dq
printf \(dq$fmt\(dq \(dq${pr_row[@]}\(dq
}
ate \fBwalk_rows\fP pft_handle print_row
}
.EE
.SH WARNINGS
.TP
.B Hosted Array
Do not attempt to manipulate the ate-hosted array without the
.B ate
handle.
Directly adding or removing elements from the hosted array will
cause the index to be out-of-date.
Additionally, if added or removed elements result in an uneven
number of elements (not evenly-divisible into the row_size),
some data will not be accessible from
.BR ate.