]> git.scottworley.com Git - nix-env-apps/commitdiff
Basic functionality
authorScott Worley <scottworley@scottworley.com>
Sat, 13 Sep 2025 17:24:52 +0000 (10:24 -0700)
committerScott Worley <scottworley@scottworley.com>
Sat, 13 Sep 2025 17:24:52 +0000 (10:24 -0700)
.gitignore [new file with mode: 0644]
apps.py [new file with mode: 0644]
default.nix [new file with mode: 0644]
setup.py [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..1d26af3
--- /dev/null
@@ -0,0 +1,2 @@
+.mypy_cache
+result
diff --git a/apps.py b/apps.py
new file mode 100644 (file)
index 0000000..4b0d0d5
--- /dev/null
+++ b/apps.py
@@ -0,0 +1,101 @@
+from gi.repository import Gtk
+import os
+import subprocess
+
+import gi
+gi.require_version("Gtk", "4.0")
+
+
+def on_edit(_):
+    config_dir = os.path.join(
+        os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config')),
+        'nixpkgs',
+        'overlays')
+    os.makedirs(config_dir, exist_ok=True)
+    config_file = os.path.join(config_dir, 'userPackages.nix')
+    try:
+        with open(config_file, mode="x") as f:
+            f.write('''final: prev: {
+  userPackages = final.buildEnv {
+    name = "userPackages";
+    paths = (with final; [
+
+
+
+    ];
+  };
+}
+''')
+    except FileExistsError:
+        pass
+    subprocess.run(['xdg-open', config_file], check=True)
+
+
+def try_exec_terminal(terminal, args):
+    try:
+        os.execvp(terminal, [terminal] + args)
+    except FileNotFoundError:
+        pass
+
+
+def on_apply(_):
+    command = ['nix-env', '-riA', 'nixos.userPackages']
+    command_string = ' '.join(command)
+    close_string = ''' && read -p "SUCCESS: Press ENTER to close this window" || read -p "FAILURE: Press ENTER to close this window"'''
+    # This should be a simple `xdg-terminal` invocation, but as of 2025,
+    # xdg-terminal is extremely broken in Gnome:
+    #   * It doesn't cause a terminal window to appear
+    #   * It doesn't run the given command
+    #   * It exits with status 0, so you can't even tell that it failed
+    #   * There's no way for the user to configure their preferred terminal?
+    # So we just try launching a whole bunch of terminals until we find one
+    # that works
+    if os.fork() == 0:
+        try_exec_terminal('kitty', ['sh', '-c', command_string + close_string])
+        try_exec_terminal(
+            'alactritty', [
+                '-e', 'sh', '-c', command_string + close_string])
+        try_exec_terminal('kgx', ['--'] + command)
+        try_exec_terminal(
+            'konsole', [
+                '-e', 'sh', '-c', command_string + close_string])
+        try_exec_terminal('xfce4-terminal', ['--hold', '-e', command_string])
+        try_exec_terminal('st', ['sh', '-c', command_string + close_string])
+        try_exec_terminal(
+            'urxvt', [
+                '-e', 'sh', '-c', command_string + close_string])
+        try_exec_terminal(
+            'xterm', [
+                '-e', 'sh', '-c', command_string + close_string])
+
+        # Don't even try gnome-terminal.  Sometimes it will start, but not run the command,
+        # and exit with status 0 so we wouldn't even be able to tell that there was a problem.
+        # try_exec_terminal('gnome-terminal', ['--', 'sh', '-c', command_string + close_string])
+
+        # As a last resort, run the command directly, without a terminal, where
+        # the user probably can't see it.  :(
+        os.execvp(command[0], command)
+
+
+def on_activate(app):
+    win = Gtk.ApplicationWindow(application=app)
+    box = Gtk.Box()
+    box.set_orientation(Gtk.Orientation.VERTICAL)
+    edit = Gtk.Button(label="Edit Configuration")
+    apply = Gtk.Button(label="Apply Configuration")
+    edit.connect('clicked', on_edit)
+    apply.connect('clicked', on_apply)
+    box.append(edit)
+    box.append(apply)
+    win.set_child(box)
+    win.present()
+
+
+def main():
+    app = Gtk.Application(application_id='net.chkno.nix-env-apps')
+    app.connect('activate', on_activate)
+    app.run(None)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/default.nix b/default.nix
new file mode 100644 (file)
index 0000000..17ddac7
--- /dev/null
@@ -0,0 +1,14 @@
+{ pkgs ? import <nixpkgs> { } }:
+pkgs.python3Packages.callPackage ({ buildPythonPackage, gobject-introspection
+  , gtk4, lib, pygobject3, wrapGAppsHook4, }:
+  buildPythonPackage rec {
+    pname = "apps";
+    version = "1.0";
+    src = lib.cleanSource ./.;
+    nativeBuildInputs = [ gobject-introspection wrapGAppsHook4 ];
+
+    buildInputs = [ gtk4 ];
+
+    pythonPath = [ pygobject3 ];
+
+  }) { }
diff --git a/setup.py b/setup.py
new file mode 100644 (file)
index 0000000..63dd5f7
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,11 @@
+from setuptools import setup
+
+setup(
+    name='apps',
+    py_modules=['apps'],
+    entry_points={
+        'console_scripts': [
+            'apps = apps:main',
+        ],
+    }
+)