Hyprland icon indicating copy to clipboard operation
Hyprland copied to clipboard

nix: home-manager: add config wrapper (wip)

Open spikespaz opened this issue 3 years ago • 10 comments

@fufexan @viperML

This is a work-in-progress PR. Its intent is to introduce a complete wrapper module for Nix Home Manager for all configurations presented on the Wiki.

You can see a current example utilizing all implemented features:

https://github.com/spikespaz/dotfiles/tree/master/users/jacob/desktops/hyprland

Help is appreciated, if you can spare the time. Let me now and we can get organized.

Comments, questions, concerns? I am eager to discuss.

Checklist

  • [ ] Ensure naming scheme is consistent, and renames are appropriate.
  • [ ] Update nix/README.md for an overview and guide.
  • [ ] Figure out how to generate nice Nix documentation, link it to the Wiki.
  • [ ] Ensure every configuration is implemented
    • [X] General
    • [X] Decoration
    • [X] Layouts
      • [X] Dwindle Layout
      • [ ] Master Layout
    • [X] Animations
      • [X] Bezier Curves
    • [X] Input
      • [X] Keyboard
      • [X] Touchpad
      • [ ] Touchdevice
    • [X] Gestures
    • [X] Misc
    • [ ] Monitors
    • [ ] Binds
      • [ ] Dispatchers
    • [X] Window Rules
      • [X] Window Rule Groups
    • [X] Debug
  • [ ] Ensure every configuration is documented
    • [X] General
    • [ ] Decoration
    • [ ] Layouts
      • [ ] Dwindle Layout
      • [ ] Master Layout
    • [ ] Animations
      • [ ] Bezier Curves
    • [X] Input
      • [ ] Keyboard
      • [X] Touchpad
      • [ ] Touchdevice
    • [ ] Gestures
    • [ ] Misc
    • [ ] Monitors
    • [ ] Binds
      • [ ] Dispatchers
    • [ ] Window Rules
      • [ ] Window Rule Groups
    • [ ] Debug
  • [ ] Ensure options have correct types, new ones if needed
    • [ ] General
    • [ ] Decoration
    • [ ] Layouts
      • [ ] Dwindle Layout
      • [ ] Master Layout
    • [ ] Animations
      • [ ] Bezier Curves
    • [ ] Input
      • [ ] Keyboard
      • [ ] Touchpad
      • [ ] Touchdevice
    • [ ] Gestures
    • [ ] Misc
    • [ ] Monitors
    • [ ] Binds
      • [ ] Dispatchers
    • [ ] Window Rules
      • [ ] Window Rule Groups
    • [ ] Debug

Layout

nix
├── default.nix
├── hm-module
│   ├── config
│   │   ├── animations.nix
│   │   ├── binds.nix
│   │   ├── debug.nix
│   │   ├── decoration.nix
│   │   ├── dwindle.nix
│   │   ├── general.nix
│   │   ├── gestures.nix
│   │   ├── input.nix
│   │   ├── keyboard.nix
│   │   ├── misc.nix
│   │   ├── touchpad.nix
│   │   └── windowrules.nix
│   ├── config.nix
│   └── default.nix
├── meson-build.patch
├── module.nix
├── pr.md
├── update-inputs.sh
├── wlroots.nix
├── xwayland-hidpi.patch
└── xwayland-vsync.patch

Introduced hm-module/ and all children. config.nix is the template for the config file to write, while config/ houses the options avaiable to the user. Also observe default.nix.

Module is exposed as a flake output, hyprland.homeManagerModules.default.

spikespaz avatar Oct 18 '22 09:10 spikespaz

I don't maintain this project anymore, and even less hunders of lines of nix by you.

viperML avatar Oct 18 '22 10:10 viperML

Oh my god that's huge. It's great, no doubt, but I think we can do better than this.

I'd rather spend the time implementing a TOML config in Hyprland itself, and then utilising Nix's formats.toToml over a freeform module to generate the config. I think it's way easier to maintain and also benefits non-Nix users.

fufexan avatar Oct 18 '22 10:10 fufexan

lmfao

vaxerski avatar Oct 18 '22 11:10 vaxerski

Oh my god that's huge. It's great, no doubt, but I think we can do better than this.

I'd rather spend the time implementing a TOML config in Hyprland itself, and then utilising Nix's formats.toToml over a freeform module to generate the config. I think it's way easier to maintain and also benefits non-Nix users.

It would be pretty peasy to switch it to toml

spikespaz avatar Oct 18 '22 13:10 spikespaz

I think vaxry likes his shit config parser

spikespaz avatar Oct 18 '22 13:10 spikespaz

