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

163 lines, 65 significant
1#!/usr/bin/env python2
2"""frontend/builtin_def.py.
3
4Metadata:
5
6- Is used for lookup in cmd_eval.py
7- Should be used for completion
8 - complete names of builtins
9 - complete flags they take
10 - handle aliases : . and source, [ and test
11- Should be reflected in the contents of the 'help' builtin
12
13NOTE: bash has help -d -m -s. Default is -s, like a man page.
14
15Links on special builtins:
16http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_14
17"""
18from __future__ import print_function
19
20from typing import Dict, List, Optional, Any
21
22# Special builtins can't be redefined by functions. On the other hand, 'cd'
23# CAN be redefined.
24#
25# http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_14
26# https://www.gnu.org/software/bash/manual/html_node/Special-Builtins.html
27
28# yapf: disable
29_NORMAL_BUILTINS = [
30 'read', 'echo', 'printf', 'mapfile', 'readarray',
31
32 'cd', 'pushd', 'popd', 'dirs', 'pwd',
33
34 'source', # note that . alias is special
35
36 'umask', 'ulimit', 'wait', 'jobs', 'fg', 'bg',
37
38 'shopt',
39 'complete', 'compgen', 'compopt', 'compadjust', 'compexport',
40
41 'getopts',
42
43 # introspection / meta
44 'builtin', 'command', 'type', 'hash', 'help', 'history',
45
46 'alias', 'unalias',
47 'bind',
48
49 #
50 # YSH
51 #
52 'append',
53 'write', 'json', 'json8', 'pp',
54 'hay', 'haynode',
55 'use',
56 'error', 'failed',
57
58 # take a block
59 # push-registers added below
60 'fork', 'forkwait',
61 'fopen',
62 'ctx',
63
64 'runproc',
65 'boolstatus',
66]
67# yapf: enable
68
69
70class _Builtin(object):
71
72 def __init__(self, index, name, enum_name=None, kind='normal'):
73 # type: (int, str, Optional[str], str) -> None
74 """
75 kind: normal, special, assign
76 """
77 self.index = index
78 self.name = name # e.g. : or [
79 self.enum_name = enum_name or name # e.g. builtin_num::colon
80 self.kind = kind
81
82
83class _BuiltinDef(object):
84 """
85 NOTE: This isn't used anywhere! We're registering nothing.
86
87 We want to complete the flags to builtins. So this is a mapping from name
88 to arg spec. There might not be any flags.
89 """
90
91 def __init__(self):
92 # type: () -> None
93 self.builtins = [] # type: List[_Builtin]
94 self.index = 1 # start with 1
95
96 def Add(self, *posargs, **kwargs):
97 # type: (Any, Any) -> None
98 # NOTE: *posargs works around flake8/pyflakes bug!
99 self.builtins.append(_Builtin(self.index, *posargs, **kwargs))
100 self.index += 1
101
102
103def _Init(b):
104 # type: (_BuiltinDef) -> None
105
106 #
107 # Special builtins
108 #
109
110 b.Add(':', enum_name='colon', kind='special')
111 b.Add('.', enum_name='dot', kind='special')
112 # Python keyword
113 b.Add('exec', enum_name='exec_', kind='special')
114 for name in ['eval', 'set', 'shift', 'times', 'trap', 'unset']:
115 b.Add(name, kind='special')
116
117 #
118 # Assignment builtins.
119 # Note: control flow aren't builtins in OSH: break continue return
120 #
121
122 for name in ["readonly", "local", "declare", "typeset"]:
123 b.Add(name, kind='assign')
124 b.Add('export', enum_name='export_', kind='assign') # C++ keyword conflict
125
126 b.Add('true', enum_name='true_') # C++ Keywords
127 b.Add('false', enum_name='false_')
128 b.Add('try', enum_name='try_')
129 b.Add('assert', enum_name='assert_') # avoid Python keyword
130
131 for name in _NORMAL_BUILTINS:
132 b.Add(name)
133
134 # Slight variants
135 b.Add('test')
136 b.Add('[', enum_name='bracket')
137
138 b.Add('push-registers', enum_name='push_registers')
139 b.Add('source-guard', enum_name='source_guard')
140 b.Add('is-main', enum_name='is_main')
141
142 # Implementation detail of $(<file)
143 # TODO: change to 'internal cat' (issue 1013)
144 b.Add('__cat', enum_name='cat')
145
146
147_BUILTIN_DEF = _BuiltinDef()
148
149_Init(_BUILTIN_DEF)
150
151# Exposed in consts.py for completion
152BUILTIN_NAMES = [b.name for b in _BUILTIN_DEF.builtins]
153
154
155def All():
156 # type: () -> List[_Builtin]
157 return _BUILTIN_DEF.builtins
158
159
160def BuiltinDict():
161 # type: () -> Dict[str, _Builtin]
162 """For the slow path in frontend/match.py."""
163 return dict((b.name, b) for b in _BUILTIN_DEF.builtins)