ttkode 0.3.0a2__tar.gz → 0.3.2a2__tar.gz
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.
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/PKG-INFO +2 -2
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/pyproject.toml +7 -3
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/ttkode/__init__.py +3 -3
- ttkode-0.3.0a2/ttkode/app/main.py → ttkode-0.3.2a2/ttkode/__main__.py +5 -3
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/ttkode/app/__init__.py +0 -1
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/ttkode/plugin.py +2 -2
- ttkode-0.3.2a2/ttkode/plugins/_010/__init__.py +0 -0
- ttkode-0.3.2a2/ttkode/plugins/_010/findwidget.py +270 -0
- ttkode-0.3.2a2/ttkode/plugins/_010_findplugin.py +45 -0
- ttkode-0.3.2a2/ttkode/plugins/_020_debugplugin.py +39 -0
- ttkode-0.3.0a2/ttkode/__main__.py → ttkode-0.3.2a2/ttkode/plugins/testplugin.py +11 -6
- ttkode-0.3.2a2/ttkode/plugins/testplugin1.py +36 -0
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/ttkode.egg-info/PKG-INFO +2 -2
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/ttkode.egg-info/SOURCES.txt +7 -2
- ttkode-0.3.2a2/ttkode.egg-info/entry_points.txt +2 -0
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/ttkode.egg-info/requires.txt +1 -1
- ttkode-0.3.0a2/ttkode.egg-info/entry_points.txt +0 -2
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/README.md +0 -0
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/setup.cfg +0 -0
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/ttkode/app/about.py +0 -0
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/ttkode/app/activitybar.py +0 -0
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/ttkode/app/cfg.py +0 -0
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/ttkode/app/options.py +0 -0
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/ttkode/app/ttkode.py +0 -0
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/ttkode/helper.py +0 -0
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/ttkode/proxy.py +0 -0
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/ttkode.egg-info/dependency_links.txt +0 -0
- {ttkode-0.3.0a2 → ttkode-0.3.2a2}/ttkode.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ttkode
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2a2
|
|
4
4
|
Summary: Terminal ToolKit Studio Code editor
|
|
5
5
|
Author-email: Eugenio Parodi <ceccopierangiolieugenio@googlemail.com>
|
|
6
6
|
License: MIT
|
|
@@ -19,7 +19,7 @@ Classifier: Topic :: Terminals
|
|
|
19
19
|
Classifier: Topic :: Software Development :: User Interfaces
|
|
20
20
|
Requires-Python: >=3.9
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
|
-
Requires-Dist: pyTermTk>=0.42.
|
|
22
|
+
Requires-Dist: pyTermTk>=0.42.1-a.0
|
|
23
23
|
Requires-Dist: appdirs
|
|
24
24
|
Requires-Dist: copykitten
|
|
25
25
|
Requires-Dist: pygments
|
|
@@ -24,7 +24,7 @@ classifiers = [
|
|
|
24
24
|
"Topic :: Software Development :: User Interfaces",
|
|
25
25
|
]
|
|
26
26
|
dependencies = [
|
|
27
|
-
'pyTermTk>=0.42.
|
|
27
|
+
'pyTermTk>=0.42.1-a.0',
|
|
28
28
|
'appdirs',
|
|
29
29
|
'copykitten',
|
|
30
30
|
'pygments'
|
|
@@ -37,10 +37,14 @@ Issues = "https://github.com/ceccopierangiolieugenio/pyTermTk/issues"
|
|
|
37
37
|
Changelog = "https://github.com/ceccopierangiolieugenio/pyTermTk/blob/main/apps/ttkode/CHANGELOG.md"
|
|
38
38
|
|
|
39
39
|
[project.scripts]
|
|
40
|
-
ttkode = "ttkode:main"
|
|
40
|
+
ttkode = "ttkode.__main__:main"
|
|
41
41
|
|
|
42
42
|
[tool.setuptools]
|
|
43
|
-
packages = [
|
|
43
|
+
packages = [
|
|
44
|
+
"ttkode", "ttkode.app",
|
|
45
|
+
"ttkode.plugins",
|
|
46
|
+
"ttkode.plugins._010",
|
|
47
|
+
]
|
|
44
48
|
|
|
45
49
|
[tool.setuptools.dynamic]
|
|
46
50
|
version = {attr = "ttkode.__version__"}
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
23
|
# SOFTWARE.
|
|
24
24
|
|
|
25
|
-
__version__:str = '0.3.
|
|
25
|
+
__version__:str = '0.3.2-a.2'
|
|
26
26
|
|
|
27
|
-
from .helper import TTkodeHelper
|
|
28
27
|
from .plugin import TTkodePlugin, TTkodePluginActivity
|
|
29
|
-
from .proxy import TTKodeViewerProxy, ttkodeProxy
|
|
28
|
+
from .proxy import TTKodeViewerProxy, ttkodeProxy
|
|
29
|
+
from .helper import TTkodeHelper
|
|
@@ -33,9 +33,8 @@ from TermTk import TTkLog
|
|
|
33
33
|
|
|
34
34
|
from ttkode import TTkodeHelper
|
|
35
35
|
from ttkode import ttkodeProxy
|
|
36
|
-
|
|
37
|
-
from .
|
|
38
|
-
from .cfg import TTKodeCfg
|
|
36
|
+
from ttkode.app.ttkode import TTKode
|
|
37
|
+
from ttkode.app.cfg import TTKodeCfg
|
|
39
38
|
|
|
40
39
|
|
|
41
40
|
def main():
|
|
@@ -82,3 +81,6 @@ def main():
|
|
|
82
81
|
TTkodeHelper._runPlugins()
|
|
83
82
|
|
|
84
83
|
root.mainloop()
|
|
84
|
+
|
|
85
|
+
if __name__ == '__main__':
|
|
86
|
+
main()
|
|
@@ -23,13 +23,13 @@
|
|
|
23
23
|
__all__ = ['TTkodePlugin', 'TTkodePluginActivity']
|
|
24
24
|
|
|
25
25
|
from dataclasses import dataclass
|
|
26
|
-
from typing import Callable,
|
|
26
|
+
from typing import Callable, List, Optional, Union
|
|
27
27
|
from enum import Enum
|
|
28
28
|
|
|
29
29
|
import TermTk as ttk
|
|
30
30
|
|
|
31
31
|
class TTkodePlugin():
|
|
32
|
-
instances: List
|
|
32
|
+
instances: List = []
|
|
33
33
|
def __init__(
|
|
34
34
|
self,
|
|
35
35
|
name : str,
|
|
File without changes
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2025 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
|
|
23
|
+
__all__ = ['FindWidget']
|
|
24
|
+
|
|
25
|
+
import os
|
|
26
|
+
import re
|
|
27
|
+
import fnmatch
|
|
28
|
+
import mimetypes
|
|
29
|
+
|
|
30
|
+
from threading import Thread
|
|
31
|
+
from typing import Generator,List,Tuple
|
|
32
|
+
|
|
33
|
+
import TermTk as ttk
|
|
34
|
+
|
|
35
|
+
import os
|
|
36
|
+
import fnmatch
|
|
37
|
+
|
|
38
|
+
from ttkode import ttkodeProxy
|
|
39
|
+
from ttkode.app.ttkode import TTKodeFileWidgetItem
|
|
40
|
+
|
|
41
|
+
import mimetypes
|
|
42
|
+
|
|
43
|
+
def is_text_file(file_path, block_size=512):
|
|
44
|
+
# Check MIME type
|
|
45
|
+
mime_type, _ = mimetypes.guess_type(file_path)
|
|
46
|
+
text_based_mime_types = [
|
|
47
|
+
'text/', 'application/json', 'application/xml',
|
|
48
|
+
'application/javascript', 'application/x-httpd-php',
|
|
49
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
|
|
50
|
+
]
|
|
51
|
+
if mime_type is not None and any(mime_type.startswith(mime) for mime in text_based_mime_types):
|
|
52
|
+
return True
|
|
53
|
+
|
|
54
|
+
# Check for non-printable characters
|
|
55
|
+
try:
|
|
56
|
+
with open(file_path, 'rb') as file:
|
|
57
|
+
block = file.read(block_size)
|
|
58
|
+
if b'\0' in block:
|
|
59
|
+
return False
|
|
60
|
+
text_characters = bytearray({7, 8, 9, 10, 12, 13, 27} | set(range(0x20, 0x100)) - {0x7f})
|
|
61
|
+
return not bool(block.translate(None, text_characters))
|
|
62
|
+
except Exception as e:
|
|
63
|
+
print(f"Error reading file: {e}")
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
def _load_gitignore_patterns(gitignore_path):
|
|
67
|
+
if os.path.exists(gitignore_path):
|
|
68
|
+
with open(gitignore_path, 'r') as f:
|
|
69
|
+
patterns = f.read().splitlines()
|
|
70
|
+
return patterns
|
|
71
|
+
return []
|
|
72
|
+
|
|
73
|
+
def _should_ignore(path, patterns):
|
|
74
|
+
for pattern in patterns:
|
|
75
|
+
if fnmatch.fnmatch(path, pattern):
|
|
76
|
+
return True
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
def _custom_walk(directory:str, patterns:List[str]=[]) -> Generator[Tuple[str, str], None, None]:
|
|
80
|
+
gitignore_path = os.path.join(directory, '.gitignore')
|
|
81
|
+
patterns = patterns + _load_gitignore_patterns(gitignore_path)
|
|
82
|
+
for entry in sorted(os.listdir(directory)):
|
|
83
|
+
full_path = os.path.join(directory, entry)
|
|
84
|
+
if _should_ignore(full_path, patterns):
|
|
85
|
+
continue
|
|
86
|
+
if os.path.isdir(full_path):
|
|
87
|
+
if entry == '.git':
|
|
88
|
+
continue
|
|
89
|
+
yield from _custom_walk(full_path, patterns)
|
|
90
|
+
else:
|
|
91
|
+
yield directory, entry
|
|
92
|
+
|
|
93
|
+
def _walk_with_gitignore(root):
|
|
94
|
+
for dirpath, filenames in os.walk(root):
|
|
95
|
+
gitignore_path = os.path.join(dirpath, '.gitignore')
|
|
96
|
+
patterns = _load_gitignore_patterns(gitignore_path)
|
|
97
|
+
|
|
98
|
+
filenames[:] = [f for f in filenames if not _should_ignore(os.path.join(dirpath, f), patterns)]
|
|
99
|
+
|
|
100
|
+
yield dirpath, filenames
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class _ToggleButton(ttk.TTkButton):
|
|
104
|
+
def __init__(self, **kwargs):
|
|
105
|
+
params = {
|
|
106
|
+
'border':False,
|
|
107
|
+
'checked':False,
|
|
108
|
+
'checkable':True,
|
|
109
|
+
'minSize':(4,1),
|
|
110
|
+
'maxSize':(4,1),
|
|
111
|
+
}
|
|
112
|
+
super().__init__(**kwargs|params)
|
|
113
|
+
|
|
114
|
+
def paintEvent(self, canvas):
|
|
115
|
+
if self.isChecked():
|
|
116
|
+
canvas.drawChar(pos=(1,0),char='▼')
|
|
117
|
+
else:
|
|
118
|
+
canvas.drawChar(pos=(1,0),char='▶')
|
|
119
|
+
|
|
120
|
+
class _MatchTreeWidgetItem(TTKodeFileWidgetItem):
|
|
121
|
+
__slots__ = ('_match','_line','_file')
|
|
122
|
+
_match:str
|
|
123
|
+
def __init__(self, *args, match:str, **kwargs):
|
|
124
|
+
self._match = match
|
|
125
|
+
super().__init__(*args, **kwargs)
|
|
126
|
+
|
|
127
|
+
class FindWidget(ttk.TTkContainer):
|
|
128
|
+
__slots__ = (
|
|
129
|
+
'_runId'
|
|
130
|
+
'_results_tree',
|
|
131
|
+
'_search_le','_replace_le','_files_inc_le','_files_exc_le')
|
|
132
|
+
_runId:int
|
|
133
|
+
_results_tree:ttk.TTkTreeWidget
|
|
134
|
+
_search_le:ttk.TTkLineEdit
|
|
135
|
+
_replace_le:ttk.TTkLineEdit
|
|
136
|
+
_files_inc_le:ttk.TTkLineEdit
|
|
137
|
+
_files_exc_le:ttk.TTkLineEdit
|
|
138
|
+
def __init__(self, **kwargs):
|
|
139
|
+
self._runId = 0
|
|
140
|
+
super().__init__(**kwargs)
|
|
141
|
+
self.setLayout(layout:=ttk.TTkGridLayout())
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
searchLayout = ttk.TTkGridLayout()
|
|
145
|
+
searchLayout.addWidget(expandReplace:=_ToggleButton(), 0, 0)
|
|
146
|
+
searchLayout.addWidget(search :=ttk.TTkLineEdit(hint='Search'), 0, 1)
|
|
147
|
+
searchLayout.addWidget(repl__l:=ttk.TTkLabel(visible=False, text='sub:'), 1, 0)
|
|
148
|
+
searchLayout.addWidget(ft_in_l:=ttk.TTkLabel(visible=False, text='inc:'), 2, 0)
|
|
149
|
+
searchLayout.addWidget(ft_ex_l:=ttk.TTkLabel(visible=False, text='exc:'), 3, 0)
|
|
150
|
+
searchLayout.addWidget(replace:=ttk.TTkLineEdit(visible=False, hint='Replace'), 1, 1)
|
|
151
|
+
searchLayout.addWidget(ft_incl:=ttk.TTkLineEdit(visible=False, hint='Files to include'), 2, 1)
|
|
152
|
+
searchLayout.addWidget(ft_excl:=ttk.TTkLineEdit(visible=False, hint='Files to exclude'), 3, 1)
|
|
153
|
+
layout.addItem(searchLayout, 0, 0)
|
|
154
|
+
|
|
155
|
+
controlsLayout = ttk.TTkGridLayout()
|
|
156
|
+
controlsLayout.addWidget(btn_search:=ttk.TTkButton(text="Search", border=False), 0,0)
|
|
157
|
+
controlsLayout.addWidget(btn_replace:=ttk.TTkButton(text='Replace', border=False, enabled=False), 0, 1)
|
|
158
|
+
controlsLayout.addWidget(btn_expand :=ttk.TTkButton(text='+', maxWidth=3, border=False), 0, 2)
|
|
159
|
+
controlsLayout.addWidget(btn_collapse:=ttk.TTkButton(text='-', maxWidth=3, border=False), 0, 3)
|
|
160
|
+
layout.addItem(controlsLayout,1,0)
|
|
161
|
+
|
|
162
|
+
layout.addWidget(res_tree:=ttk.TTkTree(dragDropMode=ttk.TTkK.DragDropMode.AllowDrag), 2,0)
|
|
163
|
+
res_tree.setHeaderLabels(["Results"])
|
|
164
|
+
res_tree.setColumnWidth(0,100)
|
|
165
|
+
|
|
166
|
+
expandReplace.toggled.connect(replace.setVisible)
|
|
167
|
+
expandReplace.toggled.connect(repl__l.setVisible)
|
|
168
|
+
expandReplace.toggled.connect(ft_incl.setVisible)
|
|
169
|
+
expandReplace.toggled.connect(ft_excl.setVisible)
|
|
170
|
+
expandReplace.toggled.connect(ft_in_l.setVisible)
|
|
171
|
+
expandReplace.toggled.connect(ft_ex_l.setVisible)
|
|
172
|
+
|
|
173
|
+
self._results_tree = res_tree
|
|
174
|
+
self._search_le = search
|
|
175
|
+
self._replace_le = replace
|
|
176
|
+
self._files_inc_le = ft_incl
|
|
177
|
+
self._files_exc_le = ft_excl
|
|
178
|
+
|
|
179
|
+
btn_search.clicked.connect(self._search)
|
|
180
|
+
btn_expand.clicked.connect(self._results_tree.expandAll)
|
|
181
|
+
btn_collapse.clicked.connect(self._results_tree.collapseAll)
|
|
182
|
+
search.returnPressed.connect(self._search)
|
|
183
|
+
res_tree.itemActivated.connect(self._activated)
|
|
184
|
+
|
|
185
|
+
@ttk.pyTTkSlot(str)
|
|
186
|
+
def _replace_txt(value):
|
|
187
|
+
btn_replace.setEnabled(bool(value))
|
|
188
|
+
|
|
189
|
+
self._replace_le.textChanged.connect(_replace_txt)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
@ttk.pyTTkSlot(ttk.TTkTreeWidgetItem, int)
|
|
193
|
+
def _activated(self, item:ttk.TTkTreeWidgetItem, _):
|
|
194
|
+
if isinstance(item, _MatchTreeWidgetItem):
|
|
195
|
+
file = item.path()
|
|
196
|
+
line = item.lineNumber()
|
|
197
|
+
ttkodeProxy.openFile(file, line)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
@ttk.pyTTkSlot()
|
|
201
|
+
def _search(self):
|
|
202
|
+
self._runId += 1
|
|
203
|
+
search_pattern = str(self._search_le.text())
|
|
204
|
+
if not search_pattern:
|
|
205
|
+
return
|
|
206
|
+
def _search_threading():
|
|
207
|
+
self._results_tree.clear()
|
|
208
|
+
group = []
|
|
209
|
+
groupSize = 1
|
|
210
|
+
for (file,root,matches) in self._search_files('.',str(search_pattern),self._runId):
|
|
211
|
+
ttk.TTkLog.debug((file,matches))
|
|
212
|
+
item = ttk.TTkTreeWidgetItem([
|
|
213
|
+
ttk.TTkString(
|
|
214
|
+
ttk.TTkCfg.theme.fileIcon.getIcon(file),
|
|
215
|
+
ttk.TTkCfg.theme.fileIconColor) + " " +
|
|
216
|
+
ttk.TTkString(f" {file} ", ttk.TTkColor.YELLOW+ttk.TTkColor.BOLD+ttk.TTkColor.bg('#000088')) +
|
|
217
|
+
ttk.TTkString(f" {root} ", ttk.TTkColor.fg("#888888"))
|
|
218
|
+
],expanded=True)
|
|
219
|
+
for num,line in matches:
|
|
220
|
+
line = line.lstrip(' ')
|
|
221
|
+
# index = line.find(search_pattern)
|
|
222
|
+
# outLine =
|
|
223
|
+
item.addChild(
|
|
224
|
+
_MatchTreeWidgetItem([
|
|
225
|
+
ttk.TTkString(str(num)+" ",ttk.TTkColor.CYAN) +
|
|
226
|
+
ttk.TTkString(line.replace('\n','')).completeColor(
|
|
227
|
+
match=search_pattern,
|
|
228
|
+
color=ttk.TTkColor.GREEN)
|
|
229
|
+
],
|
|
230
|
+
match=line,
|
|
231
|
+
lineNumber=num,
|
|
232
|
+
path=os.path.join(root,file)))
|
|
233
|
+
group.append(item)
|
|
234
|
+
if len(group) > groupSize:
|
|
235
|
+
self._results_tree.addTopLevelItems(group)
|
|
236
|
+
group = []
|
|
237
|
+
groupSize <<= 1
|
|
238
|
+
# self._results_tree.addTopLevelItem(item)
|
|
239
|
+
if group:
|
|
240
|
+
self._results_tree.addTopLevelItems(group)
|
|
241
|
+
Thread(target=_search_threading).start()
|
|
242
|
+
|
|
243
|
+
def _search_files(self, root_folder, match, runId):
|
|
244
|
+
matches = []
|
|
245
|
+
for root, file in _custom_walk(root_folder):
|
|
246
|
+
if runId != self._runId:
|
|
247
|
+
return
|
|
248
|
+
if True: # file.endswith('.py'): # file.endswith(file_extension):
|
|
249
|
+
file_path = os.path.join(root, file)
|
|
250
|
+
if not is_text_file(file_path):
|
|
251
|
+
continue
|
|
252
|
+
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
|
|
253
|
+
lines = f.readlines()
|
|
254
|
+
line_matches = [(i, line.split('\n')[0]) for i, line in enumerate(lines) if match in line]
|
|
255
|
+
if line_matches:
|
|
256
|
+
yield (file, root, line_matches)
|
|
257
|
+
|
|
258
|
+
def _search_files_re(self, root_folder, file_extension, search_pattern):
|
|
259
|
+
matches = []
|
|
260
|
+
regex = re.compile(search_pattern)
|
|
261
|
+
for root, dirs, files in os.walk(root_folder):
|
|
262
|
+
for file in files:
|
|
263
|
+
if True: # file.endswith(file_extension):
|
|
264
|
+
file_path = os.path.join(root, file)
|
|
265
|
+
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
|
|
266
|
+
lines = f.readlines()
|
|
267
|
+
line_matches = [i + 1 for i, line in enumerate(lines) if regex.search(line)]
|
|
268
|
+
if line_matches:
|
|
269
|
+
yield (file_path, line_matches)
|
|
270
|
+
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2025 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
|
|
23
|
+
__all__:list[str] = []
|
|
24
|
+
|
|
25
|
+
import os, sys
|
|
26
|
+
|
|
27
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
28
|
+
sys.path.insert(0, current_dir)
|
|
29
|
+
|
|
30
|
+
import TermTk as ttk
|
|
31
|
+
|
|
32
|
+
import ttkode
|
|
33
|
+
|
|
34
|
+
from _010.findwidget import FindWidget
|
|
35
|
+
|
|
36
|
+
_icon:str = (
|
|
37
|
+
"╔═╗\n"
|
|
38
|
+
"🔎╝")
|
|
39
|
+
|
|
40
|
+
ttkode.TTkodePluginActivity(
|
|
41
|
+
name="Find Plugin",
|
|
42
|
+
activityName='Search',
|
|
43
|
+
widget=FindWidget(),
|
|
44
|
+
icon=ttk.TTkString(_icon)
|
|
45
|
+
)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
|
|
2
|
+
# MIT License
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2025 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
|
|
5
|
+
#
|
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
# furnished to do so, subject to the following conditions:
|
|
12
|
+
#
|
|
13
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
# copies or substantial portions of the Software.
|
|
15
|
+
#
|
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
# SOFTWARE.
|
|
23
|
+
|
|
24
|
+
__all__:list[str] = []
|
|
25
|
+
|
|
26
|
+
import TermTk as ttk
|
|
27
|
+
|
|
28
|
+
import ttkode
|
|
29
|
+
|
|
30
|
+
_icon:str = (
|
|
31
|
+
" 🭑🬽\n"
|
|
32
|
+
"🪲🭘")
|
|
33
|
+
|
|
34
|
+
ttkode.TTkodePluginActivity(
|
|
35
|
+
name="Debug Plugin",
|
|
36
|
+
activityName='Debug',
|
|
37
|
+
widget=ttk.TTkTestWidget(),
|
|
38
|
+
icon=ttk.TTkString(_icon)
|
|
39
|
+
)
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
1
|
# MIT License
|
|
4
2
|
#
|
|
5
|
-
# Copyright (c)
|
|
3
|
+
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
|
|
6
4
|
#
|
|
7
5
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
6
|
# of this software and associated documentation files (the "Software"), to deal
|
|
@@ -22,7 +20,14 @@
|
|
|
22
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
21
|
# SOFTWARE.
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
import TermTk as ttk
|
|
24
|
+
|
|
25
|
+
import ttkode
|
|
26
|
+
|
|
27
|
+
def init():
|
|
28
|
+
ttk.TTkLog.debug("Test Plugin Init")
|
|
29
|
+
|
|
30
|
+
def apply():
|
|
31
|
+
ttk.TTkLog.debug("Test Plugin Apply")
|
|
26
32
|
|
|
27
|
-
|
|
28
|
-
main()
|
|
33
|
+
ttkode.TTkodePlugin(name="Test Plugin", init=init, apply=apply)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
|
|
23
|
+
import TermTk as ttk
|
|
24
|
+
|
|
25
|
+
import ttkode
|
|
26
|
+
|
|
27
|
+
def init():
|
|
28
|
+
ttk.TTkLog.debug("Test Plugin1 Init")
|
|
29
|
+
|
|
30
|
+
def apply():
|
|
31
|
+
ttk.TTkLog.debug("Test Plugin1 Apply")
|
|
32
|
+
|
|
33
|
+
def run():
|
|
34
|
+
ttk.TTkLog.debug("Test Plugin1 Run")
|
|
35
|
+
|
|
36
|
+
ttkode.TTkodePlugin(name="Test Plugin 1", init=init, apply=apply, run=run)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ttkode
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2a2
|
|
4
4
|
Summary: Terminal ToolKit Studio Code editor
|
|
5
5
|
Author-email: Eugenio Parodi <ceccopierangiolieugenio@googlemail.com>
|
|
6
6
|
License: MIT
|
|
@@ -19,7 +19,7 @@ Classifier: Topic :: Terminals
|
|
|
19
19
|
Classifier: Topic :: Software Development :: User Interfaces
|
|
20
20
|
Requires-Python: >=3.9
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
|
-
Requires-Dist: pyTermTk>=0.42.
|
|
22
|
+
Requires-Dist: pyTermTk>=0.42.1-a.0
|
|
23
23
|
Requires-Dist: appdirs
|
|
24
24
|
Requires-Dist: copykitten
|
|
25
25
|
Requires-Dist: pygments
|
|
@@ -15,6 +15,11 @@ ttkode/app/__init__.py
|
|
|
15
15
|
ttkode/app/about.py
|
|
16
16
|
ttkode/app/activitybar.py
|
|
17
17
|
ttkode/app/cfg.py
|
|
18
|
-
ttkode/app/main.py
|
|
19
18
|
ttkode/app/options.py
|
|
20
|
-
ttkode/app/ttkode.py
|
|
19
|
+
ttkode/app/ttkode.py
|
|
20
|
+
ttkode/plugins/_010_findplugin.py
|
|
21
|
+
ttkode/plugins/_020_debugplugin.py
|
|
22
|
+
ttkode/plugins/testplugin.py
|
|
23
|
+
ttkode/plugins/testplugin1.py
|
|
24
|
+
ttkode/plugins/_010/__init__.py
|
|
25
|
+
ttkode/plugins/_010/findwidget.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|