ftagger 0.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.
- __init__.py +0 -0
- ansi_codes.py +9 -0
- commands.py +273 -0
- ftagger-0.1.0.dist-info/METADATA +116 -0
- ftagger-0.1.0.dist-info/RECORD +12 -0
- ftagger-0.1.0.dist-info/WHEEL +5 -0
- ftagger-0.1.0.dist-info/entry_points.txt +2 -0
- ftagger-0.1.0.dist-info/licenses/LICENSE.txt +9 -0
- ftagger-0.1.0.dist-info/top_level.txt +6 -0
- globals.py +7 -0
- main.py +95 -0
- utils.py +13 -0
__init__.py
ADDED
|
File without changes
|
ansi_codes.py
ADDED
commands.py
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
import globals
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from utils import *
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def help() -> None:
|
|
11
|
+
info(
|
|
12
|
+
"| Name | Description | Usage |",
|
|
13
|
+
"|---------------------------------------------------------------------------------------------|",
|
|
14
|
+
"| at | adds a tag to file or folder | at <path> <tag> |",
|
|
15
|
+
"| rt | removes a tag from file or folder | rt <path> <tag> |",
|
|
16
|
+
"| gi | gets items by tag | gi <path> <tag> |",
|
|
17
|
+
"| gt | gets tags of a file or folder | gt <path> |",
|
|
18
|
+
"| li | lists files and folders and their tags | li <path> |",
|
|
19
|
+
"| rc | tags all items in a directory | rc <path> <tag> <depth> |",
|
|
20
|
+
"| rr | removes a tag from all items in a directory | rr <path> <tag> <depth> |",
|
|
21
|
+
"| ca | creates an alias for a command | ca <command> <alias> |",
|
|
22
|
+
"| ra | removes an alias | ra <alias> |",
|
|
23
|
+
"| la | lists all existing aliases | la |",
|
|
24
|
+
"| rd | resets all alias data | rd |",
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def add_tag(path: str, tag: str) -> None:
|
|
29
|
+
tag: bytes = tag.encode('utf-8')
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
current_tag: bytes = os.getxattr(path=path, attribute=b"user.tags")
|
|
34
|
+
except:
|
|
35
|
+
current_tag = "".encode('utf-8')
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
if current_tag != b'':
|
|
39
|
+
combined_tag: bytes = current_tag + ",".encode('utf-8') + tag
|
|
40
|
+
else:
|
|
41
|
+
combined_tag: bytes = tag
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
os.setxattr(path=path, attribute=b"user.tags", value=combined_tag)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def remove_tag(path: str, tag: str) -> None:
|
|
48
|
+
tag: bytes = tag.encode('utf-8')
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
values: list[str] = os.getxattr(path=path, attribute=b"user.tags").decode('utf-8').split(",")
|
|
52
|
+
values.remove(tag.decode('utf-8'))
|
|
53
|
+
values = ",".join(values).encode('utf-8')
|
|
54
|
+
|
|
55
|
+
os.setxattr(path=path, attribute=b"user.tags", value=values)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def get_items_by_tag(path: str, value: str) -> None:
|
|
59
|
+
for item in Path(path).rglob("*"):
|
|
60
|
+
try:
|
|
61
|
+
tags = os.getxattr(path=item, attribute=b"user.tags").decode('utf-8').split(",")
|
|
62
|
+
|
|
63
|
+
except:
|
|
64
|
+
tags = []
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
if value in tags:
|
|
68
|
+
if os.path.isdir(item):
|
|
69
|
+
print(f"{ac.blue}{item}{ac.clear}")
|
|
70
|
+
|
|
71
|
+
else:
|
|
72
|
+
print(item)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def get_tags(path: str) -> None:
|
|
76
|
+
try:
|
|
77
|
+
tags = os.getxattr(path=path, attribute=b"user.tags").decode('utf-8')
|
|
78
|
+
|
|
79
|
+
tags = tags.split(",")
|
|
80
|
+
|
|
81
|
+
except:
|
|
82
|
+
tags = ["~"]
|
|
83
|
+
|
|
84
|
+
for i in tags:
|
|
85
|
+
if tags == []:
|
|
86
|
+
print("~")
|
|
87
|
+
else:
|
|
88
|
+
print(i)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def list_items_and_tags(path: str) -> None:
|
|
92
|
+
for item in Path(path).rglob("*"):
|
|
93
|
+
try:
|
|
94
|
+
tags = os.getxattr(path=item, attribute=b"user.tags").decode('utf-8')
|
|
95
|
+
except:
|
|
96
|
+
tags = ""
|
|
97
|
+
|
|
98
|
+
if os.path.isdir(item):
|
|
99
|
+
print(f"{ac.blue}{ac.bold}{str(item): <30}{ac.clear}{tags: >15}")
|
|
100
|
+
else:
|
|
101
|
+
print(f"{str(item): <30}{tags: >15}")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def recursive_add_tag(path: str, tag: str, depth: int) -> None:
|
|
105
|
+
depth = int(depth)
|
|
106
|
+
|
|
107
|
+
for item in Path(path).rglob("*"):
|
|
108
|
+
if len(str(item).split("/")) <= depth:
|
|
109
|
+
add_tag(item, tag=tag)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def recursive_remove_tag(path: str, tag: str, depth: int) -> None:
|
|
113
|
+
depth = int(depth)
|
|
114
|
+
|
|
115
|
+
for item in Path(path).rglob("*"):
|
|
116
|
+
if len(str(item).split("/")) <= depth:
|
|
117
|
+
try:
|
|
118
|
+
remove_tag(item, tag)
|
|
119
|
+
except:
|
|
120
|
+
print(f"Item {item} doesn't have tag {tag}")
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def create_alias(command: str, alias: str) -> None:
|
|
124
|
+
with open(globals.FMDEFAULT, "r") as file:
|
|
125
|
+
try:
|
|
126
|
+
commands_dict: dict = json.load(file)
|
|
127
|
+
except:
|
|
128
|
+
commands_dict: dict = {}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
with open(globals.FMALIASLOOKUP, "r") as fm_alias_lookup_file, open(globals.FMALIASES, "r") as fm_alias_file:
|
|
132
|
+
try:
|
|
133
|
+
lookup_dict: dict = json.load(fm_alias_lookup_file)
|
|
134
|
+
except:
|
|
135
|
+
lookup_dict: dict = {}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
try:
|
|
139
|
+
alias_dict: dict = json.load(fm_alias_file)
|
|
140
|
+
except:
|
|
141
|
+
alias_dict: dict = {}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
lookup_dict.update({ alias: command })
|
|
145
|
+
alias_dict.update({ alias: commands_dict[command] })
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
with open(globals.FMALIASLOOKUP, "w") as fm_alias_lookup_file, open(globals.FMALIASES, "w") as fm_alias_file:
|
|
149
|
+
json.dump(lookup_dict, fm_alias_lookup_file, indent=4)
|
|
150
|
+
json.dump(alias_dict, fm_alias_file, indent=4)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
with open(globals.FMUNDOLOOKUP, "r") as file:
|
|
154
|
+
undo_dict = json.load(file)
|
|
155
|
+
|
|
156
|
+
undo_dict.update({ alias: undo_dict[command] })
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
with open(globals.FMUNDOLOOKUP, "w") as file:
|
|
160
|
+
json.dump(undo_dict, file, indent=4)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def remove_alias(alias: str) -> None:
|
|
164
|
+
with open(globals.FMALIASLOOKUP, "r") as fm_alias_lookup_file, open(globals.FMALIASES, "r") as fm_aliases_file:
|
|
165
|
+
try:
|
|
166
|
+
alias_dict: dict = json.load(fm_aliases_file)
|
|
167
|
+
lookup_dict: dict = json.load(fm_alias_lookup_file)
|
|
168
|
+
except:
|
|
169
|
+
alias_dict: dict = {}
|
|
170
|
+
lookup_dict: dict = {}
|
|
171
|
+
error("Please use the 'rd' command and re-add your aliases")
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
try:
|
|
175
|
+
lookup_dict.pop(alias)
|
|
176
|
+
alias_dict.pop(alias)
|
|
177
|
+
except:
|
|
178
|
+
error("Alias does not exist")
|
|
179
|
+
return
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
with open(globals.FMALIASLOOKUP, "w") as fm_alias_lookup_file, open(globals.FMALIASES, "w") as fm_aliases_file:
|
|
183
|
+
try:
|
|
184
|
+
json.dump(lookup_dict, fm_alias_lookup_file, indent=4)
|
|
185
|
+
json.dump(alias_dict, fm_aliases_file, indent=4)
|
|
186
|
+
except:
|
|
187
|
+
json.dump({}, fm_alias_lookup_file, indent=4)
|
|
188
|
+
json.dump({}, fm_aliases_file, indent=4)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
with open(globals.FMUNDOLOOKUP, "r") as file:
|
|
192
|
+
undo_dict = json.load(file)
|
|
193
|
+
|
|
194
|
+
undo_dict.pop(alias)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
with open(globals.FMUNDOLOOKUP, "w") as file:
|
|
198
|
+
json.dump(undo_dict, file, indent=4)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def list_aliases() -> None:
|
|
202
|
+
with open(globals.FMALIASLOOKUP, "r") as file:
|
|
203
|
+
aliases: dict = json.load(file)
|
|
204
|
+
|
|
205
|
+
for key, value in aliases.items():
|
|
206
|
+
print(f"{key}: {value}")
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def reset_data() -> None:
|
|
210
|
+
with open(globals.FMALIASLOOKUP, "w") as file:
|
|
211
|
+
json.dump({}, file, indent=4)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
with open(globals.FMALIASES, "w") as file:
|
|
215
|
+
json.dump({}, file, indent=4)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
with open(globals.FMDEFAULT, "w") as file:
|
|
219
|
+
default_data: dict = {
|
|
220
|
+
"--help": "help",
|
|
221
|
+
"at": "add_tag",
|
|
222
|
+
"rt": "remove_tag",
|
|
223
|
+
"gi": "get_items_by_tag",
|
|
224
|
+
"gt": "get_tags",
|
|
225
|
+
"li": "list_items_and_tags",
|
|
226
|
+
"rc": "recursive_add_tag",
|
|
227
|
+
"rr": "recursive_remove_tag",
|
|
228
|
+
"ca": "create_alias",
|
|
229
|
+
"ra": "remove_alias",
|
|
230
|
+
"la": "list_aliases",
|
|
231
|
+
"rd": "reset_data",
|
|
232
|
+
"un": "undo"
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
json.dump(default_data, file, indent=4)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
with open(globals.FMUNDOLOOKUP) as file:
|
|
239
|
+
default_data: dict = {
|
|
240
|
+
"at": "rt",
|
|
241
|
+
"rt": "at",
|
|
242
|
+
"rc": "rr",
|
|
243
|
+
"rr": "rc",
|
|
244
|
+
"ca": "ra",
|
|
245
|
+
"ra": "ca",
|
|
246
|
+
"tag": "rt"
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
with open(globals.FMPREVIOUSCOMMAND, "w") as file:
|
|
251
|
+
default_data: dict = {
|
|
252
|
+
"0": [
|
|
253
|
+
"/home/charlie/.local/bin/fm",
|
|
254
|
+
"la"
|
|
255
|
+
],
|
|
256
|
+
"1": [
|
|
257
|
+
"/home/charlie/.local/bin/fm",
|
|
258
|
+
"undo"
|
|
259
|
+
],
|
|
260
|
+
"2": [
|
|
261
|
+
"/home/charlie/.local/bin/fm",
|
|
262
|
+
"efdsfs"
|
|
263
|
+
],
|
|
264
|
+
"3": [
|
|
265
|
+
"/home/charlie/.local/bin/fm",
|
|
266
|
+
"efdsfs"
|
|
267
|
+
],
|
|
268
|
+
"4": [
|
|
269
|
+
"/home/charlie/Projects/fm/.venv/bin/fm",
|
|
270
|
+
"rd"
|
|
271
|
+
]
|
|
272
|
+
}
|
|
273
|
+
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ftagger
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Simple command-line file tagger
|
|
5
|
+
Author-email: Charlie O'Dwyer <charlieodwyer2289@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE.txt
|
|
12
|
+
Dynamic: license-file
|
|
13
|
+
|
|
14
|
+
# Preface
|
|
15
|
+
|
|
16
|
+
Most of this project was created before I began using GitHub, which is why the first commit is alreadyalmost finished..
|
|
17
|
+
|
|
18
|
+
I have yet to implement proper error handling, as well as a few commands.
|
|
19
|
+
|
|
20
|
+
This is just a personal project that I will use for college. The goal is not for it to be perfect, but for it to work.
|
|
21
|
+
|
|
22
|
+
Any criticism is welcome — especially about my code. It is also worth noting that this is the first documentation I've written, so I apologise if it's not up to your expected standard. Please also tell me how I can improve the docs. Thank you.
|
|
23
|
+
|
|
24
|
+
This programme has only been tested on Linux. Due to its use of the 'os' module and extended attributes, it may not work on all operating systems.
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# What Is This Project?
|
|
28
|
+
|
|
29
|
+
This project is a very simple command-line file tagger. Its main function is to tag files and folders to make organisiation easier. I wrote this programme, as I am going to start college soon, and I wanted a simple way to organise my notes. It is just a personal project. Below is an outline of the features:
|
|
30
|
+
|
|
31
|
+
- Tagging files and folders. The 'os' module is used to tag items using extended attributes. Command: at
|
|
32
|
+
|
|
33
|
+
- Removing tags from files and folders. Command: rt
|
|
34
|
+
|
|
35
|
+
- Searching for items in a directory with a given tag. Command: gi
|
|
36
|
+
|
|
37
|
+
- Getting the tags of an item. Command: gt
|
|
38
|
+
|
|
39
|
+
- Listing all items in a given directory, along with their tags. Command: li
|
|
40
|
+
|
|
41
|
+
- Creating and removing aliases for commands. Commands: ca, ra
|
|
42
|
+
|
|
43
|
+
- Listing all aliases. Command: la
|
|
44
|
+
|
|
45
|
+
- Recursively adding tags to or removing tags from items to a certain depth. Commands: rc, rr
|
|
46
|
+
|
|
47
|
+
- Resetting all dotfiles in ~/.fmdata (aliases, lookup tables, etc). Command: rd
|
|
48
|
+
|
|
49
|
+
- Undo. Undo the previous undoable command, up to five commands ago.
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# Help
|
|
53
|
+
|
|
54
|
+
Here is the output of running the command with the --help flag:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
| Name | Description | Usage |
|
|
58
|
+
|---------------------------------------------------------------------------------------------|
|
|
59
|
+
| at | adds a tag to a file or folder | at <path> <tag> |
|
|
60
|
+
| rt | removes a tag from file or folder | rt <path> <tag> |
|
|
61
|
+
| gi | searches items by tag | gi <path> <tag> |
|
|
62
|
+
| gt | displays tags of a file or folder | gt <path> |
|
|
63
|
+
| li | lists files and folders and their tags | li <path> |
|
|
64
|
+
| rc | tags all items in a directory | rc <path> <tag> <depth> |
|
|
65
|
+
| rr | removes a tag from all items in a directory | rr <path> <tag> <depth> |
|
|
66
|
+
| ca | creates an alias for a command | ca <command> <alias> |
|
|
67
|
+
| ra | removes an alias | ra <alias> |
|
|
68
|
+
| la | lists all existing aliases | la |
|
|
69
|
+
| rd | resets all alias data | rd |
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# Installation and Uninstallation
|
|
74
|
+
### To install
|
|
75
|
+
```
|
|
76
|
+
pip install ftagger
|
|
77
|
+
|
|
78
|
+
OR
|
|
79
|
+
|
|
80
|
+
pipx install ftagger
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### To uninstall
|
|
84
|
+
```
|
|
85
|
+
pip uninstall ftagger
|
|
86
|
+
|
|
87
|
+
OR
|
|
88
|
+
|
|
89
|
+
pipx uninstall ftagger
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
# Usage
|
|
94
|
+
After installation, you should be able to run the programme from a terminal. Here is an example of what that may look like:
|
|
95
|
+
```
|
|
96
|
+
fm at file1.txt tag
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Here is a breakdown of that example command:
|
|
100
|
+
fm — the command used to invoke this programme. It is like cd, ls, cat, etc
|
|
101
|
+
at — the 'add tag' command
|
|
102
|
+
file1.txt — the target. This can be a file or a folder
|
|
103
|
+
tag — the tag to add to the target
|
|
104
|
+
|
|
105
|
+
To get help about the usage of the commands, run the following command:
|
|
106
|
+
```
|
|
107
|
+
fm --help
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
This will print out the table seen under the 'Help' heading.
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# Requierments
|
|
114
|
+
Python 3.10 and above
|
|
115
|
+
|
|
116
|
+
The project has only been tested on Linux
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
ansi_codes.py,sha256=dBGMLdyjepkcBPSdmCw_TjT-4m_YuzwSDryN0GOe5_E,169
|
|
3
|
+
commands.py,sha256=NtHOJALHSwG_80CyHXcZNAJfuZmhJa_RE2uVU88y_Ko,8224
|
|
4
|
+
globals.py,sha256=QaKYnWGtLEdiEK3u0bdqkPGN7DytgUFaRvsSPS02KM0,295
|
|
5
|
+
main.py,sha256=wnF4oycYfWQPFGOcsE-t-UE_cwFreQhr1f27WK0bKb0,2455
|
|
6
|
+
utils.py,sha256=10Vf_Eydh9zyPUaHX6OdsH8KnO6xxETwss-PW8-3mE4,240
|
|
7
|
+
ftagger-0.1.0.dist-info/licenses/LICENSE.txt,sha256=H4Cfdy1mdP1us0n8OA3DGmwDrSGG-PoThIksgkTpgsc,1079
|
|
8
|
+
ftagger-0.1.0.dist-info/METADATA,sha256=ocLF2PaAITnNnk5u0hLVPTDFXN8qPwdECol8UeO0CIc,4313
|
|
9
|
+
ftagger-0.1.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
10
|
+
ftagger-0.1.0.dist-info/entry_points.txt,sha256=cYxon2VJIR8jxPUQkZ7z1_ntCHmxgUJ2spSuJNGoXbs,33
|
|
11
|
+
ftagger-0.1.0.dist-info/top_level.txt,sha256=AwOSfLiYP-tbNt70pEfhTDWoBi99idIF-fkc3kjw20w,48
|
|
12
|
+
ftagger-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT license
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Charlie O'Dwyer
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
globals.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
FMDEFAULT = f"{Path.home()}/.fmdata/.fmdefault"
|
|
4
|
+
FMALIASES = f"{Path.home()}/.fmdata/.fmaliases"
|
|
5
|
+
FMALIASLOOKUP = f"{Path.home()}/.fmdata/.fmaliaslookup"
|
|
6
|
+
FMUNDOLOOKUP = f"{Path.home()}/.fmdata/.fmundolookup"
|
|
7
|
+
FMPREVIOUSCOMMAND = f"{Path.home()}/.fmdata/.fmpreviouscommand"
|
main.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import commands
|
|
2
|
+
import json
|
|
3
|
+
import globals
|
|
4
|
+
|
|
5
|
+
from sys import argv, modules
|
|
6
|
+
from utils import *
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def call(args: list[str]) -> None:
|
|
10
|
+
with open(globals.FMDEFAULT, "r") as file:
|
|
11
|
+
commands_dict: dict = json.load(file)
|
|
12
|
+
|
|
13
|
+
with open(globals.FMALIASES, "r") as f:
|
|
14
|
+
alias_dict: dict = json.load(f)
|
|
15
|
+
|
|
16
|
+
try:
|
|
17
|
+
commands_dict.update(alias_dict)
|
|
18
|
+
except:
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
for key, value in commands_dict.items():
|
|
23
|
+
try:
|
|
24
|
+
commands_dict[key] = getattr(commands, value)
|
|
25
|
+
except:
|
|
26
|
+
try:
|
|
27
|
+
commands_dict[key] = getattr(modules[__name__], value)
|
|
28
|
+
except:
|
|
29
|
+
debug(commands_dict)
|
|
30
|
+
error(f"There may be an invalid alias. Please check the aliases you've added: {key}: {value}")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
try:
|
|
34
|
+
match len(args):
|
|
35
|
+
case 2:
|
|
36
|
+
commands_dict[args[1]]()
|
|
37
|
+
|
|
38
|
+
case 3:
|
|
39
|
+
commands_dict[args[1]](args[2])
|
|
40
|
+
|
|
41
|
+
case 4:
|
|
42
|
+
commands_dict[args[1]](args[2], args[3])
|
|
43
|
+
|
|
44
|
+
case 5:
|
|
45
|
+
commands_dict[args[1]](args[2], args[3], args[4])
|
|
46
|
+
|
|
47
|
+
except Exception:
|
|
48
|
+
debug("Error handling is not yet fully implemented, as I have decided to change how to impement it. For debugging purposes, the exception will now be raised.")
|
|
49
|
+
raise Exception
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def undo() -> None:
|
|
54
|
+
with open(globals.FMPREVIOUSCOMMAND, "r") as file:
|
|
55
|
+
previous_commands: list[str] = json.load(file)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
with open(globals.FMUNDOLOOKUP, "r") as f:
|
|
59
|
+
undo_dict: dict = json.load(f)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
for command in list(previous_commands.values())[::-1]:
|
|
63
|
+
debug(command)
|
|
64
|
+
try:
|
|
65
|
+
command[1] = undo_dict[command[1]]
|
|
66
|
+
call(command)
|
|
67
|
+
except:
|
|
68
|
+
pass
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def main() -> None:
|
|
72
|
+
command: list[str] = argv
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
with open(globals.FMPREVIOUSCOMMAND, "r") as file:
|
|
76
|
+
previous_commands: dict = json.load(file)
|
|
77
|
+
|
|
78
|
+
previous_commands.update({
|
|
79
|
+
"0": previous_commands["1"],
|
|
80
|
+
"1": previous_commands["2"],
|
|
81
|
+
"2": previous_commands["3"],
|
|
82
|
+
"3": previous_commands["4"],
|
|
83
|
+
"4": command,
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
with open(globals.FMPREVIOUSCOMMAND, "w") as file:
|
|
88
|
+
json.dump(previous_commands, file, indent=4)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
call(command)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
if __name__ == "__main__":
|
|
95
|
+
main()
|
utils.py
ADDED