]>
git.scottworley.com Git - nix-env-apps/blob - apps.py
1 # nix-env-apps: Manage declarative nix-env with a GUI
3 # This program is free software: you can redistribute it and/or modify it
4 # under the terms of the GNU General Public License as published by the
5 # Free Software Foundation, version 3.
9 from typing
import Any
, Callable
12 gi
.require_version("Gtk", "4.0")
13 from gi
.repository
import Gtk
# nopep8 pylint: disable=wrong-import-position
16 def on_edit(_
: Any
) -> None:
17 config_dir
= os
.path
.join(
18 os
.environ
.get('XDG_CONFIG_HOME', os
.path
.expanduser('~/.config')),
21 os
.makedirs(config_dir
, exist_ok
=True)
22 config_file
= os
.path
.join(config_dir
, 'userPackages.nix')
24 with open(config_file
, mode
="x", encoding
='utf-8') as f
:
25 f
.write('''final: prev: {
26 userPackages = final.buildEnv {
27 name = "userPackages";
36 except FileExistsError
:
38 subprocess
.run(['xdg-open', config_file
], check
=True)
41 def try_exec_terminal(terminal
: str, args
: list[str]) -> None:
43 os
.execvp(terminal
, [terminal
] + args
)
44 except FileNotFoundError
:
48 def on_apply(_
: Any
) -> None:
49 command
= ['nix-env', '-riA', 'nixos.userPackages']
50 command_string
= ' '.join(command
)
52 ''' && read -p "SUCCESS: Press ENTER to close this window"''' +
53 ''' || read -p "FAILURE: Press ENTER to close this window"''')
54 # This should be a simple `xdg-terminal` invocation, but as of 2025,
55 # xdg-terminal is extremely broken in Gnome:
56 # * It doesn't cause a terminal window to appear
57 # * It doesn't run the given command
58 # * It exits with status 0, so you can't even tell that it failed
59 # * There's no way for the user to configure their preferred terminal?
60 # So we just try launching a whole bunch of terminals until we find one
63 try_exec_terminal('kitty', ['sh', '-c', command_string
+ close_string
])
66 '-e', 'sh', '-c', command_string
+ close_string
])
67 try_exec_terminal('kgx', ['--'] + command
)
70 '-e', 'sh', '-c', command_string
+ close_string
])
71 try_exec_terminal('xfce4-terminal', ['--hold', '-e', command_string
])
72 try_exec_terminal('st', ['sh', '-c', command_string
+ close_string
])
75 '-e', 'sh', '-c', command_string
+ close_string
])
78 '-e', 'sh', '-c', command_string
+ close_string
])
80 # Don't even try gnome-terminal. Sometimes it will start, but not run the command,
81 # and exit with status 0 so we wouldn't even be able to tell that there was a problem.
82 # try_exec_terminal('gnome-terminal', ['--', 'sh', '-c', command_string + close_string])
84 # As a last resort, run the command directly, without a terminal, where
85 # the user probably can't see it. :(
86 os
.execvp(command
[0], command
)
89 def make_button(label
: str, action
: Callable
[[Any
], None]) -> Gtk
.Button
:
90 button
= Gtk
.Button(label
=label
)
91 button
.connect('clicked', action
)
92 button
.set_margin_top(10)
93 button
.set_margin_start(10)
94 button
.set_margin_end(10)
95 button
.set_margin_bottom(10)
99 def on_activate(app
: Gtk
.Application
) -> None:
100 win
= Gtk
.ApplicationWindow(application
=app
)
101 win
.set_title('Apps')
103 box
.set_orientation(Gtk
.Orientation
.VERTICAL
)
104 edit
= make_button("Edit Configuration", on_edit
)
105 apply = make_button("Apply Configuration", on_apply
)
113 app
= Gtk
.Application(application_id
='net.chkno.nix-env-apps')
114 app
.connect('activate', on_activate
)
118 if __name__
== '__main__':