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

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