OILS / core / util.py View on Github | oilshell.org

168 lines, 80 significant
1#t!/usr/bin/env python2
2# Copyright 2016 Andy Chu. All rights reserved.
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8"""
9util.py - Common infrastructure.
10"""
11from __future__ import print_function
12
13from display import ansi
14from core import pyutil
15from mycpp import mylib
16
17import libc
18
19from typing import List, Optional
20
21
22def RegexGroupStrings(s, indices):
23 # type: (str, List[int]) -> List[str]
24 """
25 For BASH_REMATCH: returns empty string for unmatched group
26 """
27 groups = [] # type: List[str]
28 n = len(indices)
29 for i in xrange(n / 2):
30 start = indices[2 * i]
31 end = indices[2 * i + 1]
32 if start == -1:
33 groups.append('')
34 else:
35 groups.append(s[start:end])
36 return groups
37
38
39def RegexSearch(pat, s):
40 # type: (str, str) -> Optional[List[str]]
41 """Search a string for pattern.
42
43 Return None for no match, or a list of groups that match. Used for some
44 runtime parsing.
45 """
46 indices = libc.regex_search(pat, 0, s, 0)
47 if indices is None:
48 return None
49 return RegexGroupStrings(s, indices)
50
51
52class UserExit(Exception):
53 """For explicit 'exit'."""
54
55 def __init__(self, status):
56 # type: (int) -> None
57 self.status = status
58
59
60class HistoryError(Exception):
61
62 def __init__(self, msg):
63 # type: (str) -> None
64 self.msg = msg
65
66 def UserErrorString(self):
67 # type: () -> str
68 return 'history: %s' % self.msg
69
70
71class _DebugFile(object):
72
73 def __init__(self):
74 # type: () -> None
75 pass
76
77 def write(self, s):
78 # type: (str) -> None
79 pass
80
81 def writeln(self, s):
82 # type: (str) -> None
83 pass
84
85 def isatty(self):
86 # type: () -> bool
87 return False
88
89
90class NullDebugFile(_DebugFile):
91
92 def __init__(self):
93 # type: () -> None
94 """Empty constructor for mycpp."""
95 _DebugFile.__init__(self)
96
97
98class DebugFile(_DebugFile):
99 """Trivial wrapper with writeln() method
100
101 Can we turn this into a plain mylib::File? Right now that type only exists
102 in C++, but it should probably exist in Python too.
103 """
104
105 def __init__(self, f):
106 # type: (mylib.Writer) -> None
107 _DebugFile.__init__(self)
108 self.f = f
109
110 def write(self, s):
111 # type: (str) -> None
112 """Used by dev::Tracer and ASDL node.PrettyPrint()."""
113 self.f.write(s)
114
115 def writeln(self, s):
116 # type: (str) -> None
117 self.write(s + '\n')
118 self.f.flush()
119
120 def isatty(self):
121 # type: () -> bool
122 """Used by node.PrettyPrint()."""
123 return self.f.isatty()
124
125
126def PrintTopicHeader(topic_id, f):
127 # type: (str, mylib.Writer) -> None
128 if f.isatty():
129 f.write('%s %s %s\n' % (ansi.REVERSE, topic_id, ansi.RESET))
130 else:
131 f.write('~~~ %s ~~~\n' % topic_id)
132
133 f.write('\n')
134
135
136def PrintEmbeddedHelp(loader, topic_id, f):
137 # type: (pyutil._ResourceLoader, str, mylib.Writer) -> bool
138 try:
139 contents = loader.Get('_devbuild/help/%s' % topic_id)
140 except (IOError, OSError):
141 return False
142
143 PrintTopicHeader(topic_id, f)
144 f.write(contents)
145 f.write('\n')
146 return True # found
147
148
149def _PrintVersionLine(loader, f):
150 # type: (pyutil._ResourceLoader, mylib.Writer) -> None
151 v = pyutil.GetVersion(loader)
152 f.write('Oils %s\t\thttps://www.oilshell.org/\n' % v)
153
154
155def HelpFlag(loader, topic_id, f):
156 # type: (pyutil._ResourceLoader, str, mylib.Writer) -> None
157 _PrintVersionLine(loader, f)
158 f.write('\n')
159 found = PrintEmbeddedHelp(loader, topic_id, f)
160 # Note: could assert this in C++ too
161 assert found, 'Missing %s' % topic_id
162
163
164def VersionFlag(loader, f):
165 # type: (pyutil._ResourceLoader, mylib.Writer) -> None
166 _PrintVersionLine(loader, f)
167 f.write('\n')
168 pyutil.PrintVersionDetails(loader)