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

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