OILS / frontend / flag_def.py View on Github | oilshell.org

540 lines, 308 significant
1#!/usr/bin/env python2
2"""Flag parser defintions."""
3
4from __future__ import print_function
5
6from frontend import args
7from frontend.flag_spec import (FlagSpec, FlagSpecAndMore, _FlagSpecAndMore)
8from frontend import option_def
9
10#
11# Definitions for builtin_assign
12#
13
14EXPORT_SPEC = FlagSpec('export_')
15EXPORT_SPEC.ShortFlag('-n')
16EXPORT_SPEC.ShortFlag('-f') # stubbed
17EXPORT_SPEC.ShortFlag('-p')
18
19READONLY_SPEC = FlagSpec('readonly')
20
21# TODO: Check the consistency of -a and -A against values, here and below.
22READONLY_SPEC.ShortFlag('-a')
23READONLY_SPEC.ShortFlag('-A')
24READONLY_SPEC.ShortFlag('-p')
25
26NEW_VAR_SPEC = FlagSpec('new_var')
27
28# print stuff
29NEW_VAR_SPEC.ShortFlag('-f')
30NEW_VAR_SPEC.ShortFlag('-F')
31NEW_VAR_SPEC.ShortFlag('-p')
32
33NEW_VAR_SPEC.ShortFlag('-g') # Look up in global scope
34
35# Options +r +x +n
36NEW_VAR_SPEC.PlusFlag('x') # export
37NEW_VAR_SPEC.PlusFlag('r') # readonly
38NEW_VAR_SPEC.PlusFlag('n') # named ref
39
40# Common between readonly/declare
41NEW_VAR_SPEC.ShortFlag('-a')
42NEW_VAR_SPEC.ShortFlag('-A')
43NEW_VAR_SPEC.ShortFlag('-i') # no-op for integers
44NEW_VAR_SPEC.ShortFlag('-u') # no-op for case
45NEW_VAR_SPEC.ShortFlag('-l') # no-op for case
46
47UNSET_SPEC = FlagSpec('unset')
48UNSET_SPEC.ShortFlag('-v')
49UNSET_SPEC.ShortFlag('-f')
50#UNSET_SPEC.ShortFlag('-z', args.String)
51
52#
53# Definitions for builtin_meta
54#
55
56# Unused because there are no flags! Just --.
57EVAL_SPEC = FlagSpec('eval')
58SOURCE_SPEC = FlagSpec('source')
59SOURCE_SPEC.LongFlag('--builtin')
60
61COMMAND_SPEC = FlagSpec('command')
62COMMAND_SPEC.ShortFlag('-v')
63COMMAND_SPEC.ShortFlag('-V')
64COMMAND_SPEC.ShortFlag('-p')
65
66TYPE_SPEC = FlagSpec('type')
67TYPE_SPEC.ShortFlag('-f')
68TYPE_SPEC.ShortFlag('-t')
69TYPE_SPEC.ShortFlag('-p')
70TYPE_SPEC.ShortFlag('-P')
71TYPE_SPEC.ShortFlag('-a')
72
73#
74# Definitions for builtin_pure
75#
76
77ALIAS_SPEC = FlagSpec('alias') # no flags yet
78UNALIAS_SPEC = FlagSpec('unalias') # no flags yet
79UNALIAS_SPEC.ShortFlag('-a')
80
81SHOPT_SPEC = FlagSpec('shopt')
82SHOPT_SPEC.ShortFlag('-s', long_name='--set')
83SHOPT_SPEC.ShortFlag('-u', long_name='--unset')
84SHOPT_SPEC.ShortFlag('-o') # use 'set -o' names
85# TODO: --print could print in a verbose format. (Annoying: codegen conflicts
86# with Python keyword.)
87SHOPT_SPEC.ShortFlag('-p')
88SHOPT_SPEC.ShortFlag('-q') # query option settings
89
90HASH_SPEC = FlagSpec('hash')
91HASH_SPEC.ShortFlag('-r')
92
93ECHO_SPEC = FlagSpec('echo')
94ECHO_SPEC.ShortFlag('-e') # no backslash escapes
95ECHO_SPEC.ShortFlag('-n')
96
97#
98# osh/builtin_printf.py
99#
100
101PRINTF_SPEC = FlagSpec('printf')
102PRINTF_SPEC.ShortFlag('-v', args.String)
103
104#
105# osh/builtin_misc.py
106#
107
108READ_SPEC = FlagSpec('read')
109READ_SPEC.ShortFlag('-r')
110READ_SPEC.ShortFlag('-s') # silent
111READ_SPEC.ShortFlag('-u', args.Int) # file descriptor
112READ_SPEC.ShortFlag('-t', args.Float) # timeout
113READ_SPEC.ShortFlag('-n', args.Int)
114READ_SPEC.ShortFlag('-N', args.Int)
115READ_SPEC.ShortFlag('-a', args.String) # name of array to read into
116READ_SPEC.ShortFlag('-d', args.String)
117READ_SPEC.ShortFlag('-p', args.String) # prompt
118
119# OSH extension (not really considered YSH!)
120READ_SPEC.ShortFlag('-0') # until NUL, like IFS= read -r -d ''
121# Arguably it could be named like
122# grep --null -Z
123# xargs --null -0
124# But this format is NOT recommended in YSH! It's unbuffered and slow. We
125# prefer lines with escaping.
126
127READ_SPEC.LongFlag('--all')
128READ_SPEC.LongFlag('--raw-line')
129READ_SPEC.LongFlag('--num-bytes', args.Int)
130# don't strip the trailing newline
131READ_SPEC.LongFlag('--with-eol')
132
133MAPFILE_SPEC = FlagSpec('mapfile')
134MAPFILE_SPEC.ShortFlag('-t')
135
136CD_SPEC = FlagSpec('cd')
137CD_SPEC.ShortFlag('-L')
138CD_SPEC.ShortFlag('-P')
139
140PUSHD_SPEC = FlagSpec('pushd')
141
142POPD_SPEC = FlagSpec('popd')
143
144DIRS_SPEC = FlagSpec('dirs')
145DIRS_SPEC.ShortFlag('-c')
146DIRS_SPEC.ShortFlag('-l')
147DIRS_SPEC.ShortFlag('-p')
148DIRS_SPEC.ShortFlag('-v')
149
150PWD_SPEC = FlagSpec('pwd')
151PWD_SPEC.ShortFlag('-L')
152PWD_SPEC.ShortFlag('-P')
153
154HELP_SPEC = FlagSpec('help')
155#HELP_SPEC.ShortFlag('-i') # show index
156# Note: bash has help -d -m -s, which change the formatting
157
158HISTORY_SPEC = FlagSpec('history')
159HISTORY_SPEC.ShortFlag('-a')
160HISTORY_SPEC.ShortFlag('-r')
161HISTORY_SPEC.ShortFlag('-c')
162HISTORY_SPEC.ShortFlag('-d', args.Int)
163
164#
165# osh/builtin_process.py
166#
167
168EXEC_SPEC = FlagSpec('exec')
169
170WAIT_SPEC = FlagSpec('wait')
171WAIT_SPEC.ShortFlag('-n')
172
173TRAP_SPEC = FlagSpec('trap')
174TRAP_SPEC.ShortFlag('-p')
175TRAP_SPEC.ShortFlag('-l')
176
177JOB_SPEC = FlagSpec('jobs')
178JOB_SPEC.ShortFlag('-l', help='long format')
179JOB_SPEC.ShortFlag('-p', help='prints PID only')
180JOB_SPEC.LongFlag('--debug', help='display debug info')
181
182ULIMIT_SPEC = FlagSpec('ulimit')
183
184ULIMIT_SPEC.ShortFlag('-a', help='Print all limits')
185ULIMIT_SPEC.LongFlag('--all', help='Alias for -a')
186ULIMIT_SPEC.ShortFlag('-H', help='Use hard limit')
187ULIMIT_SPEC.ShortFlag('-S', help='Use soft limit')
188
189_ULIMIT_RESOURCES = [
190 '-c',
191 '-d',
192 '-f',
193 '-n',
194 '-s',
195 '-t',
196 '-v',
197]
198
199for u_flag in _ULIMIT_RESOURCES:
200 ULIMIT_SPEC.ShortFlag(u_flag)
201
202#
203# FlagSpecAndMore
204#
205
206#
207# set and shopt
208#
209
210
211def _AddShellOptions(spec):
212 # type: (_FlagSpecAndMore) -> None
213 """Shared between 'set' builtin and the shell's own arg parser."""
214 spec.InitOptions()
215 spec.InitShopt()
216
217 for opt in option_def.All():
218 if opt.builtin == 'set':
219 spec.Option(opt.short_flag, opt.name)
220 # Notes:
221 # - shopt option don't need to be registered; we validate elsewhere
222 # - 'interactive' Has a cell for internal use, but isn't allowed to be
223 # modified.
224
225
226MAIN_SPEC = FlagSpecAndMore('main')
227
228MAIN_SPEC.ShortFlag('-c', args.String,
229 quit_parsing_flags=True) # command string
230MAIN_SPEC.LongFlag('--help')
231MAIN_SPEC.LongFlag('--version')
232
233# --tool ysh-ify, etc.
234# default is ''
235#
236# More ideas for tools
237# undefined-vars - a static analysis pass
238# parse-glob - to debug parsing
239# parse-printf
240MAIN_SPEC.LongFlag('--tool', [
241 'tokens', 'lossless-cat', 'syntax-tree', 'fmt', 'test', 'ysh-ify', 'deps',
242 'cat-em'
243])
244
245MAIN_SPEC.ShortFlag('-i') # interactive
246MAIN_SPEC.ShortFlag('-l') # login - currently no-op
247MAIN_SPEC.LongFlag('--login') # login - currently no-op
248MAIN_SPEC.LongFlag('--headless') # accepts ECMD, etc.
249
250# TODO: -h too
251# the output format when passing -n
252MAIN_SPEC.LongFlag(
253 '--ast-format',
254 ['text', 'abbrev-text', 'html', 'abbrev-html', 'oheap', 'none'],
255 default='abbrev-text')
256
257# Defines completion style.
258MAIN_SPEC.LongFlag('--completion-display', ['minimal', 'nice'], default='nice')
259# TODO: Add option for YSH prompt style? RHS prompt?
260
261MAIN_SPEC.LongFlag('--completion-demo')
262
263# Debugging feature only. $SH -n won't reparse a[x+1] and ``. Note that $SH
264# --tool automatically turns it on.
265MAIN_SPEC.LongFlag('--do-lossless')
266
267MAIN_SPEC.LongFlag('--print-status') # TODO: Replace with a shell hook
268MAIN_SPEC.LongFlag('--debug-file', args.String)
269MAIN_SPEC.LongFlag('--xtrace-to-debug-file')
270
271# This flag has is named like bash's equivalent. We got rid of --norc because
272# it can simply by --rcfile /dev/null.
273MAIN_SPEC.LongFlag('--rcfile', args.String)
274MAIN_SPEC.LongFlag('--rcdir', args.String)
275MAIN_SPEC.LongFlag('--norc')
276
277# e.g. to pass data on stdin but pretend that it came from a .hay file
278MAIN_SPEC.LongFlag('--location-str', args.String)
279MAIN_SPEC.LongFlag('--location-start-line', args.Int)
280
281_AddShellOptions(MAIN_SPEC)
282
283SET_SPEC = FlagSpecAndMore('set')
284_AddShellOptions(SET_SPEC)
285
286#
287# Types for completion
288#
289
290
291def _DefineCompletionFlags(spec):
292 # type: (_FlagSpecAndMore) -> None
293 spec.ShortFlag('-F', args.String, help='Complete with this function')
294 spec.ShortFlag('-W', args.String, help='Complete with these words')
295 spec.ShortFlag('-C',
296 args.String,
297 help='Complete with stdout lines of this command')
298
299 spec.ShortFlag(
300 '-P',
301 args.String,
302 help=
303 'Prefix is added at the beginning of each possible completion after '
304 'all other options have been applied.')
305 spec.ShortFlag('-S',
306 args.String,
307 help='Suffix is appended to each possible completion after '
308 'all other options have been applied.')
309 spec.ShortFlag('-X',
310 args.String,
311 help='''
312A glob pattern to further filter the matches. It is applied to the list of
313possible completions generated by the preceding options and arguments, and each
314completion matching filterpat is removed from the list. A leading ! in
315filterpat negates the pattern; in this case, any completion not matching
316filterpat is removed.
317''')
318
319
320def _DefineCompletionOptions(spec):
321 # type: (_FlagSpecAndMore) -> None
322 """Common -o options for complete and compgen."""
323 spec.InitOptions()
324
325 # bashdefault, default, filenames, nospace are used in git
326 spec.Option2('bashdefault',
327 help='If nothing matches, perform default bash completions')
328 spec.Option2(
329 'default',
330 help="If nothing matches, use readline's default filename completion")
331 spec.Option2(
332 'filenames',
333 help="The completion function generates filenames and should be "
334 "post-processed")
335 spec.Option2('dirnames',
336 help="If nothing matches, perform directory name completion")
337 spec.Option2(
338 'nospace',
339 help="Don't append a space to words completed at the end of the line")
340 spec.Option2(
341 'plusdirs',
342 help="After processing the compspec, attempt directory name completion "
343 "and return those matches.")
344
345
346def _DefineCompletionActions(spec):
347 # type: (_FlagSpecAndMore) -> None
348 """Common -A actions for complete and compgen."""
349
350 # NOTE: git-completion.bash uses -f and -v.
351 # My ~/.bashrc on Ubuntu uses -d, -u, -j, -v, -a, -c, -b
352 spec.InitActions()
353 spec.Action('a', 'alias')
354 spec.Action('b', 'binding')
355 spec.Action('c', 'command')
356 spec.Action('d', 'directory')
357 spec.Action('e', 'export')
358 spec.Action('f', 'file')
359 spec.Action('k', 'keyword')
360 spec.Action('j', 'job')
361 spec.Action('u', 'user')
362 spec.Action('v', 'variable')
363 spec.Action(None, 'builtin')
364 spec.Action(None, 'function')
365 spec.Action(None, 'helptopic') # help
366 spec.Action(None, 'setopt') # set -o
367 spec.Action(None, 'shopt') # shopt -s
368 spec.Action(None, 'signal') # kill -s
369 spec.Action(None, 'stopped')
370
371
372COMPLETE_SPEC = FlagSpecAndMore('complete')
373
374_DefineCompletionFlags(COMPLETE_SPEC)
375_DefineCompletionOptions(COMPLETE_SPEC)
376_DefineCompletionActions(COMPLETE_SPEC)
377
378COMPLETE_SPEC.ShortFlag('-E', help='Define the compspec for an empty line')
379COMPLETE_SPEC.ShortFlag(
380 '-D', help='Define the compspec that applies when nothing else matches')
381
382# I would like this to be less compatible
383# Field name conflicts with 'print' keyword
384#COMPLETE_SPEC.LongFlag(
385# '--print', help='Print spec')
386
387COMPGEN_SPEC = FlagSpecAndMore('compgen') # for -o and -A
388
389# TODO: Add -l for COMP_LINE. -p for COMP_POINT ?
390_DefineCompletionFlags(COMPGEN_SPEC)
391_DefineCompletionOptions(COMPGEN_SPEC)
392_DefineCompletionActions(COMPGEN_SPEC)
393
394COMPOPT_SPEC = FlagSpecAndMore('compopt') # for -o
395_DefineCompletionOptions(COMPOPT_SPEC)
396
397COMPADJUST_SPEC = FlagSpecAndMore('compadjust')
398
399COMPADJUST_SPEC.ShortFlag(
400 '-n',
401 args.String,
402 help=
403 'Do NOT split by these characters. It omits them from COMP_WORDBREAKS.')
404COMPADJUST_SPEC.ShortFlag('-s',
405 help='Treat --foo=bar and --foo bar the same way.')
406
407COMPEXPORT_SPEC = FlagSpecAndMore('compexport')
408
409COMPEXPORT_SPEC.ShortFlag('-c',
410 args.String,
411 help='Shell string to complete, like sh -c')
412
413COMPEXPORT_SPEC.LongFlag('--begin',
414 args.Int,
415 help='Simulate readline begin index into line buffer')
416
417COMPEXPORT_SPEC.LongFlag('--end',
418 args.Int,
419 help='Simulate readline end index into line buffer')
420
421# jlines is an array of strings with NO header line
422# TSV8 has a header line. It can have flag descriptions and other data.
423COMPEXPORT_SPEC.LongFlag('--format', ['jlines', 'tsv8'],
424 default='jlines',
425 help='Output format')
426
427#
428# Pure YSH
429#
430
431TRY_SPEC = FlagSpec('try_')
432TRY_SPEC.LongFlag('--assign',
433 args.String,
434 help='Assign status to this variable, and return 0')
435
436ERROR_SPEC = FlagSpec('error')
437FAILED_SPEC = FlagSpec('failed')
438
439BOOLSTATUS_SPEC = FlagSpec('boolstatus')
440ASSERT_SPEC = FlagSpec('assert')
441
442# Future directions:
443# run --builtin, run --command, run --proc:
444# to "replace" 'builtin' and # 'command'
445
446APPEND_SPEC = FlagSpec('append')
447
448SHVAR_SPEC = FlagSpec('shvar')
449#SHVAR_SPEC.Flag('-temp', args.String,
450# help='Push a NAME=val binding')
451#SHVAR_SPEC.Flag('-env', args.String,
452# help='Push a NAME=val binding and set the -x flag')
453
454CTX_SPEC = FlagSpec('ctx')
455
456PP_SPEC = FlagSpec('pp')
457
458SHVM_SPEC = FlagSpec('shvm')
459
460# --verbose?
461FORK_SPEC = FlagSpec('fork')
462FORKWAIT_SPEC = FlagSpec('forkwait')
463
464# Might want --list at some point
465MODULE_SPEC = FlagSpec('source-guard')
466
467RUNPROC_SPEC = FlagSpec('runproc')
468RUNPROC_SPEC.ShortFlag('-h', args.Bool, help='Show all procs')
469
470WRITE_SPEC = FlagSpec('write')
471WRITE_SPEC.LongFlag('--sep',
472 args.String,
473 default='\n',
474 help='Characters to separate each argument')
475WRITE_SPEC.LongFlag('--end',
476 args.String,
477 default='\n',
478 help='Characters to terminate the whole invocation')
479WRITE_SPEC.ShortFlag('-n',
480 args.Bool,
481 help="Omit newline (synonym for -end '')")
482# Do we need these two?
483WRITE_SPEC.LongFlag('--json',
484 args.Bool,
485 default=False,
486 help='Write elements as JSON strings(lossy)')
487WRITE_SPEC.LongFlag('--j8',
488 args.Bool,
489 default=False,
490 help='Write elements as J8 strings')
491# TODO: --jlines for conditional j"" prefix? Like maybe_shell_encode()
492
493# Legacy that's not really needed with J8 notation. The = operator might use a
494# separate pretty printer that shows \u{3bc}
495#
496# x means I want \x00
497# u means I want \u{1234}
498# raw is utf-8
499if 0:
500 WRITE_SPEC.LongFlag(
501 '--unicode', ['raw', 'u', 'x'],
502 default='raw',
503 help='Encode QSN with these options. '
504 'x assumes an opaque byte string, while raw and u try to '
505 'decode UTF-8.')
506
507PUSH_REGISTERS_SPEC = FlagSpec('push-registers')
508
509FOPEN_SPEC = FlagSpec('fopen')
510
511#
512# JSON
513#
514
515JSON_WRITE_SPEC = FlagSpec('json_write')
516
517# TODO: --compact is probably better
518# --pretty=F is like JSON.stringify(d, null, 0)
519JSON_WRITE_SPEC.LongFlag('--pretty',
520 args.Bool,
521 default=True,
522 help='Whitespace in output (default true)')
523
524# Unused:
525# JSON has the questionable decision of allowing (unpaired) surrogate like
526# \udc00.
527# When encoding, we try to catch the error on OUR side, rather than letting it
528# travel over the wire. But you can disable this.
529JSON_WRITE_SPEC.LongFlag(
530 '--surrogate-ok',
531 args.Bool,
532 default=False,
533 help='Invalid UTF-8 can be encoded as surrogate like \\udc00')
534
535JSON_WRITE_SPEC.LongFlag('--indent',
536 args.Int,
537 default=2,
538 help='Indent JSON by this amount')
539
540JSON_READ_SPEC = FlagSpec('json_read')