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 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
- f.write("")
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
- with open(TWD_FILE, "w") as f:
66
- f.write(path)
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
- output_handler(f"Saved TWD to {path}", path, output, simple_output)
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
- return f.read().strip()
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
- TWD = load_directory()
110
+ dirs = load_directory()
78
111
 
79
- if TWD is None:
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
- TWD = load_directory()
127
+ dirs = load_directory()
92
128
 
93
- if TWD is None or TWD == '':
129
+ if not dirs:
94
130
  output_handler("No TWD set", None, output, simple_output)
95
- else:
96
- output_handler(f"Current TWD: {TWD}", TWD, output, simple_output)
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
- If you want to execute unsetting the current TWD, please use "--force" and run again.
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
- parser.add_argument('-s', '--save', nargs='?', const='', help="Save the current or specified directory")
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
- if args.save is not None:
158
- save_directory(args.save if args.save else None, output, simple_output)
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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: twd_m4sc0
3
- Version: 1.4.1
3
+ Version: 1.5.1
4
4
  Summary: A tool to temporarily save and go to a working directory
5
5
  Home-page: https://github.com/m4sc0/twd
6
6
  Author: m4sc0
@@ -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,,
@@ -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,,