OILS / core / util.py View on Github | oils.pub

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