daps-pip 0.0.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.
- daps/__init__.py +0 -0
- daps/main.py +531 -0
- daps_pip-0.0.1.dist-info/METADATA +152 -0
- daps_pip-0.0.1.dist-info/RECORD +6 -0
- daps_pip-0.0.1.dist-info/WHEEL +4 -0
- daps_pip-0.0.1.dist-info/entry_points.txt +2 -0
daps/__init__.py
ADDED
|
File without changes
|
daps/main.py
ADDED
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
import ctypes
|
|
3
|
+
import glob
|
|
4
|
+
import importlib.util
|
|
5
|
+
import math
|
|
6
|
+
import os
|
|
7
|
+
import pathlib
|
|
8
|
+
import platform
|
|
9
|
+
import readline
|
|
10
|
+
import shutil
|
|
11
|
+
import signal
|
|
12
|
+
import subprocess
|
|
13
|
+
import sys
|
|
14
|
+
from itertools import zip_longest
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
# DO NOT MODIFY ANYTHING BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING!
|
|
18
|
+
# Colourwgfues
|
|
19
|
+
COLOR_RE = "\033[0m"
|
|
20
|
+
COLOR_USER = "\033[92m"
|
|
21
|
+
COLOR_HOST = "\033[94m"
|
|
22
|
+
COLOR_CWD = "\033[96m"
|
|
23
|
+
COLOR_ERR = "\033[91m"
|
|
24
|
+
|
|
25
|
+
ROSEWATER = "\033[38;2;245;224;220m"
|
|
26
|
+
FLAMINGO = "\033[38;2;242;205;205m"
|
|
27
|
+
PINK = "\033[38;2;245;194;231m"
|
|
28
|
+
MAUVE = "\033[38;2;203;166;247m"
|
|
29
|
+
RED = "\033[38;2;243;139;168m"
|
|
30
|
+
MAROON = "\033[38;2;235;160;172m"
|
|
31
|
+
PEACH = "\033[38;2;250;179;135m"
|
|
32
|
+
YELLOW = "\033[38;2;249;226;175m"
|
|
33
|
+
GREEN = "\033[38;2;166;227;161m"
|
|
34
|
+
TEAL = "\033[38;2;148;226;213m"
|
|
35
|
+
SKY = "\033[38;2;137;220;235m"
|
|
36
|
+
SAPPHIRE = "\033[38;2;116;199;236m"
|
|
37
|
+
BLUE = "\033[38;2;137;180;250m"
|
|
38
|
+
LAVENDER = "\033[38;2;180;190;254m"
|
|
39
|
+
|
|
40
|
+
TEXT = "\033[38;2;205;214;244m"
|
|
41
|
+
SUBTEXT = "\033[38;2;186;194;222m"
|
|
42
|
+
OVERLAY = "\033[38;2;127;132;156m"
|
|
43
|
+
|
|
44
|
+
RESET = "\033[0m"
|
|
45
|
+
BOLD = "\033[1m"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def sysfetch():
|
|
49
|
+
total, used, free = shutil.disk_usage("/")
|
|
50
|
+
os_name = None
|
|
51
|
+
device_id = None
|
|
52
|
+
gpu_name = None
|
|
53
|
+
gpu_pci_path = None
|
|
54
|
+
hostname = open("/etc/hostname").read().strip()
|
|
55
|
+
username = os.getenv("USER", "unknown")
|
|
56
|
+
wm = os.getenv("XDG_CURRENT_DESKTOP", "Unknown")
|
|
57
|
+
productname = open("/sys/devices/virtual/dmi/id/product_name").read().strip()
|
|
58
|
+
term = (
|
|
59
|
+
os.environ.get("TERM_PROGRAM") or os.environ.get("TERM") or "/dev/tty"
|
|
60
|
+
).capitalize()
|
|
61
|
+
uptime = open("/proc/uptime").read().strip().split()
|
|
62
|
+
uptime_seconds = int(math.trunc(float(uptime[0])))
|
|
63
|
+
hours = int(uptime_seconds // 3600)
|
|
64
|
+
minutes = int((uptime_seconds % 3600) // 60)
|
|
65
|
+
seconds = int(uptime_seconds % 60)
|
|
66
|
+
cpu = None
|
|
67
|
+
pacman_dir = "/var/lib/pacman/local/"
|
|
68
|
+
if os.path.exists(pacman_dir):
|
|
69
|
+
packages = sum(1 for entry in os.scandir(pacman_dir) if entry.is_dir())
|
|
70
|
+
else:
|
|
71
|
+
packages = 0
|
|
72
|
+
|
|
73
|
+
# Memory formatting
|
|
74
|
+
TotalGB = None
|
|
75
|
+
AvailableGB = None
|
|
76
|
+
|
|
77
|
+
def kb_to_gb(kb):
|
|
78
|
+
return kb / (1024**2)
|
|
79
|
+
|
|
80
|
+
def to_gb(bytes):
|
|
81
|
+
return bytes / (1024**3)
|
|
82
|
+
|
|
83
|
+
def color_blocks():
|
|
84
|
+
blocks = []
|
|
85
|
+
|
|
86
|
+
for i in range(8):
|
|
87
|
+
blocks.append(f"\033[38;5;{i}m● ")
|
|
88
|
+
|
|
89
|
+
return "".join(blocks) + RESET
|
|
90
|
+
|
|
91
|
+
with open("/proc/meminfo") as mem:
|
|
92
|
+
for line in mem:
|
|
93
|
+
if line.startswith("MemTotal:"):
|
|
94
|
+
TotalGB = kb_to_gb(
|
|
95
|
+
int(line.replace("MemTotal:", "").replace("kB", "").strip())
|
|
96
|
+
)
|
|
97
|
+
if line.startswith("MemAvailable:"):
|
|
98
|
+
AvailableGB = kb_to_gb(
|
|
99
|
+
int(line.replace("MemAvailable:", "").replace("kB", "").strip())
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
with open("/proc/cpuinfo") as f:
|
|
103
|
+
for line in f:
|
|
104
|
+
if line.startswith("model name"):
|
|
105
|
+
cpu = line.split(":", 1)[1].strip()
|
|
106
|
+
break
|
|
107
|
+
|
|
108
|
+
with open("/etc/os-release") as os_file:
|
|
109
|
+
for line in os_file:
|
|
110
|
+
if line.startswith("ID="):
|
|
111
|
+
os_name = line.strip("ID=").replace('"', "").strip().lower()
|
|
112
|
+
|
|
113
|
+
def parse_pci_ids():
|
|
114
|
+
db = {}
|
|
115
|
+
current_vendor = None
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
with open("/usr/share/hwdata/pci.ids") as f:
|
|
119
|
+
for line in f:
|
|
120
|
+
if not line.strip() or line.startswith("#"):
|
|
121
|
+
continue
|
|
122
|
+
|
|
123
|
+
if not line.startswith("\t"):
|
|
124
|
+
parts = line.strip().split(maxsplit=1)
|
|
125
|
+
if len(parts) == 2:
|
|
126
|
+
current_vendor = parts[0].lower()
|
|
127
|
+
else:
|
|
128
|
+
parts = line.strip().split(maxsplit=1)
|
|
129
|
+
if len(parts) == 2 and current_vendor:
|
|
130
|
+
device_id = parts[0].lower()
|
|
131
|
+
db[(current_vendor, device_id)] = parts[1]
|
|
132
|
+
except OSError:
|
|
133
|
+
pass
|
|
134
|
+
|
|
135
|
+
return db
|
|
136
|
+
|
|
137
|
+
def get_gpus():
|
|
138
|
+
db = parse_pci_ids()
|
|
139
|
+
gpus = []
|
|
140
|
+
|
|
141
|
+
for path in glob.glob("/sys/bus/pci/devices/*/class"):
|
|
142
|
+
try:
|
|
143
|
+
with open(path) as f:
|
|
144
|
+
if not f.read().strip().startswith("0x03"):
|
|
145
|
+
continue
|
|
146
|
+
|
|
147
|
+
base = path.rsplit("/", 1)[0]
|
|
148
|
+
|
|
149
|
+
with open(f"{base}/vendor") as v, open(f"{base}/device") as d:
|
|
150
|
+
vendor_id = v.read().strip().replace("0x", "").lower()
|
|
151
|
+
device_id = d.read().strip().replace("0x", "").lower()
|
|
152
|
+
|
|
153
|
+
name = db.get((vendor_id, device_id), f"{vendor_id}:{device_id}")
|
|
154
|
+
|
|
155
|
+
gpus.append(name)
|
|
156
|
+
|
|
157
|
+
except OSError:
|
|
158
|
+
continue
|
|
159
|
+
|
|
160
|
+
return gpus
|
|
161
|
+
|
|
162
|
+
def get_resolution():
|
|
163
|
+
drm_path = Path("/sys/class/drm")
|
|
164
|
+
try:
|
|
165
|
+
for entry in drm_path.iterdir():
|
|
166
|
+
modes_path = entry / "modes"
|
|
167
|
+
|
|
168
|
+
try:
|
|
169
|
+
content = modes_path.read_text()
|
|
170
|
+
first_line = content.splitlines()[0] if content else ""
|
|
171
|
+
|
|
172
|
+
if first_line:
|
|
173
|
+
return first_line
|
|
174
|
+
except (FileNotFoundError, PermissionError, IsADirectoryError):
|
|
175
|
+
continue
|
|
176
|
+
|
|
177
|
+
except FileNotFoundError:
|
|
178
|
+
pass
|
|
179
|
+
|
|
180
|
+
return "Unknown"
|
|
181
|
+
|
|
182
|
+
gpus = get_gpus()
|
|
183
|
+
active_ascii = None
|
|
184
|
+
info_lines = [
|
|
185
|
+
f"{LAVENDER}{username}{RESET}@{LAVENDER}{hostname}{RESET}",
|
|
186
|
+
f"{SUBTEXT}----------------{RESET}",
|
|
187
|
+
f"{LAVENDER}OS ❯{RESET} {TEXT}{os_name}{RESET}",
|
|
188
|
+
f"{LAVENDER}Host ❯{RESET} {TEXT}{productname}{RESET}",
|
|
189
|
+
f"{LAVENDER}Kernel ❯{RESET} {TEXT}{platform.system()} {platform.release()}{RESET}",
|
|
190
|
+
f"{LAVENDER}Uptime ❯{RESET} {TEXT}{hours} hours, {minutes} mins, {seconds} secs{RESET}",
|
|
191
|
+
f"{LAVENDER}Packages ❯{RESET} {TEXT}{packages}{RESET}",
|
|
192
|
+
f"{LAVENDER}Shell ❯{RESET} {TEXT}DAPS - Definitely a Python Shell{RESET}",
|
|
193
|
+
f"{LAVENDER}Terminal ❯{RESET} {TEXT}{term}{RESET}",
|
|
194
|
+
f"{LAVENDER}Resolution ❯{RESET} {TEXT}{get_resolution()}{RESET}",
|
|
195
|
+
f"{LAVENDER}WM ❯{RESET} {TEXT}{wm}{RESET}",
|
|
196
|
+
*[f"{LAVENDER}GPU ❯{RESET} {TEXT}{gpu}{RESET}" for gpu in gpus],
|
|
197
|
+
f"{LAVENDER}CPU ❯{RESET} {TEXT}{cpu}{RESET}",
|
|
198
|
+
f"{LAVENDER}Memory ❯{RESET} {TEXT}{AvailableGB:.2f} GiB / {TotalGB:.2f} GiB{RESET}",
|
|
199
|
+
f"{LAVENDER}Disk ❯{RESET} {TEXT}{to_gb(used):.2f} GiB / {to_gb(total):.2f} GiB{RESET}",
|
|
200
|
+
f"{SUBTEXT}----------------{RESET}",
|
|
201
|
+
f"{color_blocks()} ",
|
|
202
|
+
]
|
|
203
|
+
|
|
204
|
+
if "arch" in os_name.split():
|
|
205
|
+
active_ascii = [
|
|
206
|
+
" -` ",
|
|
207
|
+
" .o+` ",
|
|
208
|
+
" `ooo/ ",
|
|
209
|
+
" `+oooo: ",
|
|
210
|
+
" `+oooooo: ",
|
|
211
|
+
" -+oooooo+: ",
|
|
212
|
+
" `/:-:++oooo+: ",
|
|
213
|
+
" `/++++/+++++++: ",
|
|
214
|
+
" `/++++++++++++++: ",
|
|
215
|
+
" `/+++ooooooooooooo/` ",
|
|
216
|
+
" ./ooosssso++osssssso+` ",
|
|
217
|
+
" .oossssso-````/ossssss+` ",
|
|
218
|
+
" -osssssso. :ssssssso. ",
|
|
219
|
+
" :osssssss/ osssso+++. ",
|
|
220
|
+
" /ossssssss/ +ssssooo/- ",
|
|
221
|
+
" `/ossssso+/:- -:/+osssso+- ",
|
|
222
|
+
" `+sso+:-` `.-/+oso: ",
|
|
223
|
+
" `++:. `-/+/ ",
|
|
224
|
+
" .` `/ ",
|
|
225
|
+
]
|
|
226
|
+
elif "nyarch" in os_name.split():
|
|
227
|
+
active_ascii = [
|
|
228
|
+
" +* ",
|
|
229
|
+
" =**+ ",
|
|
230
|
+
" -****+ ",
|
|
231
|
+
" :#*****= ",
|
|
232
|
+
" :=-:. .#*******- . ",
|
|
233
|
+
" +=++++--+*******=:=++==+: ",
|
|
234
|
+
" -+=+***+=+********#*==+: ",
|
|
235
|
+
" :**#**##*******##***++= ",
|
|
236
|
+
" =#+++***####**+++*:. ",
|
|
237
|
+
" :***+-+#*=+=*#+-=**- ",
|
|
238
|
+
" -*##+*#%%*::-#%%#*+##= ",
|
|
239
|
+
" -#*##%%%%= .#%%%##**+:::::::. ",
|
|
240
|
+
" .::+#**#%%%%= ..:.=%%%%#**#*: ..-=-",
|
|
241
|
+
" .--:.+###*###**-:-::.. *%%%%*+==+..::::. ",
|
|
242
|
+
" :=: =*++++***##: .+****++++*=.. ",
|
|
243
|
+
" ::-+*******+=-: :---:..-=***###*+. ",
|
|
244
|
+
" .*#*+=:. :-:. .:-+***: ",
|
|
245
|
+
" :+=: :- :-+- ",
|
|
246
|
+
" : . ",
|
|
247
|
+
]
|
|
248
|
+
elif "fedora" in os_name.split():
|
|
249
|
+
active_ascii = [
|
|
250
|
+
" .',;::::;,'. ",
|
|
251
|
+
" .';:cccccccccccc:;,. ",
|
|
252
|
+
" .;cccccccccccccccccccccc;. ",
|
|
253
|
+
" .:cccccccccccccccccccccccccc:. ",
|
|
254
|
+
".;ccccccccccccc;.:dddl:.;ccccccc;. ",
|
|
255
|
+
".:ccccccccccccc;OWMKOOXMWd;ccccccc:. ",
|
|
256
|
+
".:ccccccccccccc;KMMc;cc;xMMc;ccccccc:. ",
|
|
257
|
+
",cccccccccccccc;MMM.;cc;;WW:;cccccccc, ",
|
|
258
|
+
":cccccccccccccc;MMM.;cccccccccccccccc: ",
|
|
259
|
+
":ccccccc;oxOOOo;MMM000k.;cccccccccccc: ",
|
|
260
|
+
"cccccc;0MMKxdd:;MMMkddc.;cccccccccccc; ",
|
|
261
|
+
"ccccc;XMO';cccc;MMM.;cccccccccccccccc' ",
|
|
262
|
+
"ccccc;MMo;ccccc;MMW.;ccccccccccccccc; ",
|
|
263
|
+
"ccccc;0MNc.ccc.xMMd;ccccccccccccccc; ",
|
|
264
|
+
"cccccc;dNMWXXXWM0:;cccccccccccccc:, ",
|
|
265
|
+
"cccccccc;.:odl:.;cccccccccccccc:,. ",
|
|
266
|
+
"ccccccccccccccccccccccccccccc:'. ",
|
|
267
|
+
":ccccccccccccccccccccccc:;,.. ",
|
|
268
|
+
" ':cccccccccccccccc::;,. ",
|
|
269
|
+
]
|
|
270
|
+
|
|
271
|
+
assert active_ascii is not None
|
|
272
|
+
|
|
273
|
+
print("\033[?7l", end="") # disable line wrap
|
|
274
|
+
for art, text in zip_longest(active_ascii, info_lines, fillvalue=""):
|
|
275
|
+
# the extra spaces are for padding
|
|
276
|
+
print(f"{LAVENDER}{art}{RESET} {text}")
|
|
277
|
+
print("\033[?7h", end="") # enable line wrap
|
|
278
|
+
print()
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
class Config:
|
|
282
|
+
def __init__(self):
|
|
283
|
+
self.aliases = {}
|
|
284
|
+
self.devicename = False
|
|
285
|
+
self.cleargreet = False
|
|
286
|
+
self.greeter = None
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def loadconf():
|
|
290
|
+
config_dir = os.path.expanduser("~/.config/daps")
|
|
291
|
+
modules_dir = os.path.join(config_dir, "modules")
|
|
292
|
+
config_file = os.path.join(config_dir, "config.py")
|
|
293
|
+
if not os.path.exists(modules_dir):
|
|
294
|
+
os.makedirs(modules_dir)
|
|
295
|
+
if not os.path.exists(config_dir):
|
|
296
|
+
os.makedirs(config_dir)
|
|
297
|
+
|
|
298
|
+
if not os.path.exists(config_file):
|
|
299
|
+
with open(config_file, "w") as f:
|
|
300
|
+
f.write("""
|
|
301
|
+
daps = Config()
|
|
302
|
+
daps.aliases = {}
|
|
303
|
+
daps.devicename = False
|
|
304
|
+
daps.cleargreet = False
|
|
305
|
+
daps.greeter = None
|
|
306
|
+
""")
|
|
307
|
+
|
|
308
|
+
config_parent = os.path.dirname(config_dir)
|
|
309
|
+
if config_parent not in sys.path:
|
|
310
|
+
sys.path.insert(0, config_parent)
|
|
311
|
+
|
|
312
|
+
spec = importlib.util.spec_from_file_location("daps.config", config_file)
|
|
313
|
+
assert spec is not None
|
|
314
|
+
config_module = importlib.util.module_from_spec(spec)
|
|
315
|
+
|
|
316
|
+
setattr(config_module, "Config", Config)
|
|
317
|
+
assert spec.loader
|
|
318
|
+
spec.loader.exec_module(config_module)
|
|
319
|
+
|
|
320
|
+
# Return the daps object as a dict
|
|
321
|
+
return config_module.daps.__dict__
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
loadconf()
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def load_modules():
|
|
328
|
+
"""Load all command modules"""
|
|
329
|
+
modules_dir = os.path.expanduser("~/.config/daps/modules")
|
|
330
|
+
module_manager = os.path.expanduser("~/.config/daps/modules/plugin.py")
|
|
331
|
+
if modules_dir not in sys.path:
|
|
332
|
+
sys.path.insert(0, os.path.dirname(modules_dir))
|
|
333
|
+
modules = {}
|
|
334
|
+
for file in os.listdir(modules_dir):
|
|
335
|
+
if file.endswith(".py") and file != "__init__.py":
|
|
336
|
+
module_name = file[:-3]
|
|
337
|
+
spec = importlib.util.spec_from_file_location(
|
|
338
|
+
module_name, os.path.join(modules_dir, file)
|
|
339
|
+
)
|
|
340
|
+
assert spec is not None
|
|
341
|
+
module = importlib.util.module_from_spec(spec)
|
|
342
|
+
assert spec.loader
|
|
343
|
+
spec.loader.exec_module(module)
|
|
344
|
+
modules[module_name] = module
|
|
345
|
+
|
|
346
|
+
return modules
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
modules = load_modules()
|
|
350
|
+
|
|
351
|
+
# Shenanigans taht make it go brrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
|
|
352
|
+
config = loadconf()
|
|
353
|
+
greeter = config.get("greeter")
|
|
354
|
+
alias = config.get("aliases", {})
|
|
355
|
+
devicename = bool(config.get("devicename", False))
|
|
356
|
+
cleargreet = bool(config.get("cleargreet", False))
|
|
357
|
+
git = bool(config.get("git", True))
|
|
358
|
+
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
|
359
|
+
readline.parse_and_bind("tab: complete")
|
|
360
|
+
readline.parse_and_bind("set show-all-if-ambiguous-on")
|
|
361
|
+
historyfile = os.path.expanduser("~/.daps.history")
|
|
362
|
+
if os.path.exists(historyfile):
|
|
363
|
+
readline.read_history_file(historyfile)
|
|
364
|
+
user = subprocess.run(["whoami"], capture_output=True, text=True).stdout.strip()
|
|
365
|
+
if devicename:
|
|
366
|
+
hostn = subprocess.run(
|
|
367
|
+
"cat /sys/devices/virtual/dmi/id/product_name",
|
|
368
|
+
shell=True,
|
|
369
|
+
capture_output=True,
|
|
370
|
+
text=True,
|
|
371
|
+
).stdout.strip()
|
|
372
|
+
else:
|
|
373
|
+
hostn = subprocess.run(
|
|
374
|
+
["cat", "/etc/hostname"], capture_output=True, text=True
|
|
375
|
+
).stdout.strip()
|
|
376
|
+
cwd = os.getcwd()
|
|
377
|
+
iden = "$"
|
|
378
|
+
if cwd == f"/home/{user}":
|
|
379
|
+
cwd = "~"
|
|
380
|
+
elif cwd == "/root":
|
|
381
|
+
if user == "root":
|
|
382
|
+
cwd = "~"
|
|
383
|
+
iden = "#"
|
|
384
|
+
else:
|
|
385
|
+
pass
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def update():
|
|
389
|
+
print("Updating.. A sudo prompt may appear soon.")
|
|
390
|
+
os.system("rm -rf /tmp/daps/")
|
|
391
|
+
os.system("git clone https://github.com/NytrixLabs/DAPS /tmp/daps")
|
|
392
|
+
os.system("sudo cp /tmp/daps/daps /usr/bin/daps")
|
|
393
|
+
os.system("rm -rf /tmp/daps/")
|
|
394
|
+
print("Done!")
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def clear():
|
|
398
|
+
os.system("clear")
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
def runfc(confsec: str):
|
|
402
|
+
torun = config.get(confsec)
|
|
403
|
+
if not torun:
|
|
404
|
+
return
|
|
405
|
+
os.system(torun)
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
def getgit():
|
|
409
|
+
try:
|
|
410
|
+
result = subprocess.run(
|
|
411
|
+
["git", "rev-parse", "--git-dir"],
|
|
412
|
+
capture_output=True,
|
|
413
|
+
text=True,
|
|
414
|
+
stderr=subprocess.DEVNULL,
|
|
415
|
+
cwd=os.getcwd(),
|
|
416
|
+
)
|
|
417
|
+
if result.returncode != 0:
|
|
418
|
+
return ""
|
|
419
|
+
|
|
420
|
+
branch_result = subprocess.run(
|
|
421
|
+
["git", "rev-parse", "--abbrev-ref", "HEAD"],
|
|
422
|
+
capture_output=True,
|
|
423
|
+
text=True,
|
|
424
|
+
cwd=os.getcwd(),
|
|
425
|
+
)
|
|
426
|
+
branch = branch_result.stdout.strip()
|
|
427
|
+
|
|
428
|
+
status_result = subprocess.run(
|
|
429
|
+
["git", "status", "--porcelain"],
|
|
430
|
+
capture_output=True,
|
|
431
|
+
text=True,
|
|
432
|
+
cwd=os.getcwd(),
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
if status_result.stdout.strip():
|
|
436
|
+
return f" ({branch}*)"
|
|
437
|
+
else:
|
|
438
|
+
return f" ({branch})"
|
|
439
|
+
except:
|
|
440
|
+
return ""
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
# out = subprocess.run([f"{torun}"], capture_output=True, text=True)
|
|
444
|
+
# print(out.stdout)
|
|
445
|
+
clear()
|
|
446
|
+
if greeter == "daps":
|
|
447
|
+
sysfetch()
|
|
448
|
+
else:
|
|
449
|
+
runfc("greeter")
|
|
450
|
+
if git:
|
|
451
|
+
repo = getgit()
|
|
452
|
+
historycleared = 0
|
|
453
|
+
errcode = None
|
|
454
|
+
while True:
|
|
455
|
+
try:
|
|
456
|
+
cwd = os.getcwd()
|
|
457
|
+
home = os.path.expanduser("~")
|
|
458
|
+
if cwd.startswith(home):
|
|
459
|
+
cwd = cwd.replace(home, "~", 1)
|
|
460
|
+
if not errcode:
|
|
461
|
+
print(
|
|
462
|
+
f"{COLOR_USER}{user}{COLOR_RE}@{COLOR_HOST}{hostn}{COLOR_RE} {COLOR_USER}({iden}){COLOR_RE} - {COLOR_CWD}{cwd}{COLOR_RE} {repo}"
|
|
463
|
+
)
|
|
464
|
+
else:
|
|
465
|
+
print(
|
|
466
|
+
f"{COLOR_ERR}[{errcode}]{COLOR_RE} - {COLOR_USER}{user}{COLOR_RE}@{COLOR_HOST}{hostn}{COLOR_RE} {COLOR_USER}({iden}){COLOR_RE} - {COLOR_CWD}{cwd}"
|
|
467
|
+
)
|
|
468
|
+
try:
|
|
469
|
+
cmd = input(f"{COLOR_USER}>{COLOR_HOST} ").strip()
|
|
470
|
+
except EOFError:
|
|
471
|
+
print("An exception occurred at ^D - EOFError.\n DAPS will now close.")
|
|
472
|
+
sys.exit(123)
|
|
473
|
+
if cmd in alias:
|
|
474
|
+
cmd = alias[cmd]
|
|
475
|
+
if not cmd:
|
|
476
|
+
continue
|
|
477
|
+
cmdsp = cmd.split()
|
|
478
|
+
ccmd = cmdsp[0]
|
|
479
|
+
ccmar = cmdsp[1:]
|
|
480
|
+
all_cmds = [ccmd] + ccmar
|
|
481
|
+
if ccmd == "cd":
|
|
482
|
+
dir = pathlib.Path(ccmar[0] if ccmar else "~")
|
|
483
|
+
if not dir.expanduser().exists():
|
|
484
|
+
print("cd: No such file or directory")
|
|
485
|
+
errcode = 2
|
|
486
|
+
os.chdir(dir.expanduser())
|
|
487
|
+
elif ccmd == "clear":
|
|
488
|
+
clear()
|
|
489
|
+
if cleargreet:
|
|
490
|
+
runfc("greeter")
|
|
491
|
+
elif ccmd == "clearhist":
|
|
492
|
+
readline.clear_history()
|
|
493
|
+
open(historyfile, "w").close()
|
|
494
|
+
historycleared = 1
|
|
495
|
+
print(
|
|
496
|
+
f"{COLOR_ERR}ATTENTION! History will no longer be recorded until you restart the shell!s"
|
|
497
|
+
)
|
|
498
|
+
elif ccmd == "update":
|
|
499
|
+
update()
|
|
500
|
+
elif ccmd == "exit":
|
|
501
|
+
sys.exit(255)
|
|
502
|
+
elif "." in ccmd:
|
|
503
|
+
module_name, func_name = ccmd.split(".", 1)
|
|
504
|
+
if module_name in modules and hasattr(modules[module_name], func_name):
|
|
505
|
+
try:
|
|
506
|
+
func = getattr(modules[module_name], func_name)
|
|
507
|
+
result = func(ccmar) if ccmar else func()
|
|
508
|
+
errcode = 0
|
|
509
|
+
except Exception as e:
|
|
510
|
+
print(f"Error running {ccmd}: {e}")
|
|
511
|
+
errcode = 1
|
|
512
|
+
else:
|
|
513
|
+
print(f"Command not found: {ccmd}")
|
|
514
|
+
errcode = 127
|
|
515
|
+
elif shutil.which(ccmd):
|
|
516
|
+
result = subprocess.run(
|
|
517
|
+
[ccmd] + ccmar, stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr
|
|
518
|
+
)
|
|
519
|
+
errcode = result.returncode
|
|
520
|
+
else:
|
|
521
|
+
result = subprocess.run(cmd, shell=True)
|
|
522
|
+
errcode = result.returncode
|
|
523
|
+
except Exception as e:
|
|
524
|
+
print(f"An exception has occurred. {e}")
|
|
525
|
+
finally:
|
|
526
|
+
if errcode == "0":
|
|
527
|
+
errcode = False
|
|
528
|
+
if historycleared:
|
|
529
|
+
readline.clear_history()
|
|
530
|
+
else:
|
|
531
|
+
readline.write_history_file(historyfile)
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: daps-pip
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: DAPS - Definitely a Python Shell
|
|
5
|
+
Author: arizona
|
|
6
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Topic :: Terminals
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# DAPS
|
|
13
|
+
|
|
14
|
+
DAPS is a shell written in pure Python. No other language is used, except JSON for the configuration file.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
DAPS is available on PyPl!
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install daps-pip
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
Basic shell commands work, like `cd` or `ls`.
|
|
27
|
+
|
|
28
|
+
Built-in commands include:
|
|
29
|
+
|
|
30
|
+
- `clear` – Clears everything on screen.
|
|
31
|
+
- `clearhist` – Clears shell history. After running this, the shell cannot record history until restarted. This prevents bugs.
|
|
32
|
+
- `exit` – Exits the shell.
|
|
33
|
+
- `update` – Updates DAPS by cloning the repository into a temp folder and copying it into `/usr/bin`.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
### `clear`
|
|
38
|
+
|
|
39
|
+
The `clear` command clears the screen.
|
|
40
|
+
See **Configuration** below for options.
|
|
41
|
+
|
|
42
|
+
### `clearhist`
|
|
43
|
+
|
|
44
|
+
Clears shell history.
|
|
45
|
+
The shell cannot record history if this command has been run, until the shell is restarted. This is a safety feature.
|
|
46
|
+
|
|
47
|
+
### `exit`
|
|
48
|
+
|
|
49
|
+
Exits the shell.
|
|
50
|
+
|
|
51
|
+
### `update`
|
|
52
|
+
|
|
53
|
+
Updates DAPS by cloning the repository into a temporary folder and copying the new version into `/usr/bin`.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Configuration
|
|
58
|
+
|
|
59
|
+
The shell creates a file named `config.json` in the `~/.config/daps/` directory (where `~` is your current user's home folder).
|
|
60
|
+
|
|
61
|
+
By default, the file contains:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
To start editing, add options inside the braces:
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### `"greeter"`
|
|
77
|
+
|
|
78
|
+
The `"greeter"` option runs a command every time the shell starts:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"greeter": "fastfetch"
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
This will run `fastfetch` at shell start.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
### `"aliases"`
|
|
91
|
+
|
|
92
|
+
The `"aliases"` option lets you create shell aliases:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"aliases": {
|
|
97
|
+
"ll": "ls -l"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Note:** Built-in shell commands cannot be used in aliases. Built-in commands are listed above.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### `"cleargreet"`
|
|
107
|
+
|
|
108
|
+
The `"cleargreet"` option specifies whether the greeter should run when using `clear`:
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"cleargreet": "yes"
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
### `"devicename"`
|
|
119
|
+
|
|
120
|
+
The `"devicename"` option specifies if the **device name** (e.g., `ASUS E410MA`) should be used instead of the hostname (e.g., `fedora`):
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"devicename": true
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
### Example of a full config
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"aliases": {
|
|
135
|
+
"ll": "ls -l"
|
|
136
|
+
},
|
|
137
|
+
"greeter": "fastfetch",
|
|
138
|
+
"cleargreet": "yes",
|
|
139
|
+
"devicename": true
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## More Information
|
|
146
|
+
|
|
147
|
+
- More features are coming soon!
|
|
148
|
+
- DAPS is protected by the **GNU license**, meaning any contributions or derivatives of the program **must be fully open source**.
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
**© 2026, Nytrix Labs**
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
daps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
daps/main.py,sha256=yHZcZpWXCPwDB_hNzvuwc8o22H0BkQFoEQkz2ZivCBM,17953
|
|
3
|
+
daps_pip-0.0.1.dist-info/METADATA,sha256=qjFIkgyBGLide3zbVHxCn4osKNloyfzOjWFNBPEOwJM,2711
|
|
4
|
+
daps_pip-0.0.1.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
5
|
+
daps_pip-0.0.1.dist-info/entry_points.txt,sha256=H5rHXYKOvylJgnWOS1yYlp5tLTSeFSicVPIyUZYwl5U,50
|
|
6
|
+
daps_pip-0.0.1.dist-info/RECORD,,
|