-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathopen
More file actions
executable file
·177 lines (149 loc) · 5.33 KB
/
Copy pathopen
File metadata and controls
executable file
·177 lines (149 loc) · 5.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#! /usr/bin/python3
import mimetypes
import os
import shlex
import subprocess
import sys
import tomllib
from pathlib import Path
DEFAULTS = {
"music": "termusic",
"wifi": "nmtui",
"mail": "aerc",
"im": "iamb",
"clipboard": "cliphist list | fzf | cliphist decode | wl-copy",
"db": "gobang",
"postman": "atac",
"directory": "yazi",
"video": "mpv",
"audio": "mpv",
"image": "kitty +kitten icat",
"text": "nvim",
"default": "xdg-open",
}
CONFIG_PATH = Path.home() / ".config" / "open" / "open.toml"
def ensure_config():
"""Create config file with defaults if it doesn't exist. Return parsed config."""
if not CONFIG_PATH.exists():
CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)
lines = []
lines.append("# Special keywords")
lines.append(f'music = "{DEFAULTS["music"]}"')
lines.append(f'wifi = "{DEFAULTS["wifi"]}"')
lines.append(f'mail = "{DEFAULTS["mail"]}"')
lines.append(f'im = "{DEFAULTS["im"]}"')
lines.append(f'clipboard = "{DEFAULTS["clipboard"]}"')
lines.append(f'db = "{DEFAULTS["db"]}"')
lines.append(f'postman = "{DEFAULTS["postman"]}"')
lines.append("")
lines.append("# Directory handler")
lines.append(f'directory = "{DEFAULTS["directory"]}"')
lines.append("")
lines.append("# MIME-type handlers")
lines.append(f'video = "{DEFAULTS["video"]}"')
lines.append(f'audio = "{DEFAULTS["audio"]}"')
lines.append(f'image = "{DEFAULTS["image"]}"')
lines.append(f'text = "{DEFAULTS["text"]}"')
lines.append("")
lines.append("# Fallback for unknown file types")
lines.append(f'default = "{DEFAULTS["default"]}"')
lines.append("")
CONFIG_PATH.write_text("\n".join(lines))
with open(CONFIG_PATH, "rb") as f:
return tomllib.load(f)
def get_handler(config, key):
"""Get handler string from config, falling back to DEFAULTS."""
return config.get(key) or DEFAULTS.get(key, "xdg-open")
def get_mime_type(path):
try:
result = subprocess.run(
["mimetype", "-b", path],
capture_output=True, text=True
)
return result.stdout.strip()
except FileNotFoundError:
mime, _ = mimetypes.guess_type(path)
return mime or ""
def launch(handler, target=None):
"""Split handler string and run it, optionally appending the target path."""
if "|" in handler:
# Pipeline command — run through the shell
subprocess.run(handler, shell=True)
return
parts = shlex.split(handler)
if target:
parts.append(target)
subprocess.run(parts)
def main():
if len(sys.argv) < 2 or sys.argv[1] in ("-h", "--help"):
print(f"Usage: {sys.argv[0]} <music|wifi|mail|im|directory|file>")
print()
print("Smart file opener that dispatches to different programs based on type.")
print()
print("Special keywords:")
print(" music Open music player")
print(" wifi Open WiFi manager")
print(" mail Open email client (aerc)")
print(" im Open instant messaging (Matrix via iamb)")
print(" cb Open clipboard manager")
print(" db Open database client (gobang)")
print(" postman Open API client (atac)")
print()
print("Arguments:")
print(" <path> Directory — open in file manager")
print(" GIF file — open in mpv")
print(" Video file — open in video player")
print(" Audio file — open in audio player")
print(" Image file — open in image viewer")
print(" Other file — open with default handler")
print()
print(f"Config: {CONFIG_PATH}")
sys.exit(0)
target = sys.argv[1]
config = ensure_config()
# Special keywords
if target == "music":
launch(get_handler(config, "music"))
return
if target == "wifi":
launch(get_handler(config, "wifi"))
return
if target == "mail":
launch(get_handler(config, "mail"))
return
if target == "im":
launch(get_handler(config, "im"))
return
if target == "cb":
launch(get_handler(config, "clipboard"))
return
if target == "db":
launch(get_handler(config, "db"))
return
if target == "postman":
launch(get_handler(config, "postman"))
return
# Directory
if os.path.isdir(target):
launch(get_handler(config, "directory"), target)
return
# File
if os.path.isfile(target):
mime = get_mime_type(target)
if mime.startswith("video/"):
launch(get_handler(config, "video"), target)
elif mime.startswith("audio/"):
launch(get_handler(config, "audio"), target)
elif mime == "image/gif":
subprocess.run(["mpv", target])
elif mime.startswith("image/"):
launch(get_handler(config, "image"), target)
elif mime.startswith("text/"):
launch(get_handler(config, "text"), target)
else:
launch(get_handler(config, "default"), target)
return
print(f"Error: '{target}' is not a valid file, directory, or keyword.")
sys.exit(1)
if __name__ == "__main__":
main()