desktop-cli 0.1.0__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.
desktop_cli/__init__.py
ADDED
|
File without changes
|
desktop_cli/main.py
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
desktop-cli — interact with .desktop files from the command line.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
import argparse
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def desktop_dirs() -> list[Path]:
|
|
13
|
+
xdg_home = Path(os.environ.get("XDG_DATA_HOME", Path.home() / ".local/share"))
|
|
14
|
+
xdg_dirs = os.environ.get("XDG_DATA_DIRS", "/usr/share:/usr/local/share")
|
|
15
|
+
return [xdg_home / "applications"] + [
|
|
16
|
+
Path(d) / "applications" for d in xdg_dirs.split(":")
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def find_desktop_file(name: str) -> Path | None:
|
|
21
|
+
"""Find a .desktop file by name, searching XDG dirs in order."""
|
|
22
|
+
if not name.endswith(".desktop"):
|
|
23
|
+
name += ".desktop"
|
|
24
|
+
for d in desktop_dirs():
|
|
25
|
+
candidate = d / name
|
|
26
|
+
if candidate.exists():
|
|
27
|
+
return candidate
|
|
28
|
+
return None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def find_all_desktop_files() -> list[Path]:
|
|
32
|
+
seen = set()
|
|
33
|
+
results = []
|
|
34
|
+
for d in desktop_dirs():
|
|
35
|
+
if not d.exists():
|
|
36
|
+
continue
|
|
37
|
+
for f in sorted(d.glob("*.desktop")):
|
|
38
|
+
if f.name not in seen:
|
|
39
|
+
seen.add(f.name)
|
|
40
|
+
results.append(f)
|
|
41
|
+
return results
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# ── Commands ──────────────────────────────────────────────────────────────────
|
|
45
|
+
|
|
46
|
+
def cmd_cat(args):
|
|
47
|
+
"""Print the contents of a desktop file."""
|
|
48
|
+
path = find_desktop_file(args.name)
|
|
49
|
+
if not path:
|
|
50
|
+
print(f"desktop: not found: {args.name}", file=sys.stderr)
|
|
51
|
+
sys.exit(1)
|
|
52
|
+
print(path.read_text(), end="")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def cmd_path(args):
|
|
56
|
+
"""Print the full path of a desktop file."""
|
|
57
|
+
path = find_desktop_file(args.name)
|
|
58
|
+
if not path:
|
|
59
|
+
print(f"desktop: not found: {args.name}", file=sys.stderr)
|
|
60
|
+
sys.exit(1)
|
|
61
|
+
print(path)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def cmd_list(args):
|
|
65
|
+
"""List all available desktop files."""
|
|
66
|
+
for f in find_all_desktop_files():
|
|
67
|
+
if args.full:
|
|
68
|
+
print(f)
|
|
69
|
+
else:
|
|
70
|
+
print(f.stem if args.no_extension else f.name)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def cmd_exec(args):
|
|
74
|
+
"""Print the Exec= line of a desktop file."""
|
|
75
|
+
path = find_desktop_file(args.name)
|
|
76
|
+
if not path:
|
|
77
|
+
print(f"desktop: not found: {args.name}", file=sys.stderr)
|
|
78
|
+
sys.exit(1)
|
|
79
|
+
for line in path.read_text().splitlines():
|
|
80
|
+
if line.startswith("Exec="):
|
|
81
|
+
cmd = line[5:].strip()
|
|
82
|
+
if not args.raw:
|
|
83
|
+
for code in ["%u", "%U", "%f", "%F", "%i", "%c", "%k"]:
|
|
84
|
+
cmd = cmd.replace(code, "")
|
|
85
|
+
cmd = cmd.strip()
|
|
86
|
+
print(cmd)
|
|
87
|
+
return
|
|
88
|
+
print(f"desktop: no Exec= found in {args.name}", file=sys.stderr)
|
|
89
|
+
sys.exit(1)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def cmd_dirs(args):
|
|
93
|
+
"""Print the directories searched for desktop files."""
|
|
94
|
+
for d in desktop_dirs():
|
|
95
|
+
print(d)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
# ── Entry point ───────────────────────────────────────────────────────────────
|
|
99
|
+
|
|
100
|
+
def main():
|
|
101
|
+
parser = argparse.ArgumentParser(
|
|
102
|
+
prog="desktop",
|
|
103
|
+
description="Interact with .desktop files from the command line.")
|
|
104
|
+
sub = parser.add_subparsers(dest="command", required=True)
|
|
105
|
+
|
|
106
|
+
p_cat = sub.add_parser("cat", help="Print contents of a desktop file")
|
|
107
|
+
p_cat.add_argument("name", help="Desktop file name (with or without .desktop)")
|
|
108
|
+
p_cat.set_defaults(func=cmd_cat)
|
|
109
|
+
|
|
110
|
+
p_path = sub.add_parser("path", help="Print full path of a desktop file")
|
|
111
|
+
p_path.add_argument("name")
|
|
112
|
+
p_path.set_defaults(func=cmd_path)
|
|
113
|
+
|
|
114
|
+
p_list = sub.add_parser("list", help="List available desktop files")
|
|
115
|
+
p_list.add_argument("--full", action="store_true", help="Print full paths")
|
|
116
|
+
p_list.add_argument("--no-extension", action="store_true", help="Strip .desktop suffix")
|
|
117
|
+
p_list.set_defaults(func=cmd_list)
|
|
118
|
+
|
|
119
|
+
p_exec = sub.add_parser("exec", help="Print the Exec= command of a desktop file")
|
|
120
|
+
p_exec.add_argument("name")
|
|
121
|
+
p_exec.add_argument("--raw", action="store_true", help="Don't strip %u/%f/etc placeholders")
|
|
122
|
+
p_exec.set_defaults(func=cmd_exec)
|
|
123
|
+
|
|
124
|
+
p_dirs = sub.add_parser("dirs", help="Print directories searched for desktop files")
|
|
125
|
+
p_dirs.set_defaults(func=cmd_dirs)
|
|
126
|
+
|
|
127
|
+
args = parser.parse_args()
|
|
128
|
+
args.func(args)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
if __name__ == "__main__":
|
|
132
|
+
main()
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: desktop-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A CLI for interacting with .desktop files
|
|
5
|
+
Author: readwithai
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/readwithai/desktop-cli
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Topic :: Desktop Environment
|
|
13
|
+
Requires-Python: >=3.9
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# desktop-cli
|
|
17
|
+
A cli for interacting with desktop files.
|
|
18
|
+
|
|
19
|
+
Desktop files are the executable files of desktop environments on Linux. [Read my blog post on the topic](https://readwithai.substack.com/p/a-primer-on-linux-desktop-files).
|
|
20
|
+
|
|
21
|
+
This is unreviewed AI-generated code.
|
|
22
|
+
|
|
23
|
+
## Alternatives and prior work
|
|
24
|
+
You could try using `locate` or similar to find desktop files. Desktop files often live in knowns locations and addition files are added to the `XDG_DATA_DIRS` environment variable. You could use this to write a shell one-liner. `gtk-launch` can be used to start desktop files (and will find them on the "desktop path").
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
pipx instal desktop-cli
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
`desktop list`
|
|
31
|
+
|
|
32
|
+
`desktop cat obsidian.desktop`
|
|
33
|
+
|
|
34
|
+
`desktop path obsidian.destop`
|
|
35
|
+
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
desktop_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
desktop_cli/main.py,sha256=MgMHVYnQd1XkXbQfHqt2kwul9qshbJgdzCQZ95X0qM4,4340
|
|
3
|
+
desktop_cli-0.1.0.dist-info/METADATA,sha256=fbLXtGLJn6G2C30uf1Qnj_YnO82oMNtMA9pic7ntIKQ,1247
|
|
4
|
+
desktop_cli-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
5
|
+
desktop_cli-0.1.0.dist-info/entry_points.txt,sha256=e2IKBRnDmrDGquaGMzAPyOJID6jZJoDtg9zH4KQcf3U,50
|
|
6
|
+
desktop_cli-0.1.0.dist-info/top_level.txt,sha256=x41vOt1pr0UOuJBAavmjZ_1AF2KLi_SxQYrx8tJU8P0,12
|
|
7
|
+
desktop_cli-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
desktop_cli
|