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

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