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

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