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

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