1 | ---
|
2 | title: Builtin Commands (Oils Reference)
|
3 | all_docs_url: ..
|
4 | body_css_class: width40
|
5 | default_highlighter: oils-sh
|
6 | preserve_anchor_case: yes
|
7 | ---
|
8 |
|
9 | <div class="doc-ref-header">
|
10 |
|
11 | [Oils Reference](index.html) — Chapter **Standard Library**
|
12 |
|
13 | </div>
|
14 |
|
15 | This chapter in the [Oils Reference](index.html) describes the standard library
|
16 | for 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 |
|
29 | Compute the absolute (positive) value of a number (float or int).
|
30 |
|
31 | = abs(-1) # => 1
|
32 | = abs(0) # => 0
|
33 | = abs(1) # => 1
|
34 |
|
35 | Note, you will need to `source --builtin math.ysh` to use this function.
|
36 |
|
37 | ### max()
|
38 |
|
39 | Compute 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 |
|
46 | For example:
|
47 |
|
48 | = max(1, 2) # => 2
|
49 | = max([1, 2, 3]) # => 3
|
50 |
|
51 | Note, you will need to `source --builtin math.ysh` to use this function.
|
52 |
|
53 | ### min()
|
54 |
|
55 | Compute 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 |
|
62 | For example:
|
63 |
|
64 | = min(2, 3) # => 2
|
65 | = max([1, 2, 3]) # => 1
|
66 |
|
67 | Note, you will need to `source --builtin math.ysh` to use this function.
|
68 |
|
69 | ### round()
|
70 |
|
71 | TODO
|
72 |
|
73 | ### sum()
|
74 |
|
75 | Computes the sum of all elements in the list.
|
76 |
|
77 | Returns 0 for an empty list.
|
78 |
|
79 | = sum([]) # => 0
|
80 | = sum([0]) # => 0
|
81 | = sum([1, 2, 3]) # => 6
|
82 |
|
83 | Note, you will need to `source --builtin list.ysh` to use this function.
|
84 |
|
85 |
|
86 | ## list
|
87 |
|
88 | ### all()
|
89 |
|
90 | Returns true if all values in the list are truthy (`x` is truthy if `Bool(x)`
|
91 | returns true).
|
92 |
|
93 | If 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 |
|
100 | Note, you will need to `source --builtin list.ysh` to use this function.
|
101 |
|
102 | ### any()
|
103 |
|
104 | Returns true if any value in the list is truthy (`x` is truthy if `Bool(x)`
|
105 | returns true).
|
106 |
|
107 | If 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 |
|
114 | Note, you will need to `source --builtin list.ysh` to use this function.
|
115 |
|
116 | ### repeat()
|
117 |
|
118 | Repeat a string or a list:
|
119 |
|
120 | = repeat('foo', 3) # => 'foofoofoo'
|
121 | = repeat(['foo', 'bar'], 2) # => ['foo', 'bar', 'foo', 'bar']
|
122 |
|
123 | Negative repetitions are equivalent to zero:
|
124 |
|
125 | = repeat('foo', -5) # => ''
|
126 | = repeat(['foo', 'bar'], -5) # => []
|
127 |
|
128 | ## two
|
129 |
|
130 | These functions are in `two.sh`
|
131 |
|
132 | source $OSH_LIB/two.sh
|
133 |
|
134 | ### log
|
135 |
|
136 | Write a message to stderr:
|
137 |
|
138 | log "hi $x"
|
139 | log '---'
|
140 |
|
141 | ### die
|
142 |
|
143 | Write an error message with the script name, and exit with status 1.
|
144 |
|
145 | die 'Expected a number'
|
146 |
|
147 | ## Args Parser
|
148 |
|
149 | YSH includes a command-line argument parsing utility called `parseArgs`. This
|
150 | is intended to be used for command-line interfaces to YSH programs.
|
151 |
|
152 | To use it, first import `args.ysh`:
|
153 |
|
154 | source --builtin args.ysh
|
155 |
|
156 | Then, 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 |
|
176 | Finally, parse `ARGV` (or any other array of strings) with:
|
177 |
|
178 | var args = parseArgs(spec, ARGV)
|
179 |
|
180 | The returned `args` is a `Dict` containing key-value pairs with the parsed
|
181 | values (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 |
|
204 | In the above example, `parser` takes in a place `&spec`, which will store the
|
205 | resulting specification and a block which is evaluated to build that
|
206 | specification.
|
207 |
|
208 | Inside 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
|
215 | flag 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 |
|
232 | The 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 |
|
237 | Flags 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 |
|
243 | Calling `parseArgs` with `ARGV = :| -n 5 |` or `ARGV = :| --count 5 |` will
|
244 | store the integer `5` under `args.count`. If the user passes in a non-integer
|
245 | value like `ARGV = :| --count abc |`, `parseArgs` will raise an error.
|
246 |
|
247 | Default 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 |
|
260 | Each 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 |
|
275 | The above example declares two positional arguments called "query" and "path".
|
276 | `parseArgs()` will then store strings under `args.query` and `args.path`. Order
|
277 | matters, so the first positional argument will be stored to `query` and the
|
278 | second to `path`. If not enough positional arguments are passed, then
|
279 | `parseArgs` will raise an error.
|
280 |
|
281 | Similar to `flag`, each `arg` name must be unique. Calling `arg` with the same
|
282 | name 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 |
|
293 | Capture zero or more positional arguments not already captured by `arg`. So,
|
294 | for `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 |
|
298 | Without 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
|
302 | will raise an error in `parser`.
|
303 |
|
304 | ### parseArgs()
|
305 |
|
306 | Given a parser specification `spec` produced by `parser`, parse a list of
|
307 | strings (usually `ARGV`.)
|
308 |
|
309 | var args = parseArgs(spec, ARGV)
|
310 |
|
311 | The 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
|
313 | topic](#Args-Parser).)
|
314 |
|
315 | `parseArgs` will raise an error if the `ARGV` is invalid per the parser
|
316 | specification. 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 | <!--
|
326 | TODO: Document chaining parsers / sub-commands
|
327 | - Either will allow parser nesting
|
328 | - Or can use `rest rest` and `parseArgs` again on `rest`
|
329 | TODO: Document the help named argument. Punting while we do not generate help messages
|
330 | -->
|