PrEditor 2.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- preditor/__init__.py +315 -0
- preditor/__main__.py +13 -0
- preditor/about_module.py +165 -0
- preditor/cli.py +192 -0
- preditor/config.py +318 -0
- preditor/constants.py +13 -0
- preditor/contexts.py +210 -0
- preditor/cores/__init__.py +0 -0
- preditor/cores/core.py +20 -0
- preditor/dccs/.hab.json +10 -0
- preditor/dccs/maya/PrEditor_maya.mod +1 -0
- preditor/dccs/maya/README.md +22 -0
- preditor/dccs/maya/plug-ins/PrEditor_maya.py +141 -0
- preditor/dccs/studiomax/PackageContents.xml +32 -0
- preditor/dccs/studiomax/PrEditor-PrEditor_Show.mcr +8 -0
- preditor/dccs/studiomax/README.md +17 -0
- preditor/dccs/studiomax/preditor.ms +16 -0
- preditor/dccs/studiomax/preditor_menu.mnx +7 -0
- preditor/debug.py +149 -0
- preditor/delayable_engine/__init__.py +302 -0
- preditor/delayable_engine/delayables.py +85 -0
- preditor/enum.py +728 -0
- preditor/excepthooks.py +165 -0
- preditor/gui/__init__.py +56 -0
- preditor/gui/app.py +163 -0
- preditor/gui/codehighlighter.py +289 -0
- preditor/gui/completer.py +237 -0
- preditor/gui/console.py +605 -0
- preditor/gui/console_base.py +911 -0
- preditor/gui/dialog.py +181 -0
- preditor/gui/drag_tab_bar.py +625 -0
- preditor/gui/editor_chooser.py +57 -0
- preditor/gui/errordialog.py +69 -0
- preditor/gui/find_files.py +137 -0
- preditor/gui/fuzzy_search/__init__.py +0 -0
- preditor/gui/fuzzy_search/fuzzy_search.py +97 -0
- preditor/gui/group_tab_widget/__init__.py +0 -0
- preditor/gui/group_tab_widget/group_tab_widget.py +528 -0
- preditor/gui/group_tab_widget/grouped_tab_menu.py +35 -0
- preditor/gui/group_tab_widget/grouped_tab_models.py +107 -0
- preditor/gui/group_tab_widget/grouped_tab_widget.py +223 -0
- preditor/gui/group_tab_widget/one_tab_widget.py +96 -0
- preditor/gui/level_buttons.py +358 -0
- preditor/gui/logger_window_handler.py +77 -0
- preditor/gui/logger_window_plugin.py +35 -0
- preditor/gui/loggerwindow.py +2405 -0
- preditor/gui/newtabwidget.py +69 -0
- preditor/gui/output_console.py +11 -0
- preditor/gui/qtdesigner/__init__.py +21 -0
- preditor/gui/qtdesigner/_log_plugin.py +29 -0
- preditor/gui/qtdesigner/console_base_plugin.py +48 -0
- preditor/gui/qtdesigner/console_predit_plugin.py +48 -0
- preditor/gui/set_text_editor_path_dialog.py +61 -0
- preditor/gui/status_label.py +99 -0
- preditor/gui/suggest_path_quotes_dialog.py +50 -0
- preditor/gui/ui/editor_chooser.ui +93 -0
- preditor/gui/ui/errordialog.ui +74 -0
- preditor/gui/ui/find_files.ui +140 -0
- preditor/gui/ui/loggerwindow.ui +1909 -0
- preditor/gui/ui/set_text_editor_path_dialog.ui +189 -0
- preditor/gui/ui/suggest_path_quotes_dialog.ui +225 -0
- preditor/gui/window.py +161 -0
- preditor/gui/workbox_mixin.py +1139 -0
- preditor/gui/workbox_text_edit.py +136 -0
- preditor/gui/workboxwidget.py +315 -0
- preditor/logging_config.py +55 -0
- preditor/osystem.py +401 -0
- preditor/plugins.py +118 -0
- preditor/prefs.py +381 -0
- preditor/resource/environment_variables.html +26 -0
- preditor/resource/error_mail.html +85 -0
- preditor/resource/error_mail_inline.html +41 -0
- preditor/resource/img/README.md +17 -0
- preditor/resource/img/arrow_forward.png +0 -0
- preditor/resource/img/check-bold.png +0 -0
- preditor/resource/img/chevron-down.png +0 -0
- preditor/resource/img/chevron-up.png +0 -0
- preditor/resource/img/close-thick.png +0 -0
- preditor/resource/img/comment-edit.png +0 -0
- preditor/resource/img/content-copy.png +0 -0
- preditor/resource/img/content-cut.png +0 -0
- preditor/resource/img/content-duplicate.png +0 -0
- preditor/resource/img/content-paste.png +0 -0
- preditor/resource/img/content-save.png +0 -0
- preditor/resource/img/debug_disabled.png +0 -0
- preditor/resource/img/eye-check.png +0 -0
- preditor/resource/img/file-plus.png +0 -0
- preditor/resource/img/file-remove.png +0 -0
- preditor/resource/img/format-align-left.png +0 -0
- preditor/resource/img/format-letter-case-lower.png +0 -0
- preditor/resource/img/format-letter-case-upper.png +0 -0
- preditor/resource/img/format-letter-case.svg +1 -0
- preditor/resource/img/information.png +0 -0
- preditor/resource/img/logging_critical.png +0 -0
- preditor/resource/img/logging_custom.png +0 -0
- preditor/resource/img/logging_debug.png +0 -0
- preditor/resource/img/logging_error.png +0 -0
- preditor/resource/img/logging_info.png +0 -0
- preditor/resource/img/logging_not_set.png +0 -0
- preditor/resource/img/logging_warning.png +0 -0
- preditor/resource/img/marker.png +0 -0
- preditor/resource/img/play.png +0 -0
- preditor/resource/img/playlist-play.png +0 -0
- preditor/resource/img/plus-minus-variant.png +0 -0
- preditor/resource/img/preditor.ico +0 -0
- preditor/resource/img/preditor.png +0 -0
- preditor/resource/img/preditor.psd +0 -0
- preditor/resource/img/preditor.svg +44 -0
- preditor/resource/img/regex.svg +1 -0
- preditor/resource/img/restart.svg +1 -0
- preditor/resource/img/skip-forward-outline.png +0 -0
- preditor/resource/img/skip-next-outline.png +0 -0
- preditor/resource/img/skip-next.png +0 -0
- preditor/resource/img/skip-previous.png +0 -0
- preditor/resource/img/subdirectory-arrow-right.png +0 -0
- preditor/resource/img/text-search-variant.png +0 -0
- preditor/resource/img/warning-big.png +0 -0
- preditor/resource/lang/python.json +30 -0
- preditor/resource/pref_updates/pref_updates.json +17 -0
- preditor/resource/settings.ini +25 -0
- preditor/resource/stylesheet/Bright.css +76 -0
- preditor/resource/stylesheet/Dark.css +210 -0
- preditor/scintilla/__init__.py +40 -0
- preditor/scintilla/delayables/__init__.py +11 -0
- preditor/scintilla/delayables/smart_highlight.py +97 -0
- preditor/scintilla/delayables/spell_check.py +174 -0
- preditor/scintilla/documenteditor.py +1924 -0
- preditor/scintilla/finddialog.py +68 -0
- preditor/scintilla/lang/__init__.py +80 -0
- preditor/scintilla/lang/config/bash.ini +15 -0
- preditor/scintilla/lang/config/batch.ini +14 -0
- preditor/scintilla/lang/config/cpp.ini +19 -0
- preditor/scintilla/lang/config/css.ini +19 -0
- preditor/scintilla/lang/config/eyeonscript.ini +17 -0
- preditor/scintilla/lang/config/html.ini +21 -0
- preditor/scintilla/lang/config/javascript.ini +24 -0
- preditor/scintilla/lang/config/lua.ini +16 -0
- preditor/scintilla/lang/config/maxscript.ini +20 -0
- preditor/scintilla/lang/config/mel.ini +18 -0
- preditor/scintilla/lang/config/mu.ini +22 -0
- preditor/scintilla/lang/config/nsi.ini +19 -0
- preditor/scintilla/lang/config/perl.ini +19 -0
- preditor/scintilla/lang/config/puppet.ini +19 -0
- preditor/scintilla/lang/config/python.ini +28 -0
- preditor/scintilla/lang/config/ruby.ini +19 -0
- preditor/scintilla/lang/config/sql.ini +7 -0
- preditor/scintilla/lang/config/xml.ini +21 -0
- preditor/scintilla/lang/config/yaml.ini +18 -0
- preditor/scintilla/lang/language.py +240 -0
- preditor/scintilla/lexers/__init__.py +0 -0
- preditor/scintilla/lexers/cpplexer.py +22 -0
- preditor/scintilla/lexers/javascriptlexer.py +27 -0
- preditor/scintilla/lexers/maxscriptlexer.py +235 -0
- preditor/scintilla/lexers/mellexer.py +369 -0
- preditor/scintilla/lexers/mulexer.py +33 -0
- preditor/scintilla/lexers/pythonlexer.py +42 -0
- preditor/scintilla/ui/finddialog.ui +160 -0
- preditor/settings.py +71 -0
- preditor/stream/__init__.py +72 -0
- preditor/stream/console_handler.py +169 -0
- preditor/stream/director.py +144 -0
- preditor/stream/manager.py +97 -0
- preditor/streamhandler_helper.py +46 -0
- preditor/utils/__init__.py +191 -0
- preditor/utils/call_stack.py +86 -0
- preditor/utils/cute.py +106 -0
- preditor/utils/stylesheets.py +54 -0
- preditor/utils/text_search.py +338 -0
- preditor/version.py +34 -0
- preditor/weakref.py +363 -0
- preditor-2.1.0.dist-info/METADATA +308 -0
- preditor-2.1.0.dist-info/RECORD +179 -0
- preditor-2.1.0.dist-info/WHEEL +5 -0
- preditor-2.1.0.dist-info/entry_points.txt +19 -0
- preditor-2.1.0.dist-info/licenses/LICENSE +165 -0
- preditor-2.1.0.dist-info/top_level.txt +3 -0
- tests/encodings/test_ecoding.py +33 -0
- tests/find_files/test_find_files.py +74 -0
- tests/ide/test_delayable_engine.py +171 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
from __future__ import absolute_import, print_function
|
|
2
|
+
|
|
3
|
+
import abc
|
|
4
|
+
import re
|
|
5
|
+
from collections import deque
|
|
6
|
+
|
|
7
|
+
from future.utils import with_metaclass
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TextSearch(with_metaclass(abc.ABCMeta, object)):
|
|
11
|
+
"""Base class used to search and markup text for matches to a search term.
|
|
12
|
+
|
|
13
|
+
Parameters:
|
|
14
|
+
callback_matching (callable): Called when matching text should be written.
|
|
15
|
+
See `print_matching` to see what inputs it must accept.
|
|
16
|
+
callback_non_matching (callable): Called when plain text should be written.
|
|
17
|
+
See `print_non_matching` to see what inputs it must accept.
|
|
18
|
+
gap_format (str): A format string used to indicate when there is a gap in
|
|
19
|
+
the results shown. These variables are provided when formatting. `dot`
|
|
20
|
+
`dot` is a `.` for each digit required to show the current line number.
|
|
21
|
+
`padding` can be used to properly pad `dot`.
|
|
22
|
+
margin_format (str): A format string used to generate the line number
|
|
23
|
+
text at the start of a text line. These variables are provided when
|
|
24
|
+
formatting. `line_num` the current line number as an int. `padding`
|
|
25
|
+
can be used to properly pad `line_num`. `match_indicator` is a string
|
|
26
|
+
that is a `:` if the line contains a match, otherwise an empty space.
|
|
27
|
+
match_count (int): The number times matching text was found including
|
|
28
|
+
multiple finds on the same line. This value is not reset internally
|
|
29
|
+
and can be used to track all matches across multiple calls of `search_text`.
|
|
30
|
+
padding (int): Set by `search_text` to the number of digits required to
|
|
31
|
+
show all line numbers in the document. Used to ensure consistent number
|
|
32
|
+
padding for all line numbers printed in the margin and gaps.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
find_text (str): The text this finder will search for.
|
|
36
|
+
case_sensitive (bool): When searching text should it ignore case.
|
|
37
|
+
context (int): The number of lines to show before and after a line with
|
|
38
|
+
a match.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self, find_text, case_sensitive=False, context=3):
|
|
42
|
+
self._padding = 0
|
|
43
|
+
self.case_sensitive = case_sensitive
|
|
44
|
+
self.context = context
|
|
45
|
+
self.find_text = find_text
|
|
46
|
+
self.gap_format = " {dot: >{padding}} \n"
|
|
47
|
+
self.margin_format = " {line_num: >{padding}}{match_indicator} "
|
|
48
|
+
self.match_count = 0
|
|
49
|
+
|
|
50
|
+
self.callback_matching = self.print_matching
|
|
51
|
+
self.callback_non_matching = self.print_non_matching
|
|
52
|
+
|
|
53
|
+
def clear_cache(self):
|
|
54
|
+
"""The finder can implement this to clear any cached data.
|
|
55
|
+
|
|
56
|
+
This is called when no matches have been found beyond the # of context lines
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
@abc.abstractmethod
|
|
60
|
+
def indicate_line(self, line):
|
|
61
|
+
"""Yields chunks of line and if each chunk should be indicated.
|
|
62
|
+
|
|
63
|
+
The first yield should always be `(None, bool)`. The None value indicates
|
|
64
|
+
that the margin should be printed. This triggers printing of `self.margin`
|
|
65
|
+
passing the bool to the match_found argument.
|
|
66
|
+
|
|
67
|
+
Yields:
|
|
68
|
+
text (str or None): The text to be printed.
|
|
69
|
+
indicate (bool): Should text treated as a match for the search term.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
def indicate_results(
|
|
73
|
+
self, line, line_num, path="undefined", workbox_name="undefined"
|
|
74
|
+
):
|
|
75
|
+
"""Writes a single line adding markup for any matches on the line."""
|
|
76
|
+
tool_tip = "Open {} at line number {}".format(path, line_num)
|
|
77
|
+
for text, indicate in self.indicate_line(line):
|
|
78
|
+
# Print the margin text after the finder tells us if the line matches
|
|
79
|
+
if text is None:
|
|
80
|
+
self.callback_non_matching(self.margin(line_num, indicate))
|
|
81
|
+
continue
|
|
82
|
+
|
|
83
|
+
# Otherwise print the next section of the line text
|
|
84
|
+
if indicate:
|
|
85
|
+
self.callback_matching(text, workbox_name, line_num, tool_tip)
|
|
86
|
+
else:
|
|
87
|
+
self.callback_non_matching(text)
|
|
88
|
+
|
|
89
|
+
def insert_lines(self, start, *lines, info):
|
|
90
|
+
"""Inserts multiple lines adding links for any matching search terms.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
start (int): The line number of the first line to insert.
|
|
94
|
+
*lines (str): Each line to insert. They will be prefixed with line
|
|
95
|
+
numbers starting with start.
|
|
96
|
+
info (dict): Kwargs passed to indicate_results.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
int: The line number of the last line that was inserted.
|
|
100
|
+
"""
|
|
101
|
+
for i, line in enumerate(lines):
|
|
102
|
+
# Note: The `+ 1` is due to line numbers being 1 based not zero based
|
|
103
|
+
self.indicate_results(line, start + i + 1, **info)
|
|
104
|
+
|
|
105
|
+
return start + i
|
|
106
|
+
|
|
107
|
+
def margin(self, line_num, match_found):
|
|
108
|
+
"""Returns the margin text rendered and ready to print.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
line_num (int): The line number to show in the margin.
|
|
112
|
+
match_found (bool): Controls the indicator of if this line has any
|
|
113
|
+
matching text. If True then a `:` is inserted otherwise a space.
|
|
114
|
+
"""
|
|
115
|
+
match_indicator = ":" if match_found else " "
|
|
116
|
+
return self.margin_format.format(
|
|
117
|
+
line_num=line_num, match_indicator=match_indicator, padding=self._padding
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
@abc.abstractmethod
|
|
121
|
+
def matches(self, line):
|
|
122
|
+
"""Returns bool for if find_text is contained in this line."""
|
|
123
|
+
|
|
124
|
+
def print_matching(self, text, workbox_name, line_num, tool_tip):
|
|
125
|
+
"""Simple callback for `callback_matching` that prints text.
|
|
126
|
+
|
|
127
|
+
The print does not insert an newline character.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
text (str): The matching text to display. This will be inserted
|
|
131
|
+
into a markdown link as the link text.
|
|
132
|
+
workbox_name (str): From editor.__workbox_name__()
|
|
133
|
+
line_number (int): The line number the url should navigate to.
|
|
134
|
+
tool_tip (str): Added as a title to the link to show up as a tool tip.
|
|
135
|
+
"""
|
|
136
|
+
href = ', {}, {}'.format(workbox_name, line_num)
|
|
137
|
+
print('[{}]({} "{}")'.format(text, href, tool_tip), end="")
|
|
138
|
+
|
|
139
|
+
def print_non_matching(self, text):
|
|
140
|
+
"""Simple callback for `callback_non_matching` that prints text.
|
|
141
|
+
|
|
142
|
+
The print does not insert an newline character.
|
|
143
|
+
"""
|
|
144
|
+
print(text, end="")
|
|
145
|
+
|
|
146
|
+
def search_text(self, text, path, workbox_name):
|
|
147
|
+
"""Search each line of text for matching text and write the the matches
|
|
148
|
+
including context lines.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
text (str): The text to search.
|
|
152
|
+
path (str): The workbox name this text represents. Should be the
|
|
153
|
+
Group_name and tab_name separated by a `/`.
|
|
154
|
+
workbox_name (str): From editor.__workbox_name__()
|
|
155
|
+
"""
|
|
156
|
+
# NOTE: splitlines discards the "newline at end of file" so it doesn't
|
|
157
|
+
# show up in the final search results.
|
|
158
|
+
lines = text.splitlines(keepends=True)
|
|
159
|
+
|
|
160
|
+
# Calculate the padding count so we can ensure all line numbers and gaps
|
|
161
|
+
# are consistently spaced in the margins.
|
|
162
|
+
self._padding = len(str(len(lines)))
|
|
163
|
+
|
|
164
|
+
# Buffer to record up to context lines of text. This will be printed
|
|
165
|
+
# only if we find a match in the middle of the document.
|
|
166
|
+
# https://stackoverflow.com/a/52009859
|
|
167
|
+
pre_history = deque(maxlen=self.context)
|
|
168
|
+
remaining_context_lines = 0
|
|
169
|
+
|
|
170
|
+
# last_insert keeps track of the last time we inserted a line. This lets
|
|
171
|
+
# us keep track of if there is a gap in output and we need to add dots.
|
|
172
|
+
last_insert = 0
|
|
173
|
+
found = False
|
|
174
|
+
|
|
175
|
+
for i, line in enumerate(lines):
|
|
176
|
+
info = dict(path=path, workbox_name=workbox_name)
|
|
177
|
+
if self.matches(line):
|
|
178
|
+
len_pre_history = len(pre_history)
|
|
179
|
+
if not found:
|
|
180
|
+
# Print the path on the first find
|
|
181
|
+
self.callback_non_matching("# File: ")
|
|
182
|
+
tool_tip = "Open {}".format(path)
|
|
183
|
+
self.callback_matching(path, workbox_name, 0, tool_tip)
|
|
184
|
+
self.callback_non_matching("\n")
|
|
185
|
+
found = True
|
|
186
|
+
elif i - last_insert - 1 - len_pre_history > 0:
|
|
187
|
+
# If there is a in output larger than context, insert dots
|
|
188
|
+
# for the width of the line numbers to indicate the gap.
|
|
189
|
+
self.callback_non_matching(
|
|
190
|
+
self.gap_format.format(
|
|
191
|
+
dot='.' * len(str(i)), padding=self._padding
|
|
192
|
+
)
|
|
193
|
+
)
|
|
194
|
+
# Add the matching line the pre-context of the matching line.
|
|
195
|
+
last_insert = self.insert_lines(
|
|
196
|
+
i - len_pre_history, *pre_history, line, info=info
|
|
197
|
+
)
|
|
198
|
+
# Reset the pre-context history now that we have printed it.
|
|
199
|
+
pre_history.clear()
|
|
200
|
+
# Reset the post context line count so we will print the full
|
|
201
|
+
# context after this latest match if no other matches are found.
|
|
202
|
+
remaining_context_lines = self.context
|
|
203
|
+
else:
|
|
204
|
+
if remaining_context_lines > 0:
|
|
205
|
+
# Print any remaining context lines after we found a result
|
|
206
|
+
last_insert = self.insert_lines(i, line, info=info)
|
|
207
|
+
remaining_context_lines -= 1
|
|
208
|
+
else:
|
|
209
|
+
# If we don't need to print any post context lines record
|
|
210
|
+
# this line into pre-context history so we can print it if
|
|
211
|
+
# we find a match on the next line.
|
|
212
|
+
# When deque reaches maxlen lines, it automatically evicts oldest
|
|
213
|
+
pre_history.append(line)
|
|
214
|
+
# Clear any cached match information the finder may have stored.
|
|
215
|
+
self.clear_cache()
|
|
216
|
+
|
|
217
|
+
# Return if this file contained any matches
|
|
218
|
+
return found
|
|
219
|
+
|
|
220
|
+
def title(self):
|
|
221
|
+
return '\nFind in workboxs: "{}"{}\n\n'.format(self.find_text, self.title_flags)
|
|
222
|
+
|
|
223
|
+
@property
|
|
224
|
+
@abc.abstractmethod
|
|
225
|
+
def title_flags(self):
|
|
226
|
+
"""Returns the text to show in the title for flags."""
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class RegexTextSearch(TextSearch):
|
|
230
|
+
"""TextSearch that processes the text using regex."""
|
|
231
|
+
|
|
232
|
+
def __init__(self, find_text, case_sensitive=False, context=3):
|
|
233
|
+
super(RegexTextSearch, self).__init__(
|
|
234
|
+
find_text, case_sensitive, context=context
|
|
235
|
+
)
|
|
236
|
+
self.pattern = re.compile(find_text, flags=0 if case_sensitive else re.I)
|
|
237
|
+
# Cache regex match objects between the `matches` call and `indicate_line`
|
|
238
|
+
# The key is the original line of text
|
|
239
|
+
self._matches = {}
|
|
240
|
+
|
|
241
|
+
def clear_cache(self):
|
|
242
|
+
# Reset regex cache for the next call to `matches`
|
|
243
|
+
self._matches = {}
|
|
244
|
+
|
|
245
|
+
def indicate_line(self, line):
|
|
246
|
+
# Check if this line is a match.
|
|
247
|
+
match = self._matches.get(line)
|
|
248
|
+
# Write the margin indicating if this line has any matches
|
|
249
|
+
yield None, bool(match)
|
|
250
|
+
|
|
251
|
+
start = 0
|
|
252
|
+
if match:
|
|
253
|
+
for m in match:
|
|
254
|
+
pre = line[start : m.start()]
|
|
255
|
+
if pre:
|
|
256
|
+
yield pre, False
|
|
257
|
+
yield line[m.start() : m.end()], True
|
|
258
|
+
start = m.end()
|
|
259
|
+
# Record the match
|
|
260
|
+
self.match_count += 1
|
|
261
|
+
post = line[start:]
|
|
262
|
+
if post:
|
|
263
|
+
yield post, False
|
|
264
|
+
else:
|
|
265
|
+
yield line, False
|
|
266
|
+
|
|
267
|
+
def matches(self, line):
|
|
268
|
+
self._matches[line] = list(self.pattern.finditer(line))
|
|
269
|
+
return bool(self._matches[line])
|
|
270
|
+
|
|
271
|
+
@property
|
|
272
|
+
def title_flags(self):
|
|
273
|
+
if self.case_sensitive:
|
|
274
|
+
return " (regex, case sensitive)"
|
|
275
|
+
return " (regex)"
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
class SimpleTextSearch(TextSearch):
|
|
279
|
+
"""A simple text matching finder that optionally considers case."""
|
|
280
|
+
|
|
281
|
+
def __init__(self, find_text, case_sensitive=False, context=3):
|
|
282
|
+
super(SimpleTextSearch, self).__init__(
|
|
283
|
+
find_text, case_sensitive, context=context
|
|
284
|
+
)
|
|
285
|
+
# Assign the correct matching method based on the desired case setting
|
|
286
|
+
if case_sensitive:
|
|
287
|
+
self._matches = self._search_text_case_sensitive
|
|
288
|
+
else:
|
|
289
|
+
self._matches = self._search_text
|
|
290
|
+
find_text = self.find_text.lower()
|
|
291
|
+
# Preserve the original find_text value but cache the value needed internally
|
|
292
|
+
self._find_text = find_text
|
|
293
|
+
|
|
294
|
+
def _search_text(self, line):
|
|
295
|
+
"""Check for pattern ignoring case."""
|
|
296
|
+
return self._find_text in line.lower()
|
|
297
|
+
|
|
298
|
+
def _search_text_case_sensitive(self, line):
|
|
299
|
+
"""Check for pattern matching case."""
|
|
300
|
+
return self._find_text in line
|
|
301
|
+
|
|
302
|
+
def indicate_line(self, line):
|
|
303
|
+
# Handle case sensitivity setting, ensuring return of the correct case
|
|
304
|
+
original_line = line
|
|
305
|
+
if not self.case_sensitive:
|
|
306
|
+
line = line.lower()
|
|
307
|
+
|
|
308
|
+
find_len = len(self._find_text)
|
|
309
|
+
start = 0
|
|
310
|
+
end = line.find(self._find_text)
|
|
311
|
+
# Write the margin indicating if this line has any matches
|
|
312
|
+
yield None, end != -1
|
|
313
|
+
|
|
314
|
+
# Write the text of the line with indications
|
|
315
|
+
while end != -1:
|
|
316
|
+
# insert prefix text
|
|
317
|
+
yield original_line[start:end], False
|
|
318
|
+
# insert indicated text preserving case
|
|
319
|
+
yield original_line[end : end + find_len], True
|
|
320
|
+
# Record the match
|
|
321
|
+
self.match_count += 1
|
|
322
|
+
|
|
323
|
+
# Check for any more matches in this line
|
|
324
|
+
start = end + find_len
|
|
325
|
+
end = line.find(self._find_text, start)
|
|
326
|
+
|
|
327
|
+
# Include text at the end of the line
|
|
328
|
+
if end < find_len:
|
|
329
|
+
yield original_line[start:], False
|
|
330
|
+
|
|
331
|
+
def matches(self, line):
|
|
332
|
+
return self._matches(line)
|
|
333
|
+
|
|
334
|
+
@property
|
|
335
|
+
def title_flags(self):
|
|
336
|
+
if self.case_sensitive:
|
|
337
|
+
return " (case sensitive)"
|
|
338
|
+
return ""
|
preditor/version.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# file generated by setuptools-scm
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
TYPE_CHECKING = False
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from typing import Tuple
|
|
16
|
+
from typing import Union
|
|
17
|
+
|
|
18
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
20
|
+
else:
|
|
21
|
+
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
23
|
+
|
|
24
|
+
version: str
|
|
25
|
+
__version__: str
|
|
26
|
+
__version_tuple__: VERSION_TUPLE
|
|
27
|
+
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
30
|
+
|
|
31
|
+
__version__ = version = '2.1.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (2, 1, 0)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = 'g5a664e468'
|