1 #!/usr/bin/env python2
2 """Flag_def.py."""
3 from __future__ import print_function
4
5 from frontend import args
6 from frontend.flag_spec import (FlagSpec, FlagSpecAndMore, _FlagSpecAndMore)
7 from frontend import option_def
8
9 #
10 # Definitions for builtin_assign
11 #
12
13 EXPORT_SPEC = FlagSpec('export_')
14 EXPORT_SPEC.ShortFlag('-n')
15 EXPORT_SPEC.ShortFlag('-f') # stubbed
16 EXPORT_SPEC.ShortFlag('-p')
17
18 READONLY_SPEC = FlagSpec('readonly')
19
20 # TODO: Check the consistency of -a and -A against values, here and below.
21 READONLY_SPEC.ShortFlag('-a')
22 READONLY_SPEC.ShortFlag('-A')
23 READONLY_SPEC.ShortFlag('-p')
24
25 NEW_VAR_SPEC = FlagSpec('new_var')
26
27 # print stuff
28 NEW_VAR_SPEC.ShortFlag('-f')
29 NEW_VAR_SPEC.ShortFlag('-F')
30 NEW_VAR_SPEC.ShortFlag('-p')
31
32 NEW_VAR_SPEC.ShortFlag('-g') # Look up in global scope
33
34 # Options +r +x +n
35 NEW_VAR_SPEC.PlusFlag('x') # export
36 NEW_VAR_SPEC.PlusFlag('r') # readonly
37 NEW_VAR_SPEC.PlusFlag('n') # named ref
38
39 # Common between readonly/declare
40 NEW_VAR_SPEC.ShortFlag('-a')
41 NEW_VAR_SPEC.ShortFlag('-A')
42 NEW_VAR_SPEC.ShortFlag('-i') # no-op for integers
43
44 UNSET_SPEC = FlagSpec('unset')
45 UNSET_SPEC.ShortFlag('-v')
46 UNSET_SPEC.ShortFlag('-f')
47 #UNSET_SPEC.ShortFlag('-z', args.String)
48
49 #
50 # Definitions for builtin_meta
51 #
52
53 # Unused because there are no flags! Just --.
54 EVAL_SPEC = FlagSpec('eval')
55 SOURCE_SPEC = FlagSpec('source')
56 SOURCE_SPEC.LongFlag('--builtin')
57
58 COMMAND_SPEC = FlagSpec('command')
59 COMMAND_SPEC.ShortFlag('-v')
60 # COMMAND_SPEC.ShortFlag('-V') # Another verbose mode.
61
62 TYPE_SPEC = FlagSpec('type')
63 TYPE_SPEC.ShortFlag('-f')
64 TYPE_SPEC.ShortFlag('-t')
65 TYPE_SPEC.ShortFlag('-p')
66 TYPE_SPEC.ShortFlag('-P')
67
68 #
69 # Definitions for builtin_pure
70 #
71
72 ALIAS_SPEC = FlagSpec('alias') # no flags yet
73 UNALIAS_SPEC = FlagSpec('unalias') # no flags yet
74
75 SHOPT_SPEC = FlagSpec('shopt')
76 SHOPT_SPEC.ShortFlag('-s', long_name='--set')
77 SHOPT_SPEC.ShortFlag('-u', long_name='--unset')
78 SHOPT_SPEC.ShortFlag('-o') # use 'set -o' names
79 # TODO: --print could print in a verbose format. (Annoying: codegen conflicts
80 # with Python keyword.)
81 SHOPT_SPEC.ShortFlag('-p')
82 SHOPT_SPEC.ShortFlag('-q') # query option settings
83
84 HASH_SPEC = FlagSpec('hash')
85 HASH_SPEC.ShortFlag('-r')
86
87 ECHO_SPEC = FlagSpec('echo')
88 ECHO_SPEC.ShortFlag('-e') # no backslash escapes
89 ECHO_SPEC.ShortFlag('-n')
90
91 #
92 # osh/builtin_printf.py
93 #
94
95 PRINTF_SPEC = FlagSpec('printf')
96 PRINTF_SPEC.ShortFlag('-v', args.String)
97
98 #
99 # osh/builtin_misc.py
100 #
101
102 READ_SPEC = FlagSpec('read')
103 READ_SPEC.ShortFlag('-r')
104 READ_SPEC.ShortFlag('-s') # silent
105 READ_SPEC.ShortFlag('-u', args.Int) # file descriptor
106 READ_SPEC.ShortFlag('-t', args.Float) # timeout
107 READ_SPEC.ShortFlag('-n', args.Int)
108 READ_SPEC.ShortFlag('-a', args.String) # name of array to read into
109 READ_SPEC.ShortFlag('-d', args.String)
110 READ_SPEC.ShortFlag('-p', args.String) # prompt
111
112 # YSH extensions
113 READ_SPEC.ShortFlag('-0') # until NUL, like -r -d ''
114 READ_SPEC.LongFlag('--all')
115 READ_SPEC.LongFlag('--line')
116 # don't strip the trailing newline
117 READ_SPEC.LongFlag('--with-eol')
118 # Decode QSN after reading a line. Note: A QSN string can't have literal
119 # newlines or tabs; they must be escaped.
120 READ_SPEC.ShortFlag('-q', long_name='--qsn')
121
122 MAPFILE_SPEC = FlagSpec('mapfile')
123 MAPFILE_SPEC.ShortFlag('-t')
124
125 CD_SPEC = FlagSpec('cd')
126 CD_SPEC.ShortFlag('-L')
127 CD_SPEC.ShortFlag('-P')
128
129 PUSHD_SPEC = FlagSpec('pushd')
130
131 POPD_SPEC = FlagSpec('popd')
132
133 DIRS_SPEC = FlagSpec('dirs')
134 DIRS_SPEC.ShortFlag('-c')
135 DIRS_SPEC.ShortFlag('-l')
136 DIRS_SPEC.ShortFlag('-p')
137 DIRS_SPEC.ShortFlag('-v')
138
139 PWD_SPEC = FlagSpec('pwd')
140 PWD_SPEC.ShortFlag('-L')
141 PWD_SPEC.ShortFlag('-P')
142
143 HELP_SPEC = FlagSpec('help')
144 #HELP_SPEC.ShortFlag('-i') # show index
145 # Note: bash has help -d -m -s, which change the formatting
146
147 HISTORY_SPEC = FlagSpec('history')
148 HISTORY_SPEC.ShortFlag('-a')
149 HISTORY_SPEC.ShortFlag('-r')
150 HISTORY_SPEC.ShortFlag('-c')
151 HISTORY_SPEC.ShortFlag('-d', args.Int)
152
153 #
154 # osh/builtin_process.py
155 #
156
157 EXEC_SPEC = FlagSpec('exec')
158
159 WAIT_SPEC = FlagSpec('wait')
160 WAIT_SPEC.ShortFlag('-n')
161
162 TRAP_SPEC = FlagSpec('trap')
163 TRAP_SPEC.ShortFlag('-p')
164 TRAP_SPEC.ShortFlag('-l')
165
166 JOB_SPEC = FlagSpec('jobs')
167 JOB_SPEC.ShortFlag('-l', help='long format')
168 JOB_SPEC.ShortFlag('-p', help='prints PID only')
169 JOB_SPEC.LongFlag('--debug', help='display debug info')
170
171 #
172 # FlagSpecAndMore
173 #
174
175 #
176 # set and shopt
177 #
178
179
180 def _AddShellOptions(spec):
181 # type: (_FlagSpecAndMore) -> None
182 """Shared between 'set' builtin and the shell's own arg parser."""
183 spec.InitOptions()
184 spec.InitShopt()
185
186 for opt in option_def.All():
187 if opt.builtin == 'set':
188 spec.Option(opt.short_flag, opt.name)
189 # Notes:
190 # - shopt option don't need to be registered; we validate elsewhere
191 # - 'interactive' Has a cell for internal use, but isn't allowed to be
192 # modified.
193
194
195 MAIN_SPEC = FlagSpecAndMore('main')
196
197 MAIN_SPEC.ShortFlag('-c', args.String,
198 quit_parsing_flags=True) # command string
199 MAIN_SPEC.LongFlag('--help')
200 MAIN_SPEC.LongFlag('--version')
201
202 # --tool ysh-ify, etc.
203 # default is ''
204 #
205 # More ideas for tools
206 # undefined-vars - a static analysis pass
207 # parse-glob - to debug parsing
208 # parse-printf
209 MAIN_SPEC.LongFlag('--tool', ['tokens', 'arena', 'syntax-tree', 'ysh-ify',
210 'deps', 'cat-em'])
211
212 MAIN_SPEC.ShortFlag('-i') # interactive
213 MAIN_SPEC.ShortFlag('-l') # login - currently no-op
214 MAIN_SPEC.LongFlag('--login') # login - currently no-op
215 MAIN_SPEC.LongFlag('--headless') # accepts ECMD, etc.
216
217 # TODO: -h too
218 # the output format when passing -n
219 MAIN_SPEC.LongFlag(
220 '--ast-format',
221 ['text', 'abbrev-text', 'html', 'abbrev-html', 'oheap', 'none'],
222 default='abbrev-text')
223
224 # Defines completion style.
225 MAIN_SPEC.LongFlag('--completion-display', ['minimal', 'nice'], default='nice')
226 # TODO: Add option for YSH prompt style? RHS prompt?
227
228 MAIN_SPEC.LongFlag('--completion-demo')
229
230 # $SH -n won't reparse a[x+1] and ``. Note that $SH --tool automatically turns
231 # it on.
232 # TODO: Do we only need this for the "arena invariant"? e.g. test/arena.sh I
233 # think we can REMOVE it if we get rid of the arena.
234 MAIN_SPEC.LongFlag('--one-pass-parse')
235
236 MAIN_SPEC.LongFlag('--print-status') # TODO: Replace with a shell hook
237 MAIN_SPEC.LongFlag('--debug-file', args.String)
238 MAIN_SPEC.LongFlag('--xtrace-to-debug-file')
239
240 # This flag has is named like bash's equivalent. We got rid of --norc because
241 # it can simply by --rcfile /dev/null.
242 MAIN_SPEC.LongFlag('--rcfile', args.String)
243 MAIN_SPEC.LongFlag('--rcdir', args.String)
244 MAIN_SPEC.LongFlag('--norc')
245
246 # e.g. to pass data on stdin but pretend that it came from a .hay file
247 MAIN_SPEC.LongFlag('--location-str', args.String)
248 MAIN_SPEC.LongFlag('--location-start-line', args.Int)
249
250 _AddShellOptions(MAIN_SPEC)
251
252 SET_SPEC = FlagSpecAndMore('set')
253 _AddShellOptions(SET_SPEC)
254
255 #
256 # Types for completion
257 #
258
259
260 def _DefineCompletionFlags(spec):
261 # type: (_FlagSpecAndMore) -> None
262 spec.ShortFlag('-F', args.String, help='Complete with this function')
263 spec.ShortFlag('-W', args.String, help='Complete with these words')
264 spec.ShortFlag('-C', args.String,
265 help='Complete with stdout lines of this command')
266
267 spec.ShortFlag(
268 '-P',
269 args.String,
270 help=
271 'Prefix is added at the beginning of each possible completion after '
272 'all other options have been applied.')
273 spec.ShortFlag('-S',
274 args.String,
275 help='Suffix is appended to each possible completion after '
276 'all other options have been applied.')
277 spec.ShortFlag('-X',
278 args.String,
279 help='''
280 A glob pattern to further filter the matches. It is applied to the list of
281 possible completions generated by the preceding options and arguments, and each
282 completion matching filterpat is removed from the list. A leading ! in
283 filterpat negates the pattern; in this case, any completion not matching
284 filterpat is removed.
285 ''')
286
287
288 def _DefineCompletionOptions(spec):
289 # type: (_FlagSpecAndMore) -> None
290 """Common -o options for complete and compgen."""
291 spec.InitOptions()
292
293 # bashdefault, default, filenames, nospace are used in git
294 spec.Option2('bashdefault',
295 help='If nothing matches, perform default bash completions')
296 spec.Option2(
297 'default',
298 help="If nothing matches, use readline's default filename completion")
299 spec.Option2(
300 'filenames',
301 help="The completion function generates filenames and should be "
302 "post-processed")
303 spec.Option2('dirnames',
304 help="If nothing matches, perform directory name completion")
305 spec.Option2(
306 'nospace',
307 help="Don't append a space to words completed at the end of the line")
308 spec.Option2(
309 'plusdirs',
310 help="After processing the compspec, attempt directory name completion "
311 "and return those matches.")
312
313
314 def _DefineCompletionActions(spec):
315 # type: (_FlagSpecAndMore) -> None
316 """Common -A actions for complete and compgen."""
317
318 # NOTE: git-completion.bash uses -f and -v.
319 # My ~/.bashrc on Ubuntu uses -d, -u, -j, -v, -a, -c, -b
320 spec.InitActions()
321 spec.Action('a', 'alias')
322 spec.Action('b', 'binding')
323 spec.Action('c', 'command')
324 spec.Action('d', 'directory')
325 spec.Action('f', 'file')
326 spec.Action('j', 'job')
327 spec.Action('u', 'user')
328 spec.Action('v', 'variable')
329 spec.Action(None, 'builtin')
330 spec.Action(None, 'function')
331 spec.Action(None, 'helptopic') # help
332 spec.Action(None, 'setopt') # set -o
333 spec.Action(None, 'shopt') # shopt -s
334 spec.Action(None, 'signal') # kill -s
335 spec.Action(None, 'stopped')
336
337
338 COMPLETE_SPEC = FlagSpecAndMore('complete')
339
340 _DefineCompletionFlags(COMPLETE_SPEC)
341 _DefineCompletionOptions(COMPLETE_SPEC)
342 _DefineCompletionActions(COMPLETE_SPEC)
343
344 COMPLETE_SPEC.ShortFlag('-E', help='Define the compspec for an empty line')
345 COMPLETE_SPEC.ShortFlag(
346 '-D', help='Define the compspec that applies when nothing else matches')
347
348 # I would like this to be less compatible
349 # Field name conflicts with 'print' keyword
350 #COMPLETE_SPEC.LongFlag(
351 # '--print', help='Print spec')
352
353 COMPGEN_SPEC = FlagSpecAndMore('compgen') # for -o and -A
354
355 # TODO: Add -l for COMP_LINE. -p for COMP_POINT ?
356 _DefineCompletionFlags(COMPGEN_SPEC)
357 _DefineCompletionOptions(COMPGEN_SPEC)
358 _DefineCompletionActions(COMPGEN_SPEC)
359
360 COMPOPT_SPEC = FlagSpecAndMore('compopt') # for -o
361 _DefineCompletionOptions(COMPOPT_SPEC)
362
363 COMPADJUST_SPEC = FlagSpecAndMore('compadjust')
364
365 COMPADJUST_SPEC.ShortFlag(
366 '-n',
367 args.String,
368 help=
369 'Do NOT split by these characters. It omits them from COMP_WORDBREAKS.')
370 COMPADJUST_SPEC.ShortFlag('-s',
371 help='Treat --foo=bar and --foo bar the same way.')
372
373 COMPEXPORT_SPEC = FlagSpecAndMore('compexport')
374
375 COMPEXPORT_SPEC.ShortFlag(
376 '-c', args.String,
377 help='Shell string to complete, like sh -c')
378
379 COMPEXPORT_SPEC.LongFlag(
380 '--begin', args.Int,
381 help='Simulate readline begin index into line buffer')
382
383 COMPEXPORT_SPEC.LongFlag(
384 '--end', args.Int,
385 help='Simulate readline end index into line buffer')
386
387 # jlines is an array of strings with NO header line
388 # TSV8 has a header line. It can have flag descriptions and other data.
389 COMPEXPORT_SPEC.LongFlag('--format', ['jlines', 'tsv8'],
390 default='jlines',
391 help='Output format')
392
393 #
394 # Pure YSH
395 #
396
397 TRY_SPEC = FlagSpec('try_')
398 TRY_SPEC.LongFlag('--assign',
399 args.String,
400 help='Assign status to this variable, and return 0')
401
402 BOOLSTATUS_SPEC = FlagSpec('boolstatus')
403
404 # Future directions:
405 # run --builtin, run --command, run --proc:
406 # to "replace" 'builtin' and # 'command'
407
408 APPEND_SPEC = FlagSpec('append')
409
410 SHVAR_SPEC = FlagSpec('shvar')
411 #SHVAR_SPEC.Flag('-temp', args.String,
412 # help='Push a NAME=val binding')
413 #SHVAR_SPEC.Flag('-env', args.String,
414 # help='Push a NAME=val binding and set the -x flag')
415
416 PP_SPEC = FlagSpec('pp')
417
418 # --verbose?
419 FORK_SPEC = FlagSpec('fork')
420 FORKWAIT_SPEC = FlagSpec('forkwait')
421
422 # Might want --list at some point
423 MODULE_SPEC = FlagSpec('module')
424
425 RUNPROC_SPEC = FlagSpec('runproc')
426 RUNPROC_SPEC.ShortFlag('-h', args.Bool, help='Show all procs')
427
428 WRITE_SPEC = FlagSpec('write')
429 WRITE_SPEC.LongFlag('--sep',
430 args.String,
431 default='\n',
432 help='Characters to separate each argument')
433 WRITE_SPEC.LongFlag('--end',
434 args.String,
435 default='\n',
436 help='Characters to terminate the whole invocation')
437 WRITE_SPEC.ShortFlag('-n',
438 args.Bool,
439 help="Omit newline (synonym for -end '')")
440 WRITE_SPEC.LongFlag('--j8',
441 args.Bool,
442 default=False,
443 help='Write elements with J8 notation, one per line')
444 # TODO: --jlines for conditional j"" prefix? Like maybe_shell_encode()
445
446 # TODO: remove this
447 WRITE_SPEC.LongFlag('--qsn',
448 args.Bool,
449 default=False,
450 help='Write elements in QSN format')
451
452 # x means I want \x00
453 # u means I want \u{1234}
454 # raw is utf-8
455 # might also want: maybe?
456 WRITE_SPEC.LongFlag('--unicode', ['raw', 'u', 'x'],
457 default='raw',
458 help='Encode QSN with these options. '
459 'x assumes an opaque byte string, while raw and u try to '
460 'decode UTF-8.')
461
462 PUSH_REGISTERS_SPEC = FlagSpec('push-registers')
463
464 FOPEN_SPEC = FlagSpec('fopen')
465
466 #
467 # Tea
468 #
469
470 TEA_MAIN_SPEC = FlagSpec('tea_main')
471 TEA_MAIN_SPEC.ShortFlag('-n', args.Bool) # Parse
472 TEA_MAIN_SPEC.ShortFlag('-c', args.String) # Command snippet
473 TEA_MAIN_SPEC.LongFlag('--translate', args.Bool)
474
475 #
476 # JSON
477 #
478
479 JSON_WRITE_SPEC = FlagSpec('json_write')
480
481 # TODO: --compact is probably better
482 # --pretty=F is like JSON.stringify(d, null, 0)
483 JSON_WRITE_SPEC.LongFlag('--pretty',
484 args.Bool,
485 default=True,
486 help='Whitespace in output (default true)')
487
488 # JSON has the questionable decision of allowing (unpaired) surrogate like
489 # \udc00.
490 # When encoding, we try to catch the error on OUR side, rather than letting it
491 # travel over the wire. But you can disable this.
492 JSON_WRITE_SPEC.LongFlag(
493 '--surrogate-ok',
494 args.Bool,
495 default=False,
496 help='Invalid UTF-8 can be encoded as surrogate like \\udc00')
497
498 JSON_WRITE_SPEC.LongFlag('--indent',
499 args.Int,
500 default=2,
501 help='Indent JSON by this amount')
502
503 JSON_READ_SPEC = FlagSpec('json_read')
504 # yajl has this option
505 JSON_READ_SPEC.LongFlag('--validate',
506 args.Bool,
507 default=True,
508 help='Validate UTF-8')