summaryrefslogtreecommitdiff
path: root/nixos/modules
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules')
-rw-r--r--nixos/modules/btop.nix86
-rw-r--r--nixos/modules/colors.nix224
-rw-r--r--nixos/modules/gms/dayz.nix1808
-rw-r--r--nixos/modules/gms/mc.nix80
-rw-r--r--nixos/modules/notes.nix55
-rw-r--r--nixos/modules/qksh.nix992
-rw-r--r--nixos/modules/vi.nix147
-rw-r--r--nixos/modules/wm.nix157
-rw-r--r--nixos/modules/yazi.nix50
9 files changed, 3599 insertions, 0 deletions
diff --git a/nixos/modules/btop.nix b/nixos/modules/btop.nix
new file mode 100644
index 0000000..6738384
--- /dev/null
+++ b/nixos/modules/btop.nix
@@ -0,0 +1,86 @@
+{ config, pkgs, ... }:
+
+{
+ xdg.configFile."btop/btop.conf".force = true;
+
+ programs.btop = {
+ enable = true;
+ settings = {
+ color_theme = "TTY";
+ theme_background = true;
+ truecolor = true;
+ force_tty = false;
+ presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty";
+ vim_keys = false;
+ rounded_corners = false;
+ terminal_sync = true;
+ update_ms = 2000;
+ background_update = true;
+ clock_format = "%X";
+ base_10_sizes = false;
+ base_10_bitrate = "Auto";
+ log_level = "WARNING";
+ save_config_on_exit = true;
+ shown_boxes = "cpu mem net proc";
+ graph_symbol = "braille";
+ graph_symbol_cpu = "default";
+ graph_symbol_gpu = "default";
+ graph_symbol_mem = "default";
+ graph_symbol_net = "default";
+ graph_symbol_proc = "default";
+ cpu_bottom = false;
+ cpu_graph_upper = "Auto";
+ cpu_graph_lower = "Auto";
+ cpu_invert_lower = true;
+ cpu_single_graph = false;
+ check_temp = true;
+ cpu_sensor = "Auto";
+ show_coretemp = true;
+ cpu_core_map = "";
+ temp_scale = "celsius";
+ show_cpu_freq = true;
+ freq_mode = "first";
+ show_cpu_watts = true;
+ show_uptime = true;
+ custom_cpu_name = "";
+ proc_left = false;
+ proc_sorting = "cpu lazy";
+ proc_reversed = false;
+ proc_tree = false;
+ proc_colors = true;
+ proc_gradient = true;
+ proc_per_core = false;
+ proc_mem_bytes = true;
+ proc_cpu_graphs = true;
+ proc_info_smaps = false;
+ proc_filter_kernel = false;
+ proc_aggregate = false;
+ keep_dead_proc_usage = false;
+ mem_graphs = true;
+ mem_below_net = false;
+ show_swap = true;
+ swap_disk = true;
+ zfs_arc_cached = true;
+ show_disks = true;
+ disks_filter = "";
+ only_physical = true;
+ use_fstab = true;
+ disk_free_priv = false;
+ show_io_stat = true;
+ io_mode = false;
+ io_graph_combined = false;
+ io_graph_speeds = "";
+ zfs_hide_datasets = false;
+ net_iface = "";
+ net_auto = true;
+ net_sync = true;
+ net_download = 100;
+ net_upload = 100;
+ show_gpu_info = "Auto";
+ shown_gpus = "amd nvidia intel";
+ gpu_mirror_graph = true;
+ nvml_measure_pcie_speeds = true;
+ rsmi_measure_pcie_speeds = true;
+ };
+ };
+}
diff --git a/nixos/modules/colors.nix b/nixos/modules/colors.nix
new file mode 100644
index 0000000..98ce1cc
--- /dev/null
+++ b/nixos/modules/colors.nix
@@ -0,0 +1,224 @@
+{ pkgs, ... }:
+
+let
+ colors-script = pkgs.writeShellScriptBin "colors" ''
+ [ -z "$1" ] && echo "usage: colors <image>" >&2 && exit 1
+ [ ! -f "$1" ] && echo "colors: file not found: $1" >&2 && exit 1
+
+ colors="$HOME/.colors"
+ mkdir -p "$colors"
+
+ awww_out=$(${pkgs.awww}/bin/awww img -o HDMI-A-1 "$1" --transition-type grow --transition-duration 1.5 --transition-fps 120 2>&1)
+ [ $? -ne 0 ] && echo "colors: awww: $awww_out" >&2
+ ${pkgs.awww}/bin/awww clear --outputs DP-1 2>/dev/null
+
+ raw=$(${pkgs.imagemagick}/bin/magick "$1" -thumbnail 50x50^ -colors 8 -unique-colors txt:- 2>&1)
+
+ base=$(printf '%s\n' "$raw" \
+ | ${pkgs.gnugrep}/bin/grep -oE '#[0-9A-Fa-f]{6}' \
+ | ${pkgs.gawk}/bin/awk '{
+ r = strtonum("0x" substr($0,2,2))
+ g = strtonum("0x" substr($0,4,2))
+ b = strtonum("0x" substr($0,6,2))
+ printf "%d %s\n", int(0.299*r + 0.587*g + 0.114*b), $0
+ }' \
+ | ${pkgs.coreutils}/bin/sort -n \
+ | ${pkgs.gawk}/bin/awk '{print $2}' \
+ | ${pkgs.coreutils}/bin/head -8)
+
+ [ -z "$base" ] && echo "colors: magick failed" >&2 && echo "$raw" >&2 && exit 1
+
+ n=$(printf '%s\n' "$base" | ${pkgs.coreutils}/bin/wc -l)
+ last=$(printf '%s\n' "$base" | ${pkgs.coreutils}/bin/tail -1)
+ while [ "$n" -lt 8 ]; do
+ base=$(printf '%s\n%s' "$base" "$last")
+ n=$((n+1))
+ done
+
+ bright=$(printf '%s\n' "$base" | ${pkgs.gawk}/bin/awk '{
+ r = strtonum("0x" substr($0,2,2))
+ g = strtonum("0x" substr($0,4,2))
+ b = strtonum("0x" substr($0,6,2))
+ r = int(r*1.4); if (r>255) r=255
+ g = int(g*1.4); if (g>255) g=255
+ b = int(b*1.4); if (b>255) b=255
+ printf "#%02X%02X%02X\n", r, g, b
+ }')
+
+ cols=$(printf '%s\n%s' "$base" "$bright")
+
+ c0=$(printf '%s\n' "$cols" | ${pkgs.gnused}/bin/sed -n '1p')
+ c1=$(printf '%s\n' "$cols" | ${pkgs.gnused}/bin/sed -n '2p')
+ c2=$(printf '%s\n' "$cols" | ${pkgs.gnused}/bin/sed -n '3p')
+ c3=$(printf '%s\n' "$cols" | ${pkgs.gnused}/bin/sed -n '4p')
+ c4=$(printf '%s\n' "$cols" | ${pkgs.gnused}/bin/sed -n '5p')
+ c5=$(printf '%s\n' "$cols" | ${pkgs.gnused}/bin/sed -n '6p')
+ c6=$(printf '%s\n' "$cols" | ${pkgs.gnused}/bin/sed -n '7p')
+ c7=$(printf '%s\n' "$cols" | ${pkgs.gnused}/bin/sed -n '8p')
+ c8=$(printf '%s\n' "$cols" | ${pkgs.gnused}/bin/sed -n '9p')
+ c9=$(printf '%s\n' "$cols" | ${pkgs.gnused}/bin/sed -n '10p')
+ c10=$(printf '%s\n' "$cols" | ${pkgs.gnused}/bin/sed -n '11p')
+ c11=$(printf '%s\n' "$cols" | ${pkgs.gnused}/bin/sed -n '12p')
+ c12=$(printf '%s\n' "$cols" | ${pkgs.gnused}/bin/sed -n '13p')
+ c13=$(printf '%s\n' "$cols" | ${pkgs.gnused}/bin/sed -n '14p')
+ c14=$(printf '%s\n' "$cols" | ${pkgs.gnused}/bin/sed -n '15p')
+ c15=$(printf '%s\n' "$cols" | ${pkgs.gnused}/bin/sed -n '16p')
+
+ bg="$c0"
+ fg=$(printf '%s\n' "$cols" | ${pkgs.gawk}/bin/awk -v bg="$c0" '
+ function lum(hex, r,g,b,rs,gs,bs) {
+ r = strtonum("0x" substr(hex,2,2)) / 255
+ g = strtonum("0x" substr(hex,4,2)) / 255
+ b = strtonum("0x" substr(hex,6,2)) / 255
+ rs = (r<=0.04045) ? r/12.92 : ((r+0.055)/1.055)^2.4
+ gs = (g<=0.04045) ? g/12.92 : ((g+0.055)/1.055)^2.4
+ bs = (b<=0.04045) ? b/12.92 : ((b+0.055)/1.055)^2.4
+ return 0.2126*rs + 0.7152*gs + 0.0722*bs
+ }
+ function contrast(a,b, l1,l2,t) {
+ l1 = lum(a); l2 = lum(b)
+ if (l1 < l2) { t=l1; l1=l2; l2=t }
+ return (l1+0.05) / (l2+0.05)
+ }
+ BEGIN { best=""; bestc=0 }
+ {
+ c = contrast($0, bg)
+ if (c > bestc) { bestc=c; best=$0 }
+ }
+ END { print best }
+ ')
+ cursor="$fg"
+
+ printf '%s' "$1" > "$colors/colors"
+
+ printf '%s\n' "$cols" | ${pkgs.gawk}/bin/awk '{printf "color%d=%s\n", NR-1, $0}' > "$colors/colors.sh"
+ printf 'background="%s"\nforeground="%s"\ncursor="%s"\n' "$bg" "$fg" "$cursor" >> "$colors/colors.sh"
+
+ cat > "$colors/colors.json" << ENDJSON
+ {
+ "wallpaper": "$1",
+ "alpha": "100",
+ "special": {
+ "background": "$bg",
+ "foreground": "$fg",
+ "cursor": "$cursor"
+ },
+ "colors": {
+ "color0": "$c0",
+ "color1": "$c1",
+ "color2": "$c2",
+ "color3": "$c3",
+ "color4": "$c4",
+ "color5": "$c5",
+ "color6": "$c6",
+ "color7": "$c7",
+ "color8": "$c8",
+ "color9": "$c9",
+ "color10": "$c10",
+ "color11": "$c11",
+ "color12": "$c12",
+ "color13": "$c13",
+ "color14": "$c14",
+ "color15": "$c15"
+ }
+ }
+ ENDJSON
+
+ printf '%s\n' "$cols" > "$colors/colors.txt"
+
+ cat > "$colors/kitty.conf" << ENDKITTY
+ foreground $fg
+ background $bg
+ background_opacity 1.0
+ cursor $cursor
+
+ active_tab_foreground $bg
+ active_tab_background $fg
+ inactive_tab_foreground $fg
+ inactive_tab_background $bg
+
+ active_border_color $fg
+ inactive_border_color $bg
+ bell_border_color $c1
+
+ color0 $c0
+ color8 $c8
+ color1 $c1
+ color9 $c9
+ color2 $c2
+ color10 $c10
+ color3 $c3
+ color11 $c11
+ color4 $c4
+ color12 $c12
+ color5 $c5
+ color13 $c13
+ color6 $c6
+ color14 $c14
+ color7 $c7
+ color15 $c15
+ ENDKITTY
+
+ cat > "$colors/colors.fish" << ENDFISH
+ set fish_color_autosuggestion \$(echo "$c8" | sed 's/#//')
+ set fish_color_cancel \$(echo "$c1" | sed 's/#//') '--reverse'
+ set fish_color_command \$(echo "$c10" | sed 's/#//')
+ set fish_color_comment \$(echo "$c8" | sed 's/#//')
+ set fish_color_cwd \$(echo "$c2" | sed 's/#//')
+ set fish_color_cwd_root \$(echo "$c1" | sed 's/#//')
+ set fish_color_end \$(echo "$c3" | sed 's/#//')
+ set fish_color_error \$(echo "$c1" | sed 's/#//')
+ set fish_color_escape \$(echo "$c5" | sed 's/#//')
+ set fish_color_history_current --bold
+ set fish_color_host \$(echo "$c12" | sed 's/#//')
+ set fish_color_host_remote \$(echo "$c12" | sed 's/#//')
+ set fish_color_keyword \$(echo "$c5" | sed 's/#//')
+ set fish_color_match --background=\$(echo "$c4" | sed 's/#//')
+ set fish_color_normal \$(echo "$fg" | sed 's/#//')
+ set fish_color_operator \$(echo "$c6" | sed 's/#//')
+ set fish_color_option \$(echo "$c3" | sed 's/#//')
+ set fish_color_param \$(echo "$c12" | sed 's/#//')
+ set fish_color_quote \$(echo "$c11" | sed 's/#//')
+ set fish_color_redirection \$(echo "$c5" | sed 's/#//')
+ set fish_color_search_match --background=\$(echo "$c8" | sed 's/#//')
+ set fish_color_selection --background=\$(echo "$c8" | sed 's/#//')
+ set fish_color_status \$(echo "$c1" | sed 's/#//')
+ set fish_color_user \$(echo "$c10" | sed 's/#//')
+ set fish_color_valid_path --underline
+ set fish_pager_color_background \$(echo "$bg" | sed 's/#//')
+ set fish_pager_color_completion \$(echo "$fg" | sed 's/#//')
+ set fish_pager_color_description \--background=\$(echo "$c8" | sed 's/#//')
+ set fish_pager_color_prefix \$(echo "$c10" | sed 's/#//')
+ set fish_pager_color_progress \$(echo "$c8" | sed 's/#//')
+ set fish_pager_color_secondary_background \$(echo "$bg" | sed 's/#//')
+ set fish_pager_color_secondary_completion \$(echo "$fg" | sed 's/#//')
+ set fish_pager_color_secondary_description \$(echo "$c8" | sed 's/#//')
+ set fish_pager_color_secondary_prefix \$(echo "$c10" | sed 's/#//')
+ set fish_pager_color_selected_background --background=\$(echo "$c8" | sed 's/#//')
+ set fish_pager_color_selected_completion \$(echo "$fg" | sed 's/#//')
+ set fish_pager_color_selected_description \$(echo "$c8" | sed 's/#//')
+ set fish_pager_color_selected_prefix \$(echo "$c10" | sed 's/#//')
+ ENDFISH
+
+ {
+ printf '%s\n' "$cols" | ${pkgs.gawk}/bin/awk '{printf "\033]4;%d;%s\007", NR-1, $0}'
+ printf '\033]10;%s\007' "$fg"
+ printf '\033]11;%s\007' "$bg"
+ printf '\033]12;%s\007' "$cursor"
+ } > "$colors/sequences"
+
+ for pty in /proc/*/fd/0; do
+ [ -c "$pty" ] && [ -w "$pty" ] && ${pkgs.coreutils}/bin/cat "$colors/sequences" > "$pty" 2>/dev/null
+ done
+
+ printf '%s\n' "$base" | ${pkgs.gawk}/bin/awk '{
+ r = strtonum("0x" substr($0,2,2))
+ g = strtonum("0x" substr($0,4,2))
+ b = strtonum("0x" substr($0,6,2))
+ printf "\033[48;2;%d;%d;%dm \033[0m %s\n", r, g, b, $0
+ }'
+ '';
+in
+{
+ home.packages = [ colors-script ];
+}
diff --git a/nixos/modules/gms/dayz.nix b/nixos/modules/gms/dayz.nix
new file mode 100644
index 0000000..128a10c
--- /dev/null
+++ b/nixos/modules/gms/dayz.nix
@@ -0,0 +1,1808 @@
+{ config, pkgs, ... }:
+
+let
+ dayzDir = "${config.home.homeDirectory}/.local/share/Steam/steamapps/compatdata/221100/pfx/drive_c/users/steamuser/Documents/DayZ";
+in
+{
+ home.packages = [ (pkgs.writeShellApplication {
+ name = "meowz";
+ runtimeInputs = with pkgs; [ curl jq fzf steamcmd ];
+ excludeShellChecks = [ "SC2155" "SC2162" "SC2207" "SC2086" "SC2178" "SC2128" ];
+ text = ''
+
+config="$HOME/.config/dayz"
+favfile="$config/favorites"
+logfile="$config/last_launch.log"
+steamapps="$HOME/.local/share/Steam/steamapps"
+workshop="$steamapps/workshop/content/221100"
+d=$'\x1f'
+
+mkdir -p "$config"
+touch "$favfile"
+sed -i '/^[[:space:]]*$/d' "$favfile"
+awk -F"$d" 'NF==4' "$favfile" > "$favfile.tmp" && mv "$favfile.tmp" "$favfile"
+
+log() { printf '%s\n' "$*"; }
+err() { printf '%s\n' "$*" >&2; }
+
+api() {
+ curl -sg -A "mozilla" "https://api.battlemetrics.com$1"
+}
+
+fetch_servers() {
+ local path="/servers?filter[game]=dayz&page[size]=100$1"
+ local pages=0
+ while [ -n "$path" ] && [ "$pages" -lt 4 ]; do
+ local resp=$(api "$path")
+ echo "$resp" | jq -e . >/dev/null 2>&1 || break
+ echo "$resp" | jq -r '.data[]? | "\(.id)|\(.attributes.ip):\(.attributes.port)|\(.attributes.name) [\(.attributes.players)/\(.attributes.maxPlayers)]"'
+ path=$(echo "$resp" | jq -r '.links.next // empty' | sed 's|.*battlemetrics.com||')
+ pages=$((pages + 1))
+ done
+}
+
+if [ "''${1:-}" = "--fetch" ]; then
+ fetch_servers "''${2:+&filter[search]=$2}"
+ exit 0
+fi
+
+steamuser=""
+[ -f "$config/steamuser" ] && steamuser=$(cat "$config/steamuser")
+if [ -z "$steamuser" ]; then
+ read -p "steam username: " steamuser
+ echo "$steamuser" > "$config/steamuser"
+fi
+
+steampass=""
+[ -f "$config/steampass" ] && steampass=$(cat "$config/steampass")
+if [ -z "$steampass" ]; then
+ read -rsp "steam password (stored in plaintext, blank to skip caching): " steampass
+ echo
+ if [ -n "$steampass" ]; then
+ (umask 177; echo "$steampass" > "$config/steampass")
+ fi
+fi
+
+loginmarker="$config/steam_authenticated"
+
+get_mods_by_id() {
+ api "/servers/$1" | jq -r '.data?.attributes?.details?.modIds[]? // empty' | paste -sd, -
+}
+
+get_mods() {
+ local ip="$1" port="$2"
+ local m=$(curl -s "https://dayzsalauncher.com/api/v1/server/$ip:$port" | jq -r '.result?.mods[]?.steamWorkshopId // empty' | paste -sd, -)
+ if [ -z "$m" ]; then
+ local id=$(api "/servers?filter[game]=dayz&filter[search]=$ip:$port" | jq -r '.data[0]?.id // empty')
+ [ -n "$id" ] && m=$(get_mods_by_id "$id")
+ fi
+ echo "$m"
+}
+
+download_mods() {
+ local mods=($(echo "$1" | tr ',' '\n'))
+ [ "''${#mods[@]}" -eq 0 ] && return 0
+
+ touch "$config/blacklist"
+ local missing=()
+ for mod in "''${mods[@]}"; do
+ grep -qx "$mod" "$config/blacklist" && continue
+ find "$workshop/$mod" -mindepth 1 2>/dev/null | grep -q . || missing+=("$mod")
+ done
+ [ "''${#missing[@]}" -eq 0 ] && { log "mods already present"; return 0; }
+
+ local runner="steamcmd"
+ command -v steamcmd >/dev/null 2>&1 || { err "steamcmd not found"; return 1; }
+
+ mods=("''${missing[@]}")
+ local cmds=""
+ for mod in "''${mods[@]}"; do
+ cmds="$cmds +workshop_download_item 221100 $mod"
+ done
+
+ if pgrep -x steam >/dev/null; then
+ log "closing steam..."
+ steam -shutdown
+ while pgrep -x steam >/dev/null; do sleep 1; done
+ fi
+
+ log "downloading mods..."
+ local attempt=1
+ while [ "$attempt" -le 4 ]; do
+ [ "$attempt" -gt 1 ] && log "retry $attempt/4, ''${#mods[@]} mods"
+ local out
+ local login_args=("$steamuser")
+ if [ ! -f "$loginmarker" ] && [ -n "$steampass" ]; then
+ login_args=("$steamuser" "$steampass")
+ fi
+ out=$($runner +@sSteamCmdForcePlatformType linux -forceipv4 +login "''${login_args[@]}" $cmds +quit | tee /dev/tty) || true
+
+ if echo "$out" | grep -q "Waiting for user info"; then
+ touch "$loginmarker"
+ fi
+ if echo "$out" | grep -q "FAILED"; then
+ rm -f "$loginmarker"
+ fi
+
+ if echo "$out" | grep -q "Invalid Password"; then
+ err "wrong password, clearing cache"
+ rm -f "$config/steampass"
+ steampass=""
+ fi
+
+ local failed=()
+ for mod in "''${mods[@]}"; do
+ if echo "$out" | grep -q "Success. Downloaded item $mod "; then
+ continue
+ fi
+ if echo "$out" | grep -qE "Download item $mod failed \((Access Denied|No match|File Not Found)\)"; then
+ err "mod $mod unavailable, blacklisting"
+ grep -qx "$mod" "$config/blacklist" || echo "$mod" >> "$config/blacklist"
+ continue
+ fi
+ failed+=("$mod")
+ done
+
+ [ "''${#failed[@]}" -eq 0 ] && { log "mods downloaded"; return 0; }
+
+ mods=("''${failed[@]}")
+ cmds=""
+ for mod in "''${mods[@]}"; do
+ cmds="$cmds +workshop_download_item 221100 $mod"
+ done
+ attempt=$((attempt + 1))
+ sleep 3
+ done
+
+ err "failed to download: ''${mods[*]}"
+ return 1
+}
+
+launch() {
+ local ip="$1" port="$2" mods="$3" mod_arg=""
+
+ if [ -z "$ip" ] || [ -z "$port" ]; then
+ err "invalid ip/port"
+ return 1
+ fi
+
+ log "verifying server..."
+ local verify
+ verify=$(api "/servers?filter[game]=dayz&filter[search]=$ip:$port" | jq -r --arg ip "$ip" --arg port "$port" '.data[]? | select(.attributes.ip == $ip and (.attributes.port | tostring) == $port) | "\(.attributes.name) [\(.attributes.players)/\(.attributes.maxPlayers)]"' | head -n 1)
+ if [ -n "$verify" ]; then
+ log "found: $verify"
+ else
+ err "server not found on battlemetrics, connecting anyway"
+ fi
+
+ if [ -z "$mods" ]; then
+ log "no mod list found, may still require mods"
+ else
+ log "downloading mods..."
+ download_mods "$mods" || err "some mods failed, launching anyway"
+ for m in $(echo "$mods" | tr ',' '\n'); do
+ [ -z "$m" ] && continue
+ local folder=$(find "$workshop/$m" -maxdepth 1 -type d -name "@*" 2>/dev/null | head -n 1)
+ [ -z "$folder" ] && folder="$workshop/$m"
+ find "$folder" -iname "*.pbo" 2>/dev/null | grep -q . || { err "missing pbo for $m, skipping"; continue; }
+ mod_arg="$mod_arg;z:''${folder//\//\\}"
+ done
+ mod_arg="''${mod_arg#;}"
+ [ -n "$mod_arg" ] && mod_arg="-mod=$mod_arg"
+ sleep 3
+ fi
+
+ echo "$(date '+%F %T') connect=$ip:$port $mod_arg" >> "$logfile"
+
+ if ! pgrep -x steam >/dev/null; then
+ log "starting steam..."
+ if [ ! -f "$loginmarker" ]; then
+ if [ -n "$steampass" ]; then
+ steam -login "$steamuser" "$steampass" >>"$config/steam.log" 2>&1 & disown
+ else
+ steam -login "$steamuser" >>"$config/steam.log" 2>&1 & disown
+ fi
+ else
+ steam >>"$config/steam.log" 2>&1 & disown
+ fi
+ while ! pgrep -x steam >/dev/null; do sleep 1; done
+ sleep 5
+ fi
+
+ log "connecting to $ip:$port..."
+ if [ -n "$mod_arg" ]; then
+ steam -applaunch 221100 -noLauncher "-connect=$ip" "-port=$port" "$mod_arg" >>"$config/steam.log" 2>&1
+ else
+ steam -applaunch 221100 -noLauncher "-connect=$ip" "-port=$port" >>"$config/steam.log" 2>&1
+ fi
+}
+
+pick_server() {
+ fzf --prompt="server> " --delimiter="|" --with-nth=3.. --layout=reverse \
+ --disabled --ansi \
+ --bind "start:reload:$0 --fetch" \
+ --bind "change:reload:sleep 0.4; $0 --fetch {q}"
+}
+
+save_favorite() {
+ local ip="$1" port="$2" name="$3"
+ if grep -qF "$ip$d$port$d" "$favfile"; then
+ err "already saved"
+ return
+ fi
+ local mods=$(get_mods "$ip" "$port")
+ printf "%s%s%s%s%s%s%s\n" "$ip" "$d" "$port" "$d" "$mods" "$d" "$name" >> "$favfile"
+ log "saved $name"
+}
+
+show_favorites() {
+ grep -vE '^[[:space:]]*$' "$favfile" | fzf --prompt="fav> " --delimiter="$d" --with-nth=4 --layout=reverse
+}
+
+while true; do
+ action=$(printf "favorites\nbrowse\nadd manual\nremove\nrefresh mods\nquit\n" | fzf --prompt="dayz> " --layout=reverse)
+
+ case "$action" in
+ browse)
+ selection=$(pick_server)
+ [ -z "$selection" ] && continue
+ id=$(echo "$selection" | cut -d'|' -f1)
+ ip_port=$(echo "$selection" | cut -d'|' -f2)
+ name=$(echo "$selection" | cut -d'|' -f3- | sed 's/ \[[0-9]*\/[0-9]*\]$//')
+ ip=''${ip_port%%:*}
+ port=''${ip_port##*:}
+ confirm=$(printf "play\nsave to favorites\n" | fzf --prompt="$name> " --layout=reverse)
+ case "$confirm" in
+ play) mods=$(get_mods_by_id "$id"); launch "$ip" "$port" "$mods"; exit 0 ;;
+ "save to favorites") save_favorite "$ip" "$port" "$name"; show_favorites ;;
+ esac
+ ;;
+ favorites)
+ selection=$(show_favorites)
+ [ -z "$selection" ] && continue
+ ip=$(echo "$selection" | cut -d"$d" -f1)
+ port=$(echo "$selection" | cut -d"$d" -f2)
+ mods=$(echo "$selection" | cut -d"$d" -f3)
+ launch "$ip" "$port" "$mods"
+ exit 0
+ ;;
+ "add manual")
+ read -p "ip: " ip
+ read -p "port: " port
+ read -p "name: " name
+ save_favorite "$ip" "$port" "$name"
+ show_favorites
+ ;;
+ remove)
+ selection=$(show_favorites)
+ [ -z "$selection" ] && continue
+ grep -vF "$selection" "$favfile" | grep -vE '^[[:space:]]*$' > "$favfile.tmp" && mv "$favfile.tmp" "$favfile"
+ show_favorites
+ ;;
+ "refresh mods")
+ selection=$(show_favorites)
+ [ -z "$selection" ] && continue
+ ip=$(echo "$selection" | cut -d"$d" -f1)
+ port=$(echo "$selection" | cut -d"$d" -f2)
+ name=$(echo "$selection" | cut -d"$d" -f4)
+ mods=$(get_mods "$ip" "$port")
+ grep -vF "$selection" "$favfile" | grep -vE '^[[:space:]]*$' > "$favfile.tmp" && mv "$favfile.tmp" "$favfile"
+ printf "%s%s%s%s%s%s%s\n" "$ip" "$d" "$port" "$d" "$mods" "$d" "$name" >> "$favfile"
+ show_favorites
+ ;;
+ quit|"") break ;;
+ esac
+done
+ '';
+ }) ];
+
+ xdg.desktopEntries.meowz = {
+ name = "MeowZ";
+ comment = "dayz server launcher";
+ exec = "kitty --hold -e meowz";
+ icon = "applications-games";
+ terminal = false;
+ categories = [ "Game" ];
+ };
+
+ home.file."${dayzDir}/DayZ.cfg".text = ''
+ language="English";
+ adapter=-1;
+ 3D_Performance=57692;
+ Resolution_Bpp=32;
+ WinX=0;
+ WinY=0;
+ WindowWidth=1920;
+ WindowHeight=1080;
+ MSAA=0;
+ PostFX=0;
+ VSync=1;
+ FXAO=0;
+ AToC=0;
+ AnisoFilter=4;
+ TerrainDetail=2;
+ FXAA=0;
+ refreshMode=200;
+ maxGPUToRenderFrames=1;
+ '';
+
+ home.file."${dayzDir}/steamuser_settings.DayZProfile".text = ''
+ version=1;
+ blood=1;
+ singleVoice=0;
+ gamma=1;
+ lastMPServer="";
+ lastMPServerName="";
+ lastMPMission="";
+ inputVersion=1;
+ perspective=1;
+ trackIR=1;
+ freeTrack=1;
+ mouseSmoothing=0;
+ maxSamplesPlayed=96;
+ vonInputMode=0;
+ TexQuality=1;
+ WaterQuality=1;
+ tripleHead=0;
+ showTitles=1;
+ vehicleFreelook=0;
+ pauseMode=0;
+ shadowQuality=1;
+ headBob=0;
+ fov=0.95993;
+ sceneComplexity=150000;
+ shadowZDistance=80;
+ viewDistance=1200;
+ preferredObjectViewDistance=1200;
+ terrainGrid=12.5;
+ volumeMaster=5;
+ volumeCD=0.5;
+ volumeFX=4;
+ volumeSpeech=5;
+ volumeVoN=10;
+ vonRecThreshold=0.029999999;
+ brightness=1;
+ uiTopLeftX=0.12500001;
+ uiTopLeftY=0;
+ uiBottomRightX=0.875;
+ uiBottomRightY=1;
+ IGUIScale=0.55000001;
+ showHUD=1;
+ hudBrightness=1.0;
+ showCrosshair=0;
+ showQuickbar=1;
+ showVehicleHUD=1;
+ showServerInfo=0;
+ '';
+
+ home.file."${dayzDir}/steamuser.dayz_preset_User.xml".text = ''
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<preset>
+ <input name="UAMoveForward">
+ <btn name="kW" />
+ <btn name="x1LeftThumbUp" />
+ </input>
+ <input name="UAMoveBack">
+ <btn name="kS" />
+ <btn name="x1LeftThumbDown" />
+ </input>
+ <input name="UAMoveLeft">
+ <btn name="kA" />
+ <btn name="x1LeftThumbLeft" />
+ </input>
+ <input name="UAMoveRight">
+ <btn name="kD" />
+ <btn name="x1LeftThumbRight" />
+ </input>
+ <input name="UATurbo">
+ <btn name="kLShift" />
+ </input>
+ <input name="UAWalkRunTemp">
+ <btn name="kLControl" />
+ </input>
+ <input name="UAWalkRunToggle">
+ <btn name="kLControl">
+ <event name="doubleclick" />
+ </btn>
+ </input>
+ <input name="UAToggleTurbo">
+ <btn name="x1ThumbLeft" />
+ </input>
+ <input name="UAWalkForward">
+ <btn name="x1LeftThumbUp" />
+ </input>
+ <input name="UAWalkBack">
+ <btn name="x1LeftThumbDown" />
+ </input>
+ <input name="UAWalkLeft">
+ <btn name="x1LeftThumbLeft" />
+ </input>
+ <input name="UAWalkRight">
+ <btn name="x1LeftThumbRight" />
+ </input>
+ <input name="UAGetOver">
+ <btn name="kSpace" />
+ <btn name="x1A">
+ <event name="clickorhold" />
+ </btn>
+ </input>
+ <input name="UAGetOverControllerHelper">
+ <btn name="x1A">
+ <event name="clickorhold" />
+ </btn>
+ </input>
+ <input name="UAStance">
+ <btn name="x1B" />
+ </input>
+ <input name="UALeanLeft">
+ <btn name="mB5" />
+ </input>
+ <input name="UALeanRight">
+ <btn name="mB4" />
+ </input>
+ <input name="UALeanLeftGamepad">
+ <btn name="x1ShoulderLeft" />
+ </input>
+ <input name="UALeanRightGamepad">
+ <btn name="x1ShoulderRight" />
+ </input>
+ <input name="UAPersonCamSwitchSide">
+ <btn name="x1ThumbRight">
+ <event name="holdbegin" />
+ </btn>
+ </input>
+ <input name="UAAimLeft">
+ <btn name="mLeft" />
+ <btn name="x1RightThumbLeft" />
+ </input>
+ <input name="UAAimRight">
+ <btn name="mRight" />
+ <btn name="x1RightThumbRight" />
+ </input>
+ <input name="UAAimUp">
+ <btn name="mUp" />
+ <btn name="x1RightThumbUp" />
+ </input>
+ <input name="UAAimDown">
+ <btn name="mDown" />
+ <btn name="x1RightThumbDown" />
+ </input>
+ <input name="UATrackLeft">
+ <btn name="irYawLeft" />
+ </input>
+ <input name="UATrackRight">
+ <btn name="irYawRight" />
+ </input>
+ <input name="UATrackUp">
+ <btn name="irPitchUp" />
+ </input>
+ <input name="UATrackDown">
+ <btn name="irPitchDown" />
+ </input>
+ <input name="UAPersonView">
+ <btn name="x1ThumbRight" />
+ <btn name="kB" />
+ </input>
+ <input name="UALookAround">
+ <btn name="kLMenu" />
+ <btn name="x1ShoulderLeft">
+ <event name="hold" />
+ </btn>
+ </input>
+ <input name="UALookAroundToggle">
+ <btn name="kLMenu">
+ <event name="doubleclick" />
+ </btn>
+ </input>
+ <input name="UAZoomIn">
+ <btn name="mBMiddle" />
+ </input>
+ <input name="UAZoomInToggle">
+ <btn name="x1ShoulderLeft">
+ <event name="doubleclick" />
+ </btn>
+ </input>
+ <input name="UAToggleNVG">
+ <btn name="kL">
+ <event name="hold" />
+ </btn>
+ </input>
+ <input name="UAToggleHeadlight">
+ <btn name="kL" />
+ <btn name="x1Y" />
+ </input>
+ <input name="UAADSToggle">
+ <btn name="kLShift">
+ <event name="click" />
+ </btn>
+ <btn name="x1ThumbRight">
+ <event name="click" />
+ </btn>
+ </input>
+ <input name="UAZoomInOptics">
+ <btn name="mWheelUp" />
+ <btn name="x1PadRight">
+ <event name="click" />
+ </btn>
+ </input>
+ <input name="UAZoomOutOptics">
+ <btn name="mWheelDown" />
+ <btn name="x1PadRight">
+ <event name="hold" />
+ </btn>
+ </input>
+ <input name="UAZoomInOpticsControllerHelper">
+ <btn name="x1PadRight">
+ <event name="click" />
+ </btn>
+ </input>
+ <input name="UAZoomOutOpticsControllerHelper">
+ <btn name="x1PadRight">
+ <event name="hold" />
+ </btn>
+ </input>
+ <input name="UAThrowitem">
+ <btn name="kG">
+ <event name="click" />
+ </btn>
+ <btn name="x1X">
+ <event name="doubleclick" />
+ </btn>
+ </input>
+ <input name="UADropitem">
+ <btn name="kG">
+ <event name="hold" />
+ </btn>
+ <btn name="x1X">
+ <event name="hold" />
+ </btn>
+ </input>
+ <input name="UAGear">
+ <btn name="kTab" />
+ <btn name="x1View" />
+ </input>
+ <input name="UAFire">
+ <btn name="mBLeft" />
+ <btn name="x1TriggerRight" />
+ </input>
+ <input name="UAHeavyMeleeAttack">
+ <btn name="x1Y" />
+ </input>
+ <input name="UAMeleeAttackModifier">
+ <btn name="kLShift" />
+ </input>
+ <input name="UAWeaponMeleeAttack">
+ <btn name="kF" />
+ <btn name="x1X" />
+ </input>
+ <input name="UAHoldBreath">
+ <btn name="kLControl" />
+ <btn name="x1ThumbLeft" />
+ </input>
+ <input name="UADefaultAction">
+ <btn name="mBLeft" />
+ <btn name="x1TriggerRight" />
+ </input>
+ <input name="UAAction">
+ <btn name="kF" />
+ <btn name="x1X" />
+ </input>
+ <input name="UAPrevAction">
+ <btn name="mWheelUp" />
+ <btn name="x1PadDown">
+ <event name="click" />
+ </btn>
+ </input>
+ <input name="UANextAction">
+ <btn name="mWheelDown" />
+ <btn name="x1PadUp">
+ <event name="click" />
+ </btn>
+ </input>
+ <input name="UATempRaiseWeapon">
+ <btn name="mBRight" />
+ </input>
+ <input name="UATempRaiseWeaponGamepad">
+ <btn name="x1TriggerLeft" />
+ </input>
+ <input name="UAReloadMagazine">
+ <btn name="kR" />
+ <btn name="x1Y" />
+ </input>
+ <input name="UAZeroingUp">
+ <btn name="x1PadUp" />
+ <btn name="kPrior" />
+ </input>
+ <input name="UAZeroingDown">
+ <btn name="x1PadDown" />
+ <btn name="kNext" />
+ </input>
+ <input name="UAToggleWeapons">
+ <btn name="kX" />
+ <btn name="x1A">
+ <btn name="x1TriggerLeft" />
+ </btn>
+ </input>
+ <input name="UAUIQuickbarToggle">
+ <btn name="kGrave" />
+ </input>
+ <input name="UAItem0">
+ <btn name="k1" />
+ </input>
+ <input name="UAItem1">
+ <btn name="k2" />
+ </input>
+ <input name="UAItem2">
+ <btn name="k3" />
+ </input>
+ <input name="UAItem3">
+ <btn name="k4" />
+ </input>
+ <input name="UAItem4">
+ <btn name="k5" />
+ </input>
+ <input name="UAItem5">
+ <btn name="k6" />
+ </input>
+ <input name="UAItem6">
+ <btn name="k7" />
+ </input>
+ <input name="UAItem7">
+ <btn name="k8" />
+ </input>
+ <input name="UAItem8">
+ <btn name="k9" />
+ </input>
+ <input name="UAItem9">
+ <btn name="k0" />
+ </input>
+ <input name="UAChat">
+ <btn name="kReturn" />
+ </input>
+ <input name="UAVoiceOverNet">
+ <btn name="kCapital">
+ <event name="hold" />
+ </btn>
+ <btn name="x1PadLeft">
+ <event name="hold" />
+ </btn>
+ </input>
+ <input name="UAVoiceOverNetToggle">
+ <btn name="kCapital">
+ <event name="doubleclick" />
+ </btn>
+ <btn name="x1PadLeft">
+ <event name="doubleclick" />
+ </btn>
+ </input>
+ <input name="UAVoiceLevel">
+ <btn name="kUp" />
+ <btn name="x1PadLeft">
+ <event name="click" />
+ </btn>
+ </input>
+ <input name="UAVoiceDistanceUp">
+ <btn name="kUp" />
+ <btn name="x1ShoulderRight">
+ <btn name="x1PadLeft" />
+ </btn>
+ </input>
+ <input name="UAVoiceDistanceDown">
+ <btn name="kDown" />
+ <btn name="x1ShoulderLeft">
+ <btn name="x1PadLeft" />
+ </btn>
+ </input>
+ <input name="UAVoiceModifierHelper">
+ <btn name="x1PadLeft" />
+ </input>
+ <input name="UAGestureSlot01">
+ <btn name="kF1" />
+ </input>
+ <input name="UAGestureSlot02">
+ <btn name="kF2" />
+ </input>
+ <input name="UAGestureSlot03">
+ <btn name="kF3" />
+ </input>
+ <input name="UAGestureSlot04">
+ <btn name="kF4" />
+ </input>
+ <input name="UAGestureSlot05">
+ <btn name="kF5" />
+ </input>
+ <input name="UAGestureSlot06">
+ <btn name="kF6" />
+ </input>
+ <input name="UAGestureSlot07">
+ <btn name="kF7" />
+ </input>
+ <input name="UAGestureSlot08">
+ <btn name="kF8" />
+ </input>
+ <input name="UAGestureSlot09">
+ <btn name="kF9" />
+ </input>
+ <input name="UAGestureSlot10">
+ <btn name="kF10" />
+ </input>
+ <input name="UAGestureSlot11">
+ <btn name="kF11" />
+ </input>
+ <input name="EmoteGreeting">
+ <btn name="kF1" />
+ </input>
+ <input name="EmoteSOS">
+ <btn name="kF2" />
+ </input>
+ <input name="EmoteHeart">
+ <btn name="kF3" />
+ </input>
+ <input name="EmoteTaunt">
+ <btn name="kF4" />
+ </input>
+ <input name="EmoteLyingDown" />
+ <input name="EmoteTauntKiss">
+ <btn name="kF6" />
+ </input>
+ <input name="EmotePoint">
+ <btn name="kF7" />
+ </input>
+ <input name="EmoteTauntElbow">
+ <btn name="kF8" />
+ </input>
+ <input name="EmoteThumb">
+ <btn name="kF9" />
+ </input>
+ <input name="EmoteThumbDown" />
+ <input name="EmoteThroat">
+ <btn name="kF10" />
+ </input>
+ <input name="EmoteDance" />
+ <input name="EmoteSalute" />
+ <input name="EmoteTimeout" />
+ <input name="EmoteFacepalm" />
+ <input name="EmoteClap" />
+ <input name="EmoteSilent" />
+ <input name="EmoteWatching" />
+ <input name="EmoteHold" />
+ <input name="EmoteListening" />
+ <input name="EmotePointSelf" />
+ <input name="EmoteLookAtMe" />
+ <input name="EmoteTauntThink" />
+ <input name="EmoteMove" />
+ <input name="EmoteGetDown" />
+ <input name="EmoteCome" />
+ <input name="EmoteSurrender">
+ <btn name="kF5" />
+ </input>
+ <input name="EmoteCampfireSit" />
+ <input name="EmoteSitA" />
+ <input name="EmoteSitB" />
+ <input name="EmoteRPSRandom" />
+ <input name="EmoteRPSRock" />
+ <input name="EmoteRPSPaper" />
+ <input name="EmoteRPSScisors" />
+ <input name="EmoteNod" />
+ <input name="EmoteShake" />
+ <input name="EmoteShrug" />
+ <input name="EmoteSuicide">
+ <btn name="kF11" />
+ </input>
+ <input name="EmoteVomit" />
+ <input name="UACarLeft">
+ <btn name="kA" />
+ <btn name="x1LeftThumbLeft" />
+ </input>
+ <input name="UACarRight">
+ <btn name="kD" />
+ <btn name="x1LeftThumbRight" />
+ </input>
+ <input name="UACarForward">
+ <btn name="kW" />
+ <btn name="x1TriggerRight" />
+ </input>
+ <input name="UACarBack">
+ <btn name="kS" />
+ <btn name="x1TriggerLeft" />
+ </input>
+ <input name="UACarShiftGearUp">
+ <btn name="kE" />
+ <btn name="x1B" />
+ </input>
+ <input name="UACarShiftGearDown">
+ <btn name="kQ" />
+ <btn name="x1A" />
+ </input>
+ <input name="UAVehicleTurbo">
+ <btn name="kLShift" />
+ <btn name="x1TriggerRight" />
+ </input>
+ <input name="UAVehicleSlow">
+ <btn name="kLControl" />
+ <btn name="x1TriggerRight" />
+ </input>
+ <input name="UACarHorn">
+ <btn name="kH" />
+ <btn name="x1ThumbLeft" />
+ </input>
+ <input name="UACarHandbrake">
+ <btn name="kSpace" />
+ <btn name="x1ShoulderRight" />
+ </input>
+ <input name="UAUILeft">
+ <btn name="kLeft" />
+ <btn name="x1PadLeft" />
+ <btn name="x1LeftThumbLeft" />
+ <btn name="x1RightThumbLeft" />
+ </input>
+ <input name="UAUIRight">
+ <btn name="kRight" />
+ <btn name="x1PadRight" />
+ <btn name="x1LeftThumbRight" />
+ <btn name="x1RightThumbRight" />
+ </input>
+ <input name="UAUIUp">
+ <btn name="kUp" />
+ <btn name="x1PadUp" />
+ <btn name="x1LeftThumbUp" />
+ <btn name="x1RightThumbUp" />
+ </input>
+ <input name="UAUIDown">
+ <btn name="kDown" />
+ <btn name="x1PadDown" />
+ <btn name="x1LeftThumbDown" />
+ <btn name="x1RightThumbDown" />
+ </input>
+ <input name="UAUISelect">
+ <btn name="kReturn" />
+ <btn name="kNumpadEnter" />
+ <btn name="x1A" />
+ </input>
+ <input name="UAUIBack">
+ <btn name="kEscape" />
+ <btn name="x1B">
+ <event name="click" />
+ </btn>
+ </input>
+ <input name="UAMenuSelect">
+ <btn name="mBLeft" />
+ </input>
+ <input name="UAMenuBack">
+ <btn name="mBRight" />
+ </input>
+ <input name="UAUICtrlX">
+ <btn name="x1X" />
+ </input>
+ <input name="UAUICtrlY">
+ <btn name="x1Y" />
+ </input>
+ <input name="UAUIMenu">
+ <btn name="kEscape" />
+ <btn name="x1Menu" />
+ </input>
+ <input name="UAUITabLeft">
+ <btn name="kLBracket" />
+ <btn name="x1ShoulderLeft" />
+ </input>
+ <input name="UAUITabRight">
+ <btn name="kRBracket" />
+ <btn name="x1ShoulderRight" />
+ </input>
+ <input name="UAUICredits">
+ <btn name="x1View" />
+ </input>
+ <input name="UAUICopyDebugMonitorPos">
+ <btn name="kP" />
+ </input>
+ <input name="UAUIThumbRight">
+ <btn name="x1ThumbRight" />
+ </input>
+ <input name="UAUIPadLeft">
+ <btn name="x1PadLeft" />
+ </input>
+ <input name="UAUIPadRight">
+ <btn name="x1PadRight" />
+ </input>
+ <input name="UAUIRightStickHorizontal">
+ <btn name="x1RightThumbHorizontal" />
+ </input>
+ <input name="UAUIRightStickVertical">
+ <btn name="x1RightThumbVertical" />
+ </input>
+ <input name="UAUIGesturesOpen">
+ <btn name="kPeriod" />
+ <btn name="x1PadRight" />
+ </input>
+ <input name="UAUIQuickbarRadialOpen">
+ <btn name="kComma" />
+ <btn name="x1ShoulderRight" />
+ </input>
+ <input name="UAUIQuickbarRadialInventoryOpen">
+ <btn name="kComma" />
+ <btn name="x1ThumbLeft" />
+ </input>
+ <input name="UAUIRadialMenuStickHelper">
+ <btn name="x1ThumbRight" />
+ </input>
+ <input name="UAUILeftInventory">
+ <btn name="x1PadLeft" />
+ <btn name="x1RightThumbLeft" />
+ </input>
+ <input name="UAUIRightInventory">
+ <btn name="x1PadRight" />
+ <btn name="x1RightThumbRight" />
+ </input>
+ <input name="UAUIUpInventory">
+ <btn name="x1PadUp" />
+ <btn name="x1RightThumbUp" />
+ </input>
+ <input name="UAUIDownInventory">
+ <btn name="x1PadDown" />
+ <btn name="x1RightThumbDown" />
+ </input>
+ <input name="UAUINextUp">
+ <btn name="x1TriggerLeft" />
+ </input>
+ <input name="UAUINextDown">
+ <btn name="x1TriggerRight" />
+ </input>
+ <input name="UAUIInventoryContainerUp">
+ <btn name="x1TriggerLeft" />
+ </input>
+ <input name="UAUIInventoryContainerDown">
+ <btn name="x1TriggerRight" />
+ </input>
+ <input name="UAUIInventoryTabLeft">
+ <btn name="kLBracket" />
+ <btn name="x1ShoulderLeft" />
+ </input>
+ <input name="UAUIInventoryTabRight">
+ <btn name="kRBracket" />
+ <btn name="x1ShoulderRight" />
+ </input>
+ <input name="UAUIRotateInventory">
+ <btn name="kSpace" />
+ </input>
+ <input name="UAUIFastEquip">
+ <btn name="x1Y">
+ <event name="click" />
+ </btn>
+ </input>
+ <input name="UAUIPutInHandsFromVicinity">
+ <btn name="x1A">
+ <event name="click" />
+ </btn>
+ </input>
+ <input name="UAUIPutInHandsFromInventory">
+ <btn name="x1A">
+ <event name="click" />
+ </btn>
+ </input>
+ <input name="UAUISplit">
+ <btn name="x1Y">
+ <event name="hold" />
+ </btn>
+ </input>
+ <input name="UAUICombine">
+ <btn name="x1B">
+ <event name="hold" />
+ </btn>
+ </input>
+ <input name="UAUIDragNDrop">
+ <btn name="kReturn" />
+ <btn name="kNumpadEnter" />
+ <btn name="x1A" />
+ </input>
+ <input name="UAUIFastTransferToVicinity">
+ <btn name="x1X">
+ <event name="hold" />
+ </btn>
+ </input>
+ <input name="UAUIExpandCollapseContainer">
+ <btn name="x1ThumbRight">
+ <event name="click" />
+ </btn>
+ </input>
+ <input name="UAUISelectItem">
+ <btn name="x1A" />
+ </input>
+ <input name="UAUIFastTransferItem">
+ <btn name="x1X">
+ <event name="click" />
+ </btn>
+ </input>
+ <input name="UAMapToggle">
+ <btn name="kM" />
+ </input>
+ <input name="UAMapMovementHorizontal">
+ <btn name="x1LeftThumbHorizontal" />
+ </input>
+ <input name="UAMapMovementVertical">
+ <btn name="x1LeftThumbVertical" />
+ </input>
+ <input name="UAMapZoom">
+ <btn name="x1RightThumbVertical" />
+ </input>
+ <input name="UASwitchPreset">
+ <btn name="x1Y" />
+ </input>
+ <input name="UAMoveUp">
+ <btn name="kQ" />
+ <btn name="x1TriggerRight" />
+ </input>
+ <input name="UAMoveDown">
+ <btn name="kZ" />
+ <btn name="x1TriggerLeft" />
+ </input>
+ <input name="UABuldResetCamera">
+ <btn name="kNumpad0" />
+ </input>
+ <input name="UABuldTurbo">
+ <btn name="kU" />
+ </input>
+ <input name="UABuldSlow">
+ <btn name="kJ" />
+ </input>
+ <input name="UABuldFreeLook">
+ <btn name="kNumpad5" />
+ </input>
+ <input name="UABuldRunScript">
+ <btn name="kF10" />
+ </input>
+ <input name="UABuldSelectToggle">
+ <btn name="kSpace" />
+ </input>
+ <input name="UABuldSelect">
+ <btn name="mBLeft" />
+ </input>
+ <input name="UABuldSelectAddMod">
+ <btn name="k7" />
+ </input>
+ <input name="UABuldSelectRemoveMod">
+ <btn name="k8" />
+ </input>
+ <input name="UABuldModifySelected">
+ <btn name="mBRight" />
+ </input>
+ <input name="UABuldCycleMod">
+ <btn name="k5" />
+ </input>
+ <input name="UABuldRotationXAxisMod">
+ <btn name="k1" />
+ </input>
+ <input name="UABuldRotationZAxisMod">
+ <btn name="k3" />
+ </input>
+ <input name="UABuldCoordModCycle">
+ <btn name="k6" />
+ </input>
+ <input name="UABuldSampleTerrainHeight">
+ <btn name="mBRight" />
+ </input>
+ <input name="UABuldSetTerrainHeight">
+ <btn name="mBLeft" />
+ </input>
+ <input name="UABuldScaleMod">
+ <btn name="kE" />
+ </input>
+ <input name="UABuldElevateMod">
+ <btn name="kT" />
+ </input>
+ <input name="UABuldSmoothMod">
+ <btn name="kLShift" />
+ </input>
+ <input name="UABuldFlattenMod">
+ <btn name="kLMenu" />
+ </input>
+ <input name="UABuldBrushRatioUp">
+ <btn name="kB">
+ <btn name="mWheelUp" />
+ </btn>
+ </input>
+ <input name="UABuldBrushRatioDown">
+ <btn name="kB">
+ <btn name="mWheelDown" />
+ </btn>
+ </input>
+ <input name="UABuldBrushOuterUp">
+ <btn name="kN">
+ <btn name="mWheelUp" />
+ </btn>
+ </input>
+ <input name="UABuldBrushOuterDown">
+ <btn name="kN">
+ <btn name="mWheelDown" />
+ </btn>
+ </input>
+ <input name="UABuldBrushStrengthUp">
+ <btn name="kM">
+ <btn name="mWheelUp" />
+ </btn>
+ </input>
+ <input name="UABuldBrushStrengthDown">
+ <btn name="kM">
+ <btn name="mWheelDown" />
+ </btn>
+ </input>
+ <input name="UABuldToggleNearestObjectArrow">
+ <btn name="kH" />
+ </input>
+ <input name="UABuldCycleBrushMod">
+ <btn name="kG" />
+ </input>
+ <input name="UABuldSelectionType">
+ <btn name="kF" />
+ </input>
+ <input name="UABuldCreateLastSelectedObject">
+ <btn name="kV" />
+ </input>
+ <input name="UABuldDuplicateSelection">
+ <btn name="kC" />
+ </input>
+ <input name="UABuldDeleteSelection">
+ <btn name="kR" />
+ </input>
+ <input name="UABuldUndo">
+ <btn name="kLControl">
+ <btn name="kX" />
+ </btn>
+ </input>
+ <input name="UABuldRedo">
+ <btn name="kLControl">
+ <btn name="kY" />
+ </btn>
+ </input>
+ <input name="UABuldMoveLeft">
+ <btn name="mLeft" />
+ <btn name="kA" />
+ </input>
+ <input name="UABuldMoveRight">
+ <btn name="mRight" />
+ <btn name="kD" />
+ </input>
+ <input name="UABuldMoveForward">
+ <btn name="mUp" />
+ <btn name="kW" />
+ </input>
+ <input name="UABuldMoveBack">
+ <btn name="mDown" />
+ <btn name="kS" />
+ </input>
+ <input name="UABuldMoveUp">
+ <btn name="kQ" />
+ </input>
+ <input name="UABuldMoveDown">
+ <btn name="kZ" />
+ </input>
+ <input name="UABuldLeft">
+ <btn name="kLeft" />
+ </input>
+ <input name="UABuldRight">
+ <btn name="kRight" />
+ </input>
+ <input name="UABuldForward">
+ <btn name="kUp" />
+ </input>
+ <input name="UABuldBack">
+ <btn name="kDown" />
+ </input>
+ <input name="UABuldLookLeft">
+ <btn name="kNumpad4" />
+ </input>
+ <input name="UABuldLookRight">
+ <btn name="kNumpad6" />
+ </input>
+ <input name="UABuldLookUp">
+ <btn name="kNumpad8" />
+ </input>
+ <input name="UABuldLookDown">
+ <btn name="kNumpad2" />
+ </input>
+ <input name="UABuldZoomIn">
+ <btn name="kAdd" />
+ </input>
+ <input name="UABuldZoomOut">
+ <btn name="kSubstract" />
+ </input>
+ <input name="UABuldTextureInfo">
+ <btn name="kI" />
+ </input>
+ <input name="UABuldObjectRotateLeft">
+ <btn name="kNumpad4" />
+ <btn name="mBLeft">
+ <btn name="mLeft" />
+ </btn>
+ </input>
+ <input name="UABuldObjectRotateRight">
+ <btn name="kNumpad6" />
+ <btn name="mBLeft">
+ <btn name="mRight" />
+ </btn>
+ </input>
+ <input name="UABuldObjectRotateForward">
+ <btn name="kNumpad8" />
+ <btn name="mBLeft">
+ <btn name="mUp" />
+ </btn>
+ </input>
+ <input name="UABuldObjectRotateBack">
+ <btn name="kNumpad2" />
+ <btn name="mBLeft">
+ <btn name="mDown" />
+ </btn>
+ </input>
+ <input name="UABuldViewerMoveLeft">
+ <btn name="kA" />
+ <btn name="mBRight">
+ <btn name="mLeft" />
+ </btn>
+ </input>
+ <input name="UABuldViewerMoveRight">
+ <btn name="kD" />
+ <btn name="mBRight">
+ <btn name="mRight" />
+ </btn>
+ </input>
+ <input name="UABuldViewerMoveForward">
+ <btn name="kW" />
+ <btn name="mBRight">
+ <btn name="mUp" />
+ </btn>
+ </input>
+ <input name="UABuldViewerMoveBack">
+ <btn name="kS" />
+ <btn name="mBRight">
+ <btn name="mDown" />
+ </btn>
+ </input>
+ <input name="UABuldViewerMoveUp">
+ <btn name="kQ" />
+ </input>
+ <input name="UABuldViewerMoveDown">
+ <btn name="kZ" />
+ </input>
+ <input name="UABuldPreviousAnimation">
+ <btn name="kPrior" />
+ <btn name="kLBracket" />
+ </input>
+ <input name="UABuldNextAnimation">
+ <btn name="kNext" />
+ <btn name="kRBracket" />
+ </input>
+ <input name="UABuldRecedeAnimation">
+ <btn name="mWheelUp" />
+ <btn name="kSemicolon" />
+ </input>
+ <input name="UABuldAdvanceAnimation">
+ <btn name="mWheelDown" />
+ <btn name="kApostrophe" />
+ </input>
+ <input name="UABuldAlignToTerrain">
+ <btn name="k9" />
+ </input>
+ <input name="UAStand">
+ <btn name="kE" />
+ </input>
+ <input name="UACrouch">
+ <btn name="kC" />
+ </input>
+ <input name="UAProne">
+ <btn name="kV" />
+ </input>
+ <input name="UABBPRotate">
+ <btn name="kUp" />
+ </input>
+ <input name="UACycleSize">
+ <btn name="kLeft" />
+ </input>
+ <input name="UANextSnap">
+ <btn name="mWheelUp" />
+ </input>
+ <input name="UAPrevSnap">
+ <btn name="mWheelDown" />
+ </input>
+ <input name="UASnapLook">
+ <btn name="kDown" />
+ </input>
+ <input name="UABBPTogInv" />
+ <input name="UASIBHeliForward">
+ <btn name="kW" />
+ <btn name="x1LeftThumbUp" />
+ </input>
+ <input name="UASIBHeliCyclicLeft">
+ <btn name="kA" />
+ <btn name="x1LeftThumbLeft" />
+ </input>
+ <input name="UASIBHeliBack">
+ <btn name="kS" />
+ <btn name="x1LeftThumbDown" />
+ </input>
+ <input name="UASIBHeliCyclicRight">
+ <btn name="kD" />
+ <btn name="x1LeftThumbRight" />
+ </input>
+ <input name="UASIBHeliForwardM">
+ <btn name="mDown" />
+ <btn name="x1RightThumbDown" />
+ </input>
+ <input name="UASIBHeliBackM">
+ <btn name="mUp" />
+ <btn name="x1RightThumbUp" />
+ </input>
+ <input name="UASIBHeliLeftM">
+ <btn name="mLeft" />
+ <btn name="x1RightThumbLeft" />
+ </input>
+ <input name="UASIBHeliRightM">
+ <btn name="mRight" />
+ <btn name="x1RightThumbRight" />
+ </input>
+ <input name="UASIBHeliEngine_new">
+ <btn name="kC" />
+ <btn name="x1B" />
+ </input>
+ <input name="UASIBHeliAutopilot">
+ <btn name="mBRight" />
+ <btn name="x1Y" />
+ </input>
+ <input name="UASIBHeliHide">
+ <btn name="kX" />
+ <btn name="x1X" />
+ </input>
+ <input name="UASIBHeliLeft">
+ <btn name="kQ" />
+ <btn name="x1ShoulderLeft" />
+ </input>
+ <input name="UASIBHeliRight">
+ <btn name="kE" />
+ <btn name="x1ShoulderRight" />
+ </input>
+ <input name="UASIBHeliUp">
+ <btn name="kLShift" />
+ <btn name="x1TriggerRight" />
+ </input>
+ <input name="UASIBHeliDown">
+ <btn name="kZ" />
+ <btn name="x1TriggerLeft" />
+ </input>
+ <input name="UABetterInspect">
+ <btn name="kB" />
+ </input>
+ <input name="UALBAdminMenuToggle">
+ <btn name="kU" />
+ </input>
+ <input name="UALBAdminMenuOpen">
+ <btn name="kI" />
+ </input>
+ <input name="UALBMEarPlugsToggle">
+ <btn name="kN" />
+ </input>
+ <input name="UALBMEarPlugsLouder">
+ <btn name="kEquals" />
+ </input>
+ <input name="UALBMEarPlugsQuieter">
+ <btn name="kMinus" />
+ </input>
+ <input name="UALBMGroupOpenMap">
+ <btn name="kM" />
+ </input>
+ <input name="UALBMGroupOpenMapGroup">
+ <btn name="kP" />
+ </input>
+ <input name="UALBMGroupTacticalPing">
+ <btn name="kT" />
+ </input>
+ <input name="UALBMGroupTacticalPingClear">
+ <btn name="kC" />
+ </input>
+ <input name="UALBMGroupDeleteMarker">
+ <btn name="kDelete" />
+ </input>
+ <input name="UALBMGroupToggleVisibility">
+ <btn name="kK" />
+ </input>
+ <input name="UALBMSwitchChatChannel">
+ <btn name="kComma" />
+ </input>
+ <input name="UALBMGroupToggleCompass">
+ <btn name="kH" />
+ </input>
+ <input name="UALBMGroupTogglePlayerList">
+ <btn name="kU" />
+ </input>
+ <input name="UALBMGroupToggleMiniMap">
+ <btn name="kB" />
+ </input>
+ <input name="UALBMGroupAcceptInvite">
+ <btn name="kLControl">
+ <btn name="kJ" />
+ </btn>
+ <btn name="kRControl">
+ <btn name="kJ" />
+ </btn>
+ </input>
+ <input name="UALBMHoverLoot">
+ <btn name="k0" />
+ </input>
+ <input name="UALBMOpenRestrictions">
+ <btn name="kLControl">
+ <btn name="kR" />
+ </btn>
+ </input>
+ <input name="Loaded_ToggleVisor">
+ <btn name="kL" />
+ </input>
+ <input name="UASchanaAutorunToggle">
+ <btn name="kF10" />
+ </input>
+ <input name="UATogglePlayerControls">
+ <btn name="kSpace" />
+ </input>
+ <input name="UAHealTargets">
+ <btn name="kJ" />
+ </input>
+ <input name="UAToggleFreeCam">
+ <btn name="kBackspace" />
+ </input>
+ <input name="UACopyPositionClipboard">
+ <btn name="kP" />
+ </input>
+ <input name="UARepairVehicleAtCrosshairs">
+ <btn name="kK" />
+ </input>
+ <input name="UAFocusOnGame">
+ <btn name="kTab" />
+ </input>
+ <input name="UACollapseESPDropDwn" />
+ <input name="UATogglePlayerDetailEsp" />
+ <input name="UAExitSpectate">
+ <btn name="kPrior" />
+ </input>
+ <input name="UASelectObject">
+ <btn name="mBLeft" />
+ </input>
+ <input name="UADeSelectObject">
+ <btn name="kLControl" />
+ </input>
+ <input name="UAExecuteCommand">
+ <btn name="kReturn" />
+ <btn name="kNumpadEnter" />
+ </input>
+ <input name="UAUPCommand">
+ <btn name="kUp" />
+ </input>
+ <input name="UADOWNCommand">
+ <btn name="kDown" />
+ </input>
+ <input name="UAToggleAdminTools">
+ <btn name="kEnd" />
+ </input>
+ <input name="UAToggleMeshEsp">
+ <btn name="kY" />
+ </input>
+ <input name="UAOpenAdminTools">
+ <btn name="kHome" />
+ </input>
+ <input name="UATeleportToCrosshair">
+ <btn name="kH" />
+ </input>
+ <input name="UADeleteObjCrosshair">
+ <btn name="kDelete" />
+ </input>
+ <input name="UAToggleGodMode">
+ <btn name="kInsert" />
+ </input>
+ <input name="UACamForward">
+ <btn name="kW" />
+ </input>
+ <input name="UACamBackward">
+ <btn name="kS" />
+ </input>
+ <input name="UACamRight">
+ <btn name="kD" />
+ </input>
+ <input name="UACamLeft">
+ <btn name="kA" />
+ </input>
+ <input name="UACamUp">
+ <btn name="kQ" />
+ </input>
+ <input name="UACamDown">
+ <btn name="kZ" />
+ </input>
+ <input name="UACamTurbo">
+ <btn name="kLShift" />
+ </input>
+ <input name="UACamFOV">
+ <btn name="kLControl" />
+ </input>
+ <input name="UARotateLeft">
+ <btn name="mLeft" />
+ </input>
+ <input name="UARotateRight">
+ <btn name="mRight" />
+ </input>
+ <input name="UACamShiftLeft">
+ <btn name="mLeft" />
+ </input>
+ <input name="UACamShiftRight">
+ <btn name="mRight" />
+ </input>
+ <input name="UACamShiftUp">
+ <btn name="mUp" />
+ </input>
+ <input name="UACamShiftDown">
+ <btn name="mDown" />
+ </input>
+ <input name="UACamSpeedAdd">
+ <btn name="mWheelUp" />
+ </input>
+ <input name="UACamSpeedDeduct">
+ <btn name="mWheelDown" />
+ </input>
+ <input name="UACamRelease">
+ <btn name="kLControl" />
+ </input>
+ <input name="UAToggleInvis">
+ <btn name="kI" />
+ </input>
+ <input name="UALBMADMCopyTarget">
+ <btn name="kLControl">
+ <btn name="kC" />
+ </btn>
+ </input>
+ <input name="UALBMADMUndo">
+ <btn name="kLControl">
+ <btn name="kZ" />
+ </btn>
+ </input>
+ <input name="UALBMADMRedo">
+ <btn name="kLControl">
+ <btn name="kY" />
+ </btn>
+ </input>
+ <input name="UALBMADMHealSelf">
+ <btn name="kLControl">
+ <btn name="kH" />
+ </btn>
+ </input>
+ <input name="UALBMADMOpenConsole">
+ <btn name="kRControl">
+ <btn name="kMinus" />
+ </btn>
+ </input>
+ <input name="UALBMADMRepairTarget">
+ <btn name="kLControl">
+ <btn name="kR" />
+ </btn>
+ </input>
+ <input name="UALBMADMPreset1">
+ <btn name="kLControl">
+ <btn name="k1" />
+ </btn>
+ </input>
+ <input name="UALBMADMPreset2">
+ <btn name="kLControl">
+ <btn name="k2" />
+ </btn>
+ </input>
+ <input name="UALBMADMPreset3">
+ <btn name="kLControl">
+ <btn name="k3" />
+ </btn>
+ </input>
+ <input name="UALBMADMPreset4">
+ <btn name="kLControl">
+ <btn name="k4" />
+ </btn>
+ </input>
+ <input name="UALBMADMPreset5">
+ <btn name="kLControl">
+ <btn name="k5" />
+ </btn>
+ </input>
+ <input name="UALBMADMPreset6">
+ <btn name="kLControl">
+ <btn name="k6" />
+ </btn>
+ </input>
+ <input name="UALBMADMPreset7">
+ <btn name="kLControl">
+ <btn name="k7" />
+ </btn>
+ </input>
+ <input name="UALBMADMPreset8">
+ <btn name="kLControl">
+ <btn name="k8" />
+ </btn>
+ </input>
+ <input name="UALBMADMPreset9">
+ <btn name="kLControl">
+ <btn name="k9" />
+ </btn>
+ </input>
+ <input name="UALBMADMOpenMenu">
+ <btn name="kLControl">
+ <btn name="kA" />
+ </btn>
+ </input>
+ <input name="UALBMADMTeleportToCursor">
+ <btn name="kH" />
+ </input>
+ <input name="UALBMADMCopyPos">
+ <btn name="kLControl">
+ <btn name="kP" />
+ </btn>
+ <btn name="kRControl">
+ <btn name="kP" />
+ </btn>
+ </input>
+ <input name="UALBMADMDeleteCursor">
+ <btn name="kLControl">
+ <btn name="kD" />
+ </btn>
+ </input>
+ <input name="UALBMADMDeleteCursorForce">
+ <btn name="kLMenu">
+ <btn name="kD" />
+ </btn>
+ </input>
+ <input name="UALBMADMSpectatorZoomIn">
+ <btn name="mWheelUp" />
+ </input>
+ <input name="UALBMADMSpectatorZoomOut">
+ <btn name="mWheelDown" />
+ </input>
+ <input name="UALBMADMDuplicate">
+ <btn name="kLControl">
+ <btn name="kD" />
+ </btn>
+ </input>
+ <input name="UALBMADMItemCopy">
+ <btn name="kLControl">
+ <btn name="kC" />
+ </btn>
+ </input>
+ <input name="UALBMADMItemPaste">
+ <btn name="kLControl">
+ <btn name="kV" />
+ </btn>
+ </input>
+ <input name="UALBMADMSpawnerGround">
+ <btn name="kLControl">
+ <btn name="kG" />
+ </btn>
+ </input>
+ <input name="UALBMADMSpawnerInventory">
+ <btn name="kLControl">
+ <btn name="kS" />
+ </btn>
+ </input>
+ <input name="UALBMADMSpawnerCursor">
+ <btn name="kLControl">
+ <btn name="kC" />
+ </btn>
+ </input>
+ <input name="UALBMADMSpawnerTarget">
+ <btn name="kLControl">
+ <btn name="kT" />
+ </btn>
+ </input>
+ <input name="UALBMADMToggleFreecam">
+ <btn name="kLControl">
+ <btn name="kF" />
+ </btn>
+ </input>
+ <input name="UALBMADMToggleGodmode">
+ <btn name="kLControl">
+ <btn name="kG" />
+ </btn>
+ </input>
+ <input name="UALBMADMToggleInvisible">
+ <btn name="kRControl">
+ <btn name="kI" />
+ </btn>
+ </input>
+ <input name="UALBMADMToggleESP">
+ <btn name="kLControl">
+ <btn name="kE" />
+ </btn>
+ </input>
+ <input name="UAExpansionConfirm">
+ <btn name="kReturn" />
+ <btn name="kNumpadEnter" />
+ </input>
+ <controller name="PCKeyboard">
+ <limit name="doubleclick" value="0.500000" />
+ <limit name="hold" value="0.330000" />
+ <limit name="deadzone" value="0.000000" />
+ <sensitivity name="vert" value="1.000000" />
+ <sensitivity name="horz" value="1.000000" />
+ <sensitivity name="curv" value="1.000000" />
+ <sensitivity name="lvert" value="1.000000" />
+ <sensitivity name="lhorz" value="1.000000" />
+ <sensitivity name="lcurv" value="1.000000" />
+ <sensitivity name="rvert" value="1.000000" />
+ <sensitivity name="rhorz" value="1.000000" />
+ <sensitivity name="rcurv" value="1.000000" />
+ <sensitivity name="ldeadzone" value="1.000000" />
+ <sensitivity name="rdeadzone" value="1.000000" />
+ </controller>
+ <controller name="PCMouse">
+ <limit name="doubleclick" value="0.500000" />
+ <limit name="hold" value="0.330000" />
+ <limit name="deadzone" value="0.000000" />
+ <sensitivity name="vert" value="0.550000" />
+ <sensitivity name="horz" value="0.550000" />
+ <sensitivity name="curv" value="1.000000" />
+ <sensitivity name="lvert" value="1.000000" />
+ <sensitivity name="lhorz" value="1.000000" />
+ <sensitivity name="lcurv" value="1.000000" />
+ <sensitivity name="rvert" value="1.000000" />
+ <sensitivity name="rhorz" value="1.000000" />
+ <sensitivity name="rcurv" value="1.000000" />
+ <sensitivity name="ldeadzone" value="1.000000" />
+ <sensitivity name="rdeadzone" value="1.000000" />
+ </controller>
+ <controller name="X1Controller">
+ <limit name="doubleclick" value="0.500000" />
+ <limit name="hold" value="0.330000" />
+ <limit name="deadzone" value="0.030000" />
+ <sensitivity name="vert" value="1.000000" />
+ <sensitivity name="horz" value="1.000000" />
+ <sensitivity name="curv" value="1.000000" />
+ <sensitivity name="lvert" value="1.250000" />
+ <sensitivity name="lhorz" value="1.250000" />
+ <sensitivity name="lcurv" value="1.000000" />
+ <sensitivity name="rvert" value="1.250000" />
+ <sensitivity name="rhorz" value="1.250000" />
+ <sensitivity name="rcurv" value="0.500000" />
+ <sensitivity name="ldeadzone" value="0.030000" />
+ <sensitivity name="rdeadzone" value="0.030000" />
+ </controller>
+ <controller name="PS4Controller">
+ <limit name="doubleclick" value="0.500000" />
+ <limit name="hold" value="0.330000" />
+ <limit name="deadzone" value="0.030000" />
+ <sensitivity name="vert" value="1.000000" />
+ <sensitivity name="horz" value="1.000000" />
+ <sensitivity name="curv" value="1.000000" />
+ <sensitivity name="lvert" value="1.250000" />
+ <sensitivity name="lhorz" value="1.250000" />
+ <sensitivity name="lcurv" value="1.000000" />
+ <sensitivity name="rvert" value="1.250000" />
+ <sensitivity name="rhorz" value="1.250000" />
+ <sensitivity name="rcurv" value="0.500000" />
+ <sensitivity name="ldeadzone" value="0.030000" />
+ <sensitivity name="rdeadzone" value="0.030000" />
+ </controller>
+ <controller name="IRTracker">
+ <limit name="doubleclick" value="0.500000" />
+ <limit name="hold" value="0.330000" />
+ <limit name="deadzone" value="0.000000" />
+ <sensitivity name="vert" value="1.000000" />
+ <sensitivity name="horz" value="1.000000" />
+ <sensitivity name="curv" value="1.000000" />
+ <sensitivity name="lvert" value="1.000000" />
+ <sensitivity name="lhorz" value="1.000000" />
+ <sensitivity name="lcurv" value="1.000000" />
+ <sensitivity name="rvert" value="1.000000" />
+ <sensitivity name="rhorz" value="1.000000" />
+ <sensitivity name="rcurv" value="1.000000" />
+ <sensitivity name="ldeadzone" value="1.000000" />
+ <sensitivity name="rdeadzone" value="1.000000" />
+ </controller>
+ <modificator name="aiming">
+ <sensitivity name="vert" value="0.550000" />
+ <sensitivity name="horz" value="0.550000" />
+ <sensitivity name="rvert" value="1.250000" />
+ <sensitivity name="rhorz" value="1.250000" />
+ <sensitivity name="rcurv" value="0.500000" />
+ </modificator>
+ <modificator name="vehicle">
+ <sensitivity name="lhorz" value="1.000000" />
+ </modificator>
+</preset>
+ '';
+}
diff --git a/nixos/modules/gms/mc.nix b/nixos/modules/gms/mc.nix
new file mode 100644
index 0000000..d8c6734
--- /dev/null
+++ b/nixos/modules/gms/mc.nix
@@ -0,0 +1,80 @@
+{ config, pkgs, ... }:
+
+{
+ home.packages = [ pkgs.prismlauncher ];
+
+ home.file.".local/share/PrismLauncher/prismlauncher.cfg" = {
+ text = pkgs.lib.generators.toINI {} {
+ General = {
+ ApplicationTheme = "dark";
+ AutoCloseConsole = false;
+ AutomaticJavaDownload = false;
+ AutomaticJavaSwitch = true;
+ CatFit = "fit";
+ CatOpacity = 100;
+ CentralModsDir = "mods";
+ CloseAfterLaunch = false;
+ ConfigVersion = "1.3";
+ ConsoleFont = "DejaVu Sans Mono";
+ ConsoleFontSize = 11;
+ ConsoleMaxLines = 100000;
+ ConsoleOverflowStop = true;
+ DownloadsDir = "/home/cat/Downloads";
+ DownloadsDirWatchRecursive = false;
+ EnableFeralGamemode = false;
+ EnableMangoHud = false;
+ Env = "{}";
+ FallbackMRBlockedMods = 2;
+ IconTheme = "OSX";
+ IconsDir = "icons";
+ IgnoreJavaCompatibility = false;
+ IgnoreJavaWizard = false;
+ InstRenamingMode = "AskEverytime";
+ InstSortMode = "Name";
+ InstanceDir = "instances";
+ JavaArchitecture = "64";
+ JavaDir = "java";
+ JavaPath = "/nix/store/55mw2ly3dxh5008li72rx6ilc75hgvr0-openjdk-8u502-b01/bin/java";
+ Language = "en_US";
+ LaunchMaximized = false;
+ LowMemWarning = true;
+ MaxMemAlloc = 6016;
+ MinMemAlloc = 2048;
+ MinecraftWinHeight = 480;
+ MinecraftWinWidth = 854;
+ ModDependenciesDisabled = false;
+ ModMetadataDisabled = false;
+ MoveModsFromDownloadsDir = true;
+ NumberOfConcurrentDownloads = 6;
+ NumberOfConcurrentTasks = 10;
+ NumberOfManualRetries = 1;
+ OnlineFixes = false;
+ PastebinType = 3;
+ PermGen = 128;
+ ProxyAddr = "127.0.0.1";
+ ProxyPort = 8080;
+ ProxyType = "None";
+ QuitAfterGameStop = false;
+ RecordGameTime = true;
+ RequestTimeout = 60;
+ ShowConsole = false;
+ ShowConsoleOnError = true;
+ ShowGameTime = true;
+ ShowGameTimeWithoutDays = false;
+ ShowGlobalGameTime = true;
+ ShowModIncompat = false;
+ SkinsDir = "skins";
+ SkipModpackUpdatePrompt = false;
+ StatusBarVisible = false;
+ TheCat = false;
+ ToolbarsLocked = true;
+ UseDiscreteGpu = false;
+ UseNativeGLFW = false;
+ UseNativeOpenAL = false;
+ UseZink = false;
+ UserAskedAboutAutomaticJavaDownload = true;
+ };
+ };
+ force = true;
+ };
+}
diff --git a/nixos/modules/notes.nix b/nixos/modules/notes.nix
new file mode 100644
index 0000000..01356d6
--- /dev/null
+++ b/nixos/modules/notes.nix
@@ -0,0 +1,55 @@
+{ config, pkgs, ... }:
+
+{
+ home.packages = [ pkgs.obsidian ];
+
+ home.file = {
+ ".documents/obsidian/.obsidian/app.json".text = builtins.toJSON {
+ readableLineLength = true;
+ foldHeading = true;
+ showLineNumber = true;
+ spellcheck = false;
+ vimMode = false;
+ newFileLocation = "current";
+ promptDelete = false;
+ };
+ ".documents/obsidian/.obsidian/appearance.json".text = builtins.toJSON {
+ accentColor = "#ffa8db";
+ cssTheme = "";
+ theme = "obsidian";
+ };
+ ".documents/obsidian/.obsidian/core-plugins.json".text = builtins.toJSON {
+ "file-explorer" = true;
+ "global-search" = true;
+ "switcher" = false;
+ "graph" = true;
+ "backlink" = false;
+ "canvas" = false;
+ "outgoing-link" = true;
+ "tag-pane" = true;
+ "footnotes" = false;
+ "properties" = false;
+ "page-preview" = true;
+ "daily-notes" = true;
+ "templates" = false;
+ "note-composer" = false;
+ "command-palette" = false;
+ "slash-command" = false;
+ "editor-status" = true;
+ "bookmarks" = false;
+ "markdown-importer" = false;
+ "zk-prefixer" = false;
+ "random-note" = false;
+ "outline" = true;
+ "word-count" = true;
+ "slides" = false;
+ "audio-recorder" = false;
+ "workspaces" = false;
+ "file-recovery" = true;
+ "publish" = false;
+ "sync" = false;
+ "bases" = false;
+ "webviewer" = false;
+ };
+ };
+}
diff --git a/nixos/modules/qksh.nix b/nixos/modules/qksh.nix
new file mode 100644
index 0000000..9e9e85b
--- /dev/null
+++ b/nixos/modules/qksh.nix
@@ -0,0 +1,992 @@
+{ pkgs, ... }:
+
+{
+ xdg.configFile."quickshell/shell.qml".text = ''
+ import Quickshell
+ import Quickshell.Wayland
+ import Quickshell.Hyprland
+ import Quickshell.Io
+ import Quickshell.Services.Notifications
+ import QtQuick
+ import QtQuick.Layouts
+ import QtCore
+
+ Scope {
+ id: configRoot
+
+ property string colorBuf: ""
+ property var colors: {
+ "special": { "background": "#1c1c1c", "foreground": "#c0c0c0", "cursor": "#c0c0c0" },
+ "colors": {
+ "color0": "#1c1c1c", "color1": "#cc2222", "color2": "#22cc22", "color3": "#cccc22",
+ "color4": "#2222cc", "color5": "#cc22cc", "color6": "#22cccc", "color7": "#aaaaaa",
+ "color8": "#555555", "color9": "#ff4444", "color10": "#44ff44", "color11": "#ffff44",
+ "color12": "#4444ff", "color13": "#ff44ff", "color14": "#44ffff", "color15": "#ffffff"
+ }
+ }
+
+ component MText: Text {
+ font.family: "JetBrainsMono Nerd Font"
+ font.pixelSize: 12
+ font.weight: Font.Normal
+ renderType: Text.NativeRendering
+ color: root.colors.special.foreground
+ }
+
+ Settings {
+ id: barSettings
+ location: Qt.resolvedUrl("state")
+ property string position: "top"
+ property string layout: "minimal"
+ property string look: "float"
+ property string centerMode: "default"
+ }
+
+ NotificationServer {
+ id: notifServer
+ keepOnReload: true
+
+ onNotification: (notif) => {
+ if (notifModel.count >= 3) notifModel.remove(0)
+ notifModel.append({
+ nid: notif.id,
+ app: notif.appName ?? "",
+ summary: notif.summary ?? "",
+ body: notif.body ?? "",
+ timeout: notif.expireTimeout > 0 ? notif.expireTimeout : 5000
+ })
+ }
+ }
+
+ ListModel { id: notifModel }
+
+ PanelWindow {
+ id: root
+ property string position: barSettings.position
+ property string layout: barSettings.layout
+ property string look: barSettings.look
+
+ screen: Quickshell.screens.find(s => s.name === "HDMI-A-1") ?? Quickshell.screens[0]
+
+ property string activeMode: "none"
+ property bool autoHideBar: false
+
+ property var launcherTopApp: null
+
+ property string sysStats: "cpu --% | mem --%"
+ property string micState: "󰍬"
+
+ function removeNotif(nid) {
+ for (let i = 0; i < notifModel.count; i++) {
+ if (notifModel.get(i).nid === nid) {
+ notifModel.remove(i)
+ break
+ }
+ }
+ }
+
+ function launcherRefilter(q) {
+ if (!DesktopEntries.applications?.values || q === "") {
+ launcherTopApp = null; return
+ }
+ let ql = q.toLowerCase()
+ let m = DesktopEntries.applications.values.filter(
+ a => a?.name && a.name.toLowerCase().includes(ql)
+ ).sort((a, b) => {
+ let an = a.name.toLowerCase()
+ let bn = b.name.toLowerCase()
+ if (an === ql) return -1
+ if (bn === ql) return 1
+ if (an.startsWith(ql) && !bn.startsWith(ql)) return -1
+ if (!an.startsWith(ql) && bn.startsWith(ql)) return 1
+ if (an.includes("steam") && an !== "steam" && bn === "steam") return 1
+ if (bn.includes("steam") && bn !== "steam" && an === "steam") return -1
+ return an.localeCompare(bn)
+ })
+ launcherTopApp = m.length > 0 ? m[0] : null
+ }
+
+ function launcherOpen() {
+ if (!root.visible) { autoHideBar = true; root.visible = true }
+ else autoHideBar = false
+ launcherTopApp = null
+ activeMode = "launcher"
+ }
+
+ function launcherClose() {
+ activeMode = "none"
+ launcherTopApp = null
+ if (autoHideBar) { root.visible = false; autoHideBar = false }
+ }
+
+ function launcherAccept() {
+ if (launcherTopApp !== null) {
+ let exec = launcherTopApp.execString.replace(/%[fFuU]/g, "")
+ launchProc.command = ["systemd-run", "--user", "--scope", "bash", "-c", exec]
+ launchProc.running = true
+ }
+ launcherClose()
+ }
+
+ property string masterLevel: "root"
+ property var masterStack: []
+ property var masterCurrent: []
+ property var masterFiltered: []
+ property int masterSelected: 0
+
+ property var masterRootItems: [
+ { label: "sys", sub: "sys" },
+ { label: "sts", sub: "sts" },
+ { label: "rcd", sub: "rcd" },
+ { label: "wp", sub: "wallpapers" },
+ { label: "pw", sub: "pw" }
+ ]
+ property var masterSysItems: [
+ { label: "nix", cmd: ["kitty", "-e", "sudo", "nvim", "/etc/nixos/hosts/box/configuration.nix"] },
+ { label: "box", cmd: ["kitty", "-e", "sudo", "nvim", "/etc/nixos/hosts/box/box.nix"] },
+ { label: "wm", cmd: ["kitty", "-e", "sudo", "nvim", "/etc/nixos/mdls/wm.nix"] },
+ { label: "qksh", cmd: ["kitty", "-e", "sudo", "nvim", "/etc/nixos/mdls/qksh.nix"] },
+ { label: "vi", cmd: ["kitty", "-e", "sudo", "nvim", "/etc/nixos/mdls/vi.nix"] },
+ { label: "yazi", cmd: ["kitty", "-e", "sudo", "nvim", "/etc/nixos/mdls/yazi.nix"] },
+ ]
+ property var masterStsItems: [
+ { label: "animations", sub: "animations" },
+ { label: "bar", sub: "bar" }
+ ]
+ property var masterAnimationsItems: [
+ { label: "fade", cmd: ["sh", "-c", "hyprctl eval 'hl.animation({ leaf = \"workspaces\", enabled = true, speed = 1.94, bezier = \"almostLinear\", style = \"fade\" })' && hyprctl eval 'hl.animation({ leaf = \"specialWorkspace\", enabled = true, speed = 1.94, bezier = \"almostLinear\", style = \"fade\" })' && ${pkgs.libnotify}/bin/notify-send animations fade"] },
+ { label: "vertical", cmd: ["sh", "-c", "hyprctl eval 'hl.animation({ leaf = \"workspaces\", enabled = true, speed = 5, bezier = \"hard\", style = \"slidevert\" })' && hyprctl eval 'hl.animation({ leaf = \"specialWorkspace\", enabled = true, speed = 5, bezier = \"hard\", style = \"slidevert\" })' && ${pkgs.libnotify}/bin/notify-send animations vertical"] },
+ { label: "horizontal", cmd: ["sh", "-c", "hyprctl eval 'hl.animation({ leaf = \"workspaces\", enabled = true, speed = 5, bezier = \"hard\", style = \"slide\" })' && hyprctl eval 'hl.animation({ leaf = \"specialWorkspace\", enabled = true, speed = 5, bezier = \"hard\", style = \"slide\" })' && ${pkgs.libnotify}/bin/notify-send animations horizontal"] }
+ ]
+ property var masterBarItems: [{ label: "position", sub: "barPosition" }, { label: "layout", sub: "barLayout" }, { label: "mode", sub: "barMode" }, { label: "look", sub: "barLook" }]
+ property var masterBarPositionItems: [{ label: "top", barPos: "top" }, { label: "bottom", barPos: "bottom" }]
+ property var masterBarLayoutItems: [{ label: "minimal", barLyt: "minimal" }, { label: "full", barLyt: "full" }]
+ property var masterBarModeItems: [{ label: "performance", centerLyt: "performance" }, { label: "default", centerLyt: "default" }]
+ property var masterBarLookItems: [{ label: "float", barLook: "float" }, { label: "fill", barLook: "fill" }]
+ property var masterWpItems: []
+ property string masterWpBuf: ""
+ property var masterRcdOutItems: []
+ property string masterRcdOutBuf: ""
+ property var masterPwItems: [
+ { label: "lock", cmd: [""] },
+ { label: "logout", cmd: ["hyprctl", "dispatch", "hl.dsp.exit()"] },
+ { label: "reboot", cmd: ["systemctl", "reboot"] },
+ { label: "shutdown", cmd: ["systemctl", "poweroff"] }
+ ]
+
+ function rcdItems() {
+ return recProc.running
+ ? [{ label: "stop", rcdStop: true }]
+ : [{ label: "start", sub: "rcdOutput" }]
+ }
+
+ function masterItemsForLevel(l) {
+ let lookup = { sys: masterSysItems, sts: masterStsItems, animations: masterAnimationsItems, bar: masterBarItems, barPosition: masterBarPositionItems, barLayout: masterBarLayoutItems, barMode: masterBarModeItems, barLook: masterBarLookItems, wallpapers: masterWpItems, pw: masterPwItems, rcd: rcdItems(), rcdOutput: masterRcdOutItems }
+ return lookup[l] ?? masterRootItems
+ }
+
+ function masterRefilter(q) {
+ masterFiltered = q === "" ? masterCurrent : masterCurrent.filter(i => i.label.toLowerCase().includes(q.toLowerCase()))
+ let max = masterFiltered.length - 1
+ if (masterSelected > max) masterSelected = Math.max(0, max)
+ }
+
+ function masterGoTo(l) {
+ masterLevel = l
+ masterSelected = 0
+ if (l === "wallpapers") {
+ masterWpItems = []; masterWpBuf = ""
+ masterCurrent = []; masterFiltered = []
+ wpLsProc.running = true
+ } else if (l === "rcdOutput") {
+ masterRcdOutItems = []; masterRcdOutBuf = ""
+ masterCurrent = []; masterFiltered = []
+ rcdMonProc.running = true
+ } else {
+ masterCurrent = masterItemsForLevel(l)
+ masterFiltered = masterCurrent
+ }
+ }
+
+ function masterOpen() {
+ if (!root.visible) { autoHideBar = true; root.visible = true }
+ else autoHideBar = false
+ masterStack = []
+ masterGoTo("root")
+ activeMode = "master"
+ }
+
+ function masterClose() {
+ activeMode = "none"
+ if (autoHideBar) { root.visible = false; autoHideBar = false }
+ }
+
+ function masterBack() {
+ if (masterStack.length > 0) {
+ let prev = masterStack[masterStack.length - 1]
+ masterStack = masterStack.slice(0, -1)
+ masterLevel = prev
+ masterSelected = 0
+ masterCurrent = masterItemsForLevel(prev)
+ masterFiltered = masterCurrent
+ } else {
+ masterClose()
+ }
+ }
+
+ function masterAccept() {
+ let items = masterFiltered
+ let idx = masterSelected
+ if (items.length === 0 || idx < 0 || idx >= items.length) return
+ let item = items[idx]
+
+ if (item.sub !== undefined) {
+ masterStack = masterStack.concat([masterLevel])
+ masterGoTo(item.sub)
+ return
+ }
+ if (item.wp !== undefined) {
+ mProc.command = ["bash", "-c", "colors \"$HOME/.wallpapers/" + item.wp + "\""]
+ mProc.running = true
+ masterClose(); return
+ }
+ if (item.rcdOut !== undefined) {
+ recProc.command = ["bash", "-c", "mkdir -p \"$HOME/videos\" && exec ${pkgs.gpu-screen-recorder}/bin/gpu-screen-recorder -w " + item.rcdOut + " -f 60 -q ultra -k hevc -fm cfr -a default_output -o \"$HOME/videos/meow_$(date +%Y%m%d_%H%M%S).mp4\""]
+ recProc.running = true
+ mProc.command = ["${pkgs.libnotify}/bin/notify-send", "-t", "2000", "meow", "started on " + item.rcdOut]
+ mProc.running = true
+ masterClose(); return
+ }
+ if (item.rcdStop !== undefined) {
+ recProc.signal(2)
+ mProc.command = ["${pkgs.libnotify}/bin/notify-send", "-t", "2000", "meow", "saved"]
+ mProc.running = true
+ masterClose(); return
+ }
+ if (item.barPos !== undefined) { barSettings.position = item.barPos; masterClose(); return }
+ if (item.barLyt !== undefined) { barSettings.layout = item.barLyt; masterClose(); return }
+ if (item.barLook !== undefined) { barSettings.look = item.barLook; masterClose(); return }
+ if (item.centerLyt !== undefined) { barSettings.centerMode = item.centerLyt; masterClose(); return }
+ if (item.cmd !== undefined) { mProc.command = item.cmd; mProc.running = true }
+ masterClose()
+ }
+
+ onActiveModeChanged: {
+ if (activeMode !== "none" && activeMode !== "calendar" && typeof barInput !== "undefined") {
+ barInput.text = ""
+ barInput.forceActiveFocus()
+ }
+ }
+
+ WlrLayershell.keyboardFocus: activeMode !== "none" && activeMode !== "calendar" ? WlrLayershell.Exclusive : WlrLayershell.None
+
+ anchors.top: position === "top"
+ anchors.bottom: position === "bottom"
+
+ implicitWidth: look === "fill" ? (root.screen?.width ?? 1920)
+ : layout === "full" ? (root.screen?.width ?? 1920) - 12
+ : 820
+ implicitHeight: 22
+
+ margins.top: look === "fill" ? 0 : (position === "top" ? 6 : 0)
+ margins.bottom: look === "fill" ? 0 : (position === "bottom" ? 6 : 0)
+
+ exclusiveZone: 22
+ color: "transparent"
+
+ IpcHandler {
+ target: "bar"
+ function toggle(): void { root.visible = !root.visible }
+ }
+ IpcHandler {
+ target: "menu"
+ function toggle(): void {
+ if (root.activeMode === "launcher") root.launcherClose()
+ else root.launcherOpen()
+ }
+ }
+ IpcHandler {
+ target: "master"
+ function toggle(): void {
+ if (root.activeMode === "master") root.masterClose()
+ else root.masterOpen()
+ }
+ }
+ IpcHandler {
+ target: "calendar"
+ function toggle(): void {
+ if (root.activeMode === "calendar") root.activeMode = "none"
+ else root.activeMode = "calendar"
+ }
+ }
+ IpcHandler {
+ target: "mic"
+ function toggle(): void {
+ micActProc.command = ["${pkgs.wireplumber}/bin/wpctl", "set-mute", "@DEFAULT_AUDIO_SOURCE@", "toggle"]
+ micActProc.running = true
+ }
+ }
+
+ Connections {
+ target: Hyprland
+ function onFocusedWorkspaceChanged() {
+ if (root.activeMode !== "none") root.activeMode = "none"
+ }
+ }
+
+ Process {
+ id: colorProc
+ command: ["sh", "-c", "cat $HOME/.colors/colors.json"]
+ running: true
+ stdout: SplitParser {
+ splitMarker: ""
+ onRead: data => { configRoot.colorBuf += data }
+ }
+ onRunningChanged: {
+ if (!running && configRoot.colorBuf !== "") {
+ try {
+ configRoot.colors = JSON.parse(configRoot.colorBuf)
+ } catch(e) { console.log("Failed to parse colors") }
+ configRoot.colorBuf = ""
+ }
+ }
+ }
+
+ Process { id: launchProc; running: false }
+ Process {
+ id: mProc
+ running: false
+ onRunningChanged: if (!running) colorProc.running = true
+ }
+ Process { id: recProc; running: false }
+
+ Process {
+ id: rcdMonProc
+ command: ["bash", "-c", "${pkgs.hyprland}/bin/hyprctl -j monitors | ${pkgs.jq}/bin/jq -r '.[].name'"]
+ running: false
+ stdout: SplitParser {
+ splitMarker: ""
+ onRead: data => { root.masterRcdOutBuf += data }
+ }
+ onRunningChanged: {
+ if (!running && root.masterRcdOutBuf !== "") {
+ let lines = root.masterRcdOutBuf.trim().split("\n").filter(l => l.length > 0)
+ lines.push("portal")
+ root.masterRcdOutItems = lines.map(l => ({ label: l, rcdOut: l }))
+ root.masterRcdOutBuf = ""
+ if (root.activeMode === "master" && root.masterLevel === "rcdOutput") {
+ root.masterCurrent = root.masterRcdOutItems
+ root.masterFiltered = root.masterRcdOutItems
+ }
+ }
+ }
+ }
+
+ Process {
+ id: wpLsProc
+ command: ["bash", "-c", "ls $HOME/.wallpapers/"]
+ running: false
+ stdout: SplitParser {
+ splitMarker: ""
+ onRead: data => { root.masterWpBuf += data }
+ }
+ onRunningChanged: {
+ if (!running && root.masterWpBuf !== "") {
+ let lines = root.masterWpBuf.trim().split("\n").filter(l => l.length > 0)
+ root.masterWpItems = lines.map(l => ({ label: l, wp: l }))
+ root.masterWpBuf = ""
+ if (root.activeMode === "master" && root.masterLevel === "wallpapers") {
+ root.masterCurrent = root.masterWpItems
+ root.masterFiltered = root.masterWpItems
+ }
+ }
+ }
+ }
+
+ Timer {
+ interval: 2000; running: true; repeat: true; triggeredOnStart: true
+ onTriggered: {
+ if (barSettings.centerMode === "performance" && !sysProc.running) sysProc.running = true
+ if (!micProc.running) micProc.running = true
+ }
+ }
+
+ Process {
+ id: sysProc
+ command: ["sh", "-c", "echo \"cpu $(grep 'cpu ' /proc/stat | awk '{print int(($2+$4)*100/($2+$4+$5))}')% | mem $(free | awk '/Mem:/ {print int($3/$2*100)}')%\""]
+ running: false
+ stdout: SplitParser {
+ onRead: data => { root.sysStats = data.trim() }
+ }
+ }
+
+ Process {
+ id: micProc
+ command: ["sh", "-c", "${pkgs.wireplumber}/bin/wpctl get-volume @DEFAULT_AUDIO_SOURCE@ | awk '{print ($3==\"[MUTED]\"?\"󰍭\":\"󰍬\")}'"]
+ running: false
+ stdout: SplitParser {
+ onRead: data => { root.micState = data.trim() }
+ }
+ }
+
+ Process {
+ id: micActProc
+ running: false
+ onRunningChanged: if (!running) micProc.running = true
+ }
+
+ FontMetrics {
+ id: fm
+ font.family: "JetBrainsMono Nerd Font"
+ font.pixelSize: 12
+ font.weight: Font.Normal
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ color: configRoot.colors.special.background
+
+ MText {
+ anchors.centerIn: parent
+ visible: root.activeMode === "none" || root.activeMode === "calendar"
+ text: barSettings.centerMode === "performance" ? root.sysStats : ""
+ color: configRoot.colors.special.foreground
+ }
+
+ RowLayout {
+ anchors.fill: parent
+ spacing: 0
+
+ Row {
+ spacing: 0
+ Layout.fillHeight: true
+
+ Repeater {
+ model: 10
+
+ Item {
+ property int wsId: index + 1
+ property var ws: Hyprland.workspaces?.values?.find(w => w.id === wsId) ?? null
+ property bool isActive: Hyprland.focusedWorkspace?.id === wsId
+ property bool isUrgent: ws?.urgent ?? false
+ property bool hovered: harea.containsMouse
+ property string kanji: (["一","二","三","四","五","六","七","八","九","十"])[index]
+
+ visible: ws !== null || isActive
+ width: visible ? Math.round(fm.advanceWidth(kanji)) + 16 : 0
+ height: parent.height
+
+ Rectangle {
+ anchors.fill: parent
+ color: parent.isUrgent ? configRoot.colors.colors.color1
+ : parent.isActive ? configRoot.colors.special.foreground
+ : parent.hovered ? configRoot.colors.colors.color8
+ : "transparent"
+ }
+ MText {
+ anchors.centerIn: parent
+ color: parent.isUrgent ? configRoot.colors.special.background
+ : parent.isActive ? configRoot.colors.special.background
+ : parent.hovered ? configRoot.colors.special.foreground
+ : configRoot.colors.colors.color7
+ text: parent.kanji
+ }
+ MouseArea {
+ id: harea
+ anchors.fill: parent
+ hoverEnabled: true
+ onClicked: Hyprland.dispatch('hl.dsp.focus({ workspace = "' + parent.wsId + '" })')
+ }
+ }
+ }
+ }
+
+ Item {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ RowLayout {
+ anchors.fill: parent
+ anchors.leftMargin: 10
+ anchors.rightMargin: 10
+ spacing: 6
+ visible: root.activeMode === "launcher" || root.activeMode === "master"
+
+ MText {
+ Layout.alignment: Qt.AlignVCenter
+ color: configRoot.colors.colors.color7
+ text: root.activeMode === "launcher" ? ">" : root.masterStack.concat([root.masterLevel]).join(" >")
+ }
+
+ TextInput {
+ id: barInput
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignVCenter
+ height: parent.height
+ verticalAlignment: TextInput.AlignVCenter
+ font.family: "JetBrainsMono Nerd Font"
+ font.pixelSize: 12
+ color: configRoot.colors.special.foreground
+ focus: root.activeMode === "launcher" || root.activeMode === "master"
+
+ onTextChanged: {
+ if (root.activeMode === "launcher") root.launcherRefilter(text)
+ else if (root.activeMode === "master") root.masterRefilter(text)
+ }
+ onAccepted: {
+ if (root.activeMode === "launcher") root.launcherAccept()
+ else if (root.activeMode === "master") root.masterAccept()
+ }
+ Keys.onPressed: (event) => {
+ if (event.key === Qt.Key_Escape) {
+ if (root.activeMode === "launcher") root.launcherClose()
+ else if (root.activeMode === "master") root.masterBack()
+ event.accepted = true
+ } else if (root.activeMode === "master") {
+ if (event.key === Qt.Key_Down) {
+ if (root.masterSelected < root.masterFiltered.length - 1) root.masterSelected++
+ event.accepted = true
+ } else if (event.key === Qt.Key_Up) {
+ if (root.masterSelected > 0) root.masterSelected--
+ event.accepted = true
+ }
+ }
+ }
+ }
+
+ MText {
+ Layout.alignment: Qt.AlignVCenter
+ Layout.rightMargin: 4
+ color: configRoot.colors.colors.color7
+ visible: root.activeMode === "launcher" ? root.launcherTopApp !== null : (root.activeMode === "master" ? root.masterFiltered.length > 0 : false)
+ text: root.activeMode === "launcher" ? (root.launcherTopApp?.name ?? "") : (root.activeMode === "master" && root.masterSelected < root.masterFiltered.length ? (root.masterFiltered[root.masterSelected]?.label ?? "") : "")
+ }
+ }
+ }
+
+ Item {
+ Layout.fillHeight: true
+ implicitWidth: 26
+
+ Row {
+ anchors.centerIn: parent
+ spacing: 2
+
+ Item {
+ width: 20
+ height: 22
+
+ MText {
+ id: micText
+ anchors.centerIn: parent
+ text: root.micState
+ color: configRoot.colors.special.foreground
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ micActProc.command = ["${pkgs.wireplumber}/bin/wpctl", "set-mute", "@DEFAULT_AUDIO_SOURCE@", "toggle"]
+ micActProc.running = true
+ }
+ }
+ }
+ }
+ }
+
+ Item {
+ Layout.fillHeight: true
+ implicitWidth: clockText.implicitWidth + 20
+
+ Rectangle {
+ anchors.horizontalCenter: parent.left
+ width: 1; height: parent.height
+ color: configRoot.colors.colors.color8
+ }
+ MText {
+ id: clockText
+ anchors.centerIn: parent
+ font.letterSpacing: 0.02 * 11
+ color: configRoot.colors.special.foreground
+ text: Qt.formatDateTime(new Date(), "dd/MM | HH:mm:ss")
+
+ Timer {
+ interval: 1000; running: true; repeat: true
+ onTriggered: clockText.text = Qt.formatDateTime(new Date(), "dd/MM | HH:mm:ss")
+ }
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (root.activeMode === "calendar") root.activeMode = "none"
+ else root.activeMode = "calendar"
+ }
+ }
+ }
+ }
+ }
+ }
+
+ PanelWindow {
+ id: masterOverlay
+ visible: root.activeMode === "master" && root.masterFiltered.length > 0
+
+ screen: Quickshell.screens.find(s => s.name === "HDMI-A-1") ?? Quickshell.screens[0]
+
+ anchors.top: root.position === "top"
+ anchors.bottom: root.position === "bottom"
+ anchors.left: true
+ anchors.right: true
+
+ margins.top: root.position === "top" ? (root.look === "fill" ? 0 : 6) : 0
+ margins.bottom: root.position === "bottom" ? (root.look === "fill" ? 0 : 6) : 0
+
+ implicitWidth: root.implicitWidth
+ implicitHeight: root.masterFiltered.length * (root.masterLevel === "wallpapers" ? 38 : 22)
+
+ exclusiveZone: 0
+ color: "transparent"
+ WlrLayershell.layer: WlrLayershell.Overlay
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: root.masterClose()
+ }
+
+ Rectangle {
+ width: root.implicitWidth
+ height: parent.height
+ anchors.horizontalCenter: parent.horizontalCenter
+ color: configRoot.colors.special.background
+
+ Column {
+ anchors.top: parent.top
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: parent.width
+
+ Repeater {
+ model: root.masterFiltered
+
+ Rectangle {
+ width: parent.width
+ height: root.masterLevel === "wallpapers" ? 38 : 22
+ color: root.masterSelected === index ? configRoot.colors.colors.color8 : "transparent"
+
+ Image {
+ visible: root.masterLevel === "wallpapers"
+ anchors.left: parent.left
+ anchors.leftMargin: 8
+ anchors.verticalCenter: parent.verticalCenter
+ width: 46; height: 26
+ fillMode: Image.PreserveAspectCrop
+ asynchronous: true
+ source: visible ? "file:///home/cat/.wallpapers/" + modelData.wp : ""
+ }
+
+ Rectangle {
+ visible: root.masterSelected === index
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ width: 2; height: root.masterLevel === "wallpapers" ? 22 : 12
+ color: configRoot.colors.colors.color4
+ }
+
+ MText {
+ anchors.verticalCenter: parent.verticalCenter
+ x: root.masterLevel === "wallpapers" ? 64 : 14
+ text: modelData?.label ?? ""
+ color: root.masterSelected === index ? configRoot.colors.special.foreground : configRoot.colors.colors.color7
+ }
+
+ MText {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: parent.right
+ anchors.rightMargin: 12
+ visible: modelData?.sub !== undefined
+ text: "›"
+ color: root.masterSelected === index ? configRoot.colors.special.foreground : configRoot.colors.colors.color8
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ hoverEnabled: true
+ onEntered: root.masterSelected = index
+ onClicked: root.masterAccept()
+ }
+ }
+ }
+ }
+ }
+ }
+
+ PanelWindow {
+ id: notifOverlay
+ visible: notifModel.count > 0
+
+ screen: Quickshell.screens.find(s => s.name === "HDMI-A-1") ?? Quickshell.screens[0]
+
+ anchors.top: root.position === "top"
+ anchors.bottom: root.position === "bottom"
+ anchors.left: true
+ anchors.right: true
+
+ margins.top: root.position === "top" ? (root.look === "fill" ? 0 : 6) : 0
+ margins.bottom: root.position === "bottom" ? (root.look === "fill" ? 0 : 6) : 0
+
+ implicitWidth: Math.round(root.implicitWidth / 3)
+ implicitHeight: notifModel.count * 34
+
+ exclusiveZone: 0
+ color: "transparent"
+ WlrLayershell.layer: WlrLayershell.Overlay
+
+ Column {
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: Math.round(root.implicitWidth / 3)
+ spacing: 0
+
+ Repeater {
+ model: notifModel
+
+ Rectangle {
+ id: toastRect
+ width: Math.round(root.implicitWidth / 3)
+ height: 34
+ color: configRoot.colors.special.background
+
+ Rectangle {
+ visible: index > 0
+ anchors.top: parent.top
+ width: parent.width; height: 1
+ color: configRoot.colors.colors.color8
+ }
+
+ Rectangle {
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ width: 2; height: 18
+ color: configRoot.colors.colors.color3
+ }
+
+ Column {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.leftMargin: 12
+ anchors.rightMargin: 10
+ spacing: 2
+
+ MText {
+ width: parent.width
+ text: model.summary !== "" ? model.summary : model.app
+ font.pixelSize: 11
+ font.weight: Font.Medium
+ color: configRoot.colors.special.foreground
+ elide: Text.ElideRight
+ }
+
+ MText {
+ visible: model.body !== "" && model.summary !== ""
+ width: parent.width
+ text: model.body
+ font.pixelSize: 10
+ color: configRoot.colors.colors.color7
+ elide: Text.ElideRight
+ }
+ }
+
+ Timer {
+ interval: model.timeout
+ running: true
+ repeat: false
+ onTriggered: root.removeNotif(model.nid)
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: root.removeNotif(model.nid)
+ }
+ }
+ }
+ }
+ }
+
+ PanelWindow {
+ id: calendarOverlay
+ visible: root.activeMode === "calendar"
+
+ screen: Quickshell.screens.find(s => s.name === "HDMI-A-1") ?? Quickshell.screens[0]
+
+ anchors.top: root.position === "top"
+ anchors.bottom: root.position === "bottom"
+ anchors.right: true
+
+ margins.top: root.position === "top" ? (root.look === "fill" ? 0 : 6) : 0
+ margins.bottom: root.position === "bottom" ? (root.look === "fill" ? 0 : 6) : 0
+ margins.right: root.look === "fill" ? 0 : root.layout === "full" ? 6 : Math.round(((root.screen?.width ?? 1920) - 820) / 2)
+
+ implicitWidth: 216
+ implicitHeight: 186
+ color: "transparent"
+
+ WlrLayershell.layer: WlrLayershell.Overlay
+ WlrLayershell.keyboardFocus: visible ? WlrLayershell.Exclusive : WlrLayershell.None
+
+ property int selectedDay: new Date().getDate()
+ property int viewYear: new Date().getFullYear()
+ property int viewMonth: new Date().getMonth()
+
+ property var days: {
+ let today = new Date()
+ let first = new Date(viewYear, viewMonth, 1).getDay()
+ let total = new Date(viewYear, viewMonth + 1, 0).getDate()
+ let ptotal = new Date(viewYear, viewMonth, 0).getDate()
+ let res = []
+ for (let i = first - 1; i >= 0; i--) {
+ res.push({ d: ptotal - i, cur: false, today: false, monthOffset: -1 })
+ }
+ for (let i = 1; i <= total; i++) {
+ let isToday = (i === today.getDate() && viewMonth === today.getMonth() && viewYear === today.getFullYear())
+ res.push({ d: i, cur: true, today: isToday, monthOffset: 0 })
+ }
+ let n = 42 - res.length
+ for (let i = 1; i <= n; i++) {
+ res.push({ d: i, cur: false, today: false, monthOffset: 1 })
+ }
+ return res
+ }
+
+ property string title: {
+ let months = ["january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"]
+ return months[viewMonth] + " " + viewYear
+ }
+
+ function prevMonth() {
+ if (viewMonth === 0) { viewMonth = 11; viewYear-- }
+ else viewMonth--
+ }
+
+ function nextMonth() {
+ if (viewMonth === 11) { viewMonth = 0; viewYear++ }
+ else viewMonth++
+ }
+
+ onVisibleChanged: {
+ if (visible) {
+ let d = new Date()
+ viewYear = d.getFullYear()
+ viewMonth = d.getMonth()
+ selectedDay = d.getDate()
+ calendarBox.forceActiveFocus()
+ }
+ }
+
+ Rectangle {
+ id: calendarBox
+ anchors.fill: parent
+ color: configRoot.colors.special.background
+ border.color: configRoot.colors.colors.color8
+ border.width: 1
+ focus: true
+
+ Keys.onPressed: (event) => {
+ if (event.key === Qt.Key_Escape) {
+ root.activeMode = "none"
+ event.accepted = true
+ }
+ }
+
+ ColumnLayout {
+ anchors.fill: parent
+ anchors.margins: 10
+ spacing: 8
+
+ RowLayout {
+ Layout.fillWidth: true
+
+ MText {
+ text: calendarOverlay.title
+ color: configRoot.colors.special.foreground
+ }
+
+ Item { Layout.fillWidth: true }
+
+ Row {
+ spacing: 12
+
+ MText {
+ text: "<"
+ color: prevMouse.containsMouse ? configRoot.colors.special.foreground : configRoot.colors.colors.color7
+ MouseArea {
+ id: prevMouse
+ anchors.fill: parent
+ hoverEnabled: true
+ onClicked: calendarOverlay.prevMonth()
+ }
+ }
+
+ MText {
+ text: ">"
+ color: nextMouse.containsMouse ? configRoot.colors.special.foreground : configRoot.colors.colors.color7
+ MouseArea {
+ id: nextMouse
+ anchors.fill: parent
+ hoverEnabled: true
+ onClicked: calendarOverlay.nextMonth()
+ }
+ }
+ }
+ }
+
+ Grid {
+ columns: 7
+ spacing: 4
+ Layout.alignment: Qt.AlignHCenter
+
+ Repeater {
+ model: ["s", "m", "t", "w", "t", "f", "s"]
+ MText {
+ width: 22; height: 14
+ horizontalAlignment: Text.AlignHCenter
+ text: modelData
+ color: configRoot.colors.colors.color4
+ }
+ }
+ }
+
+ Grid {
+ columns: 7
+ spacing: 4
+ Layout.alignment: Qt.AlignHCenter
+
+ Repeater {
+ model: calendarOverlay.days
+
+ Rectangle {
+ width: 22; height: 22
+ property bool isHovered: dayMouse.containsMouse
+
+ color: modelData.today ? configRoot.colors.special.foreground : (isHovered ? configRoot.colors.colors.color8 : "transparent")
+
+ MText {
+ anchors.centerIn: parent
+ text: modelData.d
+ color: modelData.today ? configRoot.colors.special.background
+ : (isHovered ? configRoot.colors.special.foreground
+ : (modelData.cur ? configRoot.colors.special.foreground : configRoot.colors.colors.color8))
+ }
+
+ MouseArea {
+ id: dayMouse
+ anchors.fill: parent
+ hoverEnabled: true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ '';
+}
diff --git a/nixos/modules/vi.nix b/nixos/modules/vi.nix
new file mode 100644
index 0000000..293f44b
--- /dev/null
+++ b/nixos/modules/vi.nix
@@ -0,0 +1,147 @@
+{ config, pkgs, ... }:
+
+{
+ programs.neovim = {
+ enable = true;
+ defaultEditor = true;
+ viAlias = true;
+ vimAlias = true;
+ withRuby = false;
+ withPython3 = false;
+
+ extraPackages = with pkgs; [
+ ripgrep
+ ];
+
+ plugins = with pkgs.vimPlugins; [
+ lualine-nvim
+ telescope-nvim
+ plenary-nvim
+ nvim-web-devicons
+ neo-tree-nvim
+ nui-nvim
+ alpha-nvim
+ ];
+
+ initLua = ''
+ vim.opt.number = true
+ vim.opt.relativenumber = false
+ vim.opt.numberwidth = 4
+ vim.opt.statuscolumn = "%l %s"
+ vim.opt.tabstop = 2
+ vim.opt.softtabstop = 2
+ vim.opt.shiftwidth = 2
+ vim.opt.expandtab = true
+ vim.opt.wrap = false
+ vim.opt.ignorecase = true
+ vim.opt.smartcase = true
+ vim.opt.hlsearch = false
+ vim.opt.termguicolors = false
+ vim.opt.signcolumn = "yes"
+ vim.opt.scrolloff = 8
+ vim.opt.showmode = false
+ vim.opt.timeoutlen = 300
+ vim.opt.updatetime = 250
+ vim.opt.foldcolumn = "0"
+ vim.opt.directory = vim.fn.stdpath("state") .. "/swap//"
+
+ vim.g.mapleader = " "
+ vim.g.maplocalleader = " "
+
+ vim.keymap.set({"n", "i"}, "<c-s>", "<cmd>write<cr>", {desc = "save file"})
+ vim.keymap.set("n", "<c-q>", "<cmd>quit<cr>", {desc = "quit neovim"})
+ vim.keymap.set("n", "<c-h>", "<cmd>nohlsearch<cr>", {desc = "clear search highlight"})
+ vim.keymap.set({"n", "x"}, "gy", '"+y', {desc = "copy to clipboard"})
+ vim.keymap.set({"n", "x"}, "gp", '"+p', {desc = "paste from clipboard"})
+ vim.keymap.set("n", "<c-z>", "u", {desc = "undo"})
+ vim.keymap.set("i", "<c-z>", "<c-o>u", {desc = "undo"})
+ vim.keymap.set("n", "<c-y>", "<c-r>", {desc = "redo"})
+ vim.keymap.set("i", "<c-y>", "<c-o><c-r>", {desc = "redo"})
+ vim.keymap.set({"n", "i"}, "<c-a>", "ggVG", {desc = "select all"})
+
+ vim.keymap.set("n", "<c-f>", "<cmd>Telescope current_buffer_fuzzy_find<cr>", {desc = "search buffer"})
+
+ vim.keymap.set("n", "<leader>ff", "<cmd>Telescope find_files<cr>", {desc = "find files"})
+ vim.keymap.set("n", "<leader>fg", "<cmd>Telescope live_grep<cr>", {desc = "text search"})
+ vim.keymap.set("n", "<leader>fb", "<cmd>Telescope buffers<cr>", {desc = "find buffers"})
+ vim.keymap.set("n", "<c-e>", "<cmd>Neotree toggle<cr>", {desc = "toggle file explorer"})
+
+ vim.keymap.set("n", "<c-left>", "<c-w>h", {desc = "move left"})
+ vim.keymap.set("n", "<c-down>", "<c-w>j", {desc = "move down"})
+ vim.keymap.set("n", "<c-up>", "<c-w>k", {desc = "move up"})
+ vim.keymap.set("n", "<c-right>", "<c-w>l", {desc = "move right"})
+ vim.keymap.set("n", "<c-|>", "<cmd>vsplit<cr>", {desc = "vertical split"})
+ vim.keymap.set("n", "<c-->", "<cmd>split<cr>", {desc = "horizontal split"})
+ vim.keymap.set("n", "<c-x>", "<cmd>close<cr>", {desc = "close split"})
+
+ vim.cmd.colorscheme("default")
+ vim.opt.matchpairs = ""
+ vim.api.nvim_set_hl(0, "MatchParen", {})
+ vim.cmd("highlight clear MatchParen")
+ vim.cmd("highlight MatchParen guifg=NONE guibg=NONE gui=NONE")
+
+ require("lualine").setup({
+ options = {
+ icons_enabled = true,
+ theme = "auto",
+ component_separators = { left = "", right = "" },
+ section_separators = { left = "", right = "" },
+ },
+ })
+
+ require("telescope").setup({
+ defaults = {
+ file_ignore_patterns = { "node_modules", ".git", "%.lock" },
+ layout_strategy = "horizontal",
+ layout_config = { horizontal = { preview_width = 0.5 } },
+ },
+ })
+
+ require("neo-tree").setup({
+ window = {
+ position = "right",
+ width = 30,
+ mappings = {
+ ["l"] = "open",
+ ["h"] = "close_node",
+ ["<cr>"] = "open",
+ ["<esc>"] = "revert_preview",
+ },
+ },
+ filesystem = {
+ filtered_items = {
+ visible = false,
+ hide_dotfiles = false,
+ hide_gitignored = false,
+ hide_by_name = { ".git", ".DS_Store", "thumbs.db" },
+ },
+ follow_current_file = { enabled = true },
+ },
+ })
+
+ local alpha = require("alpha")
+ local dashboard = require("alpha.themes.dashboard")
+
+ dashboard.section.header.val = {
+ " ⠀⠀⠀⢀⡴⠲⣄⠀⠀⢀⡶⠲⡄⠀⣀⣀⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀",
+ " ⣀⣀⣀⣾⠁⠀⠹⠿⠟⠟⠀⠀⠙⣛⣉⡻⠿⠋⣿⣷⢦⣄⠀⠀⠀⠀⠀⠀",
+ " ⠭⠭⣽⠇⠀⠶⠀⢴⣦⠀⠶⠆⠸⠯⠭⠄⠀⠀⠀⠀⠀⠙⢧⡀⠀⢀⣤⣤",
+ "⠀⠀ ⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢷⣤⣾⣻⡟",
+ " ⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣧⠽⠋⠀",
+ " ⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⠀⠀⠀⠀",
+ " ⠀⠀⢷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡟⠀⠀⠀⠀",
+ "⠀ ⠀⠈⠳⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⠟⠀⠀⠀⠀⠀",
+ "⠀⠀ ⠀⠀⠉⠿⠟⠛⠛⠻⠾⠛⠛⠛⠛⠻⠟⠛⠛⠻⠾⠃⠀⠀⠀⠀⠀⠀",
+ }
+
+ dashboard.section.buttons.val = {
+ dashboard.button("f", " > find file", "<cmd>Telescope find_files<cr>"),
+ dashboard.button("n", " > new file", "<cmd>enew<cr>"),
+ dashboard.button("r", " > recent files", "<cmd>Telescope oldfiles<cr>"),
+ dashboard.button("q", " > quit", "<cmd>qa<cr>"),
+ }
+
+ alpha.setup(dashboard.opts)
+ '';
+ };
+}
diff --git a/nixos/modules/wm.nix b/nixos/modules/wm.nix
new file mode 100644
index 0000000..3d9314a
--- /dev/null
+++ b/nixos/modules/wm.nix
@@ -0,0 +1,157 @@
+{ pkgs, ... }:
+
+{
+ xdg.configFile."hypr/hyprland.lua".force = true;
+
+ wayland.windowManager.hyprland = {
+ enable = true;
+ configType = "lua";
+
+ extraConfig = ''
+ local hl = hl
+ local dsp = hl.dsp
+ local bind = hl.bind
+ local config = hl.config
+ local curve = hl.curve
+ local animation = hl.animation
+ local exec = dsp.exec_cmd
+ local focus = dsp.focus
+ local window = dsp.window
+ local workspace = dsp.workspace
+
+ hl.monitor({ output = "HDMI-A-1", mode = "1920x1080@200", position = "0x0", scale = 1 })
+ hl.monitor({ output = "DP-1", mode = "1920x1080@144", position = "-1080x-330", scale = 1, transform = 3 })
+
+ local mod = "SUPER"
+ local terminal = "kitty"
+ local browser = "helium"
+
+ hl.on("hyprland.start", function ()
+ hl.exec_cmd("systemctl --user start hyprpolkitagent")
+ hl.exec_cmd("bash -c 'awww-daemon & sleep 0.5 && awww clear --outputs DP-1'")
+ hl.exec_cmd("wl-paste --type text --watch cliphist store")
+ hl.exec_cmd("wl-paste --type image --watch cliphist store")
+ hl.exec_cmd("quickshell -p ~/.config/quickshell/shell.qml")
+ end)
+
+ config({
+ general = {
+ gaps_in = 2.5,
+ gaps_out = 5,
+ border_size = 1,
+ resize_on_border = false,
+ col = { active_border = "rgba(ffffffff)" },
+ allow_tearing = false,
+ layout = "dwindle",
+ },
+ })
+
+ config({
+ decoration = {
+ rounding = 0,
+ rounding_power = 0,
+ active_opacity = 1.0,
+ inactive_opacity = 1.0,
+ shadow = {
+ enabled = true,
+ range = 4,
+ render_power = 3,
+ color = "rgba(1a1a1aee)",
+ },
+ blur = {
+ enabled = true,
+ size = 3,
+ passes = 3,
+ vibrancy = 0,
+ },
+ },
+ })
+
+ config({
+ input = {
+ kb_layout = "us",
+ follow_mouse = 1,
+ sensitivity = 0,
+ force_no_accel = false,
+ touchpad = { natural_scroll = false },
+ },
+ })
+
+ config({
+ misc = {
+ force_default_wallpaper = 0,
+ disable_hyprland_logo = true,
+ disable_splash_rendering = true,
+ initial_workspace_tracking = true,
+ },
+ })
+
+ config({
+ dwindle = {
+ preserve_split = true,
+ },
+ })
+
+ curve("easeOutQuint", { type = "bezier", points = { {0.20, 1}, {0.30, 1} } })
+ curve("easeInOutCubic", { type = "bezier", points = { {0.65, 0.05}, {0.35, 1} } })
+ curve("linear", { type = "bezier", points = { {0, 0}, {1, 1} } })
+ curve("almostLinear", { type = "bezier", points = { {0.5, 0.5}, {0.75, 1} } })
+ curve("quick", { type = "bezier", points = { {0.15, 0}, {0.1, 1} } })
+ curve("hard", { type = "bezier", points = { {0, 1}, {0, 1} } })
+ animation({ leaf = "global", enabled = true, speed = 5, bezier = "default" })
+ animation({ leaf = "border", enabled = true, speed = 2.5, bezier = "easeOutQuint" })
+ animation({ leaf = "windows", enabled = true, speed = 2.5, bezier = "easeOutQuint" })
+ animation({ leaf = "windowsIn", enabled = true, speed = 2, bezier = "easeOutQuint", style = "popin 90%" })
+ animation({ leaf = "windowsOut", enabled = true, speed = 1, bezier = "linear", style = "popin 90%" })
+ animation({ leaf = "fadeIn", enabled = true, speed = 1, bezier = "almostLinear" })
+ animation({ leaf = "fadeOut", enabled = true, speed = 1, bezier = "almostLinear" })
+ animation({ leaf = "fade", enabled = true, speed = 1.5, bezier = "quick" })
+ animation({ leaf = "layers", enabled = true, speed = 2, bezier = "easeOutQuint" })
+ animation({ leaf = "layersIn", enabled = true, speed = 2, bezier = "easeOutQuint", style = "fade" })
+ animation({ leaf = "layersOut", enabled = true, speed = 1, bezier = "linear", style = "fade" })
+ animation({ leaf = "workspaces", enabled = true, speed = 5, bezier = "hard", style = "slidevert" })
+ animation({ leaf = "specialWorkspace", enabled = true, speed = 5, bezier = "hard", style = "slidevert" })
+
+ hl.window_rule({
+ match = { initial_class = "^(imv|mpv)$" },
+ float = true,
+ center = true,
+ size = "600 600",
+ })
+
+ bind(mod .. " + Q", exec(terminal))
+ bind(mod .. " + R", exec("quickshell ipc call menu toggle"))
+ bind(mod .. " + T", exec("quickshell ipc call master toggle"))
+ bind(mod .. " + W", exec("quickshell ipc call bar toggle"))
+ bind(mod .. " + X", exec("quickshell ipc call mic toggle"))
+ bind(mod .. " + B", exec(browser))
+ bind(mod .. " + C", window.close())
+ bind(mod .. " + V", window.float({ action = "toggle" }))
+ bind(mod .. " + F", window.fullscreen({ mode = 0 }))
+ bind(mod .. " + Tab", focus({ workspace = "m+1" }))
+ bind("ALT + S", exec('hyprshot -o .pictures/screenshots/ -f "$(date +%y-%m-%d_%H-%M-%S).png" -s -m region'))
+
+ bind(mod .. " + left", focus({ direction = "left" }))
+ bind(mod .. " + right", focus({ direction = "right" }))
+ bind(mod .. " + up", focus({ direction = "up" }))
+ bind(mod .. " + down", focus({ direction = "down" }))
+
+ bind("SHIFT + left", window.move({ direction = "left" }))
+ bind("SHIFT + right", window.move({ direction = "right" }))
+ bind("SHIFT + up", window.move({ direction = "up" }))
+ bind("SHIFT + down", window.move({ direction = "down" }))
+
+ for i = 1, 10 do
+ local key = (i == 10) and "0" or tostring(i)
+ bind(mod .. " + " .. key, focus({ workspace = i }))
+ bind(mod .. " + SHIFT + " .. key, window.move({ workspace = i }))
+ end
+
+ bind(mod .. " + S", workspace.toggle_special("magic"))
+ bind(mod .. " + SHIFT + " .. "S", window.move({ workspace = "special:magic" }))
+
+ bind(mod .. " + mouse:272", window.drag(), { mouse = true })
+ bind(mod .. " + mouse:273", window.resize(), { mouse = true })
+ '';
+ };
+}
diff --git a/nixos/modules/yazi.nix b/nixos/modules/yazi.nix
new file mode 100644
index 0000000..39c1402
--- /dev/null
+++ b/nixos/modules/yazi.nix
@@ -0,0 +1,50 @@
+{
+ programs.yazi = {
+ enable = true;
+
+ settings = {
+ mgr = {
+ ratio = [ 1 4 3 ];
+ sort_by = "alphabetical";
+ sort_dir_first = true;
+ linemode = "none";
+ show_hidden = true;
+ show_symlink = true;
+ };
+ };
+
+ theme = {
+ mgr = {
+ border_symbol = " ";
+ };
+ indicator = {
+ padding = { open = "█"; close = "█"; };
+ };
+ mode = {
+ normal_main = { fg = "black"; bg = "blue"; bold = true; };
+ normal_alt = { fg = "blue"; bg = "black"; };
+ select_main = { fg = "black"; bg = "green"; bold = true; };
+ select_alt = { fg = "green"; bg = "black"; };
+ unset_main = { fg = "black"; bg = "yellow"; bold = true; };
+ unset_alt = { fg = "yellow"; bg = "black"; };
+ };
+ status = {
+ sep_left = { open = ""; close = ""; };
+ sep_right = { open = ""; close = ""; };
+ };
+ };
+
+ keymap = {
+ manager = {
+ prepend_keymap = [
+ { on = [ "x" ]; run = "yank --cut"; }
+ { on = [ "y" ]; run = "yank"; }
+ { on = [ "p" ]; run = "paste"; }
+ { on = [ "d" ]; run = "remove"; }
+ { on = [ "r" ]; run = "rename"; }
+ { on = [ "c" ]; run = "create"; }
+ ];
+ };
+ };
+ };
+}