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
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
158BIND_SPEC = FlagSpec('bind')
159BIND_SPEC.ShortFlag('-m', args.String)
160BIND_SPEC.ShortFlag('-q', args.String)
161BIND_SPEC.ShortFlag('-u', args.String)
162BIND_SPEC.ShortFlag('-r', args.String)
163BIND_SPEC.ShortFlag('-f', args.String)
164BIND_SPEC.ShortFlag('-x', args.String)
165BIND_SPEC.ShortFlag('-l')
166BIND_SPEC.ShortFlag('-p')
167BIND_SPEC.ShortFlag('-s')
168BIND_SPEC.ShortFlag('-v')
169BIND_SPEC.ShortFlag('-P')
170BIND_SPEC.ShortFlag('-S')
171BIND_SPEC.ShortFlag('-V')
172BIND_SPEC.ShortFlag('-X')
173
174
175HISTORY_SPEC = FlagSpec('history')
176HISTORY_SPEC.ShortFlag('-a')
177HISTORY_SPEC.ShortFlag('-r')
178HISTORY_SPEC.ShortFlag('-c')
179HISTORY_SPEC.ShortFlag('-d', args.Int)
180
181#
182# osh/builtin_process.py
183#
184
185EXEC_SPEC = FlagSpec('exec')
186
187WAIT_SPEC = FlagSpec('wait')
188WAIT_SPEC.ShortFlag('-n')
189
190TRAP_SPEC = FlagSpec('trap')
191TRAP_SPEC.ShortFlag('-p')
192TRAP_SPEC.ShortFlag('-l')
193
194JOB_SPEC = FlagSpec('jobs')
195JOB_SPEC.ShortFlag('-l', help='long format')
196JOB_SPEC.ShortFlag('-p', help='prints PID only')
197JOB_SPEC.LongFlag('--debug', help='display debug info')
198
199ULIMIT_SPEC = FlagSpec('ulimit')
200
201ULIMIT_SPEC.ShortFlag('-a', help='Print all limits')
202ULIMIT_SPEC.LongFlag('--all', help='Alias for -a')
203ULIMIT_SPEC.ShortFlag('-H', help='Use hard limit')
204ULIMIT_SPEC.ShortFlag('-S', help='Use soft limit')
205
206_ULIMIT_RESOURCES = [
207 '-c',
208 '-d',
209 '-f',
210 '-n',
211 '-s',
212 '-t',
213 '-v',
214]
215
216for u_flag in _ULIMIT_RESOURCES:
217 ULIMIT_SPEC.ShortFlag(u_flag)
218
219#
220# FlagSpecAndMore
221#
222
223#
224# set and shopt
225#
226
227
228def _AddShellOptions(spec):
229 # type: (_FlagSpecAndMore) -> None
230 """Shared between 'set' builtin and the shell's own arg parser."""
231 spec.InitOptions()
232 spec.InitShopt()
233
234 for opt in option_def.All():
235 if opt.builtin == 'set':
236 spec.Option(opt.short_flag, opt.name)
237 # Notes:
238 # - shopt option don't need to be registered; we validate elsewhere
239 # - 'interactive' Has a cell for internal use, but isn't allowed to be
240 # modified.
241
242
243MAIN_SPEC = FlagSpecAndMore('main')
244
245MAIN_SPEC.ShortFlag('-c', args.String,
246 quit_parsing_flags=True) # command string
247MAIN_SPEC.LongFlag('--help')
248MAIN_SPEC.LongFlag('--version')
249
250# --tool ysh-ify, etc.
251# default is ''
252#
253# More ideas for tools
254# undefined-vars - a static analysis pass
255# parse-glob - to debug parsing
256# parse-printf
257MAIN_SPEC.LongFlag('--tool', [
258 'tokens', 'lossless-cat', 'syntax-tree', 'fmt', 'test', 'ysh-ify', 'deps',
259 'cat-em'
260])
261
262MAIN_SPEC.ShortFlag('-i') # interactive
263MAIN_SPEC.ShortFlag('-l') # login - currently no-op
264MAIN_SPEC.LongFlag('--login') # login - currently no-op
265MAIN_SPEC.LongFlag('--headless') # accepts ECMD, etc.
266
267# TODO: -h too
268# the output format when passing -n
269MAIN_SPEC.LongFlag(
270 '--ast-format',
271 ['text', 'abbrev-text', 'html', 'abbrev-html', 'oheap', 'none'],
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# Do we need these two?
507WRITE_SPEC.LongFlag('--json',
508 args.Bool,
509 default=False,
510 help='Write elements as JSON strings(lossy)')
511WRITE_SPEC.LongFlag('--j8',
512 args.Bool,
513 default=False,
514 help='Write elements as J8 strings')
515# TODO: --jlines for conditional j"" prefix? Like maybe_shell_encode()
516
517# Legacy that's not really needed with J8 notation. The = operator might use a
518# separate pretty printer that shows \u{3bc}
519#
520# x means I want \x00
521# u means I want \u{1234}
522# raw is utf-8
523if 0:
524 WRITE_SPEC.LongFlag(
525 '--unicode', ['raw', 'u', 'x'],
526 default='raw',
527 help='Encode QSN with these options. '
528 'x assumes an opaque byte string, while raw and u try to '
529 'decode UTF-8.')
530
531PUSH_REGISTERS_SPEC = FlagSpec('push-registers')
532
533FOPEN_SPEC = FlagSpec('redir')
534
535#
536# JSON
537#
538
539JSON_WRITE_SPEC = FlagSpec('json_write')
540
541# TODO: --compact is probably better
542# --pretty=F is like JSON.stringify(d, null, 0)
543JSON_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.
553JSON_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')