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

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