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

565 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(
271 '--ast-format',
272 ['text', 'abbrev-text', 'html', 'abbrev-html', 'oheap', 'none'],
273 default='abbrev-text')
274
275# Defines completion style.
276MAIN_SPEC.LongFlag('--completion-display', ['minimal', 'nice'], default='nice')
277# TODO: Add option for YSH prompt style? RHS prompt?
278
279MAIN_SPEC.LongFlag('--completion-demo')
280
281# Debugging feature only. $SH -n won't reparse a[x+1] and ``. Note that $SH
282# --tool automatically turns it on.
283MAIN_SPEC.LongFlag('--do-lossless')
284
285MAIN_SPEC.LongFlag('--print-status') # TODO: Replace with a shell hook
286MAIN_SPEC.LongFlag('--debug-file', args.String)
287MAIN_SPEC.LongFlag('--xtrace-to-debug-file')
288
289# This flag has is named like bash's equivalent. We got rid of --norc because
290# it can simply by --rcfile /dev/null.
291MAIN_SPEC.LongFlag('--rcfile', args.String)
292MAIN_SPEC.LongFlag('--rcdir', args.String)
293MAIN_SPEC.LongFlag('--norc')
294
295# e.g. to pass data on stdin but pretend that it came from a .hay file
296MAIN_SPEC.LongFlag('--location-str', args.String)
297MAIN_SPEC.LongFlag('--location-start-line', args.Int)
298
299_AddShellOptions(MAIN_SPEC)
300
301SET_SPEC = FlagSpecAndMore('set')
302_AddShellOptions(SET_SPEC)
303
304#
305# Types for completion
306#
307
308
309def _DefineCompletionFlags(spec):
310 # type: (_FlagSpecAndMore) -> None
311 spec.ShortFlag('-F', args.String, help='Complete with this function')
312 spec.ShortFlag('-W', args.String, help='Complete with these words')
313 spec.ShortFlag('-C',
314 args.String,
315 help='Complete with stdout lines of this command')
316
317 spec.ShortFlag(
318 '-P',
319 args.String,
320 help=
321 'Prefix is added at the beginning of each possible completion after '
322 'all other options have been applied.')
323 spec.ShortFlag('-S',
324 args.String,
325 help='Suffix is appended to each possible completion after '
326 'all other options have been applied.')
327 spec.ShortFlag('-X',
328 args.String,
329 help='''
330A glob pattern to further filter the matches. It is applied to the list of
331possible completions generated by the preceding options and arguments, and each
332completion matching filterpat is removed from the list. A leading ! in
333filterpat negates the pattern; in this case, any completion not matching
334filterpat is removed.
335''')
336
337
338def _DefineCompletionOptions(spec):
339 # type: (_FlagSpecAndMore) -> None
340 """Common -o options for complete and compgen."""
341 spec.InitOptions()
342
343 # bashdefault, default, filenames, nospace are used in git
344 spec.Option2('bashdefault',
345 help='If nothing matches, perform default bash completions')
346 spec.Option2(
347 'default',
348 help="If nothing matches, use readline's default filename completion")
349 spec.Option2(
350 'filenames',
351 help="The completion function generates filenames and should be "
352 "post-processed")
353 spec.Option2('dirnames',
354 help="If nothing matches, perform directory name completion")
355 spec.Option2(
356 'nospace',
357 help="Don't append a space to words completed at the end of the line")
358 spec.Option2(
359 'plusdirs',
360 help="After processing the compspec, attempt directory name completion "
361 "and return those matches.")
362
363
364def _DefineCompletionActions(spec):
365 # type: (_FlagSpecAndMore) -> None
366 """Common -A actions for complete and compgen."""
367
368 # NOTE: git-completion.bash uses -f and -v.
369 # My ~/.bashrc on Ubuntu uses -d, -u, -j, -v, -a, -c, -b
370 spec.InitActions()
371 spec.Action('a', 'alias')
372 spec.Action('b', 'binding')
373 spec.Action('c', 'command')
374 spec.Action('d', 'directory')
375 spec.Action('e', 'export')
376 spec.Action('f', 'file')
377 spec.Action('k', 'keyword')
378 spec.Action('j', 'job')
379 spec.Action('u', 'user')
380 spec.Action('v', 'variable')
381 spec.Action(None, 'builtin')
382 spec.Action(None, 'function')
383 spec.Action(None, 'helptopic') # help
384 spec.Action(None, 'setopt') # set -o
385 spec.Action(None, 'shopt') # shopt -s
386 spec.Action(None, 'signal') # kill -s
387 spec.Action(None, 'stopped')
388
389
390COMPLETE_SPEC = FlagSpecAndMore('complete')
391
392_DefineCompletionFlags(COMPLETE_SPEC)
393_DefineCompletionOptions(COMPLETE_SPEC)
394_DefineCompletionActions(COMPLETE_SPEC)
395
396COMPLETE_SPEC.ShortFlag('-E', help='Define the compspec for an empty line')
397COMPLETE_SPEC.ShortFlag(
398 '-D', help='Define the compspec that applies when nothing else matches')
399
400# I would like this to be less compatible
401# Field name conflicts with 'print' keyword
402#COMPLETE_SPEC.LongFlag(
403# '--print', help='Print spec')
404
405COMPGEN_SPEC = FlagSpecAndMore('compgen') # for -o and -A
406
407# TODO: Add -l for COMP_LINE. -p for COMP_POINT ?
408_DefineCompletionFlags(COMPGEN_SPEC)
409_DefineCompletionOptions(COMPGEN_SPEC)
410_DefineCompletionActions(COMPGEN_SPEC)
411
412COMPOPT_SPEC = FlagSpecAndMore('compopt') # for -o
413_DefineCompletionOptions(COMPOPT_SPEC)
414
415COMPADJUST_SPEC = FlagSpecAndMore('compadjust')
416
417COMPADJUST_SPEC.ShortFlag(
418 '-n',
419 args.String,
420 help=
421 'Do NOT split by these characters. It omits them from COMP_WORDBREAKS.')
422COMPADJUST_SPEC.ShortFlag('-s',
423 help='Treat --foo=bar and --foo bar the same way.')
424
425COMPEXPORT_SPEC = FlagSpecAndMore('compexport')
426
427COMPEXPORT_SPEC.ShortFlag('-c',
428 args.String,
429 help='Shell string to complete, like sh -c')
430
431COMPEXPORT_SPEC.LongFlag('--begin',
432 args.Int,
433 help='Simulate readline begin index into line buffer')
434
435COMPEXPORT_SPEC.LongFlag('--end',
436 args.Int,
437 help='Simulate readline end index into line buffer')
438
439# jlines is an array of strings with NO header line
440# TSV8 has a header line. It can have flag descriptions and other data.
441COMPEXPORT_SPEC.LongFlag('--format', ['jlines', 'tsv8'],
442 default='jlines',
443 help='Output format')
444
445#
446# Pure YSH
447#
448
449TRY_SPEC = FlagSpec('try_')
450TRY_SPEC.LongFlag('--assign',
451 args.String,
452 help='Assign status to this variable, and return 0')
453
454ERROR_SPEC = FlagSpec('error')
455FAILED_SPEC = FlagSpec('failed')
456
457BOOLSTATUS_SPEC = FlagSpec('boolstatus')
458ASSERT_SPEC = FlagSpec('assert')
459
460# Future directions:
461# run --builtin, run --command, run --proc:
462# to "replace" 'builtin' and # 'command'
463
464APPEND_SPEC = FlagSpec('append')
465
466SHVAR_SPEC = FlagSpec('shvar')
467#SHVAR_SPEC.Flag('-temp', args.String,
468# help='Push a NAME=val binding')
469#SHVAR_SPEC.Flag('-env', args.String,
470# help='Push a NAME=val binding and set the -x flag')
471
472CTX_SPEC = FlagSpec('ctx')
473
474PP_SPEC = FlagSpec('pp')
475
476# --verbose?
477FORK_SPEC = FlagSpec('fork')
478FORKWAIT_SPEC = FlagSpec('forkwait')
479
480# Might want --list at some point
481SOURCE_GUARD_SPEC = FlagSpec('source-guard')
482USE_SPEC = FlagSpec('use')
483USE_SPEC.LongFlag('--extern')
484
485RUNPROC_SPEC = FlagSpec('runproc')
486RUNPROC_SPEC.ShortFlag('-h', args.Bool, help='Show all procs')
487
488INVOKE_SPEC = FlagSpec('invoke')
489INVOKE_SPEC.LongFlag('--builtin') # like 'builtin'
490INVOKE_SPEC.LongFlag('--proc-like') # like 'runproc'
491INVOKE_SPEC.LongFlag('--extern') # like 'extern'
492
493EXTERN_SPEC = FlagSpec('extern')
494
495WRITE_SPEC = FlagSpec('write')
496WRITE_SPEC.LongFlag('--sep',
497 args.String,
498 default='\n',
499 help='Characters to separate each argument')
500WRITE_SPEC.LongFlag('--end',
501 args.String,
502 default='\n',
503 help='Characters to terminate the whole invocation')
504WRITE_SPEC.ShortFlag('-n',
505 args.Bool,
506 help="Omit newline (synonym for -end '')")
507# Do we need these two?
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
542# TODO: --compact is probably better
543# --pretty=F is like JSON.stringify(d, null, 0)
544JSON_WRITE_SPEC.LongFlag('--pretty',
545 args.Bool,
546 default=True,
547 help='Whitespace in output (default true)')
548
549# Unused:
550# JSON has the questionable decision of allowing (unpaired) surrogate like
551# \udc00.
552# When encoding, we try to catch the error on OUR side, rather than letting it
553# travel over the wire. But you can disable this.
554JSON_WRITE_SPEC.LongFlag(
555 '--surrogate-ok',
556 args.Bool,
557 default=False,
558 help='Invalid UTF-8 can be encoded as surrogate like \\udc00')
559
560JSON_WRITE_SPEC.LongFlag('--indent',
561 args.Int,
562 default=2,
563 help='Indent JSON by this amount')
564
565JSON_READ_SPEC = FlagSpec('json_read')