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

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