OILS / doc / ref / chap-stdlib.md View on Github | oilshell.org

330 lines, 216 significant
1---
2title: Builtin Commands (Oils Reference)
3all_docs_url: ..
4body_css_class: width40
5default_highlighter: oils-sh
6preserve_anchor_case: yes
7---
8
9<div class="doc-ref-header">
10
11[Oils Reference](index.html) &mdash; Chapter **Standard Library**
12
13</div>
14
15This chapter in the [Oils Reference](index.html) describes the standard library
16for OSH and YSH.
17
18(These functions are implemented in OSH or YSH, not C++ or Python.)
19
20<span class="in-progress">(in progress)</span>
21
22<div id="dense-toc">
23</div>
24
25## math
26
27### abs()
28
29Compute the absolute (positive) value of a number (float or int).
30
31 = abs(-1) # => 1
32 = abs(0) # => 0
33 = abs(1) # => 1
34
35Note, you will need to `source --builtin math.ysh` to use this function.
36
37### max()
38
39Compute the maximum of 2 or more values.
40
41`max` takes two different signatures:
42
43 1. `max(a, b)` to return the maximum of `a`, `b`
44 2. `max(list)` to return the greatest item in the `list`
45
46For example:
47
48 = max(1, 2) # => 2
49 = max([1, 2, 3]) # => 3
50
51Note, you will need to `source --builtin math.ysh` to use this function.
52
53### min()
54
55Compute the minimum of 2 or more values.
56
57`min` takes two different signatures:
58
59 1. `min(a, b)` to return the minimum of `a`, `b`
60 2. `min(list)` to return the least item in the `list`
61
62For example:
63
64 = min(2, 3) # => 2
65 = max([1, 2, 3]) # => 1
66
67Note, you will need to `source --builtin math.ysh` to use this function.
68
69### round()
70
71TODO
72
73### sum()
74
75Computes the sum of all elements in the list.
76
77Returns 0 for an empty list.
78
79 = sum([]) # => 0
80 = sum([0]) # => 0
81 = sum([1, 2, 3]) # => 6
82
83Note, you will need to `source --builtin list.ysh` to use this function.
84
85
86## list
87
88### all()
89
90Returns true if all values in the list are truthy (`x` is truthy if `Bool(x)`
91returns true).
92
93If the list is empty, return true.
94
95 = any([]) # => true
96 = any([true, true]) # => true
97 = any([false, true]) # => false
98 = any(["foo", true, true]) # => true
99
100Note, you will need to `source --builtin list.ysh` to use this function.
101
102### any()
103
104Returns true if any value in the list is truthy (`x` is truthy if `Bool(x)`
105returns true).
106
107If the list is empty, return false.
108
109 = any([]) # => false
110 = any([true, false]) # => true
111 = any([false, false]) # => false
112 = any([false, "foo", false]) # => true
113
114Note, you will need to `source --builtin list.ysh` to use this function.
115
116### repeat()
117
118Repeat a string or a list:
119
120 = repeat('foo', 3) # => 'foofoofoo'
121 = repeat(['foo', 'bar'], 2) # => ['foo', 'bar', 'foo', 'bar']
122
123Negative repetitions are equivalent to zero:
124
125 = repeat('foo', -5) # => ''
126 = repeat(['foo', 'bar'], -5) # => []
127
128## two
129
130These functions are in `two.sh`
131
132 source $OSH_LIB/two.sh
133
134### log
135
136Write a message to stderr:
137
138 log "hi $x"
139 log '---'
140
141### die
142
143Write an error message with the script name, and exit with status 1.
144
145 die 'Expected a number'
146
147## Args Parser
148
149YSH includes a command-line argument parsing utility called `parseArgs`. This
150is intended to be used for command-line interfaces to YSH programs.
151
152To use it, first import `args.ysh`:
153
154 source --builtin args.ysh
155
156Then, create an argument parser **spec**ification:
157
158 parser (&spec) {
159 flag -v --verbose (help="Verbosely") # default is Bool, false
160
161 flag -P --max-procs ('int', default=-1, help='''
162 Run at most P processes at a time
163 ''')
164
165 flag -i --invert ('bool', default=true, help='''
166 Long multiline
167 Description
168 ''')
169
170 arg src (help='Source')
171 arg dest (help='Dest')
172
173 rest files
174 }
175
176Finally, parse `ARGV` (or any other array of strings) with:
177
178 var args = parseArgs(spec, ARGV)
179
180The returned `args` is a `Dict` containing key-value pairs with the parsed
181values (or defaults) for each flag and argument. For example, given
182`ARGV = :| mysrc -P 12 mydest a b c |`, `args` would be:
183
184 {
185 "verbose": false,
186 "max-procs": 12,
187 "invert": true,
188 "src": "mysrc",
189 "dest": "mydest",
190 "files": ["a", "b", "c"]
191 }
192
193### parser
194
195`parseArgs()` requires a parser specification to indicate how to parse the
196`ARGV` array. This specification should be constructed using the `parser` proc.
197
198 parser (&spec) {
199 flag -f --my-flag
200 arg myarg
201 rest otherArgs
202 }
203
204In the above example, `parser` takes in a place `&spec`, which will store the
205resulting specification and a block which is evaluated to build that
206specification.
207
208Inside of a `parser` block, you should call the following procs:
209
210- `flag` to add `--flag` options
211- `arg` to add positional arguments
212- `rest` to capture remaining positional arguments into a list
213
214`parser` will validate the parser specification for errors such as duplicate
215flag or argument names.
216
217 parser (&spec) {
218 flag -n --name
219 flag -n --name # Duplicate!
220 }
221
222 # => raises "Duplicate flag/arg name 'name' in spec" (status = 3)
223
224### flag
225
226`flag` should be called within a `parser` block.
227
228 parser (&spec) {
229 flag -v --verbose
230 }
231
232The above example declares a flag "--verbose" and a short alias "-v".
233`parseArgs()` will then store a boolean value under `args.verbose`:
234- `true` if the flag was passed at least once
235- `false` otherwise
236
237Flags can also accept values. For example, if you wanted to accept an integer count:
238
239 parser (&spec) {
240 flag -N --count ('int')
241 }
242
243Calling `parseArgs` with `ARGV = :| -n 5 |` or `ARGV = :| --count 5 |` will
244store the integer `5` under `args.count`. If the user passes in a non-integer
245value like `ARGV = :| --count abc |`, `parseArgs` will raise an error.
246
247Default values for an argument can be set with the `default` named argument.
248
249 parser (&spec) {
250 flag -N --count ('int', default=2)
251
252 # Boolean flags can be given default values too
253 flag -O --optimize ('bool', default=true)
254 }
255
256 var args = parseArgs(spec, :| -n 3 |)
257 # => args.count = 2
258 # => args.optimize = true
259
260Each name passed to `flag` must be unique to that specific `parser`. Calling
261`flag` with the same name twice will raise an error inside of `parser`.
262
263<!-- TODO: how can we explicitly pass false to a boolean flag? -->
264<!-- TODO: how about --no-XXXX variants of flags? -->
265
266### arg
267
268`arg` should be called within a `parser` block.
269
270 parser (&spec) {
271 arg query
272 arg path
273 }
274
275The above example declares two positional arguments called "query" and "path".
276`parseArgs()` will then store strings under `args.query` and `args.path`. Order
277matters, so the first positional argument will be stored to `query` and the
278second to `path`. If not enough positional arguments are passed, then
279`parseArgs` will raise an error.
280
281Similar to `flag`, each `arg` name must be unique. Calling `arg` with the same
282name twice will cause `parser` to raise an error.
283
284### rest
285
286`rest` should be called within a `parser` block.
287
288 parser (&spec) {
289 arg query
290 rest files
291 }
292
293Capture zero or more positional arguments not already captured by `arg`. So,
294for `ARGV = :| hello file.txt message.txt README.md |`, we would have
295`args.query = "file.txt"` and `args.files = ["file.txt", "message.txt",
296"README.md"]`.
297
298Without rest, passing extraneous arguments will raise an error in
299`parseArgs()`.
300
301`rest` can only be called _once_ within a `parser`. Calling it multiple times
302will raise an error in `parser`.
303
304### parseArgs()
305
306Given a parser specification `spec` produced by `parser`, parse a list of
307strings (usually `ARGV`.)
308
309 var args = parseArgs(spec, ARGV)
310
311The returned `args` is a dictionary mapping the names of each `arg`, `flag` and
312`rest` to their captured values. (See the example at the [start of this
313topic](#Args-Parser).)
314
315`parseArgs` will raise an error if the `ARGV` is invalid per the parser
316specification. For example, if it's missing a required positional argument:
317
318 parser (&spec) {
319 arg path
320 }
321
322 var args = parseArgs(spec, [])
323 # => raises an error about the missing 'path' (status = 2)
324
325<!--
326TODO: Document chaining parsers / sub-commands
327 - Either will allow parser nesting
328 - Or can use `rest rest` and `parseArgs` again on `rest`
329TODO: Document the help named argument. Punting while we do not generate help messages
330-->