twd-m4sc0 2.0.0__tar.gz → 2.0.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-2.0.0/twd_m4sc0.egg-info → twd_m4sc0-2.0.3}/PKG-INFO +29 -8
- {twd_m4sc0-2.0.0 → twd_m4sc0-2.0.3}/README.md +28 -7
- {twd_m4sc0-2.0.0 → twd_m4sc0-2.0.3}/setup.py +1 -1
- {twd_m4sc0-2.0.0 → twd_m4sc0-2.0.3}/twd/crud.py +19 -9
- twd_m4sc0-2.0.3/twd/logger.py +47 -0
- {twd_m4sc0-2.0.0 → twd_m4sc0-2.0.3}/twd/screen.py +5 -3
- {twd_m4sc0-2.0.0 → twd_m4sc0-2.0.3}/twd/twd.py +64 -50
- {twd_m4sc0-2.0.0 → twd_m4sc0-2.0.3/twd_m4sc0.egg-info}/PKG-INFO +29 -8
- twd_m4sc0-2.0.0/twd/logger.py +0 -47
- {twd_m4sc0-2.0.0 → twd_m4sc0-2.0.3}/LICENSE +0 -0
- {twd_m4sc0-2.0.0 → twd_m4sc0-2.0.3}/setup.cfg +0 -0
- {twd_m4sc0-2.0.0 → twd_m4sc0-2.0.3}/tests/__init__.py +0 -0
- {twd_m4sc0-2.0.0 → twd_m4sc0-2.0.3}/tests/test_twd.py +0 -0
- {twd_m4sc0-2.0.0 → twd_m4sc0-2.0.3}/twd/__init__.py +0 -0
- {twd_m4sc0-2.0.0 → twd_m4sc0-2.0.3}/twd/__main__.py +0 -0
- {twd_m4sc0-2.0.0 → twd_m4sc0-2.0.3}/twd_m4sc0.egg-info/SOURCES.txt +0 -0
- {twd_m4sc0-2.0.0 → twd_m4sc0-2.0.3}/twd_m4sc0.egg-info/dependency_links.txt +0 -0
- {twd_m4sc0-2.0.0 → twd_m4sc0-2.0.3}/twd_m4sc0.egg-info/entry_points.txt +0 -0
- {twd_m4sc0-2.0.0 → twd_m4sc0-2.0.3}/twd_m4sc0.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: twd_m4sc0
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.3
|
|
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
|
|
@@ -11,12 +11,11 @@ Requires-Python: >=3.6
|
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
License-File: LICENSE
|
|
13
13
|
|
|
14
|
-
|
|
15
14
|
# twd-m4sc0
|
|
16
15
|
|
|
17
16
|
`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
17
|
|
|
19
|
-
> All Versions `< v1.5` are considered deprecated and should not be used anymore because of the `config` file that was introduced in that version. This file is incompatible with newer versions and might cause issues or break the program.
|
|
18
|
+
> All Versions `< v1.5` are considered deprecated and should not be used anymore because of the `config` file that was introduced in that version. This file is incompatible with newer versions and might cause issues or break the program.
|
|
20
19
|
|
|
21
20
|
## Features
|
|
22
21
|
|
|
@@ -29,7 +28,7 @@ License-File: LICENSE
|
|
|
29
28
|
|
|
30
29
|
## Installation
|
|
31
30
|
|
|
32
|
-
### Installation using `pip
|
|
31
|
+
### Installation using `pip`
|
|
33
32
|
|
|
34
33
|
1. Install the package from the `pypi` repository:
|
|
35
34
|
|
|
@@ -37,19 +36,41 @@ License-File: LICENSE
|
|
|
37
36
|
pip install twd-m4sc0
|
|
38
37
|
```
|
|
39
38
|
|
|
40
|
-
2.
|
|
39
|
+
2. Ensure proper installation by checking the version
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
python3 -m twd -v
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Setup using in-built commands
|
|
46
|
+
|
|
47
|
+
> This setup information is only recommend if you're system is using the `.bashrc` file provided by debian based systems and it's located at `~/.bashrc`. If you're unsure what you're shell configuration file is called or where it's located please refer to your official OS documentation to ensure proper functionality.
|
|
48
|
+
|
|
49
|
+
1. Run the following command to activate the `twd` shell function
|
|
50
|
+
|
|
51
|
+
> Replace `[alias]` with an alias of your choice to customize the way you're calling the script and follow the given instructions
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
python3 -m twd --setup [alias]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Manual setup
|
|
41
58
|
|
|
42
|
-
|
|
59
|
+
1. Add the following line to your shell configuration file:
|
|
43
60
|
|
|
44
61
|
```bash
|
|
45
62
|
eval $(python3 -m twd --shell [alias])
|
|
46
63
|
```
|
|
47
64
|
|
|
48
|
-
|
|
65
|
+
2. Run the following command to apply the new configuration:
|
|
49
66
|
|
|
50
67
|
```bash
|
|
51
68
|
source ~/.bashrc
|
|
52
|
-
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
or
|
|
72
|
+
|
|
73
|
+
```bash
|
|
53
74
|
source ~/.zshrc
|
|
54
75
|
```
|
|
55
76
|
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
1
|
# twd-m4sc0
|
|
3
2
|
|
|
4
3
|
`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
4
|
|
|
6
|
-
> All Versions `< v1.5` are considered deprecated and should not be used anymore because of the `config` file that was introduced in that version. This file is incompatible with newer versions and might cause issues or break the program.
|
|
5
|
+
> All Versions `< v1.5` are considered deprecated and should not be used anymore because of the `config` file that was introduced in that version. This file is incompatible with newer versions and might cause issues or break the program.
|
|
7
6
|
|
|
8
7
|
## Features
|
|
9
8
|
|
|
@@ -16,7 +15,7 @@
|
|
|
16
15
|
|
|
17
16
|
## Installation
|
|
18
17
|
|
|
19
|
-
### Installation using `pip
|
|
18
|
+
### Installation using `pip`
|
|
20
19
|
|
|
21
20
|
1. Install the package from the `pypi` repository:
|
|
22
21
|
|
|
@@ -24,19 +23,41 @@
|
|
|
24
23
|
pip install twd-m4sc0
|
|
25
24
|
```
|
|
26
25
|
|
|
27
|
-
2.
|
|
26
|
+
2. Ensure proper installation by checking the version
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
python3 -m twd -v
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Setup using in-built commands
|
|
33
|
+
|
|
34
|
+
> This setup information is only recommend if you're system is using the `.bashrc` file provided by debian based systems and it's located at `~/.bashrc`. If you're unsure what you're shell configuration file is called or where it's located please refer to your official OS documentation to ensure proper functionality.
|
|
35
|
+
|
|
36
|
+
1. Run the following command to activate the `twd` shell function
|
|
37
|
+
|
|
38
|
+
> Replace `[alias]` with an alias of your choice to customize the way you're calling the script and follow the given instructions
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
python3 -m twd --setup [alias]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Manual setup
|
|
28
45
|
|
|
29
|
-
|
|
46
|
+
1. Add the following line to your shell configuration file:
|
|
30
47
|
|
|
31
48
|
```bash
|
|
32
49
|
eval $(python3 -m twd --shell [alias])
|
|
33
50
|
```
|
|
34
51
|
|
|
35
|
-
|
|
52
|
+
2. Run the following command to apply the new configuration:
|
|
36
53
|
|
|
37
54
|
```bash
|
|
38
55
|
source ~/.bashrc
|
|
39
|
-
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
or
|
|
59
|
+
|
|
60
|
+
```bash
|
|
40
61
|
source ~/.zshrc
|
|
41
62
|
```
|
|
42
63
|
|
|
@@ -2,9 +2,12 @@ import os
|
|
|
2
2
|
import json
|
|
3
3
|
import hashlib
|
|
4
4
|
import time
|
|
5
|
-
|
|
5
|
+
import logging
|
|
6
6
|
from collections import OrderedDict
|
|
7
7
|
|
|
8
|
+
log = logging.getLogger("log")
|
|
9
|
+
error_log = logging.getLogger("error")
|
|
10
|
+
|
|
8
11
|
|
|
9
12
|
def create_alias_id():
|
|
10
13
|
data = str(time.time()) + str(os.urandom(16))
|
|
@@ -21,8 +24,9 @@ def ensure_data_file_exists(config):
|
|
|
21
24
|
try:
|
|
22
25
|
with open(data_file, "w") as f:
|
|
23
26
|
json.dump({}, f)
|
|
27
|
+
log.info(f"Created data file at {data_file}")
|
|
24
28
|
except OSError as e:
|
|
25
|
-
error(f"Error creating data file: {e}"
|
|
29
|
+
error_log.error(f"Error creating data file: {e}")
|
|
26
30
|
|
|
27
31
|
|
|
28
32
|
def load_data(config):
|
|
@@ -32,12 +36,13 @@ def load_data(config):
|
|
|
32
36
|
try:
|
|
33
37
|
with open(data_file, "r") as f:
|
|
34
38
|
data = json.load(f)
|
|
39
|
+
log.info(f"Loaded data from {data_file}")
|
|
35
40
|
return data
|
|
36
41
|
except json.JSONDecodeError as e:
|
|
37
|
-
error(f"Error reading data file: {e}"
|
|
42
|
+
error_log.error(f"Error reading data file: {e}")
|
|
38
43
|
return {}
|
|
39
44
|
except OSError as e:
|
|
40
|
-
error(f"Error reading data file: {e}"
|
|
45
|
+
error_log.error(f"Error reading data file: {e}")
|
|
41
46
|
return {}
|
|
42
47
|
|
|
43
48
|
|
|
@@ -49,8 +54,9 @@ def save_data(config, data):
|
|
|
49
54
|
)
|
|
50
55
|
with open(data_file, "w") as f:
|
|
51
56
|
json.dump(sorted_data, f, indent=4)
|
|
57
|
+
log.info(f"Saved data to {data_file}")
|
|
52
58
|
except OSError as e:
|
|
53
|
-
error(f"Error writing to data file: {e}"
|
|
59
|
+
error_log.error(f"Error writing to data file: {e}")
|
|
54
60
|
|
|
55
61
|
|
|
56
62
|
def create_entry(config, data, path, alias=None):
|
|
@@ -61,6 +67,7 @@ def create_entry(config, data, path, alias=None):
|
|
|
61
67
|
"created_at": time.time(),
|
|
62
68
|
}
|
|
63
69
|
save_data(config, data)
|
|
70
|
+
log.info(f"Created new entry with alias_id '{alias_id}' and path '{path}'")
|
|
64
71
|
return alias_id
|
|
65
72
|
|
|
66
73
|
|
|
@@ -68,8 +75,9 @@ def delete_entry(config, data, entry_id):
|
|
|
68
75
|
if entry_id in data:
|
|
69
76
|
del data[entry_id]
|
|
70
77
|
save_data(config, data)
|
|
78
|
+
log.info(f"Deleted entry with alias_id '{entry_id}'")
|
|
71
79
|
else:
|
|
72
|
-
error(f"Entry ID {entry_id} not found"
|
|
80
|
+
error_log.error(f"Entry ID '{entry_id}' not found")
|
|
73
81
|
raise KeyError(f"Entry ID {entry_id} not found")
|
|
74
82
|
|
|
75
83
|
|
|
@@ -77,8 +85,9 @@ def update_entry(config, data, entry_id, entry):
|
|
|
77
85
|
if entry_id in data:
|
|
78
86
|
data[entry_id] = entry
|
|
79
87
|
save_data(config, data)
|
|
88
|
+
log.info(f"Updated entry with alias_id '{entry_id}'")
|
|
80
89
|
else:
|
|
81
|
-
error(f"Entry ID {entry_id} not found"
|
|
90
|
+
error_log.error(f"Entry ID '{entry_id}' not found")
|
|
82
91
|
raise KeyError(f"Entry ID {entry_id} not found")
|
|
83
92
|
|
|
84
93
|
|
|
@@ -87,8 +96,9 @@ def delete_data_file(config):
|
|
|
87
96
|
if os.path.exists(data_file):
|
|
88
97
|
try:
|
|
89
98
|
os.remove(data_file)
|
|
99
|
+
log.info(f"Deleted data file at {data_file}")
|
|
90
100
|
except OSError as e:
|
|
91
|
-
error(f"Error deleting data file: {e}"
|
|
101
|
+
error_log.error(f"Error deleting data file: {e}")
|
|
92
102
|
raise
|
|
93
103
|
else:
|
|
94
|
-
error("No data file found to delete"
|
|
104
|
+
error_log.error("No data file found to delete")
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
from logging.handlers import RotatingFileHandler
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def setup_logger(config):
|
|
7
|
+
"""Set up loggers based on the configuration provided."""
|
|
8
|
+
log_file = os.path.expanduser(config.get("log_file"))
|
|
9
|
+
error_file = os.path.expanduser(config.get("error_file"))
|
|
10
|
+
log_level = config.get("log_level", "INFO").upper()
|
|
11
|
+
max_bytes = config.get("log_max_bytes", 5 * 1024 * 1024) # Default 5MB
|
|
12
|
+
backup_count = config.get("log_backup_count", 3) # Default 3 backup files
|
|
13
|
+
|
|
14
|
+
os.makedirs(os.path.dirname(log_file), exist_ok=True)
|
|
15
|
+
os.makedirs(os.path.dirname(error_file), exist_ok=True)
|
|
16
|
+
|
|
17
|
+
# General log configuration
|
|
18
|
+
log_formatter = logging.Formatter(
|
|
19
|
+
config.get("log_format", "%(asctime)s - %(levelname)s - %(message)s")
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# Avoid duplicate handlers
|
|
23
|
+
logger = logging.getLogger("log")
|
|
24
|
+
if not logger.hasHandlers():
|
|
25
|
+
logger.setLevel(log_level)
|
|
26
|
+
log_handler = RotatingFileHandler(
|
|
27
|
+
log_file, maxBytes=max_bytes, backupCount=backup_count
|
|
28
|
+
)
|
|
29
|
+
log_handler.setFormatter(log_formatter)
|
|
30
|
+
logger.addHandler(log_handler)
|
|
31
|
+
|
|
32
|
+
# Error log configuration
|
|
33
|
+
error_logger = logging.getLogger("error")
|
|
34
|
+
if not error_logger.hasHandlers():
|
|
35
|
+
error_logger.setLevel(logging.ERROR)
|
|
36
|
+
error_handler = RotatingFileHandler(
|
|
37
|
+
error_file, maxBytes=max_bytes, backupCount=backup_count
|
|
38
|
+
)
|
|
39
|
+
error_handler.setFormatter(log_formatter)
|
|
40
|
+
error_logger.addHandler(error_handler)
|
|
41
|
+
|
|
42
|
+
return logger, error_logger
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def initialize_logging(config):
|
|
46
|
+
setup_logger(config)
|
|
47
|
+
|
|
@@ -2,7 +2,10 @@ import curses
|
|
|
2
2
|
import time
|
|
3
3
|
import os
|
|
4
4
|
from . import crud
|
|
5
|
-
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
log = logging.getLogger("log")
|
|
8
|
+
error_log = logging.getLogger("error")
|
|
6
9
|
|
|
7
10
|
CONFIG = None
|
|
8
11
|
DIRS = None
|
|
@@ -163,7 +166,7 @@ def display_select_screen(stdscr):
|
|
|
163
166
|
try:
|
|
164
167
|
crud.delete_entry(CONFIG, data, selected_entry_id)
|
|
165
168
|
except KeyError:
|
|
166
|
-
error(f"Entry ID {selected_entry_id} not found"
|
|
169
|
+
error_log.error(f"Entry ID {selected_entry_id} not found")
|
|
167
170
|
del filtered_DIRS[selected_entry_id]
|
|
168
171
|
if selected_entry >= len(filtered_DIRS):
|
|
169
172
|
selected_entry = max(len(filtered_DIRS) - 1, 0)
|
|
@@ -196,4 +199,3 @@ def display_select(config, dirs):
|
|
|
196
199
|
original_DIRS = DIRS
|
|
197
200
|
search_query = ""
|
|
198
201
|
return curses.wrapper(display_select_screen)
|
|
199
|
-
|
|
@@ -3,20 +3,28 @@ import argparse
|
|
|
3
3
|
import json
|
|
4
4
|
import time
|
|
5
5
|
import re
|
|
6
|
+
import logging
|
|
6
7
|
from importlib.metadata import version, PackageNotFoundError
|
|
7
|
-
from .logger import
|
|
8
|
+
from .logger import initialize_logging
|
|
8
9
|
from .screen import display_select
|
|
9
10
|
from . import crud
|
|
10
11
|
|
|
12
|
+
log = logging.getLogger("log")
|
|
13
|
+
error_log = logging.getLogger("error")
|
|
14
|
+
|
|
11
15
|
TWD_DIR = os.path.join(os.path.expanduser("~"), ".twd")
|
|
12
16
|
CONFIG_FILE = os.path.join(TWD_DIR, "config")
|
|
13
17
|
|
|
14
18
|
DEFAULT_CONFIG = {
|
|
15
19
|
"data_file": os.path.expanduser("~/.twd/data"),
|
|
16
20
|
"output_behaviour": 2,
|
|
21
|
+
"clear_after_screen": False,
|
|
17
22
|
"log_file": os.path.expanduser("~/.twd/log"),
|
|
18
23
|
"error_file": os.path.expanduser("~/.twd/error"),
|
|
19
|
-
"log_format": "
|
|
24
|
+
"log_format": "%(asctime)s - %(levelname)s - %(message)s",
|
|
25
|
+
"log_level": "INFO",
|
|
26
|
+
"log_max_bytes": 5 * 1024 * 1024, # 5 MB log rotation
|
|
27
|
+
"log_backup_count": 3,
|
|
20
28
|
}
|
|
21
29
|
|
|
22
30
|
|
|
@@ -31,32 +39,34 @@ def load_config():
|
|
|
31
39
|
try:
|
|
32
40
|
return json.load(file)
|
|
33
41
|
except json.JSONDecodeError as e:
|
|
34
|
-
error(f"Error loading config: {e}"
|
|
42
|
+
error_log.error(f"Error loading config: {e}")
|
|
35
43
|
return DEFAULT_CONFIG
|
|
36
44
|
|
|
37
45
|
|
|
38
46
|
CONFIG = load_config()
|
|
47
|
+
initialize_logging(CONFIG)
|
|
39
48
|
|
|
40
|
-
# Ensure data files exist
|
|
41
49
|
crud.ensure_data_file_exists(CONFIG)
|
|
42
|
-
log_file = os.path.expanduser(CONFIG.get("log_file"))
|
|
43
|
-
error_file = os.path.expanduser(CONFIG.get("error_file"))
|
|
44
50
|
|
|
45
51
|
|
|
46
52
|
def ensure_log_error_files():
|
|
53
|
+
"""Ensure that log and error files exist based on configuration settings."""
|
|
54
|
+
log_file = os.path.expanduser(CONFIG.get("log_file"))
|
|
55
|
+
error_file = os.path.expanduser(CONFIG.get("error_file"))
|
|
56
|
+
|
|
47
57
|
if not os.path.exists(log_file):
|
|
48
58
|
try:
|
|
49
59
|
with open(log_file, "w+") as f:
|
|
50
60
|
f.write("")
|
|
51
61
|
except OSError as e:
|
|
52
|
-
error(f"Error creating log file: {e}"
|
|
62
|
+
error_log.error(f"Error creating log file: {e}")
|
|
53
63
|
|
|
54
64
|
if not os.path.exists(error_file):
|
|
55
65
|
try:
|
|
56
66
|
with open(error_file, "w+") as f:
|
|
57
67
|
f.write("")
|
|
58
68
|
except OSError as e:
|
|
59
|
-
error(f"Error creating error file: {e}"
|
|
69
|
+
error_log.error(f"Error creating error file: {e}")
|
|
60
70
|
|
|
61
71
|
|
|
62
72
|
ensure_log_error_files()
|
|
@@ -66,14 +76,14 @@ def get_absolute_path(path):
|
|
|
66
76
|
try:
|
|
67
77
|
return os.path.abspath(path)
|
|
68
78
|
except Exception as e:
|
|
69
|
-
error(f"Error getting absolute path for {path}: {e}"
|
|
79
|
+
error_log.error(f"Error getting absolute path for {path}: {e}")
|
|
70
80
|
raise
|
|
71
81
|
|
|
72
82
|
|
|
73
83
|
def validate_alias(alias):
|
|
74
84
|
"""Ensure the alias contains only valid characters."""
|
|
75
85
|
if not re.match(r"^[\w-]+$", alias):
|
|
76
|
-
error(f"Invalid alias provided: {alias}"
|
|
86
|
+
error_log.error(f"Invalid alias provided: {alias}")
|
|
77
87
|
raise ValueError(
|
|
78
88
|
f"Invalid alias: '{alias}'. Aliases can only contain alphanumeric characters, dashes, and underscores."
|
|
79
89
|
)
|
|
@@ -83,18 +93,24 @@ def validate_alias(alias):
|
|
|
83
93
|
def output_handler(
|
|
84
94
|
message=None, path=None, output=True, simple_output=False, message_type=0
|
|
85
95
|
):
|
|
86
|
-
log(
|
|
96
|
+
log.info(message or path)
|
|
87
97
|
|
|
88
98
|
if CONFIG["output_behaviour"] == 1 or simple_output:
|
|
89
99
|
if path:
|
|
90
100
|
with open("/tmp/twd_path", "w") as f:
|
|
91
101
|
f.write(path)
|
|
102
|
+
if CONFIG["clear_after_screen"]:
|
|
103
|
+
with open("/tmp/twd_clear", "w") as f:
|
|
104
|
+
f.write(path)
|
|
92
105
|
if output:
|
|
93
106
|
print(path)
|
|
94
107
|
elif CONFIG["output_behaviour"] == 2:
|
|
95
108
|
if path:
|
|
96
109
|
with open("/tmp/twd_path", "w") as f:
|
|
97
110
|
f.write(path)
|
|
111
|
+
if CONFIG["clear_after_screen"]:
|
|
112
|
+
with open("/tmp/twd_clear", "w") as f:
|
|
113
|
+
f.write(path)
|
|
98
114
|
if output:
|
|
99
115
|
print(message)
|
|
100
116
|
|
|
@@ -126,12 +142,10 @@ def load_directory():
|
|
|
126
142
|
|
|
127
143
|
def show_main(alias=None, output=True, simple_output=False):
|
|
128
144
|
dirs = load_directory()
|
|
129
|
-
|
|
130
145
|
if dirs is None:
|
|
131
146
|
output_handler("No TWD found", None, output, simple_output)
|
|
132
147
|
return 1
|
|
133
148
|
else:
|
|
134
|
-
# Use alias if provided
|
|
135
149
|
if alias:
|
|
136
150
|
matched_dirs = []
|
|
137
151
|
|
|
@@ -149,14 +163,13 @@ def show_main(alias=None, output=True, simple_output=False):
|
|
|
149
163
|
|
|
150
164
|
if len(matched_dirs) == 1:
|
|
151
165
|
TWD = matched_dirs[0]["path"]
|
|
152
|
-
|
|
153
166
|
if os.path.exists(TWD):
|
|
154
167
|
output_handler(
|
|
155
168
|
f"cd {TWD}", TWD, output, simple_output, message_type=1
|
|
156
169
|
)
|
|
157
170
|
return 0
|
|
158
171
|
else:
|
|
159
|
-
error(f"Directory does not exist: {TWD}"
|
|
172
|
+
error_log.error(f"Directory does not exist: {TWD}")
|
|
160
173
|
output_handler(
|
|
161
174
|
f"Directory does not exist: {TWD}", None, output, simple_output
|
|
162
175
|
)
|
|
@@ -177,19 +190,17 @@ def show_main(alias=None, output=True, simple_output=False):
|
|
|
177
190
|
output_handler("No TWD with alias found", None, output, simple_output)
|
|
178
191
|
return 1
|
|
179
192
|
|
|
180
|
-
# Display selection using curses if alias is not given
|
|
181
193
|
selected_dir = display_select(CONFIG, dirs)
|
|
182
194
|
if selected_dir is None:
|
|
183
195
|
output_handler("No TWD selected", None, output, simple_output)
|
|
184
196
|
return 0
|
|
185
197
|
else:
|
|
186
198
|
TWD = selected_dir["path"]
|
|
187
|
-
|
|
188
199
|
if os.path.exists(TWD):
|
|
189
200
|
output_handler(f"cd {TWD}", TWD, output, simple_output, message_type=1)
|
|
190
201
|
return 0
|
|
191
202
|
else:
|
|
192
|
-
error(f"Directory does not exist: {TWD}"
|
|
203
|
+
error_log.error(f"Directory does not exist: {TWD}")
|
|
193
204
|
output_handler(
|
|
194
205
|
f"Directory does not exist: {TWD}", None, output, simple_output
|
|
195
206
|
)
|
|
@@ -198,7 +209,6 @@ def show_main(alias=None, output=True, simple_output=False):
|
|
|
198
209
|
|
|
199
210
|
def show_directory(output=True, simple_output=False):
|
|
200
211
|
dirs = load_directory()
|
|
201
|
-
|
|
202
212
|
if not dirs:
|
|
203
213
|
output_handler("No TWD set", None, output, simple_output)
|
|
204
214
|
return
|
|
@@ -240,16 +250,26 @@ This feature is to prevent accidental execution.""",
|
|
|
240
250
|
try:
|
|
241
251
|
crud.delete_data_file(CONFIG)
|
|
242
252
|
except OSError as e:
|
|
243
|
-
error(f"Error deleting TWD file: {e}"
|
|
253
|
+
error_log.error(f"Error deleting TWD file: {e}")
|
|
244
254
|
raise
|
|
245
255
|
output_handler("TWD File deleted and TWD unset", None, output, simple_output)
|
|
246
256
|
|
|
247
257
|
|
|
258
|
+
def setup(alias):
|
|
259
|
+
bashrc_path = os.path.expanduser("~/.bashrc")
|
|
260
|
+
alias = "twd" if not alias else alias
|
|
261
|
+
with open(bashrc_path, "a") as file:
|
|
262
|
+
file.write(f"\neval $(python3 -m twd --shell {alias})\n")
|
|
263
|
+
print("Please execute the following command to activate TWD:")
|
|
264
|
+
print("")
|
|
265
|
+
print(f"source {bashrc_path}")
|
|
266
|
+
|
|
267
|
+
|
|
248
268
|
def get_package_version():
|
|
249
269
|
try:
|
|
250
270
|
return version("twd_m4sc0")
|
|
251
271
|
except PackageNotFoundError as e:
|
|
252
|
-
error(f"Package version not found: {e}"
|
|
272
|
+
error_log.error(f"Package version not found: {e}")
|
|
253
273
|
return "Unknown version"
|
|
254
274
|
|
|
255
275
|
|
|
@@ -258,13 +278,14 @@ def main():
|
|
|
258
278
|
description="Temporarily save and navigate to working directories."
|
|
259
279
|
)
|
|
260
280
|
|
|
261
|
-
|
|
281
|
+
parser.add_argument(
|
|
282
|
+
"--setup", nargs="?", const="twd", help="Automatic setup in the .bashrc file"
|
|
283
|
+
)
|
|
284
|
+
|
|
262
285
|
parser.add_argument("directory", nargs="?", help="Directory to save")
|
|
263
286
|
parser.add_argument(
|
|
264
287
|
"alias", nargs="?", help="Alias for the saved directory (optional)"
|
|
265
288
|
)
|
|
266
|
-
|
|
267
|
-
# Optional Arguments/Flags
|
|
268
289
|
parser.add_argument(
|
|
269
290
|
"-s",
|
|
270
291
|
"--save",
|
|
@@ -285,63 +306,56 @@ def main():
|
|
|
285
306
|
"--version",
|
|
286
307
|
action="version",
|
|
287
308
|
version=f"TWD Version: v{get_package_version()}",
|
|
288
|
-
help="Show the current version of TWD installed",
|
|
289
309
|
)
|
|
290
310
|
parser.add_argument("-f", "--force", action="store_true", help="Force an action")
|
|
291
311
|
parser.add_argument(
|
|
292
312
|
"--shell", nargs="?", const="twd", help="Output shell function for integration"
|
|
293
313
|
)
|
|
294
314
|
parser.add_argument(
|
|
295
|
-
"--simple-output",
|
|
296
|
-
action="store_true",
|
|
297
|
-
help="Only print essential output (new directory, absolute path, etc.)",
|
|
315
|
+
"--simple-output", action="store_true", help="Only print essential output"
|
|
298
316
|
)
|
|
299
317
|
parser.add_argument(
|
|
300
318
|
"--no-output",
|
|
301
319
|
action="store_true",
|
|
302
320
|
help="Prevents the console from sending output",
|
|
303
321
|
)
|
|
304
|
-
args = parser.parse_args()
|
|
305
322
|
|
|
323
|
+
args = parser.parse_args()
|
|
306
324
|
output = not args.no_output
|
|
307
325
|
simple_output = args.simple_output
|
|
308
326
|
|
|
309
|
-
# Shell function
|
|
310
327
|
if args.shell:
|
|
311
|
-
print(rf"""
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
328
|
+
print(rf"""function {args.shell}() {{
|
|
329
|
+
python3 -m twd "$@";
|
|
330
|
+
if [ -f /tmp/twd_path ]; then
|
|
331
|
+
cd "$(cat /tmp/twd_path)";
|
|
332
|
+
/bin/rm -f /tmp/twd_path;
|
|
333
|
+
fi;
|
|
334
|
+
if [ -f /tmp/twd_clear ]; then
|
|
335
|
+
clear;
|
|
336
|
+
/bin/rm -f /tmp/twd_clear;
|
|
337
|
+
fi;
|
|
338
|
+
}}""")
|
|
339
|
+
return 0
|
|
340
|
+
|
|
341
|
+
if args.setup:
|
|
342
|
+
setup(args.setup)
|
|
320
343
|
return 0
|
|
321
344
|
|
|
322
345
|
directory = args.directory or args.dir
|
|
323
346
|
alias = args.alias or args.ali
|
|
324
347
|
|
|
325
348
|
if args.save:
|
|
326
|
-
if not directory:
|
|
327
|
-
directory = os.getcwd()
|
|
328
|
-
|
|
329
|
-
alias = args.alias or args.ali
|
|
330
|
-
|
|
331
349
|
save_directory(directory, alias, output, simple_output)
|
|
332
350
|
elif args.go:
|
|
333
|
-
alias
|
|
334
|
-
return show_main(alias, output, simple_output)
|
|
351
|
+
show_main(alias, output, simple_output)
|
|
335
352
|
elif args.list:
|
|
336
353
|
show_directory(output, simple_output)
|
|
337
354
|
elif args.unset:
|
|
338
|
-
force
|
|
339
|
-
unset_directory(output, simple_output, force)
|
|
355
|
+
unset_directory(output, simple_output, force=args.force)
|
|
340
356
|
else:
|
|
341
357
|
show_main(None, output, simple_output)
|
|
342
|
-
return 1
|
|
343
358
|
|
|
344
359
|
|
|
345
360
|
if __name__ == "__main__":
|
|
346
361
|
main()
|
|
347
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: twd_m4sc0
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.3
|
|
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
|
|
@@ -11,12 +11,11 @@ Requires-Python: >=3.6
|
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
License-File: LICENSE
|
|
13
13
|
|
|
14
|
-
|
|
15
14
|
# twd-m4sc0
|
|
16
15
|
|
|
17
16
|
`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
17
|
|
|
19
|
-
> All Versions `< v1.5` are considered deprecated and should not be used anymore because of the `config` file that was introduced in that version. This file is incompatible with newer versions and might cause issues or break the program.
|
|
18
|
+
> All Versions `< v1.5` are considered deprecated and should not be used anymore because of the `config` file that was introduced in that version. This file is incompatible with newer versions and might cause issues or break the program.
|
|
20
19
|
|
|
21
20
|
## Features
|
|
22
21
|
|
|
@@ -29,7 +28,7 @@ License-File: LICENSE
|
|
|
29
28
|
|
|
30
29
|
## Installation
|
|
31
30
|
|
|
32
|
-
### Installation using `pip
|
|
31
|
+
### Installation using `pip`
|
|
33
32
|
|
|
34
33
|
1. Install the package from the `pypi` repository:
|
|
35
34
|
|
|
@@ -37,19 +36,41 @@ License-File: LICENSE
|
|
|
37
36
|
pip install twd-m4sc0
|
|
38
37
|
```
|
|
39
38
|
|
|
40
|
-
2.
|
|
39
|
+
2. Ensure proper installation by checking the version
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
python3 -m twd -v
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Setup using in-built commands
|
|
46
|
+
|
|
47
|
+
> This setup information is only recommend if you're system is using the `.bashrc` file provided by debian based systems and it's located at `~/.bashrc`. If you're unsure what you're shell configuration file is called or where it's located please refer to your official OS documentation to ensure proper functionality.
|
|
48
|
+
|
|
49
|
+
1. Run the following command to activate the `twd` shell function
|
|
50
|
+
|
|
51
|
+
> Replace `[alias]` with an alias of your choice to customize the way you're calling the script and follow the given instructions
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
python3 -m twd --setup [alias]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Manual setup
|
|
41
58
|
|
|
42
|
-
|
|
59
|
+
1. Add the following line to your shell configuration file:
|
|
43
60
|
|
|
44
61
|
```bash
|
|
45
62
|
eval $(python3 -m twd --shell [alias])
|
|
46
63
|
```
|
|
47
64
|
|
|
48
|
-
|
|
65
|
+
2. Run the following command to apply the new configuration:
|
|
49
66
|
|
|
50
67
|
```bash
|
|
51
68
|
source ~/.bashrc
|
|
52
|
-
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
or
|
|
72
|
+
|
|
73
|
+
```bash
|
|
53
74
|
source ~/.zshrc
|
|
54
75
|
```
|
|
55
76
|
|
twd_m4sc0-2.0.0/twd/logger.py
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
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)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|