OILS / frontend / flag_def.py View on Github | oils.pub

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