OILS / frontend / flag_def.py View on Github | oilshell.org

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