I don't get it; why is this being worked on in upstream hyperland, instead of Home-Manager?

algorithmiker avatar Oct 28 '22 09:10 algorithmiker

I don't get it; why is this being worked on in upstream hyperland, instead of Home-Manager?

  1. They move slow, and it wouldn't let us add/remove options as soon as they're added to the code.
  2. The (corresponding) Nixpkgs package has been outdated for a long time.

Basically we aim towards being autonomous, while following best practices from Nixpkgs and HM.

fufexan avatar Oct 28 '22 18:10 fufexan

Yo this might be too trivial for this purpose, but i just do it with these 4 functions:

{
mkValueString = value:(
    if builtins.isBool value then	(
        if value then "true" else "false"
    )
    else if (builtins.isFloat value || builtins.isInt value) then	(
        builtins.toString value
    )
    else if builtins.isString value then (
        value
    )
    else if (
        (builtins.isList value) &&
        ((builtins.length value) == 2) &&
        ((builtins.isFloat (builtins.elemAt value 0)) || (builtins.isFloat (builtins.elemAt value 0))) &&
        ((builtins.isFloat (builtins.elemAt value 1)) || (builtins.isFloat (builtins.elemAt value 1)))
    ) then (
        builtins.toString (builtins.elemAt value 0) + " " + builtins.toString (builtins.elemAt value 1)
    )
    else abort "Unhandled value type ${builtins.typeOf value}"
);

concatAttrs = arg: func: (
    assert builtins.isAttrs arg;
    builtins.concatStringsSep "\n" (lib.attrsets.mapAttrsToList func arg)
);

mkHyprlandVariables = arg: (
    concatAttrs arg (
        name: value: name + (
            if builtins.isAttrs value then (
                " {\n" + (mkHyprlandVariables value) + "\n}"
            )
            else " = " + mkValueString value
        )
    )
);

mkHyprlandBinds = arg: (
    concatAttrs arg (
        name: value: (
            if builtins.isList value then (
                builtins.concatStringsSep "\n" (builtins.map (x: name + " = " + x) value)
            )
            else concatAttrs value (
                name2: value2: name + " = " + name2 + "," + (assert builtins.isString value2; value2)
            )
        )
    )
);
}

and then i use these to write my config like this:

