{ config, lib, pkgs, osConfig, ... }: let cfg = config.xsession.windowManager.i3; rofi = pkgs.rofi.override { plugins = [ pkgs.rofi-emoji pkgs.rofi-calc pkgs.xdotool ]; }; backgroundCommand = pkgs.writers.writeDash "background" '' ${pkgs.xorg.xrandr}/bin/xrandr | grep " connected" | grep "primary" | \ ${pkgs.gnused}/bin/sed -E "s/primary //" | \ ${pkgs.coreutils-full}/bin/cut -d' ' -f 3 | \ ${pkgs.gnused}/bin/sed -E 's/\+.*$//g' | \ ${pkgs.coreutils-full}/bin/sort -r | \ ${pkgs.coreutils-full}/bin/head -n 1 | \ ${pkgs.gawk}/bin/awk -F 'x' '{print "--width="$1" --height="$2}' | \ ${pkgs.findutils}/bin/xargs \ ${pkgs.polygon-art.polygon-art}/bin/rings \ /dev/shm/background.png && \ ${pkgs.imagemagick}/bin/convert /dev/shm/background.png \ -font ${pkgs.ubuntu_font_family}/share/fonts/ubuntu/UbuntuMono-B.ttf \ -gravity Center -pointsize 30 -annotate 0 '${osConfig.networking.hostName}' \ /dev/shm/background_with_text.png && \ ${pkgs.feh}/bin/feh --bg-scale /dev/shm/background_with_text.png ''; in { config = lib.mkIf config.gui.enable { home.packages = let fixXhost = pkgs.writers.writeBashBin "fix-xhost" '' ${pkgs.xorg.xhost}/bin/xhost + &> /dev/null ''; in [ fixXhost pkgs.autorandr pkgs.polygon-art.polygon-art pkgs.xdotool # needed for rofi-emoji ]; programs.i3status-rust = { enable = true; bars = { my = { icons = "awesome5"; theme = "gruvbox-light"; # https://github.com/greshake/i3status-rust/blob/v0.22.0/doc/blocks.md blocks = [ { block = "cpu"; interval = 1; } { block = "memory"; format = "$icon $mem_used_percents "; } { block = "load"; interval = 1; format = "$icon $1m"; } { block = "net"; } { block = "sound"; } { block = "battery"; interval = 10; format = "$icon $percentage $time"; } { block = "uptime"; } { block = "taskwarrior"; interval = 60; format = " $icon $count.eng(w:3) todo "; format_singular = " $icon 1 task "; format_everything_done = ""; warning_threshold = 10; critical_threshold = 20; filters = [ { name = "active"; filter = "+PENDING and ( +ACTIVE or +DUETODAY or +TODAY or +OVERDUE )"; } ]; } { block = "taskwarrior"; interval = 60; format = " $icon $count.eng(w:2) "; format_singular = " $icon 1 task "; format_everything_done = ""; warning_threshold = 3; critical_threshold = 5; filters = [ { name = "started"; filter = "+PENDING and +ACTIVE"; } ]; } { block = "time"; interval = 60; format = " $icon $timestamp.datetime(f:'%Y-%m-%d %R', l:de_DE) "; } { block = "tea_timer"; format = " $icon {$minutes:$seconds |}"; done_cmd = "${pkgs.noti}/bin/noti -t 'Timer Finished'"; } ]; }; }; }; programs.kitty = { enable = true; }; programs.alacritty = { enable = true; settings = { font.size = lib.mkForce 6.5; }; }; services.copyq = { enable = true; }; xsession = { enable = true; windowManager.i3 = { enable = true; extraConfig = '' default_border pixel default_orientation vertical ''; config = { modifier = "Mod4"; terminal = "alacritty"; focus = { followMouse = true; }; colors.focused = with config.lib.stylix.colors.withHashtag; { # stylix color overrides border = lib.mkForce base08; background = lib.mkForce base0A; text = lib.mkForce base00; }; startup = [ #{ command = "${pkgs.albert}/bin/albert"; always = true; } { command = toString backgroundCommand; always = true; } { command = toString (pkgs.writers.writeDash "xsettings" '' # to allow sudo commands to access X ${pkgs.xorg.xhost}/bin/xhost + # no shitty pcspkr crap ${pkgs.xorg.xset}/bin/xset -b # no sleeping monitor ${pkgs.xorg.xset}/bin/xset -dpms ${pkgs.xorg.xset}/bin/xset s off ''); always = true; } ]; bars = [ (config.lib.stylix.i3.bar // { #mode = "hide"; hiddenState = "hide"; position = "top"; workspaceButtons = true; workspaceNumbers = true; statusCommand = "${pkgs.i3status-rust}/bin/i3status-rs ${config.home.homeDirectory}/.config/i3status-rust/config-my.toml"; fonts.size = 10.0; trayOutput = "primary"; } ) ]; keybindings = { "Print" = "exec ${pkgs.flameshot}/bin/flameshot gui -c -p /share/"; "${cfg.config.modifier}+Return" = "exec ${cfg.config.terminal}"; "${cfg.config.modifier}+Shift+q" = "exit"; "${cfg.config.modifier}+q" = "kill"; "${cfg.config.modifier}+Left" = "focus left"; "${cfg.config.modifier}+Down" = "focus down"; "${cfg.config.modifier}+Up" = "focus up"; "${cfg.config.modifier}+Right" = "focus right"; "${cfg.config.modifier}+j" = "focus next"; "${cfg.config.modifier}+k" = "focus prev"; "${cfg.config.modifier}+Shift+Left" = "move left"; "${cfg.config.modifier}+Shift+Down" = "move down"; "${cfg.config.modifier}+Shift+Up" = "move up"; "${cfg.config.modifier}+Shift+Right" = "move right"; "${cfg.config.modifier}+h" = "split h"; "${cfg.config.modifier}+v" = "split v"; "${cfg.config.modifier}+f" = "fullscreen toggle"; "${cfg.config.modifier}+s" = "layout stacking"; "${cfg.config.modifier}+w" = "layout tabbed"; "${cfg.config.modifier}+e" = "layout toggle split"; "${cfg.config.modifier}+t" = "floating toggle"; #"${cfg.config.modifier}+space" = "focus mode_toggle"; "${cfg.config.modifier}+b" = "exec ${backgroundCommand}"; "${cfg.config.modifier}+p" = "focus parent"; "${cfg.config.modifier}+Shift+minus" = "move scratchpad"; "${cfg.config.modifier}+minus" = "scratchpad show"; "${cfg.config.modifier}+1" = "workspace 1"; "${cfg.config.modifier}+2" = "workspace 2"; "${cfg.config.modifier}+3" = "workspace 3"; "${cfg.config.modifier}+4" = "workspace 4"; "${cfg.config.modifier}+5" = "workspace 5"; "${cfg.config.modifier}+6" = "workspace 6"; "${cfg.config.modifier}+7" = "workspace 7"; "${cfg.config.modifier}+8" = "workspace 8"; "${cfg.config.modifier}+9" = "workspace 9"; "${cfg.config.modifier}+0" = "workspace 10"; "${cfg.config.modifier}+Shift+1" = "move container to workspace number 1"; "${cfg.config.modifier}+Shift+2" = "move container to workspace number 2"; "${cfg.config.modifier}+Shift+3" = "move container to workspace number 3"; "${cfg.config.modifier}+Shift+4" = "move container to workspace number 4"; "${cfg.config.modifier}+Shift+5" = "move container to workspace number 5"; "${cfg.config.modifier}+Shift+6" = "move container to workspace number 6"; "${cfg.config.modifier}+Shift+7" = "move container to workspace number 7"; "${cfg.config.modifier}+Shift+8" = "move container to workspace number 8"; "${cfg.config.modifier}+Shift+9" = "move container to workspace number 9"; "${cfg.config.modifier}+Shift+0" = "move container to workspace number 10"; "${cfg.config.modifier}+Escape" = "workspace back_and_forth"; # rename workspace "${cfg.config.modifier}+n" = '' exec i3-input -F 'rename workspace to "%s"' -P 'New name for this workspace: ' ''; # change to named workspace "${cfg.config.modifier}+grave" = let script = pkgs.writers.writeBash "select-workspace" '' set -e set -o pipefail ${pkgs.i3}/bin/i3-msg -t get_workspaces | \ ${pkgs.jq}/bin/jq --raw-output '.[] | .name' | \ ${rofi}/bin/rofi -dmenu -p 'Select Workspace ' | \ while read line do ${pkgs.i3}/bin/i3-msg workspace "$line" done ''; in "exec ${script}"; "${cfg.config.modifier}+Shift+grave" = let script = pkgs.writers.writeBash "move-workspace" '' set -e set -o pipefail ${pkgs.i3}/bin/i3-msg -t get_workspaces | \ ${pkgs.jq}/bin/jq --raw-output '.[] | .name' | \ ${rofi}/bin/rofi -dmenu -p 'Move to Workspace ' | \ while read line do ${pkgs.i3}/bin/i3-msg move container to workspace "$line" done ''; in "exec ${script}"; "${cfg.config.modifier}+space" = "exec ${rofi}/bin/rofi -show drun -display-drun ''"; "${cfg.config.modifier}+Shift+c" = "reload"; "${cfg.config.modifier}+Shift+r" = "restart"; "${cfg.config.modifier}+Shift+e" = "exec i3-nagbar -t warning -m 'Do you want to exit i3?' -b 'Yes' 'i3-msg exit'"; "${cfg.config.modifier}+r" = "mode resize"; # multiple monitors # autorandr --save docked # to save setup # autorandr --save undocked # to save setup # autorandr --change # automatically detects the setup "${cfg.config.modifier}+BackSpace" = let script = pkgs.writers.writeBash "autorandr" '' ${pkgs.autorandr}/bin/autorandr --change ${backgroundCommand} ''; in "exec ${toString script}"; # like vimperator "${cfg.config.modifier}+a" = "exec ${pkgs.i3-easyfocus}/bin/i3-easyfocus"; }; }; }; }; # notification tool services.dunst = { enable = true; settings = { global = { # Allow a small subset of html markup: # bold # italic # strikethrough # underline # # For a complete reference see # . # If markup is not allowed, those tags will be stripped out of the # message. markup = "yes"; plain_text = "no"; # The format of the message. Possible variables are: # %a appname # %s summary # %b body # %i iconname (including its path) # %I iconname (without its path) # %p progress value if set ([ 0%] to [100%]) or nothing # Markup is allowed format = '' %a %s %b''; # Sort messages by urgency. sort = "yes"; # Show how many messages are currently hidden (because of geometry). indicate_hidden = "yes"; # Alignment of message text. # Possible values are "left", "center" and "right". alignment = "center"; # The frequency with wich text that is longer than the notification # window allows bounces back and forth. # This option conflicts with "word_wrap". # Set to 0 to disable. bounce_freq = 0; # Show age of message if message is older than show_age_threshold # seconds. # Set to -1 to disable. show_age_threshold = 1; # Split notifications into multiple lines if they don't fit into # geometry. word_wrap = "yes"; # Ignore newlines '\n' in notifications. ignore_newline = "no"; # Hide duplicate's count and stack them stack_duplicates = "yes"; hide_duplicates_count = "no"; # The geometry of the window: # [{width}]x{height}[+/-{x}+/-{y}] # The geometry of the message window. # The height is measured in number of notifications everything else # in pixels. If the width is omitted but the height is given # ("-geometry x2"), the message window expands over the whole screen # (dmenu-like). If width is 0, the window expands to the longest # message displayed. A positive x is measured from the left, a # negative from the right side of the screen. Y is measured from # the top and down respectevly. # The width can be negative. In this case the actual width is the # screen width minus the width defined in within the geometry option. geometry = "500x10-0+0"; # Shrink window if it's smaller than the width. Will be ignored if # width is 0. shrink = "no"; # Don't remove messages, if the user is idle (no mouse or keyboard input) # for longer than idle_threshold seconds. # Set to 0 to disable. idle_threshold = 0; # The transparency of the window. Range: [0; 100]. # This option will only work if a compositing windowmanager is # present (e.g. xcompmgr, compiz, etc.). # transparency = 5 # Which monitor should the notifications be displayed on. #monitor = keyboard # Display notification on focused monitor. Possible modes are: # mouse: follow mouse pointer # keyboard: follow window with keyboard focus # none: don't follow anything # # "keyboard" needs a windowmanager that exports the # _NET_ACTIVE_WINDOW property. # This should be the case for almost all modern windowmanagers. # # If this option is set to mouse or keyboard, the monitor option # will be ignored. follow = "none"; # Should a notification popped up from history be sticky or timeout # as if it would normally do. sticky_history = "yes"; # Maximum amount of notifications kept in history history_length = 15; # Display indicators for URLs (U) and actions (A). show_indicators = "no"; # The height of a single line. If the height is smaller than the # font height, it will get raised to the font height. # This adds empty space above and under the text. line_height = 3; # Draw a line of "separatpr_height" pixel height between two # notifications. # Set to 0 to disable. separator_height = 1; # Padding between text and separator. padding = 1; # Horizontal padding. horizontal_padding = 1; # Print a notification on startup. # This is mainly for error detection, since dbus (re-)starts dunst # automatically after a crash. startup_notification = true; # Align icons left/right/off icon_position = "off"; max_icon_size = 80; frame_width = 2; }; shortcuts = { # Shortcuts are specified as [modifier+][modifier+]...key # Available modifiers are "ctrl", "mod1" (the alt-key), "mod2", # "mod3" and "mod4" (windows-key). # Xev might be helpful to find names for keys. # Close notification. close = "ctrl+space"; # Close all notifications. close_all = "ctrl+shift+space"; # Redisplay last message(s). # On the US keyboard layout "grave" is normally above TAB and left # of "1". #history = "ctrl+grave"; # Context menu. context = "mod4+u"; }; }; }; # rofi > albert programs.rofi = { enable = true; cycle = true; package = rofi; # pass.enable = true; extraConfig = { modi = "drun,calc,emoji,combi"; show-icons = true; terminal = "alacritty"; }; }; xdg.configFile."albert/albert.conf".text = '' [General] hotkey=Meta+Space showTray=false telemetry=false terminal=urxvt -e [org.albert.extension.applications] enabled=true fuzzy=true use_generic_name=true use_keywords=true [org.albert.extension.calculator] enabled=true [org.albert.extension.hashgenerator] enabled=true [org.albert.frontend.widgetboxmodel] alwaysOnTop=true clearOnHide=false displayIcons=true displayScrollbar=false displayShadow=false hideOnClose=false hideOnFocusLoss=true itemCount=5 showCentered=true theme=SolarizedBrightViolet ''; xdg.configFile."Code/User/settings.json".text = builtins.toJSON { "keyboard.dispatch" = "keyCode"; "explorer.confirmDragAndDrop" = false; "editor.tabSize" = 2; "window.zoomLevel" = -1; "git.enableSmartCommit" = true; "files.autoSave" = "onFocusChange"; "terminal.integrated.setLocaleVariables" = true; "terminal.external.linuxExec" = "xterm"; "explorer.confirmDelete" = false; "todo-tree.tags" = [ "todo" "TODO" "fixme" "FIXME" ]; "workbench.colorTheme" = "Solarized Light"; }; }; }