Repository navigation
Expand file tree
/
Copy pathshell-json-set
More file actions
executable file
·80 lines (66 loc) · 2.97 KB
/
Copy pathshell-json-set
File metadata and controls
executable file
·80 lines (66 loc) · 2.97 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
#!/usr/bin/env python3
"""Set one top-level key of ~/.config/omarchy/shell.json from a fresh read.
shell-json-set idle '{"lock": 300, "screensaver": 150}'
Read, change and replace happen in one short step, so a change another writer
made a moment ago (lock-explorer, the omarchy CLIs) is never overwritten from a
stale copy. Only the named key changes.
"""
import json, os, sys, tempfile
PATH = os.path.join(os.environ.get("HOME", ""), ".config/omarchy/shell.json")
# Config and theme files are read only when they are regular files (a symlink
# to one is fine, dotfile managers use them; a FIFO or device is not), and at
# most READ_LIMIT bytes, so a strange file cannot hang or flood the helper.
READ_LIMIT = 1024 * 1024
def read_capped(path, limit=READ_LIMIT):
try:
if not os.path.isfile(path) or os.path.getsize(path) > limit:
return None
with open(path, encoding="utf-8") as f:
text = f.read(limit + 1)
return text if len(text) <= limit else None
except (OSError, UnicodeDecodeError):
return None
def main(argv):
if len(argv) != 2 or argv[0] not in ("idle",):
print(__doc__, file=sys.stderr)
return 2
value = json.loads(argv[1])
if argv[0] == "idle":
if not isinstance(value, dict) or any(k not in ("lock", "screensaver") for k in value) \
or any(not isinstance(v, int) or v < 0 or v > 86400 for v in value.values()):
print("invalid idle value", file=sys.stderr)
return 2
target = os.path.realpath(PATH)
text = read_capped(target)
if text is None:
print("shell.json is not a readable regular file", file=sys.stderr)
return 1
doc = json.loads(text)
if not isinstance(doc, dict):
print("shell.json is not an object", file=sys.stderr)
return 1
if doc.get(argv[0]) == value:
return 0
doc[argv[0]] = value
fd, tmp = tempfile.mkstemp(prefix=".shell.json.", dir=os.path.dirname(target))
with os.fdopen(fd, "w", encoding="utf-8") as f:
f.write(json.dumps(doc, indent=2, ensure_ascii=False) + "\n")
os.chmod(tmp, os.stat(target).st_mode & 0o777)
os.replace(tmp, target)
return 0
def _refused(err):
"""A readable line for a write the filesystem would not allow.
A read-only ~/.config (home-manager and friends put one there), a file made
immutable, or a full disk all arrive here as an OSError. The panel shows
whatever comes back on stderr, and a Python traceback is no use to anybody.
"""
home = os.environ.get("HOME", "")
where = os.path.dirname(getattr(err, "filename", "") or "") or "that folder"
return ("Could not write in %s: %s. Lacquer stopped there.\n"
"A read-only folder, an immutable file or a full disk will do this."
% (where.replace(home, "~") if home else where, err.strerror or err))
if __name__ == "__main__":
try:
sys.exit(main(sys.argv[1:]))
except OSError as err:
sys.exit(_refused(err))