home.file.".config/hypr/hyprland.conf".text = mkHyprlandVariables {
    input = {
        kb_layout = "de";
        kb_variant = "bone";
        follow_mouse = true;
        touchpad = {
            natural_scroll = true;
        };
    };
    general = {
        border_size = var.BORDERPX;
        gaps_in = 5;
        gaps_out = 10;
        "col.active_border" = "rgb(${var.COLOR_ACCENT})";
        "col.inactive_border" = "rgb(${var.COLOR_BG})";
        cursor_inactive_timeout = 5;
        layout = "master";
    };
    decoration = {
        rounding = var.CORNERPX;
        multisample_edges = true;
        active_opacity = (lib.strings.toInt var.TRANSPARENCY * 0.01);
        inactive_opacity = (lib.strings.toInt var.TRANSPARENCY * 0.01);
        fullscreen_opacity = 1.0;
        blur = false;
        drop_shadow = false;
    };
    animations = {
        enabled = true;
    };
    master = {
        new_is_master = false;
        new_on_top = false;
        no_gaps_when_only = false;
    };
    gestures = {
        workspace_swipe = true;
    };
    misc = {
        disable_hyprland_logo = true;
        disable_splash_rendering = true;
        disable_autoreload = true;
        enable_swallow = true;
        swallow_regex = ".+${var.TERMINAL}.+";
    };
} + "\n" +
mkHyprlandBinds {
    bezier = {
        linear = "0,0,1,1";
    };
} + "\n" +
mkHyprlandBinds {
    monitor = {
            eDP-1 = "preferred,0x0,1";
            DP-1 = "preferred,0x1080,1";
    };
    workspace = {
        eDP-1 = "1";
        DP-1 = "11";
    };
    animation = {
        windows = "1,1,linear,slide";
        windowsIn = "1,1,linear,popin";
        windowsOut = "1,1,linear,popin";
        fade = "1,3,linear";
        workspaces = "1,1,linear,slide";
        specialWorkspace = "1,2,linear,slidevert";
    };
    wsbind = {
        # 1-10 ws to screen 1
        "1" = "eDP-1"; "2" = "eDP-1"; "3" = "eDP-1"; "4" = "eDP-1"; "5" = "eDP-1";
        "6" = "eDP-1"; "7" = "eDP-1"; "8" = "eDP-1"; "9" = "eDP-1"; "10" = "eDP-1";
        # 21-41 to second screen
        "11" = "DP-1"; "12" = "DP-1"; "13" = "DP-1"; "14" = "DP-1"; "15" = "DP-1";
        "16" = "DP-1"; "17" = "DP-1"; "18" = "DP-1"; "19" = "DP-1"; "20" = "DP-1";
    };
    bind = {
        ## audio control
        ",XF86AudioRaiseVolume" = "exec,pamixer -i 1";
        ",XF86AudioLowerVolume" = "exec,pamixer -d 1";
        ",XF86AudioMute" = "exec,pamixer -t";
        ",XF86AudioPlay" = "exec,playerctl play-pause";
        ",XF86AudioNext" = "exec,playerctl next";
        ",XF86AudioPrev" = "exec,playerctl previous";
        ## brightness control
        ",XF86MonBrightnessUp" = "exec,brightnessctl set +75";
        ",XF86MonBrightnessDown" = "exec,brightnessctl set 75-";
        ## display control
        #",XF86Display" = "exec,lock";
        ## killing application
        ",XF86RFKill" = "killactive,";
        # STARTERS
        "SUPER,T" = "exec,${var.TERMINAL}";
        "SUPER,B" = "exec,${var.WEBBROWSER}";
        "SUPER,d" = "exec,${var.FILEMANAGER}";
        "SUPER,space" = "exec,rofi -modi drun,run -show drun";
        "ALT,space" = "exec,rofi -modi drun,run -show drun";
        "SUPER,k" = "togglespecialworkspace,";
        "SUPER,o" = "toggleopaque,";
        # SHORTCUT KEYS
        "SUPER,C" = "killactive,";
        "SUPER,F" = "fullscreen,";
        "SUPER,V" = "togglefloating,e";
        # "SUPER,L" = "exec,lock";

        #############################
        # there are 3 hand positions this configuration should work:
        # - left hand on ctie (asdf)
        # - right hand on nrsg (jkl;)
        # or:
        # - left hand on ctie (asdf)
        # - right hand on mouse with all mouse button aviable
        # or:
        # - only touchscreen, and some buttons (doesn't work yet, maybe it will never fully work)
        ############################

        # window changing
        "ALT, ${right.right}" = "cyclenext,";
        "ALT, ${right.left}" = "cyclenext, prev";

        # move focused window
        "ALT SHIFT, ${right.right}" = "swapnext,";
        "ALT SHIFT, ${right.left}" = "swapnext, prev";

        # resizing focused
        "ALT CTRL, ${right.down}" = "resizeactive,0 100";
        "ALT CTRL, ${right.up}" = "resizeactive,0 -100 ";
        "ALT CTRL, ${right.right}" = "resizeactive,100 0";
        "ALT CTRL, ${right.left}" = "resizeactive,-100 0";

        # switch between workspaces by direction
        "ALT, ${left.left}" = "workspace, -1";
        "ALT, ${left.right}" = "workspace, +1";
        "ALT, ${left.up}" = "workspace, previous";
        # switch between workspaces directly
        "ALT, 1" = "workspace, 1";
        "ALT, 2" = "workspace, 2";
        "ALT, 3" = "workspace, 3";
        "ALT, 4" = "workspace, 4";
        "ALT, 5" = "workspace, 5";
        "ALT, 6" = "workspace, 6";
        "ALT, 7" = "workspace, 7";
        "ALT, 8" = "workspace, 8";
        "ALT, 9" = "workspace, 9";
        "ALT, 0" = "workspace, 10";
        "ALT CTRL, 1" = "workspace, 11";
        "ALT CTRL, 2" = "workspace, 12";
        "ALT CTRL, 3" = "workspace, 13";
        "ALT CTRL, 4" = "workspace, 14";
        "ALT CTRL, 5" = "workspace, 15";
        "ALT CTRL, 7" = "workspace, 17";
        "ALT CTRL, 8" = "workspace, 18";
        "ALT CTRL, 9" = "workspace, 19";
        "ALT CTRL, 0" = "workspace, 20";
        # move containers between workspaces by direction
        "ALT SHIFT, ${left.left}" = "movetoworkspace, -1";
        "ALT SHIFT, ${left.right}" = "movetoworkspace, +1";
        # move containers between workspaces directly
        "ALT SHIFT, 1" = "movetoworkspace, 1";
        "ALT SHIFT, 2" = "movetoworkspace, 2";
        "ALT SHIFT, 3" = "movetoworkspace, 3";
        "ALT SHIFT, 4" = "movetoworkspace, 4";
        "ALT SHIFT, 5" = "movetoworkspace, 5";
        "ALT SHIFT, 6" = "movetoworkspace, 6";
        "ALT SHIFT, 7" = "movetoworkspace, 7";
        "ALT SHIFT, 8" = "movetoworkspace, 8";
        "ALT SHIFT, 9" = "movetoworkspace, 9";
        "ALT SHIFT, 0" = "movetoworkspace, 10";
        "ALT CTRL SHIFT, 1" = "movetoworkspace, 11";
        "ALT CTRL SHIFT, 2" = "movetoworkspace, 12";
        "ALT CTRL SHIFT, 3" = "movetoworkspace, 13";
        "ALT CTRL SHIFT, 4" = "movetoworkspace, 14";
        "ALT CTRL SHIFT, 5" = "movetoworkspace, 15";
        "ALT CTRL SHIFT, 6" = "movetoworkspace, 16";
        "ALT CTRL SHIFT, 7" = "movetoworkspace, 17";
        "ALT CTRL SHIFT, 8" = "movetoworkspace, 18";
        "ALT CTRL SHIFT, 9" = "movetoworkspace, 19";
        "ALT CTRL SHIFT, 0" = "movetoworkspace, 20";
        "SUPER,mouse:274" = "killactive";
    };
    bindm = {
        "ALT,mouse:272" = "movewindow";
        "ALT,mouse:273" = "resizewindow";
    };
    bindl = {
        #",switch:Lid Switch" = "exec,lock";
    };
    windowrulev2 = [
        "float,class:Rofi"
        "tile,class:PPSSPPSDL"
        "noborder,class:Rofi"
        "center,class:Rofi"
        "monitor DP-1,class:xournalpp"
        "workspace special,class:KeePassXC"
        # no transparency for some windows
        "opaque,class:KeePassXC"
        "opaque,class:Rofi"
        "opaque,class:Alacritty"
        "opaque,class:PPSSPPSDL"
        "opaque,class:osu!"
        "opaque,class:xournalpp"
    ];
    exec-once = [
        "dunst"
        "blueman-applet"
        "${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1"
        "flameshot"
        "nm-applet --indicator"
        "xss-lock --transfer-sleep-lock -- swaylock -c 00000000"
        "keepassxc"
        "hyprpaper"
        "waybar"
    ];
};

