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 | """
|
9 | util.py - Common infrastructure.
|
10 | """
|
11 | from __future__ import print_function
|
12 |
|
13 | from display import ansi
|
14 | from core import pyutil
|
15 | from mycpp import mylib
|
16 |
|
17 | import libc
|
18 |
|
19 | from typing import List, Optional
|
20 |
|
21 |
|
22 | def 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 |
|
39 | def 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 |
|
52 | class UserExit(Exception):
|
53 | """For explicit 'exit'."""
|
54 |
|
55 | def __init__(self, status):
|
56 | # type: (int) -> None
|
57 | self.status = status
|
58 |
|
59 |
|
60 | class 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 |
|
71 | class _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 |
|
90 | class NullDebugFile(_DebugFile):
|
91 |
|
92 | def __init__(self):
|
93 | # type: () -> None
|
94 | """Empty constructor for mycpp."""
|
95 | _DebugFile.__init__(self)
|
96 |
|
97 |
|
98 | class 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 |
|
126 | def 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 |
|
136 | def 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 |
|
149 | def _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 |
|
155 | def 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 |
|
164 | def VersionFlag(loader, f):
|
165 | # type: (pyutil._ResourceLoader, mylib.Writer) -> None
|
166 | _PrintVersionLine(loader, f)
|
167 | f.write('\n')
|
168 | pyutil.PrintVersionDetails(loader)
|