twd-m4sc0 1.4.1__py3-none-any.whl → 1.5.1__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.
- twd/twd.py +84 -19
- {twd_m4sc0-1.4.1.dist-info → twd_m4sc0-1.5.1.dist-info}/METADATA +1 -1
- twd_m4sc0-1.5.1.dist-info/RECORD +11 -0
- twd_m4sc0-1.4.1.dist-info/RECORD +0 -11
- {twd_m4sc0-1.4.1.dist-info → twd_m4sc0-1.5.1.dist-info}/LICENSE +0 -0
- {twd_m4sc0-1.4.1.dist-info → twd_m4sc0-1.5.1.dist-info}/WHEEL +0 -0
- {twd_m4sc0-1.4.1.dist-info → twd_m4sc0-1.5.1.dist-info}/entry_points.txt +0 -0
- {twd_m4sc0-1.4.1.dist-info → twd_m4sc0-1.5.1.dist-info}/top_level.txt +0 -0
twd/twd.py
CHANGED
|
@@ -2,6 +2,9 @@ import os
|
|
|
2
2
|
import argparse
|
|
3
3
|
import sys
|
|
4
4
|
import json
|
|
5
|
+
import hashlib
|
|
6
|
+
import time
|
|
7
|
+
import re
|
|
5
8
|
from importlib.metadata import version, PackageNotFoundError
|
|
6
9
|
|
|
7
10
|
TWD_DIR = os.path.join(os.path.expanduser("~"), ".twd")
|
|
@@ -14,6 +17,10 @@ DEFAULT_CONFIG = {
|
|
|
14
17
|
|
|
15
18
|
os.makedirs(TWD_DIR, exist_ok=True)
|
|
16
19
|
|
|
20
|
+
def create_alias_id():
|
|
21
|
+
data = str(time.time()) + str(os.urandom(16))
|
|
22
|
+
return hashlib.sha256(data.encode()).hexdigest()[:12]
|
|
23
|
+
|
|
17
24
|
def load_config():
|
|
18
25
|
if not os.path.exists(CONFIG_FILE):
|
|
19
26
|
with open(CONFIG_FILE, 'w') as file:
|
|
@@ -34,13 +41,19 @@ TWD_FILE = os.path.expanduser(CONFIG.get("data_file", "~/.twd/data"))
|
|
|
34
41
|
def ensure_data_file_exists():
|
|
35
42
|
if not os.path.exists(TWD_FILE):
|
|
36
43
|
with open(TWD_FILE, 'w') as f:
|
|
37
|
-
|
|
44
|
+
json.dump({}, f)
|
|
38
45
|
|
|
39
46
|
ensure_data_file_exists()
|
|
40
47
|
|
|
41
48
|
def get_absolute_path(path):
|
|
42
49
|
return os.path.abspath(path)
|
|
43
50
|
|
|
51
|
+
def validate_alias(alias):
|
|
52
|
+
"""Ensure the alias contains only valid characters."""
|
|
53
|
+
if not re.match(r'^[\w-]+$', alias):
|
|
54
|
+
raise ValueError(f"Invalid alias: '{alias}'. Aliases can only contain alphanumeric characters, dashes, and underscores.")
|
|
55
|
+
return alias
|
|
56
|
+
|
|
44
57
|
def output_handler(message=None, path=None, output=True, simple_output=False, message_type=0):
|
|
45
58
|
if not output or CONFIG["output_behaviour"] == 0:
|
|
46
59
|
return
|
|
@@ -56,30 +69,53 @@ def output_handler(message=None, path=None, output=True, simple_output=False, me
|
|
|
56
69
|
elif not simple_output and message:
|
|
57
70
|
print(f"0;{message}")
|
|
58
71
|
|
|
59
|
-
def save_directory(path=None, output=True, simple_output=False):
|
|
72
|
+
def save_directory(path=None, alias=None, output=True, simple_output=False):
|
|
60
73
|
if path is None:
|
|
61
74
|
path = os.getcwd()
|
|
62
75
|
else:
|
|
63
76
|
path = get_absolute_path(path)
|
|
64
77
|
|
|
65
|
-
|
|
66
|
-
|
|
78
|
+
if alias:
|
|
79
|
+
alias = validate_alias(alias)
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
with open(TWD_FILE, 'r') as f:
|
|
83
|
+
data = json.load(f)
|
|
84
|
+
except json.JSONDecodeError:
|
|
85
|
+
data = {}
|
|
86
|
+
|
|
87
|
+
alias_id = create_alias_id()
|
|
88
|
+
data[alias_id] = {
|
|
89
|
+
"path": path,
|
|
90
|
+
"alias": alias if alias else alias_id,
|
|
91
|
+
"created_at": time.time()
|
|
92
|
+
}
|
|
67
93
|
|
|
68
|
-
|
|
94
|
+
with open(TWD_FILE, 'w') as f:
|
|
95
|
+
json.dump(data, f, indent=4)
|
|
96
|
+
|
|
97
|
+
output_handler(f"Saved TWD to {path} with alias '{alias or alias_id}'", path, output, simple_output)
|
|
69
98
|
|
|
70
99
|
def load_directory():
|
|
71
100
|
if not os.path.exists(TWD_FILE):
|
|
72
101
|
return None
|
|
102
|
+
|
|
73
103
|
with open(TWD_FILE, "r") as f:
|
|
74
|
-
|
|
104
|
+
try:
|
|
105
|
+
return json.load(f)
|
|
106
|
+
except json.JSONDecodeError:
|
|
107
|
+
return None
|
|
75
108
|
|
|
76
109
|
def go_to_directory(output=True, simple_output=False):
|
|
77
|
-
|
|
110
|
+
dirs = load_directory()
|
|
78
111
|
|
|
79
|
-
if
|
|
112
|
+
if not dirs:
|
|
80
113
|
output_handler("No TWD found", None, output, simple_output)
|
|
81
114
|
return 1
|
|
82
115
|
else:
|
|
116
|
+
last_alias, last_entry = list(dirs.items())[-1]
|
|
117
|
+
TWD = last_entry['path']
|
|
118
|
+
|
|
83
119
|
if os.path.exists(TWD):
|
|
84
120
|
output_handler(f"cd {TWD}", TWD, output, simple_output, message_type=1)
|
|
85
121
|
return 0
|
|
@@ -88,21 +124,35 @@ def go_to_directory(output=True, simple_output=False):
|
|
|
88
124
|
return 1
|
|
89
125
|
|
|
90
126
|
def show_directory(output=True, simple_output=False):
|
|
91
|
-
|
|
127
|
+
dirs = load_directory()
|
|
92
128
|
|
|
93
|
-
if
|
|
129
|
+
if not dirs:
|
|
94
130
|
output_handler("No TWD set", None, output, simple_output)
|
|
95
|
-
|
|
96
|
-
|
|
131
|
+
return
|
|
132
|
+
|
|
133
|
+
max_alias_len = max(len(entry['alias']) for entry in dirs.values()) if dirs else 0
|
|
134
|
+
max_id_len = max(len(alias_id) for alias_id in dirs.keys()) if dirs else 0
|
|
135
|
+
max_path_len = max(len(entry['path']) for entry in dirs.values()) if dirs else 0
|
|
136
|
+
|
|
137
|
+
header = f"{'Alias'.ljust(max_alias_len)} {'ID'.ljust(max_id_len)} {'Path'.ljust(max_path_len)} Created At"
|
|
138
|
+
print(header)
|
|
139
|
+
print("-" * len(header))
|
|
140
|
+
|
|
141
|
+
for alias_id, entry in dirs.items():
|
|
142
|
+
alias = entry['alias'].ljust(max_alias_len)
|
|
143
|
+
path = entry['path'].ljust(max_path_len)
|
|
144
|
+
created_at = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(entry['created_at']))
|
|
145
|
+
alias_id_str = alias_id.ljust(max_id_len)
|
|
146
|
+
output_handler(f"{alias} {alias_id_str} {path} {created_at}", None, output, simple_output)
|
|
147
|
+
|
|
97
148
|
|
|
98
149
|
def unset_directory(output=True, simple_output=False, force=False):
|
|
99
150
|
if not os.path.exists(TWD_FILE):
|
|
100
151
|
output_handler(f"No TWD file found", None, output, simple_output)
|
|
101
152
|
else:
|
|
102
153
|
if not force:
|
|
103
|
-
output_handler(r'''
|
|
104
|
-
|
|
105
|
-
|
|
154
|
+
output_handler(r'''If you want to execute deleting and therefore unsetting all set TWD's, please use "--force" or "-f" and run again.
|
|
155
|
+
|
|
106
156
|
|
|
107
157
|
This feature is to prevent accidental execution.''', None, True, False)
|
|
108
158
|
return
|
|
@@ -120,15 +170,22 @@ def main():
|
|
|
120
170
|
|
|
121
171
|
parser = argparse.ArgumentParser(description="Temporarily save and navigate to working directories.")
|
|
122
172
|
|
|
123
|
-
|
|
173
|
+
# Positional arguments
|
|
174
|
+
parser.add_argument('directory', nargs='?', help="Directory to save")
|
|
175
|
+
parser.add_argument('alias', nargs='?', help="Alias for the saved directory (optional)")
|
|
176
|
+
|
|
177
|
+
# Optional Arguments/Flags
|
|
178
|
+
parser.add_argument('-s', '--save', action='store_true', help="Save the current or specified directory")
|
|
179
|
+
parser.add_argument('-d', '--directory', help="Directory to save")
|
|
180
|
+
parser.add_argument('-a', '--alias', help="Alias for the saved directory")
|
|
124
181
|
parser.add_argument('-g', '--go', action='store_true', help="Go to the saved directory")
|
|
125
182
|
parser.add_argument('-l', '--list', action='store_true', help="Show saved TWD")
|
|
126
183
|
parser.add_argument('-u', '--unset', action='store_true', help="Unset the saved TWD")
|
|
127
184
|
parser.add_argument('-v', '--version', action='version', version=f'TWD Version: {get_package_version()}', help='Show the current version of TWD installed')
|
|
185
|
+
parser.add_argument('-f', '--force', action='store_true', help="Force an action")
|
|
128
186
|
parser.add_argument('--shell', action='store_true', help="Output shell function for integration")
|
|
129
187
|
parser.add_argument('--simple-output', action='store_true', help="Only print essential output (new directory, absolute path, etc.)")
|
|
130
188
|
parser.add_argument('--no-output', action='store_true', help="Prevents the console from sending output")
|
|
131
|
-
parser.add_argument('-f', '--force', action='store_true', help="Force an action")
|
|
132
189
|
args = parser.parse_args()
|
|
133
190
|
|
|
134
191
|
output = not args.no_output
|
|
@@ -154,8 +211,16 @@ def main():
|
|
|
154
211
|
''')
|
|
155
212
|
return 0
|
|
156
213
|
|
|
157
|
-
|
|
158
|
-
|
|
214
|
+
directory = args.directory or args.directory
|
|
215
|
+
alias = args.alias or args.alias
|
|
216
|
+
|
|
217
|
+
if args.save:
|
|
218
|
+
if not directory:
|
|
219
|
+
directory = args.directory or os.getcwd()
|
|
220
|
+
|
|
221
|
+
alias = args.alias or args.alias
|
|
222
|
+
|
|
223
|
+
save_directory(directory, alias, output, simple_output)
|
|
159
224
|
elif args.go:
|
|
160
225
|
return go_to_directory(output, simple_output)
|
|
161
226
|
elif args.list:
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
tests/test_twd.py,sha256=XrxOo99oqida_7qZ48pA6BCazZekDmG5syw9NvjZWDU,484
|
|
3
|
+
twd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
twd/__main__.py,sha256=gM_Py51pQFH3CXdDIuPzBW6eNlFH1UHeRAmgAPWQyik,61
|
|
5
|
+
twd/twd.py,sha256=N-wBGkLgFQ5f5Prml56-MdpBBR9y1OekZZTeZxNz-go,7986
|
|
6
|
+
twd_m4sc0-1.5.1.dist-info/LICENSE,sha256=eQSDjcD_fvOwfjmrzxKJhtZsSI39seMawuvsgeD_dfw,1062
|
|
7
|
+
twd_m4sc0-1.5.1.dist-info/METADATA,sha256=FJkYLm_PtFlwmqbIo5a2n9LiKnvjN3kAbUNS5nlxX6I,2341
|
|
8
|
+
twd_m4sc0-1.5.1.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
9
|
+
twd_m4sc0-1.5.1.dist-info/entry_points.txt,sha256=QfYDHHjipkVN4oalpACFmIeYHb7GQCJY4SC12bTsiQQ,37
|
|
10
|
+
twd_m4sc0-1.5.1.dist-info/top_level.txt,sha256=PXToru2Yr2Xh3F_F-pHXtuOQVp5x7KKCPFf94P_VI5U,10
|
|
11
|
+
twd_m4sc0-1.5.1.dist-info/RECORD,,
|
twd_m4sc0-1.4.1.dist-info/RECORD
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
tests/test_twd.py,sha256=XrxOo99oqida_7qZ48pA6BCazZekDmG5syw9NvjZWDU,484
|
|
3
|
-
twd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
twd/__main__.py,sha256=gM_Py51pQFH3CXdDIuPzBW6eNlFH1UHeRAmgAPWQyik,61
|
|
5
|
-
twd/twd.py,sha256=giOvr8bdsKXpzLUJpKRAOrb1b4Hmk5iRtB5VbPp1zhE,5626
|
|
6
|
-
twd_m4sc0-1.4.1.dist-info/LICENSE,sha256=eQSDjcD_fvOwfjmrzxKJhtZsSI39seMawuvsgeD_dfw,1062
|
|
7
|
-
twd_m4sc0-1.4.1.dist-info/METADATA,sha256=I_ws3VlH60rr8NFZ8zU--i8yclxKVpvG643RdlvaaZY,2341
|
|
8
|
-
twd_m4sc0-1.4.1.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
9
|
-
twd_m4sc0-1.4.1.dist-info/entry_points.txt,sha256=QfYDHHjipkVN4oalpACFmIeYHb7GQCJY4SC12bTsiQQ,37
|
|
10
|
-
twd_m4sc0-1.4.1.dist-info/top_level.txt,sha256=PXToru2Yr2Xh3F_F-pHXtuOQVp5x7KKCPFf94P_VI5U,10
|
|
11
|
-
twd_m4sc0-1.4.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|