and yes submaps are not supported by this, i dont use them

quantenzitrone avatar Nov 18 '22 01:11 quantenzitrone

If I wanted to test this, do I have to build your fork of Hyprland, @spikespaz ?

algorithmiker avatar Nov 26 '22 14:11 algorithmiker

If I wanted to test this, do I have to build your fork of Hyprland, @spikespaz ?

You need to add my fork as a flake input, and merge the nix-hm-module branch with this upstream's main branch. You should not need to rebuild the derivation as long as the package manifest in my fork matches the one you were previously using. I recommend adding the cachix instance as a substituter in your system config.

spikespaz avatar Nov 27 '22 05:11 spikespaz

I don't get it; why is this being worked on in upstream hyperland, instead of Home-Manager?

1. They move slow, and it wouldn't let us add/remove options as soon as they're added to the code.

2. The (corresponding) Nixpkgs package has been outdated for a long time.

Basically we aim towards being autonomous, while following best practices from Nixpkgs and HM.

If you have any features for hyprland you would like to be merged in nixpkgs you can ping me directly on matrix. Just now it seems like hyprland patches many things which makes keeping it up-to-date also harder.

Mic92 avatar Feb 19 '23 05:02 Mic92

@Mic92 thank you for wanting to support us.

I'll get in touch with the current Hyprland maintainer in Nixpkgs and try to update the package, as well as add the unpackaged hyprland-protocols, hyprpicker, hyprpaper and xdg-desktop-portal-hyprland.

As for the Home Manager part, I will try to add the module there (and in NixOS as well) as soon as the packages are in.

I will ping you for reviews. Thanks again.

fufexan avatar Feb 19 '23 20:02 fufexan

Deprecating and closing this PR in favor of: https://github.com/spikespaz/dotfiles/tree/master/hm-modules/hyprland

Use the module from my flake, because it is still WIP.

You can find basic instructions in the readme of the repository. There are no instructions specifically for the module itself because I still consider it "for advanced Nix users only", however if you fit that description, please DO USE IT AND PROVIDE FEEDBACK!

Check out the config.nix, default.nix, keybinds.nix windowrules.nix, and monitors.nix files in the following subdirectory: https://github.com/spikespaz/dotfiles/tree/master/users/jacob/desktops/hyprland

spikespaz avatar Jun 09 '23 05:06 spikespaz

Cross-referencing: https://github.com/hyprwm/hyprland-wiki/pull/273#issuecomment-1647417182

spikespaz avatar Jul 30 '23 07:07 spikespaz