fishertools 0.2.1__py3-none-any.whl → 0.4.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.
- fishertools/__init__.py +16 -5
- fishertools/errors/__init__.py +11 -3
- fishertools/errors/exception_types.py +282 -0
- fishertools/errors/explainer.py +87 -1
- fishertools/errors/models.py +73 -1
- fishertools/errors/patterns.py +40 -0
- fishertools/examples/cli_example.py +156 -0
- fishertools/examples/learn_example.py +65 -0
- fishertools/examples/logger_example.py +176 -0
- fishertools/examples/menu_example.py +101 -0
- fishertools/examples/storage_example.py +175 -0
- fishertools/input_utils.py +185 -0
- fishertools/learn/__init__.py +19 -2
- fishertools/learn/examples.py +88 -1
- fishertools/learn/knowledge_engine.py +321 -0
- fishertools/learn/repl/__init__.py +19 -0
- fishertools/learn/repl/cli.py +31 -0
- fishertools/learn/repl/code_sandbox.py +229 -0
- fishertools/learn/repl/command_handler.py +544 -0
- fishertools/learn/repl/command_parser.py +165 -0
- fishertools/learn/repl/engine.py +479 -0
- fishertools/learn/repl/models.py +121 -0
- fishertools/learn/repl/session_manager.py +284 -0
- fishertools/learn/repl/test_code_sandbox.py +261 -0
- fishertools/learn/repl/test_code_sandbox_pbt.py +148 -0
- fishertools/learn/repl/test_command_handler.py +224 -0
- fishertools/learn/repl/test_command_handler_pbt.py +189 -0
- fishertools/learn/repl/test_command_parser.py +160 -0
- fishertools/learn/repl/test_command_parser_pbt.py +100 -0
- fishertools/learn/repl/test_engine.py +190 -0
- fishertools/learn/repl/test_session_manager.py +310 -0
- fishertools/learn/repl/test_session_manager_pbt.py +182 -0
- fishertools/learn/test_knowledge_engine.py +241 -0
- fishertools/learn/test_knowledge_engine_pbt.py +180 -0
- fishertools/patterns/__init__.py +46 -0
- fishertools/patterns/cli.py +175 -0
- fishertools/patterns/logger.py +140 -0
- fishertools/patterns/menu.py +99 -0
- fishertools/patterns/storage.py +127 -0
- fishertools/readme_transformer.py +631 -0
- fishertools/safe/__init__.py +6 -1
- fishertools/safe/files.py +329 -1
- fishertools/transform_readme.py +105 -0
- fishertools-0.4.0.dist-info/METADATA +104 -0
- fishertools-0.4.0.dist-info/RECORD +131 -0
- {fishertools-0.2.1.dist-info → fishertools-0.4.0.dist-info}/WHEEL +1 -1
- tests/test_documentation_properties.py +329 -0
- tests/test_documentation_structure.py +349 -0
- tests/test_errors/test_exception_types.py +446 -0
- tests/test_errors/test_exception_types_pbt.py +333 -0
- tests/test_errors/test_patterns.py +52 -0
- tests/test_input_utils/__init__.py +1 -0
- tests/test_input_utils/test_input_utils.py +65 -0
- tests/test_learn/test_examples.py +179 -1
- tests/test_learn/test_explain_properties.py +307 -0
- tests/test_patterns_cli.py +611 -0
- tests/test_patterns_docstrings.py +473 -0
- tests/test_patterns_logger.py +465 -0
- tests/test_patterns_menu.py +440 -0
- tests/test_patterns_storage.py +447 -0
- tests/test_readme_enhancements_v0_3_1.py +2036 -0
- tests/test_readme_transformer/__init__.py +1 -0
- tests/test_readme_transformer/test_readme_infrastructure.py +1023 -0
- tests/test_readme_transformer/test_transform_readme_integration.py +431 -0
- tests/test_safe/test_files.py +726 -1
- fishertools-0.2.1.dist-info/METADATA +0 -256
- fishertools-0.2.1.dist-info/RECORD +0 -81
- {fishertools-0.2.1.dist-info → fishertools-0.4.0.dist-info}/licenses/LICENSE +0 -0
- {fishertools-0.2.1.dist-info → fishertools-0.4.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Command handler for the Knowledge Engine REPL.
|
|
3
|
+
|
|
4
|
+
This module handles execution of all REPL commands and returns formatted output.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import random
|
|
8
|
+
from typing import List, Dict, Optional, Any
|
|
9
|
+
from difflib import get_close_matches
|
|
10
|
+
|
|
11
|
+
from fishertools.learn.knowledge_engine import KnowledgeEngine
|
|
12
|
+
from fishertools.learn.repl.session_manager import SessionManager
|
|
13
|
+
from fishertools.learn.repl.models import TopicDisplay, ExampleDisplay
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class CommandHandler:
|
|
17
|
+
"""
|
|
18
|
+
Handles execution of REPL commands and returns formatted output.
|
|
19
|
+
|
|
20
|
+
Supports commands for:
|
|
21
|
+
- Topic browsing (/list, /search, /random, /categories, /category, /path)
|
|
22
|
+
- Topic information (/related)
|
|
23
|
+
- Progress tracking (/progress, /stats)
|
|
24
|
+
- Help and information (/help, /commands, /about)
|
|
25
|
+
- Hints and tips (/hint, /tip, /tips)
|
|
26
|
+
|
|
27
|
+
Example:
|
|
28
|
+
>>> engine = KnowledgeEngine()
|
|
29
|
+
>>> manager = SessionManager()
|
|
30
|
+
>>> handler = CommandHandler(engine, manager)
|
|
31
|
+
>>> output = handler.handle_list()
|
|
32
|
+
>>> print(output)
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(self, engine: KnowledgeEngine, session_manager: SessionManager):
|
|
36
|
+
"""
|
|
37
|
+
Initialize the command handler.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
engine: Knowledge Engine instance
|
|
41
|
+
session_manager: Session Manager instance
|
|
42
|
+
"""
|
|
43
|
+
self.engine = engine
|
|
44
|
+
self.session_manager = session_manager
|
|
45
|
+
|
|
46
|
+
def handle_list(self) -> str:
|
|
47
|
+
"""
|
|
48
|
+
Handle /list command - display all topics organized by category.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Formatted string with all topics organized by category
|
|
52
|
+
"""
|
|
53
|
+
output = "📚 Available Topics:\n"
|
|
54
|
+
output += "=" * 50 + "\n\n"
|
|
55
|
+
|
|
56
|
+
categories = sorted(self.engine.categories.keys())
|
|
57
|
+
|
|
58
|
+
for category in categories:
|
|
59
|
+
topics = self.engine.get_topics_by_category(category)
|
|
60
|
+
output += f"📂 {category}\n"
|
|
61
|
+
for topic in topics:
|
|
62
|
+
output += f" • {topic}\n"
|
|
63
|
+
output += "\n"
|
|
64
|
+
|
|
65
|
+
output += f"Total topics: {len(self.engine.list_topics())}\n"
|
|
66
|
+
output += "Type a topic name to view it, or use /search <keyword> to find topics.\n"
|
|
67
|
+
|
|
68
|
+
return output
|
|
69
|
+
|
|
70
|
+
def handle_search(self, keyword: str) -> str:
|
|
71
|
+
"""
|
|
72
|
+
Handle /search command - search for topics by keyword.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
keyword: Keyword to search for
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
Formatted string with search results
|
|
79
|
+
"""
|
|
80
|
+
if not keyword or not keyword.strip():
|
|
81
|
+
return "❌ Please provide a search keyword.\nUsage: /search <keyword>"
|
|
82
|
+
|
|
83
|
+
results = self.engine.search_topics(keyword)
|
|
84
|
+
|
|
85
|
+
if not results:
|
|
86
|
+
# Try fuzzy matching for suggestions
|
|
87
|
+
all_topics = self.engine.list_topics()
|
|
88
|
+
suggestions = get_close_matches(keyword, all_topics, n=3, cutoff=0.6)
|
|
89
|
+
|
|
90
|
+
output = f"❌ No topics found for '{keyword}'.\n"
|
|
91
|
+
if suggestions:
|
|
92
|
+
output += "\nDid you mean:\n"
|
|
93
|
+
for suggestion in suggestions:
|
|
94
|
+
output += f" • {suggestion}\n"
|
|
95
|
+
return output
|
|
96
|
+
|
|
97
|
+
output = f"🔍 Search results for '{keyword}':\n"
|
|
98
|
+
output += "=" * 50 + "\n\n"
|
|
99
|
+
|
|
100
|
+
for topic in results:
|
|
101
|
+
output += f"• {topic}\n"
|
|
102
|
+
|
|
103
|
+
output += f"\nFound {len(results)} topic(s).\n"
|
|
104
|
+
output += "Type a topic name to view it.\n"
|
|
105
|
+
|
|
106
|
+
return output
|
|
107
|
+
|
|
108
|
+
def handle_random(self) -> str:
|
|
109
|
+
"""
|
|
110
|
+
Handle /random command - display a random topic.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
Formatted string with random topic name
|
|
114
|
+
"""
|
|
115
|
+
topic_dict = self.engine.get_random_topic()
|
|
116
|
+
topic_name = topic_dict.get("topic", "Unknown")
|
|
117
|
+
|
|
118
|
+
output = f"🎲 Random topic: {topic_name}\n"
|
|
119
|
+
output += f"Type '{topic_name}' to view it.\n"
|
|
120
|
+
|
|
121
|
+
return output
|
|
122
|
+
|
|
123
|
+
def handle_categories(self) -> str:
|
|
124
|
+
"""
|
|
125
|
+
Handle /categories command - display all available categories.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Formatted string with all categories
|
|
129
|
+
"""
|
|
130
|
+
output = "📂 Available Categories:\n"
|
|
131
|
+
output += "=" * 50 + "\n\n"
|
|
132
|
+
|
|
133
|
+
categories = sorted(self.engine.categories.keys())
|
|
134
|
+
|
|
135
|
+
for category in categories:
|
|
136
|
+
count = len(self.engine.get_topics_by_category(category))
|
|
137
|
+
output += f"• {category} ({count} topics)\n"
|
|
138
|
+
|
|
139
|
+
output += f"\nTotal categories: {len(categories)}\n"
|
|
140
|
+
output += "Use /category <name> to view topics in a category.\n"
|
|
141
|
+
|
|
142
|
+
return output
|
|
143
|
+
|
|
144
|
+
def handle_category(self, category_name: str) -> str:
|
|
145
|
+
"""
|
|
146
|
+
Handle /category command - display topics in a category.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
category_name: Name of the category
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
Formatted string with topics in the category
|
|
153
|
+
"""
|
|
154
|
+
if not category_name or not category_name.strip():
|
|
155
|
+
return "❌ Please provide a category name.\nUsage: /category <name>"
|
|
156
|
+
|
|
157
|
+
topics = self.engine.get_topics_by_category(category_name)
|
|
158
|
+
|
|
159
|
+
if not topics:
|
|
160
|
+
# Try fuzzy matching
|
|
161
|
+
all_categories = list(self.engine.categories.keys())
|
|
162
|
+
suggestions = get_close_matches(category_name, all_categories, n=3, cutoff=0.6)
|
|
163
|
+
|
|
164
|
+
output = f"❌ Category '{category_name}' not found.\n"
|
|
165
|
+
if suggestions:
|
|
166
|
+
output += "\nDid you mean:\n"
|
|
167
|
+
for suggestion in suggestions:
|
|
168
|
+
output += f" • {suggestion}\n"
|
|
169
|
+
return output
|
|
170
|
+
|
|
171
|
+
output = f"📂 Topics in '{category_name}':\n"
|
|
172
|
+
output += "=" * 50 + "\n\n"
|
|
173
|
+
|
|
174
|
+
for topic in topics:
|
|
175
|
+
output += f"• {topic}\n"
|
|
176
|
+
|
|
177
|
+
output += f"\nTotal topics: {len(topics)}\n"
|
|
178
|
+
output += "Type a topic name to view it.\n"
|
|
179
|
+
|
|
180
|
+
return output
|
|
181
|
+
|
|
182
|
+
def handle_path(self) -> str:
|
|
183
|
+
"""
|
|
184
|
+
Handle /path command - display the recommended learning path.
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
Formatted string with learning path
|
|
188
|
+
"""
|
|
189
|
+
path = self.engine.get_learning_path()
|
|
190
|
+
|
|
191
|
+
output = "🛤️ Recommended Learning Path:\n"
|
|
192
|
+
output += "=" * 50 + "\n\n"
|
|
193
|
+
|
|
194
|
+
for i, topic_name in enumerate(path, 1):
|
|
195
|
+
topic = self.engine.get_topic(topic_name)
|
|
196
|
+
difficulty = topic.get("difficulty", "Unknown")
|
|
197
|
+
output += f"{i}. {topic_name} ({difficulty})\n"
|
|
198
|
+
|
|
199
|
+
output += f"\nTotal topics: {len(path)}\n"
|
|
200
|
+
output += "Type a topic name to start learning.\n"
|
|
201
|
+
|
|
202
|
+
return output
|
|
203
|
+
|
|
204
|
+
def handle_related(self, topic_name: str) -> str:
|
|
205
|
+
"""
|
|
206
|
+
Handle /related command - display related topics.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
topic_name: Name of the current topic
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
Formatted string with related topics
|
|
213
|
+
"""
|
|
214
|
+
if not topic_name:
|
|
215
|
+
return "❌ No current topic. View a topic first.\n"
|
|
216
|
+
|
|
217
|
+
related = self.engine.get_related_topics(topic_name)
|
|
218
|
+
|
|
219
|
+
if not related:
|
|
220
|
+
return f"ℹ️ No related topics for '{topic_name}'.\n"
|
|
221
|
+
|
|
222
|
+
output = f"🔗 Topics related to '{topic_name}':\n"
|
|
223
|
+
output += "=" * 50 + "\n\n"
|
|
224
|
+
|
|
225
|
+
for topic in related:
|
|
226
|
+
output += f"• {topic}\n"
|
|
227
|
+
|
|
228
|
+
output += f"\nTotal related topics: {len(related)}\n"
|
|
229
|
+
output += "Type a topic name to view it.\n"
|
|
230
|
+
|
|
231
|
+
return output
|
|
232
|
+
|
|
233
|
+
def handle_progress(self) -> str:
|
|
234
|
+
"""
|
|
235
|
+
Handle /progress command - display learning progress.
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
Formatted string with progress statistics
|
|
239
|
+
"""
|
|
240
|
+
progress = self.session_manager.get_progress()
|
|
241
|
+
|
|
242
|
+
output = "📊 Learning Progress:\n"
|
|
243
|
+
output += "=" * 50 + "\n\n"
|
|
244
|
+
output += f"Topics viewed: {progress.viewed_topics}\n"
|
|
245
|
+
output += f"Examples executed: {progress.executed_examples}\n"
|
|
246
|
+
output += f"Session duration: {progress.session_duration:.1f} seconds\n"
|
|
247
|
+
|
|
248
|
+
if progress.last_viewed_topic:
|
|
249
|
+
output += f"Last viewed topic: {progress.last_viewed_topic}\n"
|
|
250
|
+
|
|
251
|
+
return output
|
|
252
|
+
|
|
253
|
+
def handle_stats(self) -> str:
|
|
254
|
+
"""
|
|
255
|
+
Handle /stats command - display detailed statistics.
|
|
256
|
+
|
|
257
|
+
Returns:
|
|
258
|
+
Formatted string with detailed statistics
|
|
259
|
+
"""
|
|
260
|
+
progress = self.session_manager.get_progress()
|
|
261
|
+
session_info = self.session_manager.get_session_info()
|
|
262
|
+
|
|
263
|
+
output = "📈 Detailed Statistics:\n"
|
|
264
|
+
output += "=" * 50 + "\n\n"
|
|
265
|
+
output += f"Topics viewed: {progress.viewed_topics}\n"
|
|
266
|
+
output += f"Examples executed: {progress.executed_examples}\n"
|
|
267
|
+
output += f"Session duration: {session_info['session_duration_seconds']:.1f} seconds\n"
|
|
268
|
+
output += f"Session history length: {session_info['session_history_length']}\n"
|
|
269
|
+
output += f"Created at: {session_info['created_at']}\n"
|
|
270
|
+
output += f"Last updated: {session_info['last_updated']}\n"
|
|
271
|
+
|
|
272
|
+
return output
|
|
273
|
+
|
|
274
|
+
def handle_hint(self, topic_name: str) -> str:
|
|
275
|
+
"""
|
|
276
|
+
Handle /hint command - display a hint for the current topic.
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
topic_name: Name of the current topic
|
|
280
|
+
|
|
281
|
+
Returns:
|
|
282
|
+
Formatted string with a hint
|
|
283
|
+
"""
|
|
284
|
+
if not topic_name:
|
|
285
|
+
return "❌ No current topic. View a topic first.\n"
|
|
286
|
+
|
|
287
|
+
topic = self.engine.get_topic(topic_name)
|
|
288
|
+
if not topic:
|
|
289
|
+
return f"❌ Topic '{topic_name}' not found.\n"
|
|
290
|
+
|
|
291
|
+
tips = topic.get("tips", [])
|
|
292
|
+
if not tips:
|
|
293
|
+
return f"ℹ️ No hints available for '{topic_name}'.\n"
|
|
294
|
+
|
|
295
|
+
hint = random.choice(tips)
|
|
296
|
+
|
|
297
|
+
output = f"💡 Hint for '{topic_name}':\n"
|
|
298
|
+
output += "=" * 50 + "\n\n"
|
|
299
|
+
output += f"{hint}\n"
|
|
300
|
+
|
|
301
|
+
return output
|
|
302
|
+
|
|
303
|
+
def handle_tip(self) -> str:
|
|
304
|
+
"""
|
|
305
|
+
Handle /tip command - display a learning tip.
|
|
306
|
+
|
|
307
|
+
Returns:
|
|
308
|
+
Formatted string with a learning tip
|
|
309
|
+
"""
|
|
310
|
+
tips = [
|
|
311
|
+
"💡 Try modifying the examples to see how they work!",
|
|
312
|
+
"💡 Use /search to find topics related to what you're learning.",
|
|
313
|
+
"💡 Check /progress to see how much you've learned.",
|
|
314
|
+
"💡 Use /related to explore connected concepts.",
|
|
315
|
+
"💡 Practice by running and modifying examples.",
|
|
316
|
+
"💡 Read the common mistakes section to avoid errors.",
|
|
317
|
+
"💡 Use /path to follow a structured learning path.",
|
|
318
|
+
]
|
|
319
|
+
|
|
320
|
+
tip = random.choice(tips)
|
|
321
|
+
return f"{tip}\n"
|
|
322
|
+
|
|
323
|
+
def handle_tips(self, topic_name: str) -> str:
|
|
324
|
+
"""
|
|
325
|
+
Handle /tips command - display all tips for a topic.
|
|
326
|
+
|
|
327
|
+
Args:
|
|
328
|
+
topic_name: Name of the current topic
|
|
329
|
+
|
|
330
|
+
Returns:
|
|
331
|
+
Formatted string with all tips
|
|
332
|
+
"""
|
|
333
|
+
if not topic_name:
|
|
334
|
+
return "❌ No current topic. View a topic first.\n"
|
|
335
|
+
|
|
336
|
+
topic = self.engine.get_topic(topic_name)
|
|
337
|
+
if not topic:
|
|
338
|
+
return f"❌ Topic '{topic_name}' not found.\n"
|
|
339
|
+
|
|
340
|
+
tips = topic.get("tips", [])
|
|
341
|
+
if not tips:
|
|
342
|
+
return f"ℹ️ No tips available for '{topic_name}'.\n"
|
|
343
|
+
|
|
344
|
+
output = f"💡 Tips for '{topic_name}':\n"
|
|
345
|
+
output += "=" * 50 + "\n\n"
|
|
346
|
+
|
|
347
|
+
for i, tip in enumerate(tips, 1):
|
|
348
|
+
output += f"{i}. {tip}\n"
|
|
349
|
+
|
|
350
|
+
return output
|
|
351
|
+
|
|
352
|
+
def handle_help(self, command: Optional[str] = None) -> str:
|
|
353
|
+
"""
|
|
354
|
+
Handle /help command - display help information.
|
|
355
|
+
|
|
356
|
+
Args:
|
|
357
|
+
command: Optional specific command to get help for
|
|
358
|
+
|
|
359
|
+
Returns:
|
|
360
|
+
Formatted string with help information
|
|
361
|
+
"""
|
|
362
|
+
if command:
|
|
363
|
+
return self._get_command_help(command)
|
|
364
|
+
|
|
365
|
+
output = "📖 Available Commands:\n"
|
|
366
|
+
output += "=" * 50 + "\n\n"
|
|
367
|
+
output += "Topic Browsing:\n"
|
|
368
|
+
output += " /list - Show all topics by category\n"
|
|
369
|
+
output += " /search <keyword> - Search for topics\n"
|
|
370
|
+
output += " /random - Show a random topic\n"
|
|
371
|
+
output += " /categories - Show all categories\n"
|
|
372
|
+
output += " /category <name> - Show topics in a category\n"
|
|
373
|
+
output += " /path - Show recommended learning path\n\n"
|
|
374
|
+
output += "Topic Navigation:\n"
|
|
375
|
+
output += " /related - Show related topics\n"
|
|
376
|
+
output += " /next - Go to next topic in path\n"
|
|
377
|
+
output += " /prev - Go to previous topic in path\n"
|
|
378
|
+
output += " /goto <topic> - Go to specific topic\n\n"
|
|
379
|
+
output += "Code Execution:\n"
|
|
380
|
+
output += " /run <num> - Run example number\n"
|
|
381
|
+
output += " /modify <num> - Modify and run example\n"
|
|
382
|
+
output += " /exit_edit - Exit edit mode\n\n"
|
|
383
|
+
output += "Progress Tracking:\n"
|
|
384
|
+
output += " /progress - Show learning progress\n"
|
|
385
|
+
output += " /stats - Show detailed statistics\n"
|
|
386
|
+
output += " /reset_progress - Reset all progress\n\n"
|
|
387
|
+
output += "Session Management:\n"
|
|
388
|
+
output += " /history - Show session history\n"
|
|
389
|
+
output += " /clear_history - Clear session history\n"
|
|
390
|
+
output += " /session - Show session info\n\n"
|
|
391
|
+
output += "Help and Information:\n"
|
|
392
|
+
output += " /help - Show this help message\n"
|
|
393
|
+
output += " /help <command> - Get help for a command\n"
|
|
394
|
+
output += " /commands - Show all commands\n"
|
|
395
|
+
output += " /about - About the REPL\n"
|
|
396
|
+
output += " /hint - Get a hint for current topic\n"
|
|
397
|
+
output += " /tip - Get a learning tip\n"
|
|
398
|
+
output += " /tips - Show all tips for current topic\n\n"
|
|
399
|
+
output += "Session Control:\n"
|
|
400
|
+
output += " /exit, /quit - Exit the REPL\n\n"
|
|
401
|
+
output += "Type /help <command> for more details on a specific command.\n"
|
|
402
|
+
|
|
403
|
+
return output
|
|
404
|
+
|
|
405
|
+
def _get_command_help(self, command: str) -> str:
|
|
406
|
+
"""
|
|
407
|
+
Get detailed help for a specific command.
|
|
408
|
+
|
|
409
|
+
Args:
|
|
410
|
+
command: Command name
|
|
411
|
+
|
|
412
|
+
Returns:
|
|
413
|
+
Formatted help text for the command
|
|
414
|
+
"""
|
|
415
|
+
help_text = {
|
|
416
|
+
"list": "Show all available topics organized by category.\nUsage: /list",
|
|
417
|
+
"search": "Search for topics by keyword.\nUsage: /search <keyword>\nExample: /search list",
|
|
418
|
+
"random": "Display a random topic to encourage exploration.\nUsage: /random",
|
|
419
|
+
"categories": "Show all available topic categories.\nUsage: /categories",
|
|
420
|
+
"category": "Show all topics in a specific category.\nUsage: /category <name>\nExample: /category \"Basic Types\"",
|
|
421
|
+
"path": "Show the recommended learning path from beginner to advanced.\nUsage: /path",
|
|
422
|
+
"related": "Show topics related to the current topic.\nUsage: /related",
|
|
423
|
+
"progress": "Show your learning progress.\nUsage: /progress",
|
|
424
|
+
"stats": "Show detailed learning statistics.\nUsage: /stats",
|
|
425
|
+
"hint": "Get a hint for the current topic.\nUsage: /hint",
|
|
426
|
+
"tip": "Get a random learning tip.\nUsage: /tip",
|
|
427
|
+
"tips": "Show all tips for the current topic.\nUsage: /tips",
|
|
428
|
+
"help": "Show help information.\nUsage: /help or /help <command>",
|
|
429
|
+
"run": "Run a code example.\nUsage: /run <example_number>\nExample: /run 1",
|
|
430
|
+
"modify": "Modify and run a code example.\nUsage: /modify <example_number>\nExample: /modify 1",
|
|
431
|
+
"exit_edit": "Exit edit mode.\nUsage: /exit_edit",
|
|
432
|
+
"history": "Show your session history.\nUsage: /history",
|
|
433
|
+
"clear_history": "Clear your session history.\nUsage: /clear_history",
|
|
434
|
+
"session": "Show current session information.\nUsage: /session",
|
|
435
|
+
"reset_progress": "Reset all learning progress.\nUsage: /reset_progress",
|
|
436
|
+
"commands": "Show all available commands.\nUsage: /commands",
|
|
437
|
+
"about": "Show information about the REPL.\nUsage: /about",
|
|
438
|
+
"exit": "Exit the REPL.\nUsage: /exit or /quit",
|
|
439
|
+
"quit": "Exit the REPL.\nUsage: /quit or /exit",
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
command_lower = command.lower()
|
|
443
|
+
if command_lower in help_text:
|
|
444
|
+
return f"📖 Help for '{command}':\n" + "=" * 50 + "\n\n" + help_text[command_lower] + "\n"
|
|
445
|
+
else:
|
|
446
|
+
return f"❌ No help available for '{command}'.\nType /help to see all commands.\n"
|
|
447
|
+
|
|
448
|
+
def handle_commands(self) -> str:
|
|
449
|
+
"""
|
|
450
|
+
Handle /commands command - show all commands categorized.
|
|
451
|
+
|
|
452
|
+
Returns:
|
|
453
|
+
Formatted string with all commands
|
|
454
|
+
"""
|
|
455
|
+
output = "📋 All Commands:\n"
|
|
456
|
+
output += "=" * 50 + "\n\n"
|
|
457
|
+
output += "Topic Browsing: /list, /search, /random, /categories, /category, /path\n"
|
|
458
|
+
output += "Navigation: /related, /next, /prev, /goto\n"
|
|
459
|
+
output += "Code: /run, /modify, /exit_edit\n"
|
|
460
|
+
output += "Progress: /progress, /stats, /reset_progress\n"
|
|
461
|
+
output += "Session: /history, /clear_history, /session\n"
|
|
462
|
+
output += "Help: /help, /commands, /about, /hint, /tip, /tips\n"
|
|
463
|
+
output += "Control: /exit, /quit\n\n"
|
|
464
|
+
output += "Type /help <command> for details on a specific command.\n"
|
|
465
|
+
|
|
466
|
+
return output
|
|
467
|
+
|
|
468
|
+
def handle_about(self) -> str:
|
|
469
|
+
"""
|
|
470
|
+
Handle /about command - show information about the REPL.
|
|
471
|
+
|
|
472
|
+
Returns:
|
|
473
|
+
Formatted string with about information
|
|
474
|
+
"""
|
|
475
|
+
output = "ℹ️ About Knowledge Engine REPL:\n"
|
|
476
|
+
output += "=" * 50 + "\n\n"
|
|
477
|
+
output += "The Knowledge Engine REPL is an interactive learning tool for Python.\n"
|
|
478
|
+
output += "It provides:\n"
|
|
479
|
+
output += " • Interactive topic browsing and discovery\n"
|
|
480
|
+
output += " • Safe code execution in a sandbox environment\n"
|
|
481
|
+
output += " • Learning progress tracking\n"
|
|
482
|
+
output += " • Contextual hints and guidance\n"
|
|
483
|
+
output += " • Session persistence for resuming learning\n\n"
|
|
484
|
+
output += "Type /help to get started.\n"
|
|
485
|
+
|
|
486
|
+
return output
|
|
487
|
+
|
|
488
|
+
def format_topic_display(self, topic_name: str) -> str:
|
|
489
|
+
"""
|
|
490
|
+
Format a topic for display.
|
|
491
|
+
|
|
492
|
+
Args:
|
|
493
|
+
topic_name: Name of the topic to display
|
|
494
|
+
|
|
495
|
+
Returns:
|
|
496
|
+
Formatted string with topic information
|
|
497
|
+
"""
|
|
498
|
+
topic = self.engine.get_topic(topic_name)
|
|
499
|
+
if not topic:
|
|
500
|
+
return f"❌ Topic '{topic_name}' not found.\n"
|
|
501
|
+
|
|
502
|
+
output = f"\n📚 {topic_name}\n"
|
|
503
|
+
output += "=" * 50 + "\n\n"
|
|
504
|
+
|
|
505
|
+
# Category and difficulty
|
|
506
|
+
category = topic.get("category", "Unknown")
|
|
507
|
+
difficulty = topic.get("difficulty", "Unknown")
|
|
508
|
+
output += f"Category: {category} | Difficulty: {difficulty}\n\n"
|
|
509
|
+
|
|
510
|
+
# Description
|
|
511
|
+
description = topic.get("description", "")
|
|
512
|
+
if description:
|
|
513
|
+
output += f"Description:\n{description}\n\n"
|
|
514
|
+
|
|
515
|
+
# Examples
|
|
516
|
+
examples = topic.get("examples", [])
|
|
517
|
+
if examples:
|
|
518
|
+
output += "Examples:\n"
|
|
519
|
+
for i, example in enumerate(examples, 1):
|
|
520
|
+
output += f"\n Example {i}: {example.get('description', '')}\n"
|
|
521
|
+
output += f" ```python\n"
|
|
522
|
+
code_lines = example.get('code', '').split('\n')
|
|
523
|
+
for line in code_lines:
|
|
524
|
+
output += f" {line}\n"
|
|
525
|
+
output += f" ```\n"
|
|
526
|
+
|
|
527
|
+
# Common mistakes
|
|
528
|
+
mistakes = topic.get("common_mistakes", [])
|
|
529
|
+
if mistakes:
|
|
530
|
+
output += "\nCommon Mistakes:\n"
|
|
531
|
+
for mistake in mistakes:
|
|
532
|
+
output += f" ⚠️ {mistake}\n"
|
|
533
|
+
|
|
534
|
+
# Related topics
|
|
535
|
+
related = self.engine.get_related_topics(topic_name)
|
|
536
|
+
if related:
|
|
537
|
+
output += "\nRelated Topics:\n"
|
|
538
|
+
for related_topic in related:
|
|
539
|
+
output += f" • {related_topic}\n"
|
|
540
|
+
|
|
541
|
+
output += "\n" + "=" * 50 + "\n"
|
|
542
|
+
output += "Commands: /run <num>, /modify <num>, /related, /next, /prev, /goto <topic>\n"
|
|
543
|
+
|
|
544
|
+
return output
|