forked from UTSAVS26/PyVerse
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfile_navigation.py
More file actions
193 lines (179 loc) · 7.22 KB
/
Copy pathfile_navigation.py
File metadata and controls
193 lines (179 loc) · 7.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
from pathlib import Path
import os
import json
import pyautogui
import sys
import subprocess
import shutil
class FileNavigator:
def __init__(self):
self.current_dir = Path.home()
self.commands = [
"open", "show", "go to", "navigate to",
"list", "up", "down", "rename",
"delete", "create",
"close"
]
self.system_folders = {
"downloads": str(Path.home() / "Downloads"),
"documents": str(Path.home() / "Documents"),
"desktop": str(Path.home() / "Desktop"),
"pictures": str(Path.home() / "Pictures"),
"music": str(Path.home() / "Music"),
"videos": str(Path.home() / "Videos"),
}
def _get_command_handlers(self):
"""Return a mapping of command keywords to their handler functions."""
return {
'list': lambda text: self.list_dir(),
'up': lambda text: self.navigate_up(),
'down': self.navigate_down,
'open': self.open,
'show': self.open,
'go to': self.open,
'navigate to': self.open,
'rename': lambda text: self.rename(text),
'delete': lambda text: self.delete(text),
'create': lambda text: self.create(text),
'close': self.close
}
def parse_command(self, text):
try:
text_dict = json.loads(text)
recognized_text = text_dict['text'].lower().strip()
print(f"Recognized: {recognized_text}")
handlers = self._get_command_handlers()
for keyword, handler in handlers.items():
if self._matches_command(recognized_text, [keyword]):
handler(recognized_text)
return
print("Unrecognized command.")
except json.JSONDecodeError:
print("Error: Invalid JSON format in recognized text")
except Exception as e:
print(f"Error: {e}")
def _matches_command(self, text, keywords):
return any(keyword in text for keyword in keywords)
def _open_cross_platform(self, path):
try:
if sys.platform == "win32":
os.startfile(path)
elif sys.platform == "darwin":
subprocess.run(["open", str(path)])
else:
subprocess.run(["xdg-open", str(path)])
except Exception as e:
print(f"Failed to open {path}: {e}")
# User-facing commands
def list_dir(self, path=None):
path = Path(path) if path else self.current_dir
if path.exists() and path.is_dir():
print(f"Contents of {path}:")
for p in path.iterdir():
print(p.name)
else:
print(f"Directory not found: {path}")
def open(self, text):
# Check for system folders
for folder, path in self.system_folders.items():
if folder in text:
self._open_cross_platform(path)
print(f"Opened: {path}")
if Path(path).is_dir():
self.current_dir = Path(path)
return
# Try to open file/folder in current directory
parts = text.split()
for i, word in enumerate(parts):
if word in ["open", "show", "go", "navigate"] and i+1 < len(parts):
target_path = self.current_dir / parts[i+1]
self._open_cross_platform(target_path)
print(f"Opened: {target_path}")
if target_path.is_dir():
self.current_dir = target_path
return
print("No valid path specified to open.")
def close(self, text):
pyautogui.hotkey('alt', 'f4')
print("Closed current window.")
self.current_dir = Path.home()
def navigate_up(self):
self.current_dir = self.current_dir.parent
self._open_cross_platform(self.current_dir)
def navigate_down(self, arg):
# If called from dispatcher, arg is text; if called directly, arg is folder name
if isinstance(arg, str) and (" " in arg or "down" in arg):
# Called from dispatcher with text
parts = arg.split()
if len(parts) > 1:
folder_name = parts[parts.index('down') + 1] if 'down' in parts else parts[-1]
self.navigate_down(folder_name)
else:
print("No folder specified for navigation.")
else:
# Called directly with folder name
folder = arg
new_dir = self.current_dir / folder
if new_dir.exists() and new_dir.is_dir():
self.current_dir = new_dir
print(f"Moved down to: {self.current_dir}")
self._open_cross_platform(self.current_dir)
else:
print(f"Folder not found: {folder}")
def rename(self, text):
parts = text.split()
if "rename" in parts and len(parts) >= 3:
idx = parts.index("rename")
if idx + 2 < len(parts):
old_name = parts[idx+1]
new_name = parts[idx+2]
old_path = self.current_dir / old_name
new_path = self.current_dir / new_name
if old_path.exists():
old_path.rename(new_path)
print(f"Renamed {old_name} to {new_name}")
else:
print(f"File/Folder not found: {old_name}")
return
print("Invalid rename command format. Use: rename <old> <new>")
def delete(self, text):
parts = text.split()
if "delete" in parts and len(parts) > 1:
idx = parts.index("delete")
if idx + 1 < len(parts):
name = parts[idx+1]
path = self.current_dir / name
if path.exists():
if path.is_dir():
confirm = input(f"Delete directory '{name}' and all its contents? [y/N]: ")
if confirm.lower() == 'y':
shutil.rmtree(path)
print(f"Deleted: {name}")
else:
print("Deletion cancelled.")
else:
path.unlink()
print(f"Deleted: {name}")
else:
print(f"File/Folder not found: {name}")
return
print("No file or folder specified to delete.")
def create(self, text):
parts = text.split()
if "create" in parts and len(parts) > 1:
idx = parts.index("create")
if idx + 1 < len(parts):
name = parts[idx+1]
is_dir = "folder" in text or "directory" in text
path = self.current_dir / name
if not path.exists():
if is_dir:
path.mkdir()
print(f"Directory created: {name}")
else:
path.touch()
print(f"File created: {name}")
else:
print(f"File/Folder already exists: {name}")
return
print("No file or folder specified to create.")