OILS
/
frontend
/
flag_def.py
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')
|