twd-m4sc0 1.5.1__tar.gz → 1.5.3__tar.gz
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_m4sc0-1.5.3/PKG-INFO +153 -0
- twd_m4sc0-1.5.3/README.md +140 -0
- {twd_m4sc0-1.5.1 → twd_m4sc0-1.5.3}/setup.py +2 -2
- twd_m4sc0-1.5.3/twd/logger.py +47 -0
- twd_m4sc0-1.5.3/twd/twd.py +348 -0
- twd_m4sc0-1.5.3/twd_m4sc0.egg-info/PKG-INFO +153 -0
- {twd_m4sc0-1.5.1 → twd_m4sc0-1.5.3}/twd_m4sc0.egg-info/SOURCES.txt +1 -0
- twd_m4sc0-1.5.1/PKG-INFO +0 -141
- twd_m4sc0-1.5.1/README.md +0 -128
- twd_m4sc0-1.5.1/twd/twd.py +0 -236
- twd_m4sc0-1.5.1/twd_m4sc0.egg-info/PKG-INFO +0 -141
- {twd_m4sc0-1.5.1 → twd_m4sc0-1.5.3}/LICENSE +0 -0
- {twd_m4sc0-1.5.1 → twd_m4sc0-1.5.3}/setup.cfg +0 -0
- {twd_m4sc0-1.5.1 → twd_m4sc0-1.5.3}/tests/__init__.py +0 -0
- {twd_m4sc0-1.5.1 → twd_m4sc0-1.5.3}/tests/test_twd.py +0 -0
- {twd_m4sc0-1.5.1 → twd_m4sc0-1.5.3}/twd/__init__.py +0 -0
- {twd_m4sc0-1.5.1 → twd_m4sc0-1.5.3}/twd/__main__.py +0 -0
- {twd_m4sc0-1.5.1 → twd_m4sc0-1.5.3}/twd_m4sc0.egg-info/dependency_links.txt +0 -0
- {twd_m4sc0-1.5.1 → twd_m4sc0-1.5.3}/twd_m4sc0.egg-info/entry_points.txt +0 -0
- {twd_m4sc0-1.5.1 → twd_m4sc0-1.5.3}/twd_m4sc0.egg-info/top_level.txt +0 -0
twd_m4sc0-1.5.3/PKG-INFO
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: twd_m4sc0
|
|
3
|
+
Version: 1.5.3
|
|
4
|
+
Summary: A tool to temporarily save and go to a working directory
|
|
5
|
+
Home-page: https://github.com/m4sc0/twd
|
|
6
|
+
Author: m4sc0
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.6
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# twd-m4sc0
|
|
16
|
+
|
|
17
|
+
`twd-m4sc0` is a command-line tool that allows you to temporarily save a working directory and easily navigate back to it. It's designed for developers and users who frequently need to switch between directories in the terminal.
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- Save the current or specified working directory.
|
|
22
|
+
- Go back to a saved directory using an optional alias.
|
|
23
|
+
- List all saved directories with metadata.
|
|
24
|
+
- Unset and delete saved directories.
|
|
25
|
+
- Integrates with your shell for seamless directory management.
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
### Installation using `pip`:
|
|
30
|
+
|
|
31
|
+
1. Install the package from the `pypi` repository:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install twd-m4sc0
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
2. Add the following line to your `.bashrc` or `.zshrc` to set up the shell function:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
eval $(python3 -m twd --shell)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
3. Exit and reopen the terminal or reload using:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
source ~/.bashrc
|
|
47
|
+
# or
|
|
48
|
+
source ~/.zshrc
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
### Save a directory
|
|
54
|
+
|
|
55
|
+
- Save the current directory or a specified directory:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
twd -s [path] [alias]
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
If no path is specified, the current directory is saved. The alias is optional, and if not provided, an auto-generated ID will be used.
|
|
62
|
+
|
|
63
|
+
### Go to a saved directory
|
|
64
|
+
|
|
65
|
+
- Navigate to a saved directory using an optional alias:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
twd -g [alias]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
If no alias is provided, the most recently saved directory will be used. If an alias is provided, it will navigate to the directory associated with that alias.
|
|
72
|
+
|
|
73
|
+
### List saved directories
|
|
74
|
+
|
|
75
|
+
- Display a list of all saved directories:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
twd -l
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Unset the TWD and delete the data file
|
|
82
|
+
|
|
83
|
+
- Unset and delete the saved directories:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
twd -u
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
You can force this action using the `--force` flag to avoid accidental execution.
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
twd -u --force
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Optional Parameters
|
|
96
|
+
|
|
97
|
+
#### Simple Output
|
|
98
|
+
|
|
99
|
+
For cleaner, minimal output intended for scripting or piping.
|
|
100
|
+
|
|
101
|
+
- Example with `--simple-output`:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
twd -s --simple-output
|
|
105
|
+
/home/user/.config
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
- Example without `--simple-output`:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
Saved TWD to /home/user/.config
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
#### No Output
|
|
115
|
+
|
|
116
|
+
Suppresses all output (including confirmation messages).
|
|
117
|
+
|
|
118
|
+
- Example with `--no-output`:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
twd -s --no-output
|
|
122
|
+
# No output
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
#### Force
|
|
126
|
+
|
|
127
|
+
Use the `--force` flag to force certain actions, such as when unsetting directories with the `-u` flag.
|
|
128
|
+
|
|
129
|
+
- Example:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
twd -u --force
|
|
133
|
+
TWD File deleted and TWD unset
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Contribution
|
|
137
|
+
|
|
138
|
+
To set up a development environment:
|
|
139
|
+
|
|
140
|
+
1. Clone the repository:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
git clone https://github.com/m4sc0/twd
|
|
144
|
+
cd twd
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
2. Install the package in editable mode using `pip`:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
pip install -e .
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
3. Make your changes, and contribute!
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
|
|
2
|
+
# twd-m4sc0
|
|
3
|
+
|
|
4
|
+
`twd-m4sc0` is a command-line tool that allows you to temporarily save a working directory and easily navigate back to it. It's designed for developers and users who frequently need to switch between directories in the terminal.
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
- Save the current or specified working directory.
|
|
9
|
+
- Go back to a saved directory using an optional alias.
|
|
10
|
+
- List all saved directories with metadata.
|
|
11
|
+
- Unset and delete saved directories.
|
|
12
|
+
- Integrates with your shell for seamless directory management.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
### Installation using `pip`:
|
|
17
|
+
|
|
18
|
+
1. Install the package from the `pypi` repository:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install twd-m4sc0
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
2. Add the following line to your `.bashrc` or `.zshrc` to set up the shell function:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
eval $(python3 -m twd --shell)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
3. Exit and reopen the terminal or reload using:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
source ~/.bashrc
|
|
34
|
+
# or
|
|
35
|
+
source ~/.zshrc
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
### Save a directory
|
|
41
|
+
|
|
42
|
+
- Save the current directory or a specified directory:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
twd -s [path] [alias]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If no path is specified, the current directory is saved. The alias is optional, and if not provided, an auto-generated ID will be used.
|
|
49
|
+
|
|
50
|
+
### Go to a saved directory
|
|
51
|
+
|
|
52
|
+
- Navigate to a saved directory using an optional alias:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
twd -g [alias]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
If no alias is provided, the most recently saved directory will be used. If an alias is provided, it will navigate to the directory associated with that alias.
|
|
59
|
+
|
|
60
|
+
### List saved directories
|
|
61
|
+
|
|
62
|
+
- Display a list of all saved directories:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
twd -l
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Unset the TWD and delete the data file
|
|
69
|
+
|
|
70
|
+
- Unset and delete the saved directories:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
twd -u
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
You can force this action using the `--force` flag to avoid accidental execution.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
twd -u --force
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Optional Parameters
|
|
83
|
+
|
|
84
|
+
#### Simple Output
|
|
85
|
+
|
|
86
|
+
For cleaner, minimal output intended for scripting or piping.
|
|
87
|
+
|
|
88
|
+
- Example with `--simple-output`:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
twd -s --simple-output
|
|
92
|
+
/home/user/.config
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
- Example without `--simple-output`:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
Saved TWD to /home/user/.config
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### No Output
|
|
102
|
+
|
|
103
|
+
Suppresses all output (including confirmation messages).
|
|
104
|
+
|
|
105
|
+
- Example with `--no-output`:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
twd -s --no-output
|
|
109
|
+
# No output
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
#### Force
|
|
113
|
+
|
|
114
|
+
Use the `--force` flag to force certain actions, such as when unsetting directories with the `-u` flag.
|
|
115
|
+
|
|
116
|
+
- Example:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
twd -u --force
|
|
120
|
+
TWD File deleted and TWD unset
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Contribution
|
|
124
|
+
|
|
125
|
+
To set up a development environment:
|
|
126
|
+
|
|
127
|
+
1. Clone the repository:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
git clone https://github.com/m4sc0/twd
|
|
131
|
+
cd twd
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
2. Install the package in editable mode using `pip`:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
pip install -e .
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
3. Make your changes, and contribute!
|
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name="twd_m4sc0",
|
|
5
|
-
version="1.5.
|
|
5
|
+
version="1.5.3",
|
|
6
6
|
packages=find_packages(),
|
|
7
7
|
entry_points={
|
|
8
8
|
"console_scripts": [
|
|
@@ -18,7 +18,7 @@ setup(
|
|
|
18
18
|
"License :: OSI Approved :: MIT License",
|
|
19
19
|
"Operating System :: OS Independent",
|
|
20
20
|
],
|
|
21
|
-
python_requires=
|
|
21
|
+
python_requires=">=3.6",
|
|
22
22
|
long_description=open("README.md").read(),
|
|
23
23
|
long_description_content_type="text/markdown",
|
|
24
24
|
)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def format_message(message, config):
|
|
6
|
+
"""Format the log message according to the provided config."""
|
|
7
|
+
result = config.get("log_format", "[$T]: $M")
|
|
8
|
+
result = result.replace("$T", time.strftime("%Y-%m-%d %H:%M:%S"))
|
|
9
|
+
result = result.replace("$M", message)
|
|
10
|
+
return result
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def ensure_directory_exists(file_path):
|
|
14
|
+
"""Ensure the directory for the given file path exists."""
|
|
15
|
+
directory = os.path.dirname(file_path)
|
|
16
|
+
if not os.path.exists(directory):
|
|
17
|
+
os.makedirs(directory, exist_ok=True)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def write_log(message, config):
|
|
21
|
+
"""Write log message to the log file specified in the config."""
|
|
22
|
+
log_file = os.path.expanduser(config.get("log_file"))
|
|
23
|
+
log_file = os.path.abspath(log_file)
|
|
24
|
+
ensure_directory_exists(log_file) # Ensure the directory exists
|
|
25
|
+
with open(log_file, "a+") as f:
|
|
26
|
+
f.write(message + "\n")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def write_error(message, config):
|
|
30
|
+
"""Write error message to the error file specified in the config."""
|
|
31
|
+
error_file = os.path.expanduser(config.get("error_file"))
|
|
32
|
+
error_file = os.path.abspath(error_file)
|
|
33
|
+
ensure_directory_exists(error_file) # Ensure the directory exists
|
|
34
|
+
with open(error_file, "a+") as f:
|
|
35
|
+
f.write(message + "\n")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def log(message, config):
|
|
39
|
+
"""Log the message using the provided config."""
|
|
40
|
+
formatted_message = format_message(message, config)
|
|
41
|
+
write_log(formatted_message, config)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def error(message, config):
|
|
45
|
+
"""Log the error using the provided config."""
|
|
46
|
+
formatted_message = format_message(message, config)
|
|
47
|
+
write_error(formatted_message, config)
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import argparse
|
|
3
|
+
import json
|
|
4
|
+
import hashlib
|
|
5
|
+
import time
|
|
6
|
+
import re
|
|
7
|
+
from importlib.metadata import version, PackageNotFoundError
|
|
8
|
+
from .logger import log, error
|
|
9
|
+
|
|
10
|
+
TWD_DIR = os.path.join(os.path.expanduser("~"), ".twd")
|
|
11
|
+
CONFIG_FILE = os.path.join(TWD_DIR, "config")
|
|
12
|
+
|
|
13
|
+
DEFAULT_CONFIG = {
|
|
14
|
+
"data_file": os.path.expanduser("~/.twd/data"),
|
|
15
|
+
"output_behaviour": 2,
|
|
16
|
+
"log_file": os.path.expanduser("~/.twd/log"),
|
|
17
|
+
"error_file": os.path.expanduser("~/.twd/error"),
|
|
18
|
+
"log_format": "[$T]: $M",
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
# os.makedirs(TWD_DIR, exist_ok=True)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def create_alias_id():
|
|
25
|
+
data = str(time.time()) + str(os.urandom(16))
|
|
26
|
+
return hashlib.sha256(data.encode()).hexdigest()[:12]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def load_config():
|
|
30
|
+
if not os.path.exists(CONFIG_FILE):
|
|
31
|
+
with open(CONFIG_FILE, "w") as file:
|
|
32
|
+
json.dump(DEFAULT_CONFIG, file, indent=4)
|
|
33
|
+
return DEFAULT_CONFIG
|
|
34
|
+
else:
|
|
35
|
+
with open(CONFIG_FILE, "r") as file:
|
|
36
|
+
try:
|
|
37
|
+
return json.load(file)
|
|
38
|
+
except json.JSONDecodeError as e:
|
|
39
|
+
error(f"Error loading config: {e}", DEFAULT_CONFIG)
|
|
40
|
+
return DEFAULT_CONFIG
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
CONFIG = load_config()
|
|
44
|
+
|
|
45
|
+
TWD_FILE = os.path.expanduser(CONFIG.get("data_file", "~/.twd/data"))
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def ensure_data_file_exists():
|
|
49
|
+
if not os.path.exists(TWD_FILE):
|
|
50
|
+
try:
|
|
51
|
+
with open(TWD_FILE, "w") as f:
|
|
52
|
+
json.dump({}, f)
|
|
53
|
+
except OSError as e:
|
|
54
|
+
error(f"Error creating data file: {e}", CONFIG)
|
|
55
|
+
|
|
56
|
+
log_file = os.path.expanduser(CONFIG.get("log_file"))
|
|
57
|
+
error_file = os.path.expanduser(CONFIG.get("error_file"))
|
|
58
|
+
|
|
59
|
+
if not os.path.exists(log_file):
|
|
60
|
+
try:
|
|
61
|
+
with open(log_file, "w+") as f:
|
|
62
|
+
f.write("")
|
|
63
|
+
except OSError as e:
|
|
64
|
+
error(f"Error creating log file: {e}", CONFIG)
|
|
65
|
+
|
|
66
|
+
if not os.path.exists(error_file):
|
|
67
|
+
try:
|
|
68
|
+
with open(error_file, "w+") as f:
|
|
69
|
+
f.write("")
|
|
70
|
+
except OSError as e:
|
|
71
|
+
error(f"Error creating error file: {e}", CONFIG)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
ensure_data_file_exists()
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def get_absolute_path(path):
|
|
78
|
+
try:
|
|
79
|
+
return os.path.abspath(path)
|
|
80
|
+
except Exception as e:
|
|
81
|
+
error(f"Error getting absolute path for {path}: {e}", CONFIG)
|
|
82
|
+
raise
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def validate_alias(alias):
|
|
86
|
+
"""Ensure the alias contains only valid characters."""
|
|
87
|
+
if not re.match(r"^[\w-]+$", alias):
|
|
88
|
+
error(f"Invalid alias provided: {alias}", CONFIG)
|
|
89
|
+
raise ValueError(
|
|
90
|
+
f"Invalid alias: '{alias}'. Aliases can only contain alphanumeric characters, dashes, and underscores."
|
|
91
|
+
)
|
|
92
|
+
return alias
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def output_handler(
|
|
96
|
+
message=None, path=None, output=True, simple_output=False, message_type=0
|
|
97
|
+
):
|
|
98
|
+
log(f"Type: {message_type}, Msg: {message or path}", CONFIG)
|
|
99
|
+
|
|
100
|
+
if not output or CONFIG["output_behaviour"] == 0:
|
|
101
|
+
return
|
|
102
|
+
|
|
103
|
+
if not message and not path:
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
if message_type == 1:
|
|
107
|
+
print(f"1;{message}")
|
|
108
|
+
elif message_type == 0:
|
|
109
|
+
if simple_output and path:
|
|
110
|
+
print(f"0;{path}")
|
|
111
|
+
elif not simple_output and message:
|
|
112
|
+
print(f"0;{message}")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def save_directory(path=None, alias=None, output=True, simple_output=False):
|
|
116
|
+
if path is None:
|
|
117
|
+
path = os.getcwd()
|
|
118
|
+
else:
|
|
119
|
+
path = get_absolute_path(path)
|
|
120
|
+
|
|
121
|
+
if alias:
|
|
122
|
+
alias = validate_alias(alias)
|
|
123
|
+
|
|
124
|
+
try:
|
|
125
|
+
with open(TWD_FILE, "r") as f:
|
|
126
|
+
data = json.load(f)
|
|
127
|
+
except json.JSONDecodeError as e:
|
|
128
|
+
error(f"Error reading TWD file: {e}", CONFIG)
|
|
129
|
+
data = {}
|
|
130
|
+
|
|
131
|
+
alias_id = create_alias_id()
|
|
132
|
+
data[alias_id] = {
|
|
133
|
+
"path": path,
|
|
134
|
+
"alias": alias if alias else alias_id,
|
|
135
|
+
"created_at": time.time(),
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
try:
|
|
139
|
+
with open(TWD_FILE, "w") as f:
|
|
140
|
+
json.dump(data, f, indent=4)
|
|
141
|
+
except OSError as e:
|
|
142
|
+
error(f"Error writing to TWD file: {e}", CONFIG)
|
|
143
|
+
raise
|
|
144
|
+
|
|
145
|
+
output_handler(
|
|
146
|
+
f"Saved TWD to {path} with alias '{alias or alias_id}'",
|
|
147
|
+
path,
|
|
148
|
+
output,
|
|
149
|
+
simple_output,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def load_directory():
|
|
154
|
+
if not os.path.exists(TWD_FILE):
|
|
155
|
+
return None
|
|
156
|
+
|
|
157
|
+
try:
|
|
158
|
+
with open(TWD_FILE, "r") as f:
|
|
159
|
+
return json.load(f)
|
|
160
|
+
except json.JSONDecodeError as e:
|
|
161
|
+
error(f"Error loading TWD file: {e}", CONFIG)
|
|
162
|
+
return None
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def go_to_directory(alias=None, output=True, simple_output=False):
|
|
166
|
+
dirs = load_directory()
|
|
167
|
+
|
|
168
|
+
if not dirs:
|
|
169
|
+
output_handler("No TWD found", None, output, simple_output)
|
|
170
|
+
return 1
|
|
171
|
+
else:
|
|
172
|
+
for entry_id, entry in dirs.items():
|
|
173
|
+
if "alias" in entry and entry["alias"] and entry["alias"] == alias:
|
|
174
|
+
TWD = entry["path"]
|
|
175
|
+
|
|
176
|
+
if os.path.exists(TWD):
|
|
177
|
+
output_handler(
|
|
178
|
+
f"cd {TWD}", TWD, output, simple_output, message_type=1
|
|
179
|
+
)
|
|
180
|
+
return 0
|
|
181
|
+
else:
|
|
182
|
+
error(f"Directory does not exist: {TWD}", CONFIG)
|
|
183
|
+
output_handler(
|
|
184
|
+
f"Directory does not exist: {TWD}", None, output, simple_output
|
|
185
|
+
)
|
|
186
|
+
return 1
|
|
187
|
+
|
|
188
|
+
output_handler("No TWD with alias found", None, output, simple_output)
|
|
189
|
+
return 1
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def show_directory(output=True, simple_output=False):
|
|
193
|
+
dirs = load_directory()
|
|
194
|
+
|
|
195
|
+
if not dirs:
|
|
196
|
+
output_handler("No TWD set", None, output, simple_output)
|
|
197
|
+
return
|
|
198
|
+
|
|
199
|
+
max_alias_len = max(len(entry["alias"]) for entry in dirs.values()) if dirs else 0
|
|
200
|
+
max_id_len = max(len(alias_id) for alias_id in dirs.keys()) if dirs else 0
|
|
201
|
+
max_path_len = max(len(entry["path"]) for entry in dirs.values()) if dirs else 0
|
|
202
|
+
|
|
203
|
+
header = f"{'Alias'.ljust(max_alias_len)} {'ID'.ljust(max_id_len)} {'Path'.ljust(max_path_len)} Created At"
|
|
204
|
+
print(header)
|
|
205
|
+
print("-" * len(header))
|
|
206
|
+
|
|
207
|
+
for alias_id, entry in dirs.items():
|
|
208
|
+
alias = entry["alias"].ljust(max_alias_len)
|
|
209
|
+
path = entry["path"].ljust(max_path_len)
|
|
210
|
+
created_at = time.strftime(
|
|
211
|
+
"%Y-%m-%d %H:%M:%S", time.localtime(entry["created_at"])
|
|
212
|
+
)
|
|
213
|
+
alias_id_str = alias_id.ljust(max_id_len)
|
|
214
|
+
output_handler(
|
|
215
|
+
f"{alias} {alias_id_str} {path} {created_at}",
|
|
216
|
+
None,
|
|
217
|
+
output,
|
|
218
|
+
simple_output,
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def unset_directory(output=True, simple_output=False, force=False):
|
|
223
|
+
if not os.path.exists(TWD_FILE):
|
|
224
|
+
output_handler(f"No TWD file found", None, output, simple_output)
|
|
225
|
+
else:
|
|
226
|
+
if not force:
|
|
227
|
+
output_handler(
|
|
228
|
+
r"""If you want to execute deleting and therefore unsetting all set TWD's, please use "--force" or "-f" and run again.
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
This feature is to prevent accidental execution.""",
|
|
232
|
+
None,
|
|
233
|
+
True,
|
|
234
|
+
False,
|
|
235
|
+
)
|
|
236
|
+
return
|
|
237
|
+
try:
|
|
238
|
+
os.remove(TWD_FILE)
|
|
239
|
+
except OSError as e:
|
|
240
|
+
error(f"Error deleting TWD file: {e}", CONFIG)
|
|
241
|
+
raise
|
|
242
|
+
output_handler(f"TWD File deleted and TWD unset", None, output, simple_output)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def get_package_version():
|
|
246
|
+
try:
|
|
247
|
+
return version("twd_m4sc0")
|
|
248
|
+
except PackageNotFoundError as e:
|
|
249
|
+
error(f"Package version not found: {e}", CONFIG)
|
|
250
|
+
return "Unknown version"
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def main():
|
|
254
|
+
global TWD_FILE
|
|
255
|
+
|
|
256
|
+
parser = argparse.ArgumentParser(
|
|
257
|
+
description="Temporarily save and navigate to working directories."
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
# Positional arguments
|
|
261
|
+
parser.add_argument("directory", nargs="?", help="Directory to save")
|
|
262
|
+
parser.add_argument(
|
|
263
|
+
"alias", nargs="?", help="Alias for the saved directory (optional)"
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
# Optional Arguments/Flags
|
|
267
|
+
parser.add_argument(
|
|
268
|
+
"-s",
|
|
269
|
+
"--save",
|
|
270
|
+
action="store_true",
|
|
271
|
+
help="Save the current or specified directory",
|
|
272
|
+
)
|
|
273
|
+
parser.add_argument("-d", "--dir", nargs="?", help="Directory to save")
|
|
274
|
+
parser.add_argument("-a", "--ali", nargs="?", help="Alias for the saved directory")
|
|
275
|
+
parser.add_argument(
|
|
276
|
+
"-g", "--go", nargs="?", const=None, help="Go to the saved directory"
|
|
277
|
+
)
|
|
278
|
+
parser.add_argument("-l", "--list", action="store_true", help="Show saved TWD")
|
|
279
|
+
parser.add_argument(
|
|
280
|
+
"-u", "--unset", action="store_true", help="Unset the saved TWD"
|
|
281
|
+
)
|
|
282
|
+
parser.add_argument(
|
|
283
|
+
"-v",
|
|
284
|
+
"--version",
|
|
285
|
+
action="version",
|
|
286
|
+
version=f"TWD Version: {get_package_version()}",
|
|
287
|
+
help="Show the current version of TWD installed",
|
|
288
|
+
)
|
|
289
|
+
parser.add_argument("-f", "--force", action="store_true", help="Force an action")
|
|
290
|
+
parser.add_argument(
|
|
291
|
+
"--shell", action="store_true", help="Output shell function for integration"
|
|
292
|
+
)
|
|
293
|
+
parser.add_argument(
|
|
294
|
+
"--simple-output",
|
|
295
|
+
action="store_true",
|
|
296
|
+
help="Only print essential output (new directory, absolute path, etc.)",
|
|
297
|
+
)
|
|
298
|
+
parser.add_argument(
|
|
299
|
+
"--no-output",
|
|
300
|
+
action="store_true",
|
|
301
|
+
help="Prevents the console from sending output",
|
|
302
|
+
)
|
|
303
|
+
args = parser.parse_args()
|
|
304
|
+
|
|
305
|
+
output = not args.no_output
|
|
306
|
+
simple_output = args.simple_output
|
|
307
|
+
|
|
308
|
+
if args.shell:
|
|
309
|
+
print(r"""
|
|
310
|
+
function twd() {
|
|
311
|
+
output=$(python3 -m twd "$@");
|
|
312
|
+
while IFS= read -r line; do
|
|
313
|
+
if [[ -z "$line" ]]; then
|
|
314
|
+
continue;
|
|
315
|
+
fi;
|
|
316
|
+
type=$(echo "$line" | cut -d';' -f1);
|
|
317
|
+
message=$(echo "$line" | cut -d';' -f2-);
|
|
318
|
+
if [[ "$type" == "1" ]]; then
|
|
319
|
+
eval "$message";
|
|
320
|
+
else
|
|
321
|
+
echo "$message";
|
|
322
|
+
fi;
|
|
323
|
+
done <<< "$output";
|
|
324
|
+
}
|
|
325
|
+
""")
|
|
326
|
+
return 0
|
|
327
|
+
|
|
328
|
+
directory = args.directory or args.dir
|
|
329
|
+
alias = args.alias or args.ali
|
|
330
|
+
|
|
331
|
+
if args.save:
|
|
332
|
+
if not directory:
|
|
333
|
+
directory = args.directory or os.getcwd()
|
|
334
|
+
|
|
335
|
+
alias = args.alias or args.ali
|
|
336
|
+
|
|
337
|
+
save_directory(directory, alias, output, simple_output)
|
|
338
|
+
elif args.go:
|
|
339
|
+
alias = args.go
|
|
340
|
+
return go_to_directory(alias, output, simple_output)
|
|
341
|
+
elif args.list:
|
|
342
|
+
show_directory(output, simple_output)
|
|
343
|
+
elif args.unset:
|
|
344
|
+
force = args.force
|
|
345
|
+
unset_directory(output, simple_output, force)
|
|
346
|
+
else:
|
|
347
|
+
parser.print_help()
|
|
348
|
+
return 1
|