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

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