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

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