From ec72b6818a3f3f243b88816e3f201fbf07c9a1bd Mon Sep 17 00:00:00 2001 From: chodak166 Date: Wed, 10 Jun 2026 18:40:34 +0200 Subject: [PATCH 1/9] Updated i3 config to use fsel --- .config/i3/config | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.config/i3/config b/.config/i3/config index b0cb4de..4b5ac16 100644 --- a/.config/i3/config +++ b/.config/i3/config @@ -149,9 +149,12 @@ bindsym $mod+Return exec kitty # bindsym $mod+d exec ulauncher bindsym Mod1+F2 exec dmenu_run -# set $menu alacritty --title launcher -e fsel -bindsym $mod+d exec kitty --title launcher -o cursor_trail=0 -e fsel -r --detach -for_window [title="^launcher$"] floating enable, resize set width 500 height 430, border none +bindsym $mod+d exec --no-startup-id alacritty --title launcher -e bash -l -c "fsel -r --detach" + +# bindsym $mod+d exec --no-startup-id alacritty --title launcher -e top +for_window [title="^launcher$"] floating enable, resize set width 600 height 530, border none +for_window [title="^launcher$"] move position center + # run app assigned to current workspace From 43153c8dcf9fcfebb291974099369fc3853e71c2 Mon Sep 17 00:00:00 2001 From: chodak166 Date: Sat, 13 Jun 2026 14:24:30 +0200 Subject: [PATCH 2/9] Added initial arch init files --- .dotfiles.d/init/arch/init-cargo-tools.sh | 25 +++++++++++++++++++++++ .dotfiles.d/init/arch/init-nvim.sh | 16 +++++++++++++++ .dotfiles.d/init/arch/init-shell.sh | 23 +++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100755 .dotfiles.d/init/arch/init-cargo-tools.sh create mode 100755 .dotfiles.d/init/arch/init-nvim.sh create mode 100755 .dotfiles.d/init/arch/init-shell.sh diff --git a/.dotfiles.d/init/arch/init-cargo-tools.sh b/.dotfiles.d/init/arch/init-cargo-tools.sh new file mode 100755 index 0000000..cd36bd7 --- /dev/null +++ b/.dotfiles.d/init/arch/init-cargo-tools.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -euo pipefail + +echo "[1/4] Updating pacman and installing prerequisites (curl, base-devel, imagemagick, glow)..." +sudo pacman -Syu --noconfirm +sudo pacman -S --noconfirm curl base-devel imagemagick glow + +echo "[2/4] Downloading and installing rustup (latest rustc/cargo)..." +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + +rustup default stable + +echo "[3/4] Sourcing cargo environment..." +source "$HOME/.cargo/env" + +echo " -> Installed: $(rustc --version)" +echo " -> Installed: $(cargo --version)" + +echo "[4/4] Installing tools..." +cargo install fsel@3.5.1-kiwicrab +cargo install --force yazi-build +cargo install resvg + +echo "Done!" + diff --git a/.dotfiles.d/init/arch/init-nvim.sh b/.dotfiles.d/init/arch/init-nvim.sh new file mode 100755 index 0000000..e106e12 --- /dev/null +++ b/.dotfiles.d/init/arch/init-nvim.sh @@ -0,0 +1,16 @@ +#!/bin/env bash + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)" + +sudo pacman -Syu --noconfirm +sudo pacman -S --noconfirm \ + jq \ + ripgrep \ + fd \ + zoxide \ + base-devel \ + just \ + neovim + +nvim --version + diff --git a/.dotfiles.d/init/arch/init-shell.sh b/.dotfiles.d/init/arch/init-shell.sh new file mode 100755 index 0000000..53ab06a --- /dev/null +++ b/.dotfiles.d/init/arch/init-shell.sh @@ -0,0 +1,23 @@ +#!/bin/env bash + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)" + +sudo pacman -Syu --noconfirm +sudo pacman -S --noconfirm zsh eza unzip + +sudo chsh -s "$(which zsh)" "$USER" + +source "${SCRIPT_DIR}/../ensure-locale.sh" + +cd ~ +git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf +./.fzf/install + +mkdir -p ~/.local/share/fonts +cd ~/.local/share/fonts + +fontName=DejaVuSansMono +curl -L -O "https://github.com/ryanoasis/nerd-fonts/releases/download/v3.4.0/${fontName}.zip" +unzip ${fontName}.zip +rm ${fontName}.zip + From 87a79aa7f74ef7e92e081b897cdaf2a0bd1b9040 Mon Sep 17 00:00:00 2001 From: chodak166 Date: Wed, 17 Jun 2026 17:54:39 +0200 Subject: [PATCH 3/9] Added conform shfmt config --- .bashrc | 10 +++++++++ .config/nvim/lazy-lock.json | 27 +++++++++++------------ .config/nvim/lua/plugins/conform.lua | 10 +++++++++ .config/yazi/yazi.toml | 8 +++---- .dotfiles.d/init/arch/init-cargo-tools.sh | 4 ++-- .local/share/applications/mimeinfo.cache | 6 +++++ .local/share/applications/nvim.desktop | 8 +++++++ .local/share/applications/yazi.desktop | 8 +++++++ .tmux.conf | 5 ++++- .zshrc | 3 +++ 10 files changed, 68 insertions(+), 21 deletions(-) create mode 100644 .config/nvim/lua/plugins/conform.lua create mode 100644 .local/share/applications/mimeinfo.cache create mode 100644 .local/share/applications/nvim.desktop create mode 100644 .local/share/applications/yazi.desktop diff --git a/.bashrc b/.bashrc index 9d4649d..2065bb1 100755 --- a/.bashrc +++ b/.bashrc @@ -158,3 +158,13 @@ alias bat=batcat [ -f "$HOME/.local/bin/env" ] && . "$HOME/.local/bin/env" . "$HOME/.cargo/env" + +# Sway / Wayland environment +export XDG_CURRENT_DESKTOP=sway +export XDG_SESSION_TYPE=wayland +export QT_QPA_PLATFORM=wayland +export QT_WAYLAND_DISABLE_WINDOWDECORATION=1 +export GDK_BACKEND=wayland +export MOZ_ENABLE_WAYLAND=1 +export SDL_VIDEODRIVER=wayland +export _JAVA_AWT_WM_NONREPARENTING=1 diff --git a/.config/nvim/lazy-lock.json b/.config/nvim/lazy-lock.json index 2dddbd2..4686a7c 100644 --- a/.config/nvim/lazy-lock.json +++ b/.config/nvim/lazy-lock.json @@ -1,34 +1,33 @@ { - "LazyVim": { "branch": "main", "commit": "83d90f339defdb109a6ede333865a66ffc7ef6aa" }, - "avante.nvim": { "branch": "main", "commit": "0e40cb0c0f13b87be8a2276a844428d60c466d78" }, + "LazyVim": { "branch": "main", "commit": "c10948c50b18fae7f256433afdef09e432410480" }, + "avante.nvim": { "branch": "main", "commit": "dee2402ed0b7c1d3710c0c8eed3d26aa055e118e" }, "blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" }, "bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" }, - "catppuccin": { "branch": "main", "commit": "8edd468af4d63212b84d69b2ddb5ffc9023ef5eb" }, - "clangd_extensions.nvim": { "branch": "main", "commit": "78c2ecd659d54972be17aa6ba2deac3c53223b80" }, + "catppuccin": { "branch": "main", "commit": "49a926655a2f5579e9c276470fc300baaa49e524" }, "conform.nvim": { "branch": "master", "commit": "619363c30309d29ffa631e67c8183f2a72caa373" }, "diffview.nvim": { "branch": "main", "commit": "4516612fe98ff56ae0415a259ff6361a89419b0a" }, "dotenv.nvim": { "branch": "main", "commit": "7d516e9293c6e3ac21830fb10a4e8674c02747c6" }, "dressing.nvim": { "branch": "master", "commit": "2d7c2db2507fa3c4956142ee607431ddb2828639" }, "flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" }, "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, - "gitsigns.nvim": { "branch": "main", "commit": "dd3f588bacbeb041be6facf1742e42097f62165d" }, - "grug-far.nvim": { "branch": "main", "commit": "5506c2f59dc9ab2ed6c233585412b24d31d51521" }, + "gitsigns.nvim": { "branch": "main", "commit": "25050e4ed39e628282831d4cbecb1850454ce915" }, + "grug-far.nvim": { "branch": "main", "commit": "c995bbacf8229dc096ec1c3d60f8531059c86c1b" }, "hybrid-theme": { "branch": "main", "commit": "b131110fbe63481d7d263c71982206a70a04d236" }, "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, "just-runner.nvim": { "branch": "main", "commit": "f29d405aa828900df242600720a2b0e57261489f" }, "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, "lazydev.nvim": { "branch": "main", "commit": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d" }, - "lualine.nvim": { "branch": "master", "commit": "131a558e13f9f28b15cd235557150ccb23f89286" }, - "mason-lspconfig.nvim": { "branch": "main", "commit": "7b01e2974a47d489bb92f47a41e4c0088ea8f86e" }, - "mason.nvim": { "branch": "main", "commit": "bb639d4bf385a4d89f478b83af4d770be05ab7eb" }, - "mini.ai": { "branch": "main", "commit": "4ce4c35e411ea329a15d4b15e9c89c2a3089e437" }, - "mini.files": { "branch": "main", "commit": "423d6b5afb7a94e658950d470957f830d43dd41e" }, - "mini.icons": { "branch": "main", "commit": "520995f1d75da0e4cc901ee95080b1ff2bc46b94" }, + "lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "21c5b3ebeaa0412e28096bb0701434c51c1fbf76" }, + "mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" }, + "mini.ai": { "branch": "main", "commit": "4511b3481707c1d021485475d34f2ed2a50bf47b" }, + "mini.files": { "branch": "main", "commit": "02874bc653fbecf2bee2c65441d0ebd09110f011" }, + "mini.icons": { "branch": "main", "commit": "ac38c983aed0a2bd32a65ca3e2348e12e58ca292" }, "mini.pairs": { "branch": "main", "commit": "30cf2f01c4aaa2033db67376b9924fa2442c05d6" }, "noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" }, "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, - "nvim-lint": { "branch": "master", "commit": "d48f3a76189d03b2239f6df1b2f7e3fa8353743b" }, - "nvim-lspconfig": { "branch": "master", "commit": "9573948c38bfabeec353ae7dd7d3ffec4c506a6b" }, + "nvim-lint": { "branch": "master", "commit": "1ba49820a3c29ba6ab1b2dd441a63b3822c4e39b" }, + "nvim-lspconfig": { "branch": "master", "commit": "a683e0ddf0cf64c6cd689e18ffb480ade3c162b7" }, "nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" }, "nvim-treesitter-textobjects": { "branch": "main", "commit": "851e865342e5a4cb1ae23d31caf6e991e1c99f1e" }, "nvim-ts-autotag": { "branch": "main", "commit": "88c1453db4ba7dd24131086fe51fdf74e587d275" }, diff --git a/.config/nvim/lua/plugins/conform.lua b/.config/nvim/lua/plugins/conform.lua new file mode 100644 index 0000000..0dc9d18 --- /dev/null +++ b/.config/nvim/lua/plugins/conform.lua @@ -0,0 +1,10 @@ +return { + "stevearc/conform.nvim", + opts = { + formatters = { + shfmt = { + args = { "-i", "2", "-ci", "-bn", "-sr" }, + }, + }, + }, +} diff --git a/.config/yazi/yazi.toml b/.config/yazi/yazi.toml index 21409dd..4a5376f 100644 --- a/.config/yazi/yazi.toml +++ b/.config/yazi/yazi.toml @@ -10,10 +10,10 @@ url = "*/" run = "git" group = "git" -# [opener] -# edit = [ -# { run = 'nvim "$@"', desc = "Open in Neovim", block = true, for = "unix" }, -# ] +[opener] +edit = [ + { run = 'nvim "$@"', desc = "Open in Neovim", block = true, for = "unix" }, +] # [[plugin.prepend_previewers]] # url = "*" diff --git a/.dotfiles.d/init/arch/init-cargo-tools.sh b/.dotfiles.d/init/arch/init-cargo-tools.sh index cd36bd7..5a8c166 100755 --- a/.dotfiles.d/init/arch/init-cargo-tools.sh +++ b/.dotfiles.d/init/arch/init-cargo-tools.sh @@ -6,7 +6,8 @@ sudo pacman -Syu --noconfirm sudo pacman -S --noconfirm curl base-devel imagemagick glow echo "[2/4] Downloading and installing rustup (latest rustc/cargo)..." -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y +# curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y +sudo pacman -S rustup rustup default stable @@ -22,4 +23,3 @@ cargo install --force yazi-build cargo install resvg echo "Done!" - diff --git a/.local/share/applications/mimeinfo.cache b/.local/share/applications/mimeinfo.cache new file mode 100644 index 0000000..ba69156 --- /dev/null +++ b/.local/share/applications/mimeinfo.cache @@ -0,0 +1,6 @@ +[MIME Cache] +application/x-shellscript=nvim.desktop; +inode/directory=yazi.desktop; +text/html=nvim.desktop; +text/markdown=nvim.desktop; +text/plain=nvim.desktop; diff --git a/.local/share/applications/nvim.desktop b/.local/share/applications/nvim.desktop new file mode 100644 index 0000000..5a2a4f2 --- /dev/null +++ b/.local/share/applications/nvim.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Type=Application +Name=Neovim +Exec=kitty nvim %F +Terminal=false +Icon=nvim +Categories=Utility;TextEditor; +MimeType=text/plain;text/markdown;text/html;application/x-shellscript; diff --git a/.local/share/applications/yazi.desktop b/.local/share/applications/yazi.desktop new file mode 100644 index 0000000..d226716 --- /dev/null +++ b/.local/share/applications/yazi.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Type=Application +Name=Yazi +Exec=kitty yazi %f +Terminal=false +Icon=kitty +Categories=Utility;FileManager; +MimeType=inode/directory; diff --git a/.tmux.conf b/.tmux.conf index 6e35dc6..fd9eb79 100644 --- a/.tmux.conf +++ b/.tmux.conf @@ -2,6 +2,9 @@ set -g default-command /usr/bin/zsh set -g default-terminal "tmux-256color" +run ~/.tmux.d/tmux-gruvbox/gruvbox-tpm.tmux +set -g @tmux-gruvbox 'dark' # or 'dark256', 'light', 'light256' + # disable mouse mode (to use selection mode from current terminal) set-option -g mouse off @@ -26,7 +29,7 @@ bind-key -n Home send-key C-a bind-key -n End send-key C-e # set status bar color -set -g status-bg "dark cyan" +# set -g status-bg "dark cyan" # window rename set-option -g status-interval 5 diff --git a/.zshrc b/.zshrc index 9aa1175..8c49204 100644 --- a/.zshrc +++ b/.zshrc @@ -199,3 +199,6 @@ export SUDO_EDITOR=nvim [ -f ~/.fzf.zsh ] && source ~/.fzf.zsh + +# opencode +export PATH=/home/chodak/.opencode/bin:$PATH From 6dc56f4f12b7defbd1b9603d3176d9d4925a1f7a Mon Sep 17 00:00:00 2001 From: chodak166 Date: Thu, 18 Jun 2026 20:18:46 +0200 Subject: [PATCH 4/9] Added waybar config --- .config/nvim/lazy-lock.json | 1 - .config/nvim/lua/plugins/colorscheme.lua | 68 +++++----- .config/waybar/config.jsonc | 135 +++++++++++++++++++ .config/waybar/disk.py | 157 +++++++++++++++++++++++ .config/waybar/network.py | 140 ++++++++++++++++++++ .config/waybar/network.sh | 97 ++++++++++++++ .config/waybar/style.css | 77 +++++++++++ .config/waybar/top.sh | 30 +++++ .config/waybar/watch.sh | 5 + 9 files changed, 675 insertions(+), 35 deletions(-) create mode 100644 .config/waybar/config.jsonc create mode 100755 .config/waybar/disk.py create mode 100755 .config/waybar/network.py create mode 100755 .config/waybar/network.sh create mode 100644 .config/waybar/style.css create mode 100755 .config/waybar/top.sh create mode 100755 .config/waybar/watch.sh diff --git a/.config/nvim/lazy-lock.json b/.config/nvim/lazy-lock.json index 4686a7c..ec559f8 100644 --- a/.config/nvim/lazy-lock.json +++ b/.config/nvim/lazy-lock.json @@ -12,7 +12,6 @@ "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, "gitsigns.nvim": { "branch": "main", "commit": "25050e4ed39e628282831d4cbecb1850454ce915" }, "grug-far.nvim": { "branch": "main", "commit": "c995bbacf8229dc096ec1c3d60f8531059c86c1b" }, - "hybrid-theme": { "branch": "main", "commit": "b131110fbe63481d7d263c71982206a70a04d236" }, "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, "just-runner.nvim": { "branch": "main", "commit": "f29d405aa828900df242600720a2b0e57261489f" }, "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, diff --git a/.config/nvim/lua/plugins/colorscheme.lua b/.config/nvim/lua/plugins/colorscheme.lua index 8394a72..f81ac04 100644 --- a/.config/nvim/lua/plugins/colorscheme.lua +++ b/.config/nvim/lua/plugins/colorscheme.lua @@ -13,39 +13,39 @@ -- } -- Local development: --- return { --- dir = "/home/chodak/src/git/nvim-hybrid-theme", --- name = "hybrid-theme", --- lazy = false, --- priority = 1000, --- config = function() --- require("hybrid-theme").setup({ --- theme = "dark", --- transparent = false, --- background_variant = "flat", --- italics = { --- comments = true, --- keywords = false, --- functions = false, --- strings = false, --- variables = false, --- }, --- }) --- require("hybrid-theme").colorscheme() --- end, --- } - return { - { - "chodak166/nvim-hybrid-theme", - name = "hybrid-theme", - lazy = false, - priority = 1000, - config = function() - require("hybrid-theme").setup({ - background_variant = "semi_flat", - }) - require("hybrid-theme").colorscheme() - end, - }, + dir = "/home/chodak/src/git/nvim-hybrid-theme", + name = "hybrid-theme", + lazy = false, + priority = 1000, + config = function() + require("hybrid-theme").setup({ + theme = "dark", + transparent = false, + background_variant = "flat", + italics = { + comments = true, + keywords = false, + functions = false, + strings = false, + variables = false, + }, + }) + require("hybrid-theme").colorscheme() + end, } + +-- return { +-- { +-- "chodak166/nvim-hybrid-theme", +-- name = "hybrid-theme", +-- lazy = false, +-- priority = 1000, +-- config = function() +-- require("hybrid-theme").setup({ +-- background_variant = "semi_flat", +-- }) +-- require("hybrid-theme").colorscheme() +-- end, +-- }, +-- } diff --git a/.config/waybar/config.jsonc b/.config/waybar/config.jsonc new file mode 100644 index 0000000..5d95ab3 --- /dev/null +++ b/.config/waybar/config.jsonc @@ -0,0 +1,135 @@ +// -*- mode: json -*- + +{ + "layer": "top", + "position": "top", + + "modules-left": [ + "sway/workspaces", + "custom/right-arrow-dark" + ], + "modules-center": [ + "custom/left-arrow-dark", + "sway/window", + "custom/right-arrow-dark" + ], + "modules-right": [ + "custom/left-arrow-dark", + "pulseaudio", + "custom/left-arrow-light", + "custom/left-arrow-dark", + "custom/network", + "custom/left-arrow-light", + "custom/left-arrow-dark", + "custom/disk", + "custom/left-arrow-light", + "custom/left-arrow-dark", + "memory", + "custom/left-arrow-light", + "custom/left-arrow-dark", + "custom/top", + "custom/left-arrow-light", + "custom/left-arrow-dark", + "battery", + "custom/left-arrow-light", + "custom/left-arrow-dark", + "clock#0", + "custom/left-arrow-light", + "custom/left-arrow-dark", + "tray" + ], + + "custom/left-arrow-dark": { + "format": "", + "tooltip": false + }, + "custom/left-arrow-light": { + "format": "", + "tooltip": false + }, + "custom/right-arrow-dark": { + "format": "", + "tooltip": false + }, + + "sway/workspaces": { + "disable-scroll": true, + "format": "{name}" + }, + + "sway/window": { + "max-length": 70, + "format": "{title}" + }, + + "custom/network": { + "exec": "/home/chodak/.config/waybar/network.py", + "interval": 10, + "return-type": "json", + "tooltip": true + }, + + "clock#2": { + "format": "{:%H:%M}", + "tooltip": false + }, + "clock#3": { + "format": "{:%d/%m}", + "tooltip": false + }, + "clock#0": { + "format": "{:%H:%M %d/%m/%y}", + "tooltip": false + }, + + "pulseaudio": { + "format": "{icon} {volume:2}%", + "format-bluetooth": "{icon} {volume}%", + "format-muted": "MUTE", + "format-icons": { + "headphones": "", + "default": [ + "", + "" + ] + }, + "scroll-step": 5, + "on-click": "pamixer -t", + "on-click-right": "pavucontrol" + }, + "memory": { + "interval": 5, + "format": " {}%" + }, + "custom/top": { + "exec": "~/.config/waybar/top.sh", + "interval": 5, + "return-type": "json", + "tooltip": true + }, + "battery": { + "states": { + "good": 95, + "warning": 30, + "critical": 15 + }, + "format": "{icon} {capacity}%", + "format-icons": [ + "", + "", + "", + "", + "" + ] + }, + "custom/disk": { + "exec": "/home/chodak/.config/waybar/disk.py", + "interval": 30, + "return-type": "json", + "tooltip": true, + "escape": false + }, + "tray": { + "icon-size": 24 + } +} diff --git a/.config/waybar/disk.py b/.config/waybar/disk.py new file mode 100755 index 0000000..dab4761 --- /dev/null +++ b/.config/waybar/disk.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +"""Waybar disk module: shows disk usage across all mounted partitions.""" + +import json +import os + +# Filesystem types to ignore (virtual / non-disk) +IGNORE_FSTYPES = { + "tmpfs", "devtmpfs", "proc", "sysfs", "cgroup", "cgroup2", + "pstore", "bpf", "debugfs", "tracefs", "securityfs", "configfs", + "hugetlbfs", "devpts", "ramfs", "fuse.gvfsd-fuse", "fusectl", + "mqueue", "rpc_pipefs", "overlay", "squashfs", +} + +# Pango color thresholds +COLOR_LOW = "#a6e3a1" # green — < 70% +COLOR_MID = "#f9e2af" # yellow — 70–89% +COLOR_HIGH = "#f38ba8" # red — ≥ 90% + + +def _pct_color(pct: float) -> str: + """Return a Pango color string for the given usage percentage.""" + if pct >= 90: + return COLOR_HIGH + if pct >= 70: + return COLOR_MID + return COLOR_LOW + + +def _span(color: str, text: str) -> str: + """Wrap text in a Pango with the given foreground color.""" + return f"{text}" + + +def get_partitions(): + """Return list of (device, mountpoint, fstype) for real partitions.""" + partitions = [] + seen_devices = set() + + try: + with open("/proc/mounts") as f: + for line in f: + parts = line.split() + if len(parts) < 3: + continue + device, mountpoint, fstype = parts[:3] + + if fstype in IGNORE_FSTYPES: + continue + if not device.startswith("/dev/"): + continue + if device in seen_devices: + continue + seen_devices.add(device) + + partitions.append((device, mountpoint, fstype)) + except OSError: + pass + + return partitions + + +def get_usage(mountpoint): + """Return (total_bytes, used_bytes, pct) for a mountpoint, or None.""" + try: + st = os.statvfs(mountpoint) + total = st.f_frsize * st.f_blocks + free = st.f_frsize * st.f_bfree + used = total - free + pct = (used / total) * 100 if total > 0 else 0.0 + return total, used, pct + except OSError: + return None + + +def fmt_size(bytes_val): + """Format bytes as human-readable.""" + if bytes_val >= 1 << 40: + return f"{bytes_val / (1 << 40):.1f}T" + if bytes_val >= 1 << 30: + return f"{bytes_val / (1 << 30):.1f}G" + if bytes_val >= 1 << 20: + return f"{bytes_val / (1 << 20):.1f}M" + if bytes_val >= 1 << 10: + return f"{bytes_val / (1 << 10):.1f}K" + return f"{bytes_val}B" + + +def main(): + partitions = get_partitions() + + if not partitions: + print(json.dumps( + {"text": " —", "tooltip": "No disk partitions found"}, + ensure_ascii=False)) + return + + tooltip_lines = [] + root_pct = None + bar_parts = [] + + for device, mountpoint, fstype in partitions: + usage = get_usage(mountpoint) + if usage is None: + continue + total, used, pct = usage + + total_str = fmt_size(total) + used_str = fmt_size(used) + color = _pct_color(pct) + + # Icons per mountpoint + if mountpoint == "/": + icon = "" + elif mountpoint == "/home": + icon = "" + elif mountpoint == "/boot": + icon = "" + elif "/media/" in mountpoint or "/run/media/" in mountpoint: + icon = "" + else: + icon = "" + + # Tooltip line with colored percentage + pct_span = _span(color, f"{pct:5.1f}%") + warn = " ⚠" if pct >= 90 else "" + tooltip_lines.append( + f"{icon} {mountpoint:20s} {used_str:>6s} / {total_str:>6s} ({pct_span}){warn}" + ) + + # Track root for bar display + if mountpoint == "/": + root_pct = pct + + # Build bar text using Pango markup + if root_pct is not None: + bar_icon = "⚠" if root_pct >= 90 else "" + bar_color = _pct_color(root_pct) + bar_text = ( + f"{bar_icon}" + f" {_span(bar_color, f'{root_pct:.0f}%')}" + ) + elif tooltip_lines: + bar_text = f" —" + else: + bar_text = " —" + + tooltip = "\n".join(tooltip_lines) if tooltip_lines else "No partitions" + + print(json.dumps( + {"text": bar_text, "tooltip": tooltip}, + ensure_ascii=False)) + + +if __name__ == "__main__": + main() + diff --git a/.config/waybar/network.py b/.config/waybar/network.py new file mode 100755 index 0000000..dc67b1a --- /dev/null +++ b/.config/waybar/network.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +"""Waybar network module: shows interface, IP, and up/down transfer rate.""" + +import json +import os +import re +import subprocess +import time + +STATE_FILE_TMPL = "/tmp/waybar-network-stats-{}" +ICON = "󰲝" # nerd font network icon +NO_NET_ICON = "󰖪" + + +def run(cmd: list[str]) -> str: + """Run a command and return stdout, or empty string on failure.""" + try: + return subprocess.check_output( + cmd, stderr=subprocess.DEVNULL, text=True + ).strip() + except subprocess.CalledProcessError: + return "" + + +def get_default_interface() -> str | None: + """Return the default route interface name.""" + output = run(["ip", "route"]) + for line in output.splitlines(): + if line.startswith("default"): + parts = line.split() + # "default via X.X.X.X dev INTERFACE ..." + if len(parts) >= 5: + return parts[4] + return None + + +def get_ip(iface: str) -> str | None: + """Return the IPv4 address of the given interface.""" + output = run(["ip", "-4", "addr", "show", iface]) + m = re.search(r"inet\s+(\d+\.\d+\.\d+\.\d+)", output) + return m.group(1) if m else None + + +def iface_type(iface: str) -> str: + """Classify interface as WiFi, Ethernet, or generic.""" + if re.match(r"^(wlan|wlp)", iface): + return "WiFi" + if re.match(r"^(eth|enp|eno|ens)", iface): + return "Ethernet" + return iface + + +def format_rate(bps: float) -> str: + """Format bytes-per-second as human-readable with one decimal.""" + bps = max(bps, 0) + if bps >= 1_073_741_824: + return f"{bps / 1_073_741_824:.1f}G" + if bps >= 1_048_576: + return f"{bps / 1_048_576:.1f}M" + if bps >= 1024: + return f"{bps / 1024:.1f}K" + return f"{bps:.1f}B" + + +def main() -> None: + iface = get_default_interface() + if iface is None: + print(json.dumps( + {"text": f"{NO_NET_ICON} No net", + "tooltip": "No network connection"}, + ensure_ascii=False)) + return + + ip = get_ip(iface) + if ip is None: + print(json.dumps( + {"text": f"{NO_NET_ICON} No IP", + "tooltip": f"Interface {iface} has no IP"}, + ensure_ascii=False)) + return + + itype = iface_type(iface) + + # Read current byte counters + now_ts = time.time_ns() + rx_path = f"/sys/class/net/{iface}/statistics/rx_bytes" + tx_path = f"/sys/class/net/{iface}/statistics/tx_bytes" + + try: + with open(rx_path) as f: + now_rx = int(f.read().strip()) + with open(tx_path) as f: + now_tx = int(f.read().strip()) + except (OSError, ValueError): + now_rx = now_tx = 0 + + # Transfer rate calculation + rate_down = "" + rate_up = "" + state_file = STATE_FILE_TMPL.format(iface) + + if os.path.exists(state_file): + try: + with open(state_file) as f: + prev_rx, prev_tx, prev_ts = map(int, f.read().split()) + delta_ns = now_ts - prev_ts + if delta_ns > 0: + delta_rx = now_rx - prev_rx + delta_tx = now_tx - prev_tx + rx_bps = delta_rx * 1e9 / delta_ns + tx_bps = delta_tx * 1e9 / delta_ns + rate_down = format_rate(rx_bps) + rate_up = format_rate(tx_bps) + except (OSError, ValueError): + pass + + # Save current state for next run + with open(state_file, "w") as f: + f.write(f"{now_rx} {now_tx} {now_ts}") + + # Build output + if rate_down and rate_up: + rate_str = f" ↓{rate_down} ↑{rate_up}" + tooltip_rate = f"↓ {rate_down}/s ↑ {rate_up}/s" + else: + rate_str = "" + tooltip_rate = "↓ ?/s ↑ ?/s" + + text = ( + f"{ICON}" + f" {iface} {ip}{rate_str}" + ) + tooltip = f"{itype}: {iface} — {ip} | {tooltip_rate}" + + print(json.dumps({"text": text, "tooltip": tooltip}, ensure_ascii=False)) + + +if __name__ == "__main__": + main() + diff --git a/.config/waybar/network.sh b/.config/waybar/network.sh new file mode 100755 index 0000000..4f6dd70 --- /dev/null +++ b/.config/waybar/network.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash + +# Get the default interface used for routing +INTERFACE=$(ip route 2>/dev/null | grep '^default' | awk '{print $5}' | head -1) + +if [ -z "$INTERFACE" ]; then + echo '{"text": "󰖪 No net", "tooltip": "No network connection"}' + exit 0 +fi + +# Get IPv4 address of the interface +IP=$(ip -4 addr show "$INTERFACE" 2>/dev/null | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -1) + +if [ -z "$IP" ]; then + echo '{"text": "󰖪 No IP", "tooltip": "Interface '"$INTERFACE"' has no IP"}' + exit 0 +fi + +# Determine interface type and set appropriate icon +if [[ "$INTERFACE" =~ ^(wlan|wlp) ]]; then + ICON="󰲝" # generic network icon (nerd font) + TYPE="WiFi" +elif [[ "$INTERFACE" =~ ^(eth|enp|eno|ens) ]]; then + ICON="󰲝" # generic network icon (nerd font) + TYPE="Ethernet" +else + ICON="󰲝" # generic network icon (nerd font) + TYPE="$INTERFACE" +fi + +# --- Transfer rate calculation --- + +# Path to sysfs statistics +RX_FILE="/sys/class/net/$INTERFACE/statistics/rx_bytes" +TX_FILE="/sys/class/net/$INTERFACE/statistics/tx_bytes" +STATE_FILE="/tmp/waybar-network-stats-$INTERFACE" + +# Read current byte counters +NOW_RX=$(cat "$RX_FILE" 2>/dev/null) +NOW_TX=$(cat "$TX_FILE" 2>/dev/null) +NOW_TS=$(date +%s%N) # nanoseconds for precision + +# Helper: format bytes/sec to human-readable +format_rate() { + local bytes_per_sec="$1" + if [ "$bytes_per_sec" -lt 0 ]; then + bytes_per_sec=0 + fi + if [ "$bytes_per_sec" -ge 1073741824 ]; then + awk -v n="$bytes_per_sec" 'BEGIN { printf "%.1fG", n / 1073741824 }' + elif [ "$bytes_per_sec" -ge 1048576 ]; then + awk -v n="$bytes_per_sec" 'BEGIN { printf "%.1fM", n / 1048576 }' + elif [ "$bytes_per_sec" -ge 1024 ]; then + awk -v n="$bytes_per_sec" 'BEGIN { printf "%.1fK", n / 1024 }' + else + awk -v n="$bytes_per_sec" 'BEGIN { printf "%.1fB", n }' + fi +} + +RATE_DOWN="" +RATE_UP="" + +if [ -f "$STATE_FILE" ]; then + # Read previous values: rx tx timestamp_ns + read -r PREV_RX PREV_TX PREV_TS < "$STATE_FILE" + + if [ -n "$PREV_RX" ] && [ -n "$PREV_TX" ] && [ -n "$PREV_TS" ]; then + # Calculate time delta in seconds (nanosecond difference) + DELTA_NS=$((NOW_TS - PREV_TS)) + if [ "$DELTA_NS" -gt 0 ]; then + DELTA_RX=$((NOW_RX - PREV_RX)) + DELTA_TX=$((NOW_TX - PREV_TX)) + + # bytes per second = delta_bytes / (delta_ns / 1e9) + RX_BPS=$(awk -v rx="$DELTA_RX" -v ns="$DELTA_NS" 'BEGIN { printf "%.0f", rx * 1000000000 / ns }') + TX_BPS=$(awk -v tx="$DELTA_TX" -v ns="$DELTA_NS" 'BEGIN { printf "%.0f", tx * 1000000000 / ns }') + + if [ -n "$RX_BPS" ] && [ -n "$TX_BPS" ]; then + RATE_DOWN=$(format_rate "$RX_BPS") + RATE_UP=$(format_rate "$TX_BPS") + fi + fi + fi +fi + +# Save current state for next run +echo "$NOW_RX $NOW_TX $NOW_TS" > "$STATE_FILE" + +# --- Build output --- + +if [ -n "$RATE_DOWN" ] && [ -n "$RATE_UP" ]; then + RATE_STR=" ↓${RATE_DOWN} ↑${RATE_UP}" +else + RATE_STR="" +fi + +echo "{\"text\": \"$ICON $INTERFACE $IP${RATE_STR}\", \"tooltip\": \"$TYPE: $INTERFACE — $IP | ↓ ${RATE_DOWN:-?}/s ↑ ${RATE_UP:-?}/s\"}" diff --git a/.config/waybar/style.css b/.config/waybar/style.css new file mode 100644 index 0000000..a9d2135 --- /dev/null +++ b/.config/waybar/style.css @@ -0,0 +1,77 @@ +* { + font-size: 13px; + font-family: monospace; +} + +window#waybar { + background: #282828; + color: #fbf1c7; +} + +#custom-right-arrow-dark, +#custom-left-arrow-dark { + color: #1d2021; +} +#custom-right-arrow-light, +#custom-left-arrow-light { + color: #282828; + background: #1d2021; +} + +#workspaces, +#window, +#clock.0, +#clock.2, +#clock.3, +#pulseaudio, +#memory, +#custom-top, +#battery, +#custom-disk, +#custom-network, +#tray { + background: #1d2021; +} + +#workspaces button { + padding: 0 2px; + color: #a89984; +} +#workspaces button.focused { + color: #fabd2f; + font-weight: bold; + /* border-bottom: 2px solid #fabd2f; */ +} +#workspaces button:hover { + box-shadow: inherit; + text-shadow: inherit; +} +#workspaces button:hover { + background: #1d2021; + border: #1d2021; + padding: 0 3px; +} + +/* Right-side widgets: lighter sandy yellow */ +#window, +#clock, +#pulseaudio, +#memory, +#custom-top, +#battery, +#custom-disk, +#custom-network, +#tray { + color: #f5d67b; +} + +#window, +#clock, +#pulseaudio, +#memory, +#custom-top, +#battery, +#custom-disk, +#custom-network { + padding: 0 10px; +} diff --git a/.config/waybar/top.sh b/.config/waybar/top.sh new file mode 100755 index 0000000..ae05501 --- /dev/null +++ b/.config/waybar/top.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +# Get the top CPU-consuming process, excluding kernel threads and this script +read -r NAME CPU < <( + ps -eo comm,pcpu --sort=-pcpu --no-headers 2>/dev/null | + awk '{ + # Skip kernel threads (names in brackets) + if ($1 ~ /^\[/) next + # Skip this script and ps itself + if ($1 == "top.sh" || $1 == "ps") next + # Output the first matching line and exit + print $1, $2 + exit + }' +) + +if [ -z "$NAME" ]; then + echo '{"text": " --", "tooltip": "No process data"}' + exit 0 +fi + +# Round CPU to integer +CPU=$(printf "%.0f" "$CPU") + +# Truncate long process names (keep bar readable) +if [ ${#NAME} -gt 10 ]; then + NAME="${NAME:0:9}…" +fi + +echo "{\"text\": \"󰍛 $NAME ${CPU}%\", \"tooltip\": \"Top CPU: $NAME — ${CPU}%\"}" diff --git a/.config/waybar/watch.sh b/.config/waybar/watch.sh new file mode 100755 index 0000000..4474036 --- /dev/null +++ b/.config/waybar/watch.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +while inotifywait -e close_write ~/.config/waybar; do + killall -SIGUSR2 waybar +done From 03d799581b56af1d58bb7ae2e39c5e13f69ca0b9 Mon Sep 17 00:00:00 2001 From: chodak166 Date: Thu, 18 Jun 2026 20:42:43 +0200 Subject: [PATCH 5/9] Updated waybar config --- .config/waybar/config.jsonc | 54 ++++--------------------------- .config/waybar/style.css | 64 +++++++++++-------------------------- 2 files changed, 25 insertions(+), 93 deletions(-) diff --git a/.config/waybar/config.jsonc b/.config/waybar/config.jsonc index 5d95ab3..2ff3b9d 100644 --- a/.config/waybar/config.jsonc +++ b/.config/waybar/config.jsonc @@ -6,52 +6,20 @@ "modules-left": [ "sway/workspaces", - "custom/right-arrow-dark" - ], - "modules-center": [ - "custom/left-arrow-dark", - "sway/window", - "custom/right-arrow-dark" + "sway/window" ], + "modules-center": [], "modules-right": [ - "custom/left-arrow-dark", "pulseaudio", - "custom/left-arrow-light", - "custom/left-arrow-dark", - "custom/network", - "custom/left-arrow-light", - "custom/left-arrow-dark", - "custom/disk", - "custom/left-arrow-light", - "custom/left-arrow-dark", + "custom/network", + "custom/disk", "memory", - "custom/left-arrow-light", - "custom/left-arrow-dark", "custom/top", - "custom/left-arrow-light", - "custom/left-arrow-dark", - "battery", - "custom/left-arrow-light", - "custom/left-arrow-dark", + "battery", "clock#0", - "custom/left-arrow-light", - "custom/left-arrow-dark", "tray" ], - "custom/left-arrow-dark": { - "format": "", - "tooltip": false - }, - "custom/left-arrow-light": { - "format": "", - "tooltip": false - }, - "custom/right-arrow-dark": { - "format": "", - "tooltip": false - }, - "sway/workspaces": { "disable-scroll": true, "format": "{name}" @@ -69,14 +37,6 @@ "tooltip": true }, - "clock#2": { - "format": "{:%H:%M}", - "tooltip": false - }, - "clock#3": { - "format": "{:%d/%m}", - "tooltip": false - }, "clock#0": { "format": "{:%H:%M %d/%m/%y}", "tooltip": false @@ -84,7 +44,7 @@ "pulseaudio": { "format": "{icon} {volume:2}%", - "format-bluetooth": "{icon} {volume}%", + "format-bluetooth": "{icon} {volume}%", "format-muted": "MUTE", "format-icons": { "headphones": "", @@ -99,7 +59,7 @@ }, "memory": { "interval": 5, - "format": " {}%" + "format": " {}%" }, "custom/top": { "exec": "~/.config/waybar/top.sh", diff --git a/.config/waybar/style.css b/.config/waybar/style.css index a9d2135..022196d 100644 --- a/.config/waybar/style.css +++ b/.config/waybar/style.css @@ -1,6 +1,6 @@ * { font-size: 13px; - font-family: monospace; + font-family: JetBrainsMono NFP; } window#waybar { @@ -8,21 +8,10 @@ window#waybar { color: #fbf1c7; } -#custom-right-arrow-dark, -#custom-left-arrow-dark { - color: #1d2021; -} -#custom-right-arrow-light, -#custom-left-arrow-light { - color: #282828; - background: #1d2021; -} - +/* All widgets share a stylized rounded background */ #workspaces, #window, -#clock.0, -#clock.2, -#clock.3, +#clock, #pulseaudio, #memory, #custom-top, @@ -31,47 +20,30 @@ window#waybar { #custom-network, #tray { background: #1d2021; + border-radius: 6px; + margin: 4px 3px; + padding: 0 10px; + color: #f5d67b; +} + +#tray { + padding: 0 6px; } +/* Workspaces: dimmed inactive, bold yellow active */ #workspaces button { - padding: 0 2px; + padding: 0 6px; color: #a89984; + background: transparent; + border-radius: 4px; } #workspaces button.focused { - color: #fabd2f; + color: #f5d67b; + background: transparent; font-weight: bold; - /* border-bottom: 2px solid #fabd2f; */ } #workspaces button:hover { box-shadow: inherit; text-shadow: inherit; -} -#workspaces button:hover { - background: #1d2021; - border: #1d2021; - padding: 0 3px; -} - -/* Right-side widgets: lighter sandy yellow */ -#window, -#clock, -#pulseaudio, -#memory, -#custom-top, -#battery, -#custom-disk, -#custom-network, -#tray { - color: #f5d67b; -} - -#window, -#clock, -#pulseaudio, -#memory, -#custom-top, -#battery, -#custom-disk, -#custom-network { - padding: 0 10px; + background: #32302f; } From 6914eaeacbdad4cbf6e4998cf31ef5caf473e682 Mon Sep 17 00:00:00 2001 From: chodak166 Date: Sat, 20 Jun 2026 20:08:39 +0200 Subject: [PATCH 6/9] Added sway configs; added tmux theme --- .config/nvim/lazy-lock.json | 19 +- .config/nvim/lua/plugins/colorscheme.lua | 68 +-- .config/sway/config | 610 +++++++++++++++++++++++ .config/sway/scripts/always-float | 11 + .config/sway/scripts/autoapp | 28 ++ .config/sway/scripts/backlight | 36 ++ .config/sway/scripts/gammastep-adjust | 101 ++++ .config/sway/scripts/output-profile | 44 ++ .config/sway/scripts/swayexit | 46 ++ .config/sway/scripts/translate-wl | 48 ++ .config/sway/scripts/volctl | 68 +++ .config/waybar/config.jsonc | 14 +- .config/waybar/disk.py | 16 +- .config/waybar/network.py | 13 +- .config/waybar/style.css | 4 + .local/bin/btswitch | 447 +++++++++++++++++ .tmux.d/tmux-gruvbox | 1 + 17 files changed, 1521 insertions(+), 53 deletions(-) create mode 100644 .config/sway/config create mode 100755 .config/sway/scripts/always-float create mode 100755 .config/sway/scripts/autoapp create mode 100755 .config/sway/scripts/backlight create mode 100755 .config/sway/scripts/gammastep-adjust create mode 100755 .config/sway/scripts/output-profile create mode 100755 .config/sway/scripts/swayexit create mode 100755 .config/sway/scripts/translate-wl create mode 100755 .config/sway/scripts/volctl create mode 100755 .local/bin/btswitch create mode 160000 .tmux.d/tmux-gruvbox diff --git a/.config/nvim/lazy-lock.json b/.config/nvim/lazy-lock.json index ec559f8..01bb543 100644 --- a/.config/nvim/lazy-lock.json +++ b/.config/nvim/lazy-lock.json @@ -1,6 +1,6 @@ { "LazyVim": { "branch": "main", "commit": "c10948c50b18fae7f256433afdef09e432410480" }, - "avante.nvim": { "branch": "main", "commit": "dee2402ed0b7c1d3710c0c8eed3d26aa055e118e" }, + "avante.nvim": { "branch": "main", "commit": "d9c33ebe1e7205f416796b5b383d6894abe47495" }, "blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" }, "bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" }, "catppuccin": { "branch": "main", "commit": "49a926655a2f5579e9c276470fc300baaa49e524" }, @@ -10,8 +10,9 @@ "dressing.nvim": { "branch": "master", "commit": "2d7c2db2507fa3c4956142ee607431ddb2828639" }, "flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" }, "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, - "gitsigns.nvim": { "branch": "main", "commit": "25050e4ed39e628282831d4cbecb1850454ce915" }, + "gitsigns.nvim": { "branch": "main", "commit": "2038c666bd9d8a0b7349a0b6ee00dc83104b9ecf" }, "grug-far.nvim": { "branch": "main", "commit": "c995bbacf8229dc096ec1c3d60f8531059c86c1b" }, + "hybrid-theme": { "branch": "main", "commit": "6ae348938376f345e02eea4e6c27c0874b05f33a" }, "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, "just-runner.nvim": { "branch": "main", "commit": "f29d405aa828900df242600720a2b0e57261489f" }, "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, @@ -19,20 +20,20 @@ "lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" }, "mason-lspconfig.nvim": { "branch": "main", "commit": "21c5b3ebeaa0412e28096bb0701434c51c1fbf76" }, "mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" }, - "mini.ai": { "branch": "main", "commit": "4511b3481707c1d021485475d34f2ed2a50bf47b" }, - "mini.files": { "branch": "main", "commit": "02874bc653fbecf2bee2c65441d0ebd09110f011" }, - "mini.icons": { "branch": "main", "commit": "ac38c983aed0a2bd32a65ca3e2348e12e58ca292" }, - "mini.pairs": { "branch": "main", "commit": "30cf2f01c4aaa2033db67376b9924fa2442c05d6" }, + "mini.ai": { "branch": "main", "commit": "d73c36349aa7b0bab5f77ad71701a1d42211a1df" }, + "mini.files": { "branch": "main", "commit": "a5689dae6b732955e33eec225b798d6815063179" }, + "mini.icons": { "branch": "main", "commit": "e56797f90192d81f1fda02e662fc3e8e3d775027" }, + "mini.pairs": { "branch": "main", "commit": "4a014143fcb4e9df26198ccb3ecff3b9e77a048c" }, "noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" }, "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, - "nvim-lint": { "branch": "master", "commit": "1ba49820a3c29ba6ab1b2dd441a63b3822c4e39b" }, - "nvim-lspconfig": { "branch": "master", "commit": "a683e0ddf0cf64c6cd689e18ffb480ade3c162b7" }, + "nvim-lint": { "branch": "master", "commit": "01c9842c089069ab497430159312b2c8868a4590" }, + "nvim-lspconfig": { "branch": "master", "commit": "bfcc0171a43f22afa61d927ffe9fcb6cb85dc99e" }, "nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" }, "nvim-treesitter-textobjects": { "branch": "main", "commit": "851e865342e5a4cb1ae23d31caf6e991e1c99f1e" }, "nvim-ts-autotag": { "branch": "main", "commit": "88c1453db4ba7dd24131086fe51fdf74e587d275" }, "persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" }, "plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" }, - "render-markdown.nvim": { "branch": "main", "commit": "5adf0895310c1904e5abfaad40a2baad7fe44a07" }, + "render-markdown.nvim": { "branch": "main", "commit": "f422cb5c6855f150e2ddcfaf44e7157b98b34f6a" }, "snacks.nvim": { "branch": "main", "commit": "882c996cf28183f4d63640de0b4c02ec886d01f2" }, "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, "tokyonight.nvim": { "branch": "main", "commit": "cdc07ac78467a233fd62c493de29a17e0cf2b2b6" }, diff --git a/.config/nvim/lua/plugins/colorscheme.lua b/.config/nvim/lua/plugins/colorscheme.lua index f81ac04..8394a72 100644 --- a/.config/nvim/lua/plugins/colorscheme.lua +++ b/.config/nvim/lua/plugins/colorscheme.lua @@ -13,39 +13,39 @@ -- } -- Local development: -return { - dir = "/home/chodak/src/git/nvim-hybrid-theme", - name = "hybrid-theme", - lazy = false, - priority = 1000, - config = function() - require("hybrid-theme").setup({ - theme = "dark", - transparent = false, - background_variant = "flat", - italics = { - comments = true, - keywords = false, - functions = false, - strings = false, - variables = false, - }, - }) - require("hybrid-theme").colorscheme() - end, -} - -- return { --- { --- "chodak166/nvim-hybrid-theme", --- name = "hybrid-theme", --- lazy = false, --- priority = 1000, --- config = function() --- require("hybrid-theme").setup({ --- background_variant = "semi_flat", --- }) --- require("hybrid-theme").colorscheme() --- end, --- }, +-- dir = "/home/chodak/src/git/nvim-hybrid-theme", +-- name = "hybrid-theme", +-- lazy = false, +-- priority = 1000, +-- config = function() +-- require("hybrid-theme").setup({ +-- theme = "dark", +-- transparent = false, +-- background_variant = "flat", +-- italics = { +-- comments = true, +-- keywords = false, +-- functions = false, +-- strings = false, +-- variables = false, +-- }, +-- }) +-- require("hybrid-theme").colorscheme() +-- end, -- } + +return { + { + "chodak166/nvim-hybrid-theme", + name = "hybrid-theme", + lazy = false, + priority = 1000, + config = function() + require("hybrid-theme").setup({ + background_variant = "semi_flat", + }) + require("hybrid-theme").colorscheme() + end, + }, +} diff --git a/.config/sway/config b/.config/sway/config new file mode 100644 index 0000000..fd901c1 --- /dev/null +++ b/.config/sway/config @@ -0,0 +1,610 @@ +#---------------------------------------------------------------- +# Sway Config — Arch + Wayland +# +# Migrated from i3/X11 config. All X11-specific tools have been +# replaced with Wayland-native equivalents (see migration notes +# throughout this file). +# +# Install script: arch-init.sh +#---------------------------------------------------------------- + + +################################################################# +# Variables +################################################################# + +# Mod key: Mod4 = Super/Windows key, Mod1 = Alt +set $mod Mod4 + +# Helper scripts directory (Wayland replacements for ratflow scripts) +set $scriptsDir ~/.config/sway/scripts + +# Config directory +set $configDir ~/.config/sway + + +################################################################# +# Workspaces +################################################################# + +set $workspace1 1: >_ +set $workspace2 2: dev +set $workspace3 3: www +set $workspace4 4: files +set $workspace5 5: e-mail +set $workspace6 6: IM +set $workspace7 7: video +set $workspace8 8: workspace +set $workspace9 9: workspace +set $workspace10 10: Music +set $workspace11 V: VM + +# Switch to workspace +bindsym $mod+1 workspace $workspace1 +bindsym $mod+2 workspace $workspace2 +bindsym $mod+3 workspace $workspace3 +bindsym $mod+4 workspace $workspace4 +bindsym $mod+5 workspace $workspace5 +bindsym $mod+6 workspace $workspace6 +bindsym $mod+7 workspace $workspace7 +bindsym $mod+8 workspace $workspace8 +bindsym $mod+9 workspace $workspace9 +bindsym $mod+0 workspace $workspace10 + +# Move focused container to workspace +bindsym $mod+Shift+1 move container to workspace $workspace1 +bindsym $mod+Shift+2 move container to workspace $workspace2 +bindsym $mod+Shift+3 move container to workspace $workspace3 +bindsym $mod+Shift+4 move container to workspace $workspace4 +bindsym $mod+Shift+5 move container to workspace $workspace5 +bindsym $mod+Shift+6 move container to workspace $workspace6 +bindsym $mod+Shift+7 move container to workspace $workspace7 +bindsym $mod+Shift+8 move container to workspace $workspace8 +bindsym $mod+Shift+9 move container to workspace $workspace9 +bindsym $mod+Shift+0 move container to workspace $workspace10 + +# Next/prev workspace +bindsym $mod+x workspace next +bindsym $mod+Shift+x move container to workspace next +bindsym $mod+z workspace prev +bindsym $mod+Shift+z move container to workspace prev + +# Moving workspace across monitors +# MIGRATION: xrandr replaced by swaymsg output commands +bindsym $mod+Control+Left move workspace to output left +bindsym $mod+Control+Right move workspace to output right + + +################################################################# +# Output / Monitor Management +# MIGRATION: xrandr → swaymsg output / kanshi for auto profiles +################################################################# + +# Define your outputs — run `swaymsg -t get_outputs` to get names +set $leftOutput eDP-1 +set $rightOutput HDMI-A-1 + +# Default monitor setup +# sway handles output layout natively, no xrandr needed +output $rightOutput pos 1920 0 +output $leftOutput pos 0 0 + +# Mode for toggling outputs (replaces i3 "outputs" mode) +mode "outputs" { + # $mod+Shift+1: turn off left monitor; $mod+1: turn it on + bindsym $mod+Shift+1 output $leftOutput disable; mode "default" + bindsym $mod+1 output $leftOutput enable; mode "default" + + # $mod+Shift+2: turn off right monitor; $mod+2: turn it on + bindsym $mod+Shift+2 output $rightOutput disable; mode "default" + bindsym $mod+2 output $rightOutput enable; mode "default" + + bindsym Return mode "default" + bindsym Escape mode "default" +} + +bindsym $mod+m mode "outputs" + + +################################################################# +# Wallpaper +# MIGRATION: feh → swaybg (Wayland-native wallpaper setter) +# Omarchy also uses swaybg for this purpose. +################################################################# + +set $wallpaper1 /usr/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png +set $wallpaper2 /usr/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png + +# swaybg is a native Wayland wallpaper setter +output $leftOutput bg $wallpaper1 fill +output $rightOutput bg $wallpaper2 fill + + +################################################################# +# Input Device Configuration +# MIGRATION: synclient → sway input {} blocks +# X11 touchpad/synaptics config replaced by libinput via sway. +################################################################# + +input "type:touchpad" { + tap enabled + click_method button_areas + scroll_method two_finger + dwt enabled + # natural_scroll enabled # uncomment if you prefer macOS-style scrolling +} + +input "type:keyboard" { + xkb_layout pl + # xkb_variant ... + # xkb_options caps:escape # uncomment to remap Caps Lock to Escape +} + + +################################################################# +# Application Launchers +# MIGRATION: ulauncher works on Wayland but is GTK-based. +# Alternatives: wofi (native), rofi-wayland, tofi. +# dmenu_run replaced by wofi (or keep as dmenu_path | wofi -d). +# Omarchy uses Walker — a modern Wayland-native launcher. +################################################################# + +# Terminal +bindsym $mod+Return exec kitty + +# App launcher: wofi (lightweight, Wayland-native) +# Alternatives: rofi -show drun (rofi-wayland package), tofi +bindsym $mod+d exec fuzzel +bindsym Mod1+F2 exec wofi --show run + +# Clipboard manager — show history (Ctrl+Alt+H) +# bindsym Control+Mod1+h exec copyq toggle +bindsym Control+Mod1+h exec cliphist list | fuzzel --width 80 --dmenu | cliphist decode | wl-copy + +# Run app assigned to current workspace +bindsym $mod+Shift+a exec $scriptsDir/autoapp + + +################################################################# +# Window Navigation +# MIGRATION: i3-msg workspace back_and_forth → same in sway +################################################################# + +bindsym $mod+Tab workspace back_and_forth + + +################################################################# +# Window Management +# MIGRATION: nearly identical to i3 — sway is i3-compatible +################################################################# + +# Use Mouse+$mod to drag floating windows +floating_modifier $mod + +# Kill focused window +bindsym $mod+Shift+q kill + +# Change focus (vim keys) +bindsym $mod+j focus left +bindsym $mod+k focus down +bindsym $mod+l focus up +bindsym $mod+semicolon focus right + +# Change focus (arrow keys) +bindsym $mod+Left focus left +bindsym $mod+Down focus down +bindsym $mod+Up focus up +bindsym $mod+Right focus right + +# Move focused window (vim keys) +bindsym $mod+Shift+j move left +bindsym $mod+Shift+k move down +bindsym $mod+Shift+l move up +bindsym $mod+Shift+semicolon move right + +# Move focused window (arrow keys) +bindsym $mod+Shift+Left move left +bindsym $mod+Shift+Down move down +bindsym $mod+Shift+Up move up +bindsym $mod+Shift+Right move right + +# Split orientation +bindsym $mod+h split h +bindsym $mod+v split v + +# Fullscreen +bindsym $mod+f fullscreen + +# Layout modes +bindsym $mod+s layout stacking +bindsym $mod+w layout tabbed +bindsym $mod+e layout toggle split + +# Toggle tiling / floating +bindsym $mod+Shift+space floating toggle +bindsym $mod+button2 floating toggle + +# Focus tiling/floating toggle +bindsym $mod+space focus mode_toggle + +# Focus parent container +bindsym $mod+a focus parent + +# Always-float toggle (custom script) +bindsym $mod+Shift+f exec $scriptsDir/always-float + + +################################################################# +# Resize Mode +################################################################# + +mode "resize" { + bindsym j resize shrink width 10 px or 10 ppt + bindsym k resize grow height 10 px or 10 ppt + bindsym l resize shrink height 10 px or 10 ppt + bindsym semicolon resize grow width 10 px or 10 ppt + + bindsym Left resize shrink width 10 px or 10 ppt + bindsym Down resize grow height 10 px or 10 ppt + bindsym Up resize shrink height 10 px or 10 ppt + bindsym Right resize grow width 10 px or 10 ppt + + bindsym Return mode "default" + bindsym Escape mode "default" +} + +bindsym $mod+r mode "resize" + + +################################################################# +# Screenshots +# MIGRATION: screengrab (X11) → grim + slurp (Wayland-native) +# grim = screen capture (replaces scrot/import/screengrab) +# slurp = region selector (Wayland-native) +# wl-copy copies to Wayland clipboard +# Omarchy also uses grim + slurp (+ satty for annotation). +################################################################# + +# Fullscreen screenshot → save to ~/Pictures and copy to clipboard +bindsym Print exec grim -t png ~/Pictures/screenshot_$(date +%Y%m%d_%H%M%S).png && grim -t png - | wl-copy -t image/png + +# Region screenshot → select area with slurp +bindsym Shift+Print exec grim -t png -g "$(slurp)" ~/Pictures/screenshot_$(date +%Y%m%d_%H%M%S).png && grim -t png -g "$(slurp)" - | wl-copy -t image/png + +# Active window screenshot (sway-specific: get focused window geometry) +bindsym Control+Print exec grim -t png -g "$(swaymsg -t get_tree | jq -j '.. | select(.type?) | select(.focused) | .rect | "\(.x),\(.y) \(.width)x\(.height)"')" ~/Pictures/screenshot_$(date +%Y%m%d_%H%M%S).png + + +################################################################# +# Calendar +# MIGRATION: osmo/gsimplecal (X11) → keep osmo if desired, +# or use waybar clock module + rofi/wofi calendar script. +# Omarchy uses waybar clock module only (no standalone calendar app). +################################################################# + +bindsym $mod+c exec osmo -c +# Alternative: wofi-based calendar popup +# bindsym $mod+c exec $scriptsDir/calendar-popup + + +################################################################# +# Screen Color Temperature +# MIGRATION: redshift (X11) → gammastep (Wayland fork of redshift) +# or wlsunset (lighter alternative). +# Omarchy uses hyprsunset (Hyprland-specific), but for sway +# gammastep is the standard choice. +# $scriptsDir/gammastep-adjust replaces redshift-adjust. +################################################################# + +bindsym $mod+Control+KP_Next exec $scriptsDir/gammastep-adjust "-500" +bindsym $mod+Control+KP_Prior exec $scriptsDir/gammastep-adjust "+500" +bindsym $mod+Control+l exec gammastep -x + + +################################################################# +# Translation of Selected Text +# MIGRATION: trans-xsel (X11 xsel) → translate-shell + wl-clipboard +# Uses wl-paste / wl-copy instead of xsel/xclip. +################################################################# + +bindsym $mod+t exec bash -c "$scriptsDir/translate-wl en:pl &" +bindsym $mod+Shift+t exec bash -c "$scriptsDir/translate-wl pl:en &" + + +################################################################# +# Multimedia Keys & Audio +# MIGRATION: PulseAudio volctl → PipeWire + wpctl (or pamixer) +# Arch + Wayland standard is PipeWire with WirePlumber. +# Volume OSD: SwayOSD (Omarchy approach) or swayosd-server. +# The $scriptsDir/volctl wrapper uses wpctl/pamixer underneath. +################################################################# + +# Volume controls (primary sink) +bindsym XF86AudioRaiseVolume exec --no-startup-id $scriptsDir/volctl up +bindsym XF86AudioLowerVolume exec --no-startup-id $scriptsDir/volctl down +bindsym XF86AudioMute exec --no-startup-id $scriptsDir/volctl toggle + +# Volume controls (secondary sink, e.g. HDMI) +bindsym Shift+XF86AudioRaiseVolume exec --no-startup-id SINK_NUM=1 $scriptsDir/volctl up +bindsym Shift+XF86AudioLowerVolume exec --no-startup-id SINK_NUM=1 $scriptsDir/volctl down +bindsym Shift+XF86AudioMute exec --no-startup-id SINK_NUM=1 $scriptsDir/volctl toggle + +# Screen brightness +# MIGRATION: xbacklight / ratflow-backlight → brightnessctl +bindsym XF86MonBrightnessUp exec --no-startup-id $scriptsDir/backlight up +bindsym XF86MonBrightnessDown exec --no-startup-id $scriptsDir/backlight down + +# Media player controls +# MIGRATION: clementine-specific → playerctl (agnostic MPRIS controller) +# playerctl works with any MPRIS2-compatible player (Spotify, mpv, etc.) +bindsym XF86AudioPlay exec playerctl play-pause +bindsym XF86AudioPause exec playerctl pause +bindsym XF86AudioNext exec playerctl next +bindsym XF86AudioPrev exec playerctl previous + + +################################################################# +# Projector / Screen Layout +# MIGRATION: xrandr shell scripts → swaymsg output commands +# kanshi can auto-switch profiles on hotplug. +################################################################# + +bindsym $mod+p exec $scriptsDir/output-profile projector +bindsym $mod+Shift+p exec $scriptsDir/output-profile edp-only + + +################################################################# +# Session / Power Management +# MIGRATION: i3-nagbar → swaynag, i3exit → loginctl-based script +# swayidle handles DPMS/idle (replaces xset dpms). +# swaylock replaces i3lock. +# Omarchy uses hyprlock+hypridle, sway equivalents are swaylock+swayidle. +################################################################# + +# Reload sway config +bindsym $mod+Shift+c exec swaymsg reload + +# Suspend +bindsym $mod+Escape exec systemctl suspend + +# Restart sway +bindsym $mod+Shift+r exec swaymsg reload + +# Exit sway +bindsym $mod+Shift+e exec swaynag -t warning -m 'Exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit' + +# Session management mode (replaces i3exit) +set $exitScript $scriptsDir/swayexit + +mode "session_management" { + bindsym l exec --no-startup-id $exitScript lock, mode "default" + bindsym e exec --no-startup-id $exitScript logout, mode "default" + bindsym s exec --no-startup-id $exitScript suspend, mode "default" + bindsym h exec --no-startup-id $exitScript hibernate, mode "default" + bindsym r exec --no-startup-id $exitScript reboot, mode "default" + bindsym Shift+s exec --no-startup-id $exitScript shutdown, mode "default" + + bindsym Return mode "default" + bindsym Escape mode "default" +} + +bindsym $mod+Pause mode "session_management" + + +################################################################# +# New Workspace +# MIGRATION: yad → zenity (or rofi/wofi) +# yad has some Wayland issues; zenity is GTK and works. +# Alternatively, use wofi for a pure Wayland input dialog. +################################################################# + +bindsym $mod+n exec name=$(wofi --dmenu --prompt "Workspace name") && swaymsg workspace "$name" + + +################################################################# +# Theme / Appearance +# MIGRATION: No i3 client colors — sway has the same syntax. +# compton → not needed (sway has built-in compositor with +# basic effects). For blur/shadows, use swayfx (fork of sway). +# Omarchy uses Hyprland which has built-in blur/animation; +# for sway, swayfx adds these features. +################################################################# + +# Font +set $fontName "Source Sans 3 Semi-Bold" +set $fontSize 10 +set $barFontSize 9 + +font pango: $fontName $fontSize + +# Window colors +# border background text indicator +client.focused #252525 #252525 #D9D9D9 #101010 +client.focused_inactive #101010 #101010 #606060 #101010 +client.unfocused #101010 #000000 #606060 #101010 +client.urgent #F05000 #F05000 #F0F0F0 #101010 + +# Default border style +default_border pixel 2 +default_floating_border normal 2 + +# Gaps (optional — sway supports gaps natively, unlike stock i3) +# gaps inner 5 +# gaps outer 2 + +# Window opacity (requires swayfx for per-window opacity, or use +# sway's built-in opacity for all windows) +# for_window [app_id="kitty"] opacity 0.95 + + +################################################################# +# Bar — Waybar +# MIGRATION: i3bar + py3status → waybar +# waybar is the standard bar for wlroots-based compositors. +# Omarchy uses waybar with extensive modules. +# Config files: ~/.config/waybar/config.jsonc + style.css +################################################################# + +bar { + swaybar_command waybar +} + + +################################################################# +# Window Assignments +# MIGRATION: class= → app_id= for native Wayland apps. +# XWayland apps still use class=. Use `swaymsg -t get_tree` +# to find the correct app_id for native Wayland apps. +# Note: some apps may need both rules. +################################################################# + +# Development +assign [app_id="qtcreator"] $workspace2 +assign [class="Qtcreator"] $workspace2 +assign [app_id="eclipse"] $workspace2 +assign [class="Eclipse"] $workspace2 + +# Browser +assign [app_id="firefox"] $workspace3 +assign [class="Firefox"] $workspace3 +assign [app_id="chromium"] $workspace3 +assign [class="Chromium-browser"] $workspace3 +assign [class="Chrome"] $workspace3 + +# File managers +assign [app_id="pcmanfm-qt"] $workspace4 +assign [class="Pcmanfm"] $workspace4 +assign [app_id="dolphin"] $workspace4 +assign [class="Dolphin"] $workspace4 +assign [app_id="nautilus"] $workspace4 +assign [class="Nautilus"] $workspace4 +assign [app_id="thunar"] $workspace4 +assign [class="Thunar"] $workspace4 + +# E-mail +assign [app_id="thunderbird"] $workspace5 +assign [class="Thunderbird"] $workspace5 + +# IM +assign [app_id="telegram-desktop"] $workspace6 +assign [class="Telegram"] $workspace6 +assign [class="Skype"] $workspace6 + +# Video +assign [app_id="kodi"] $workspace7 +assign [class="Kodi"] $workspace7 + +# Music +assign [app_id="spotify"] $workspace10 +assign [class="Spotify"] $workspace10 +assign [class="Clementine"] $workspace10 + +# VM +assign [class="VirtualBox"] $workspace11 +assign [app_id="virt-manager"] $workspace11 + + +################################################################# +# Floating Windows +################################################################# + +for_window [app_id="screengrab"] floating enable +for_window [app_id="osmo"] floating enable +for_window [app_id="gsimplecal"] floating enable +for_window [class="Osmo"] floating enable +for_window [class="Skype"] floating enable +for_window [app_id="yad"] floating enable +for_window [class="Yad"] floating enable +for_window [app_id="wofi"] floating enable +for_window [app_id="swaync"] floating enable + + +################################################################# +# Idle Management +# MIGRATION: xset dpms → swayidle +# Locks screen after timeout, turns off display. +# Omarchy uses hypridle; sway equivalent is swayidle. +################################################################# + +set $lockCommand swaylock -f -c 000000 + +exec swayidle -w \ + timeout 600 '$lockCommand' \ + timeout 900 'swaymsg "output * dpms off"' \ + resume 'swaymsg "output * dpms on"' \ + before-sleep '$lockCommand' + + +################################################################# +# Autostart +# MIGRATION NOTES: +# dunst → mako (Wayland-native notifier, used by Omarchy) +# or swaync (Sway Notification Center, more feature-rich) +# compton → NOT NEEDED (sway has built-in compositor) +# For blur/rounded corners, use swayfx +# synclient → sway input {} block (see above) +# redshift → gammastep or wlsunset +# nm-applet → nm-applet still works on Wayland, or use +# waybar network module + impala TUI (Omarchy approach) +# parcellite → cliphist + wl-clipboard (Wayland clipboard manager) +# cliphist stores history, wl-copy/wl-paste for access +# xset dpms → swayidle (see above) +################################################################# + +# Notification daemon — mako (Omarchy uses mako) +exec --no-startup-id mako + +# Alternative: swaync (Sway Notification Center) — more feature-rich +# exec --no-startup-id swaync + +# Screen color temperature +exec --no-startup-id gammastep -l 52.43:15.15 -m wayland + +# Network manager applet (still works on Wayland) +exec --no-startup-id nm-applet --indicator + +# Clipboard manager +# Use Ctrl+Alt+H to toggle the clipboard history window +# exec --no-startup-id wl-paste --watch --type image cliphist store +exec --no-startup-id wl-paste --type text --watch cliphist store +exec --no-startup-id wl-paste --type image --watch cliphist store + +# Bluetooth manager (waybar module can handle this, or use blueman-applet) +# exec --no-startup-id blueman-applet + +# Polkit authentication agent (needed for GUI apps that need root) +exec --no-startup-id /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 + +# Background services for XDG desktop portals (screen sharing, file picker) +exec --no-startup-id dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway + + +################################################################# +# Key repeat rate +################################################################# + +# input "type:keyboard" { +# xkb_layout pl +# # xkb_variant "programmer" +# xkb_options "grp:alt_shift_toggle, compose:ralt" +# repeat_delay 300 +# repeat_rate 40 +# } +# input type:keyboard { xkb_layout pl xkb_options grp:win_space_toggle } + +# input type:keyboard { +# xkb_layout pl +# xkb_options level3:ralt_switch +# } + +# input type:keyboard { +# xkb_layout pl +# xkb_options grp:alt_shift_toggle +# } + +input type:keyboard { + xkb_layout pl,us + # lv3:ralt_switch keeps Right Alt working for Polish chars + # grp:alt_shift_toggle allows Alt+Shift to switch layouts + xkb_options lv3:ralt_switch,grp:alt_shift_toggle +} diff --git a/.config/sway/scripts/always-float b/.config/sway/scripts/always-float new file mode 100755 index 0000000..5a01c8a --- /dev/null +++ b/.config/sway/scripts/always-float @@ -0,0 +1,11 @@ +#!/bin/bash +#---------------------------------------------------------------- +# always-float — Toggle floating on the currently focused window +# +# Adapted from the ratflow always-float script. +# Uses swaymsg instead of i3-msg. +# +# Dependencies: sway +#---------------------------------------------------------------- + +swaymsg floating toggle diff --git a/.config/sway/scripts/autoapp b/.config/sway/scripts/autoapp new file mode 100755 index 0000000..f760fe4 --- /dev/null +++ b/.config/sway/scripts/autoapp @@ -0,0 +1,28 @@ +#!/bin/bash +#---------------------------------------------------------------- +# autoapp — Launch the application assigned to current workspace +# +# Adapted from the ratflow autoapp script. +# Reads workspace assignments and launches the matching app. +# Uses swaymsg instead of i3-msg. +# +# Dependencies: sway, jq +#---------------------------------------------------------------- + +# Get current workspace name +WORKSPACE=$(swaymsg -t get_workspaces | jq -r '.[] | select(.focused) | .name') + +# Map workspace names to applications +# Customize these to match your workflow +case "$WORKSPACE" in + *">_"*) kitty ;; + *"dev"*) kitty ;; + *"www"*) firefox ;; + *"files"*) thunar ;; + *"e-mail"*) thunderbird ;; + *"IM"*) telegram-desktop ;; + *"video"*) mpv ;; + *"Music"*) spotify ;; + *"VM"*) virt-manager ;; + *) echo "No app assigned to workspace: $WORKSPACE" ;; +esac diff --git a/.config/sway/scripts/backlight b/.config/sway/scripts/backlight new file mode 100755 index 0000000..5c9279d --- /dev/null +++ b/.config/sway/scripts/backlight @@ -0,0 +1,36 @@ +#!/bin/bash +#---------------------------------------------------------------- +# backlight — Screen brightness control using brightnessctl +# +# Replaces the old ratflow backlight script (xbacklight-based). +# brightnessctl works on Wayland without X11 dependencies. +# +# Usage: +# backlight up — increase brightness by 5% +# backlight down — decrease brightness by 5% +# backlight set N — set brightness to N percent +# backlight get — print current brightness percentage +# +# Dependencies: brightnessctl +#---------------------------------------------------------------- + +STEP=5 + +case "$1" in + up) + brightnessctl set "${STEP}%+" -q + ;; + down) + brightnessctl set "${STEP}%-" -q + ;; + set) + brightnessctl set "${2}%" -q + ;; + get) + brightnessctl info | grep -oP '\d+%' | head -1 | tr -d '%' + ;; + *) + echo "Usage: backlight {up|down|set N|get}" + exit 1 + ;; +esac diff --git a/.config/sway/scripts/gammastep-adjust b/.config/sway/scripts/gammastep-adjust new file mode 100755 index 0000000..eddd412 --- /dev/null +++ b/.config/sway/scripts/gammastep-adjust @@ -0,0 +1,101 @@ +#!/bin/bash +#---------------------------------------------------------------- +# gammastep-adjust — Adjust gammastep color temperature +# +# Replaces the old ratflow redshift-adjust script. +# gammastep is the Wayland fork of redshift; it uses the same +# temperature range (1000K–25000K, default 6500K = daylight). +# +# Usage: +# gammastep-adjust -100 — make screen warmer (lower temperature by 100K) +# gammastep-adjust +100 — make screen cooler (raise temperature by 100K) +# +# How it works: +# gammastep doesn't support runtime temperature changes directly. +# This script writes the current temperature to a state file, +# kills any running gammastep, and launches a new one in one-shot +# mode (-O) with the new temperature. +# +# State file: /tmp/gammastep-current-temp +# PID file: /tmp/gammastep-pid +# Default: 6500 (neutral/daylight) +# +# Dependencies: gammastep +#---------------------------------------------------------------- +set -x + +STATE_FILE="/tmp/gammastep-current-temp" +PID_FILE="/tmp/gammastep-pid" +DEFAULT_TEMP=6500 +MIN_TEMP=1000 +MAX_TEMP=25000 + +# Read current temperature or use default +if [ -f "$STATE_FILE" ]; then + CURRENT=$(cat "$STATE_FILE") +else + CURRENT=$DEFAULT_TEMP +fi + +# Parse argument +DELTA="${1:-0}" +# Strip the sign to get the absolute value +ABS_DELTA="${DELTA#+}" +ABS_DELTA="${ABS_DELTA#-}" + +if [ -z "$ABS_DELTA" ]; then + echo "Usage: gammastep-adjust <+/-N>" + echo " Example: gammastep-adjust -100 (warmer)" + echo " Example: gammastep-adjust +100 (cooler)" + exit 1 +fi + +# Calculate new temperature +NEW_TEMP=$((CURRENT + DELTA)) + +# Clamp to valid range +if [ "$NEW_TEMP" -lt "$MIN_TEMP" ]; then + NEW_TEMP=$MIN_TEMP +fi +if [ "$NEW_TEMP" -gt "$MAX_TEMP" ]; then + NEW_TEMP=$MAX_TEMP +fi + +# Save new state +echo "$NEW_TEMP" >"$STATE_FILE" + +# Kill existing gammastep instance(s) +# Priority 1: use PID file if available (most precise) +if [ -f "$PID_FILE" ]; then + OLD_PID=$(cat "$PID_FILE") + if kill -0 "$OLD_PID" 2>/dev/null; then + kill "$OLD_PID" 2>/dev/null + # Give gammastep a moment to release the display and exit + sleep 0.2 + fi + rm -f "$PID_FILE" +fi + +# Priority 2: kill any stray gammastep processes +# -x (exact match) ensures we don't kill this script (gammastep-adjust) +pkill -x gammastep 2>/dev/null +sleep 0.1 + +# Launch gammastep with the new temperature. +# +# IMPORTANT: We use "setsid" (create a new session) so that gammastep is +# completely detached from the shell that Sway spawns for this keybinding. +# Without setsid, Sway kills gammastep when the keybinding shell exits, +# even with "&" — because the process is still in the same process group. +# setsid makes gammastep its own session leader, immune to cleanup. +# if [ "$NEW_TEMP" -ge "$DEFAULT_TEMP" ]; then +# # At or above neutral — reset to no tint +# setsid gammastep -x 2>/dev/null & +# echo $! >"$PID_FILE" +# echo "Temperature reset to neutral ($DEFAULT_TEMP K)" +# else +# Below neutral — apply one-shot manual temperature +setsid gammastep -O "$NEW_TEMP" 2>/dev/null & +echo $! >"$PID_FILE" +echo "Temperature set to $NEW_TEMP K" +# fi diff --git a/.config/sway/scripts/output-profile b/.config/sway/scripts/output-profile new file mode 100755 index 0000000..9bebb94 --- /dev/null +++ b/.config/sway/scripts/output-profile @@ -0,0 +1,44 @@ +#!/bin/bash +#---------------------------------------------------------------- +# output-profile — Switch sway output profiles +# +# Replaces xrandr shell scripts used in the old i3 config. +# Uses swaymsg output commands to configure displays. +# +# Usage: +# output-profile projector — enable HDMI output (mirror or extend) +# output-profile edp-only — disable all external outputs +# output-profile dual — dual monitor setup +# +# Dependencies: sway +# +# NOTE: Edit the output names to match your hardware. +# Run `swaymsg -t get_outputs` to list connected outputs. +#---------------------------------------------------------------- + +# Output names — adjust to match your hardware +LAPTOP="eDP-1" +EXTERNAL="HDMI-A-1" + +case "$1" in + projector) + # Enable external output, mirror the laptop display + swaymsg output "$EXTERNAL" enable pos 0 0 + swaymsg output "$LAPTOP" pos 0 0 + ;; + edp-only) + # Disable external output, laptop only + swaymsg output "$EXTERNAL" disable + ;; + dual) + # Dual monitor: laptop left, external right + swaymsg output "$LAPTOP" pos 0 0 + swaymsg output "$EXTERNAL" pos 1920 0 + ;; + *) + echo "Usage: output-profile {projector|edp-only|dual}" + echo " Edit this script to match your output names." + echo " Run 'swaymsg -t get_outputs' to list connected outputs." + exit 1 + ;; +esac diff --git a/.config/sway/scripts/swayexit b/.config/sway/scripts/swayexit new file mode 100755 index 0000000..ad2237b --- /dev/null +++ b/.config/sway/scripts/swayexit @@ -0,0 +1,46 @@ +#!/bin/bash +#---------------------------------------------------------------- +# swayexit — Session management for sway on Wayland +# +# Replaces the old i3exit script (i3/X11-based). +# Uses loginctl for session management (systemd-logind). +# +# Usage: +# swayexit lock — lock the screen (swaylock) +# swayexit logout — exit sway +# swayexit suspend — suspend to RAM +# swayexit hibernate — suspend to disk +# swayexit reboot — reboot the system +# swayexit shutdown — power off the system +# +# Dependencies: swaylock, systemd (loginctl) +#---------------------------------------------------------------- + +case "$1" in + lock) + swaylock -f -c 000000 + ;; + logout) + swaymsg exit + ;; + suspend) + swaylock -f -c 000000 & + sleep 0.5 + systemctl suspend + ;; + hibernate) + swaylock -f -c 000000 & + sleep 0.5 + systemctl hibernate + ;; + reboot) + systemctl reboot + ;; + shutdown) + systemctl poweroff + ;; + *) + echo "Usage: swayexit {lock|logout|suspend|hibernate|reboot|shutdown}" + exit 1 + ;; +esac diff --git a/.config/sway/scripts/translate-wl b/.config/sway/scripts/translate-wl new file mode 100755 index 0000000..527bf43 --- /dev/null +++ b/.config/sway/scripts/translate-wl @@ -0,0 +1,48 @@ +#!/bin/bash +#---------------------------------------------------------------- +# translate-wl — Translate selected text using translate-shell +# with Wayland clipboard (wl-clipboard) +# +# Replaces the old ratflow trans-xsel script (X11 xsel-based). +# Uses wl-paste to get clipboard content and wl-copy to write +# the translation back, plus a notification via notify-send +# (which works with mako/swaync on Wayland). +# +# Usage: +# translate-wl en:pl — translate English to Polish +# translate-wl pl:en — translate Polish to English +# translate-wl de:en — translate German to English, etc. +# +# Workflow: +# 1. Select text (it goes to Wayland primary/clipboard) +# 2. Press the bound key (e.g. $mod+t) +# 3. Script reads selection via wl-paste, translates, +# shows notification, and copies result to clipboard +# +# Dependencies: translate-shell (trans), wl-clipboard, libnotify +#---------------------------------------------------------------- + +LANG_PAIR="${1:-en:pl}" + +# Get clipboard content (user should select text first) +# wl-paste gets the clipboard content; for primary selection use wl-paste -p +TEXT=$(wl-paste -p 2>/dev/null || wl-paste 2>/dev/null) + +if [ -z "$TEXT" ]; then + notify-send -t 3000 "Translation" "No text in clipboard/selection" + exit 1 +fi + +# Translate using translate-shell +RESULT=$(trans -b "$LANG_PAIR" "$TEXT" 2>/dev/null) + +if [ -z "$RESULT" ]; then + notify-send -t 3000 "Translation" "Translation failed" + exit 1 +fi + +# Copy result to clipboard +echo -n "$RESULT" | wl-copy + +# Show notification +notify-send -t 5000 "Translation ($LANG_PAIR)" "$RESULT" diff --git a/.config/sway/scripts/volctl b/.config/sway/scripts/volctl new file mode 100755 index 0000000..39a1a03 --- /dev/null +++ b/.config/sway/scripts/volctl @@ -0,0 +1,68 @@ +#!/bin/bash +#---------------------------------------------------------------- +# volctl — Volume control wrapper for PipeWire + WirePlumber +# +# Replaces the old ratflow volctl (PulseAudio-based). +# Uses wpctl (WirePlumber CLI) for volume management. +# +# Usage: +# volctl up — increase volume by 5% +# volctl down — decrease volume by 5% +# volctl toggle — toggle mute on default sink +# volctl mute — mute default sink +# volctl unmute — unmute default sink +# +# Environment: +# SINK_NUM — if set, selects Nth sink (0=default, 1=next, etc.) +# mirrors the old VOLCTL_SINK_NUM behavior +# +# Dependencies: wireplumber, wpctl, pipewire, pipewire-pulse +#---------------------------------------------------------------- + +STEP=5 + +# Resolve which sink to use based on SINK_NUM (like old VOLCTL_SINK_NUM) +# SINK_NUM=0 or unset → default sink, SINK_NUM=1 → second sink, etc. +get_sink_id() { + local num="${SINK_NUM:-0}" + if [ "$num" = "0" ]; then + echo "@DEFAULT_AUDIO_SINK@" + else + # List sinks and pick the Nth one (1-indexed in SINK_NUM) + local sinks + sinks=$(wpctl status | grep -A 100 'Audio' | grep -A 100 'Sinks:' | grep -oP '\d+\.' | head -n $((num + 1)) | tail -1 | tr -d '.') + if [ -z "$sinks" ]; then + echo "@DEFAULT_AUDIO_SINK@" + else + echo "$sinks" + fi + fi +} + +SINK=$(get_sink_id) + +case "$1" in + up) + wpctl set-volume -l 1.5 "$SINK" "${STEP}%+" + ;; + down) + wpctl set-volume "$SINK" "${STEP}%-" + ;; + toggle) + wpctl set-mute "$SINK" toggle + ;; + mute) + wpctl set-mute "$SINK" 1 + ;; + unmute) + wpctl set-mute "$SINK" 0 + ;; + *) + echo "Usage: volctl {up|down|toggle|mute|unmute}" + echo " Set SINK_NUM env var to select sink (0=default, 1=second, etc.)" + exit 1 + ;; +esac + +# Optional: send signal to waybar to update volume display +# pkill -SIGRTMIN+1 waybar diff --git a/.config/waybar/config.jsonc b/.config/waybar/config.jsonc index 2ff3b9d..4de92dc 100644 --- a/.config/waybar/config.jsonc +++ b/.config/waybar/config.jsonc @@ -31,20 +31,20 @@ }, "custom/network": { - "exec": "/home/chodak/.config/waybar/network.py", + "exec": "/home/chodak/.config/waybar/network.py --icon-size 12pt", "interval": 10, "return-type": "json", "tooltip": true }, "clock#0": { - "format": "{:%H:%M %d/%m/%y}", + "format": "{:%d/%m/%y %H:%M}", "tooltip": false }, "pulseaudio": { - "format": "{icon} {volume:2}%", - "format-bluetooth": "{icon} {volume}%", + "format": "{icon} {volume:2}%", + "format-bluetooth": "{icon} {volume}%", "format-muted": "MUTE", "format-icons": { "headphones": "", @@ -59,7 +59,7 @@ }, "memory": { "interval": 5, - "format": " {}%" + "format": " {}%" }, "custom/top": { "exec": "~/.config/waybar/top.sh", @@ -73,7 +73,7 @@ "warning": 30, "critical": 15 }, - "format": "{icon} {capacity}%", + "format": "{icon} {capacity}%", "format-icons": [ "", "", @@ -83,7 +83,7 @@ ] }, "custom/disk": { - "exec": "/home/chodak/.config/waybar/disk.py", + "exec": "/home/chodak/.config/waybar/disk.py --icon-size 10pt", "interval": 30, "return-type": "json", "tooltip": true, diff --git a/.config/waybar/disk.py b/.config/waybar/disk.py index dab4761..d58347c 100755 --- a/.config/waybar/disk.py +++ b/.config/waybar/disk.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 """Waybar disk module: shows disk usage across all mounted partitions.""" +import argparse import json import os @@ -17,6 +18,15 @@ COLOR_LOW = "#a6e3a1" # green — < 70% COLOR_MID = "#f9e2af" # yellow — 70–89% COLOR_HIGH = "#f38ba8" # red — ≥ 90% +DEFAULT_ICON_SIZE = "24pt" + + +def parse_args(): + p = argparse.ArgumentParser() + p.add_argument("--icon-size", default=DEFAULT_ICON_SIZE, + help="Icon size (Pango size, e.g. 24pt)") + return p.parse_args() + def _pct_color(pct: float) -> str: """Return a Pango color string for the given usage percentage.""" @@ -87,6 +97,8 @@ def fmt_size(bytes_val): def main(): + args = parse_args() + isize = args.icon_size partitions = get_partitions() if not partitions: @@ -137,11 +149,11 @@ def main(): bar_icon = "⚠" if root_pct >= 90 else "" bar_color = _pct_color(root_pct) bar_text = ( - f"{bar_icon}" + f"{bar_icon}" f" {_span(bar_color, f'{root_pct:.0f}%')}" ) elif tooltip_lines: - bar_text = f" —" + bar_text = f" —" else: bar_text = " —" diff --git a/.config/waybar/network.py b/.config/waybar/network.py index dc67b1a..2d96771 100755 --- a/.config/waybar/network.py +++ b/.config/waybar/network.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 """Waybar network module: shows interface, IP, and up/down transfer rate.""" +import argparse import json import os import re @@ -10,6 +11,7 @@ import time STATE_FILE_TMPL = "/tmp/waybar-network-stats-{}" ICON = "󰲝" # nerd font network icon NO_NET_ICON = "󰖪" +DEFAULT_ICON_SIZE = "24pt" def run(cmd: list[str]) -> str: @@ -62,7 +64,16 @@ def format_rate(bps: float) -> str: return f"{bps:.1f}B" +def parse_args(): + p = argparse.ArgumentParser() + p.add_argument("--icon-size", default=DEFAULT_ICON_SIZE, + help="Icon size (Pango size, e.g. 24pt)") + return p.parse_args() + + def main() -> None: + args = parse_args() + isize = args.icon_size iface = get_default_interface() if iface is None: print(json.dumps( @@ -127,7 +138,7 @@ def main() -> None: tooltip_rate = "↓ ?/s ↑ ?/s" text = ( - f"{ICON}" + f"{ICON}" f" {iface} {ip}{rate_str}" ) tooltip = f"{itype}: {iface} — {ip} | {tooltip_rate}" diff --git a/.config/waybar/style.css b/.config/waybar/style.css index 022196d..c1fca7b 100644 --- a/.config/waybar/style.css +++ b/.config/waybar/style.css @@ -30,6 +30,10 @@ window#waybar { padding: 0 6px; } +#pulseaudio.bluetooth { + color: #89b4fa; +} + /* Workspaces: dimmed inactive, bold yellow active */ #workspaces button { padding: 0 6px; diff --git a/.local/bin/btswitch b/.local/bin/btswitch new file mode 100755 index 0000000..f4a11f8 --- /dev/null +++ b/.local/bin/btswitch @@ -0,0 +1,447 @@ +#!/usr/bin/env bash +set -u + +# ------------------------------------------------- +# CONFIGURATION +# ------------------------------------------------- +WIFI_5G="cintra-5g" +WIFI_24G="cintra-5g" + +declare -A BT_DEVICES +BT_DEVICES[TAH8506]="00:1E:7C:CA:77:00" +BT_DEVICES[SHB7150]="00:1E:7C:30:F3:69" +BT_DEVICES[HD450BT]="00:16:94:33:91:51" +BT_DEVICES[XTREME]="41:42:5D:FA:26:0A" # BT Speaker +BT_DEVICES[EM03]="F1:5A:D5:16:57:9D" # BT Speaker/powerbank +BT_DEVICES[X5]="47:0D:FF:C9:62:E1" # Bone Headphones thinkplus-X5 + +BT_AUTO_DEVICES=("TAH8506" "SHB7150") + +BT_SERVICE="bluetooth" +BT_RETRIES=6 +BT_DELAY=3 + +# Polkit rule that lets the current user start/stop bluetooth.service +# without a password, so this script runs sudo-free. Installed on first +# run via ensure_polkit_rule(). +BT_POLKIT_RULE_FILE="/etc/polkit-1/rules.d/49-btswitch.rules" +# Sentinel file to track that the rule was installed, since the user +# may not have read/execute access to the polkit rules directory. +BT_POLKIT_SENTINEL="$HOME/.config/btswitch/.polkit_rule_installed" + +# ------------------------------------------------- +# HELPERS +# ------------------------------------------------- + +wifi_switch_needed() { + [[ -n "$1" && -n "$2" && "$1" != "$2" ]] +} + +ensure_polkit_rule() { + if [[ -f "$BT_POLKIT_SENTINEL" ]]; then + return 0 + fi + + cat >&2 << EOF + +NOTE: This script needs to start/stop the bluetooth service, which normally +requires root. A one-time polkit rule can be installed so "$USER" can do this +without sudo. You will be prompted for your password once to write: + + $BT_POLKIT_RULE_FILE + +EOF + read -r -p "Install the polkit rule now? [y/N] " answer + case "$answer" in + y | Y | yes | YES) ;; + *) + echo "Skipping. The script cannot control bluetooth.service without it." >&2 + return 1 + ;; + esac + + local tmpfile + tmpfile=$(mktemp) || return 1 + + cat > "$tmpfile" << POLKIT +// Allow user "$USER" to start/stop bluetooth.service without a password. +// Generated by btswitch on $(date -Is). +polkit.addRule(function(action, subject) { + if (action.id === "org.freedesktop.systemd1.manage-units" && + subject.user === "$USER") { + try { + var unit = action.lookup("unit"); + if (unit === "$BT_SERVICE.service") { + return polkit.Result.YES; + } + } catch (e) {} + } +}); +POLKIT + + sudo cp "$tmpfile" "$BT_POLKIT_RULE_FILE" || { + echo "ERROR: Failed to write $BT_POLKIT_RULE_FILE." >&2 + rm -f "$tmpfile" + return 1 + } + rm -f "$tmpfile" + + sudo chown root:polkitd "$BT_POLKIT_RULE_FILE" 2>/dev/null \ + || sudo chown root:root "$BT_POLKIT_RULE_FILE" + sudo chmod 644 "$BT_POLKIT_RULE_FILE" + + mkdir -p "$(dirname "$BT_POLKIT_SENTINEL")" + touch "$BT_POLKIT_SENTINEL" + + echo "✔ Installed polkit rule: $BT_POLKIT_RULE_FILE" >&2 + echo " (polkitd picks it up automatically; no restart needed.)" >&2 + return 0 +} + +systemctl_bt() { + ensure_polkit_rule || { + echo "ERROR: Cannot control bluetooth.service without the polkit rule." >&2 + echo "Run 'sudo systemctl $* $BT_SERVICE' manually, or re-run this script and install the rule." >&2 + exit 1 + } + if ! systemctl "$@" "$BT_SERVICE"; then + echo "ERROR: systemctl $* $BT_SERVICE failed." >&2 + echo "If polkit prompted for a password, the rule file may be missing." >&2 + echo "Remove $BT_POLKIT_SENTINEL and re-run to reinstall it." >&2 + exit 1 + fi +} + +bt_info() { + bluetoothctl info "$1" 2> /dev/null +} + +bt_is_paired() { + bt_info "$1" | grep -q "Paired: yes" +} + +bt_is_trusted() { + bt_info "$1" | grep -q "Trusted: yes" +} + +bt_is_connected() { + bt_info "$1" | grep -q "Connected: yes" +} + +bt_is_mac_address() { + [[ "$1" =~ ^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$ ]] +} + +bt_resolve_device() { + local device="$1" + if bt_is_mac_address "$device"; then + echo "$device" + else + echo "${BT_DEVICES[$device]:-}" + fi +} + +bt_get_all_macs() { + local devices=("${!1}") + for dev in "${devices[@]}"; do + local mac + mac=$(bt_resolve_device "$dev") + [[ -n "$mac" ]] && echo "$mac" + done +} + +# ------------------------------------------------- +# BLUETOOTH CONTROL +# ------------------------------------------------- + +start_bluetooth() { + echo "Starting Bluetooth service..." + systemctl_bt start + + echo "Waiting for bluetoothd to become ready..." + for i in {1..10}; do + if bluetoothctl show | grep -q "Powered: yes"; then + bluetoothctl pairable on > /dev/null 2>&1 + return 0 + fi + bluetoothctl power on > /dev/null 2>&1 + sleep 1 + done + + echo "ERROR: Bluetooth adapter not found or could not be powered on." + return 1 +} + +bt_pair_device() { + local mac="$1" + + if bt_is_paired "$mac"; then + return 0 + fi + + echo "✖ Device $mac is not paired. Automatic pairing is not supported." + echo " Please pair it manually, then re-run this command:" + echo "" + echo " bluetoothctl" + echo " [bluetoothctl]# pair $mac" + echo " [bluetoothctl]# trust $mac" + echo " [bluetoothctl]# connect $mac" + echo " [bluetoothctl]# quit" + echo "" + echo " (Put the device in pairing mode first, if needed.)" + return 1 +} + +bt_ensure_connected() { + local mac="$1" + echo "----------------------------------------" + echo "Checking device: $mac" + + if ! bt_is_trusted "$mac"; then + echo "→ Trusting $mac" + bluetoothctl trust "$mac" > /dev/null + fi + + for ((i = 1; i <= BT_RETRIES; i++)); do + if bt_is_connected "$mac"; then + echo "✔ Connected: $mac" + return 0 + fi + + echo "→ Attempt $i/$BT_RETRIES: Connecting to $mac..." + + if ! bt_is_paired "$mac"; then + bt_pair_device "$mac" || return 1 + fi + + bluetoothctl connect "$mac" > /dev/null 2>&1 + sleep "$BT_DELAY" + + if bt_is_connected "$mac"; then + echo "✔ Success!" + return 0 + fi + done + + echo "✖ Failed to connect $mac after $BT_RETRIES attempts" + return 1 +} + +bt_safe_disconnect() { + local mac="$1" + if bt_is_connected "$mac"; then + echo "Disconnecting $mac..." + bluetoothctl disconnect "$mac" > /dev/null 2>&1 + else + echo "$mac is already offline." + fi +} + +bt_stop_all() { + local devices=("${!1}") + for dev in "${devices[@]}"; do + local mac + mac=$(bt_resolve_device "$dev") + [[ -n "$mac" ]] && bt_safe_disconnect "$mac" + done +} + +bt_start_all() { + local devices=("${!1}") + for dev in "${devices[@]}"; do + local mac + mac=$(bt_resolve_device "$dev") + [[ -n "$mac" ]] && bt_ensure_connected "$mac" + done +} + +bt_status_all() { + local devices=("${!1}") + for dev in "${devices[@]}"; do + local mac + mac=$(bt_resolve_device "$dev") + if [[ -n "$mac" ]]; then + echo "--- $dev ($mac) ---" + if bt_is_connected "$mac"; then + echo "Status: CONNECTED" + elif bt_is_paired "$mac"; then + echo "Status: Paired (Offline)" + else + echo "Status: Not Paired / Unknown" + fi + fi + done +} + +bt_scan() { + local scan_duration=30 + declare -A seen_devices + local device_count=0 + + echo "Scanning for Bluetooth devices for $scan_duration seconds..." + echo "Press Ctrl+C to stop early" + echo "----------------------------------------" + + trap 'echo ""; echo "Scan stopped"; exit 0' INT TERM + + local start_time=$(date +%s) + local end_time=$((start_time + scan_duration)) + + while true; do + local current_time=$(date +%s) + if ((current_time >= end_time)); then + break + fi + + while IFS= read -r line; do + if [[ $line =~ ^[[:space:]]*([0-9A-F:]{17})[[:space:]]+(.+)$ ]]; then + local mac="${BASH_REMATCH[1]}" + local name="${BASH_REMATCH[2]}" + + if [[ -z "${seen_devices[$mac]:-}" ]]; then + seen_devices[$mac]="$name" + ((device_count++)) + echo "[$device_count] $mac - $name" + fi + fi + done < <(hcitool scan 2> /dev/null | tail -n +2) + + sleep 1 + done + + echo "----------------------------------------" + echo "Scan complete. Found $device_count unique device(s):" + for mac in "${!seen_devices[@]}"; do + echo " $mac - ${seen_devices[$mac]}" + done + + trap - INT TERM +} + +bt_list() { + echo "=== BT_DEVICES ===" + for name in "${!BT_DEVICES[@]}"; do + echo " $name: ${BT_DEVICES[$name]}" + done + echo "" + echo "=== BT_AUTO_DEVICES ===" + for name in "${BT_AUTO_DEVICES[@]}"; do + echo " $name: ${BT_DEVICES[$name]}" + done +} + +# ------------------------------------------------- +# MAIN +# ------------------------------------------------- + +DEVICES=() +TIMED_MINUTES=0 + +parse_args() { + while [[ $# -gt 0 ]]; do + case "$1" in + -d | --device) + DEVICES+=("$2") + shift 2 + ;; + -t | --timed) + TIMED_MINUTES="$2" + shift 2 + ;; + start | stop | status | scan | list) + COMMAND="$1" + shift + ;; + *) + echo "Unknown option: $1" + echo "Usage: $0 [-d|--device DEVICE] [-t|--timed MINUTES] {start|stop|status|scan|list}" + exit 1 + ;; + esac + done +} + +parse_args "$@" + +if [[ -z "${COMMAND:-}" ]]; then + echo "Usage: $0 [-d|--device DEVICE] [-t|--timed MINUTES] {start|stop|status|scan|list}" + exit 1 +fi + +if [[ ${#DEVICES[@]} -gt 0 ]]; then + for dev in "${DEVICES[@]}"; do + mac=$(bt_resolve_device "$dev") + if [[ -z "$mac" ]]; then + echo "ERROR: Unknown device '$dev'. Valid aliases: ${!BT_DEVICES[@]}" + exit 1 + fi + done +fi + +case "$COMMAND" in + start) + if wifi_switch_needed "$WIFI_5G" "$WIFI_24G"; then + nmcli connection up "$WIFI_5G" + fi + + start_bluetooth || exit 1 + + if [[ ${#DEVICES[@]} -gt 0 ]]; then + bt_start_all DEVICES[@] + else + bt_start_all BT_AUTO_DEVICES[@] + fi + + if [[ "$TIMED_MINUTES" -gt 0 ]]; then + echo "Will disconnect after $TIMED_MINUTES minute(s)..." + sleep $((TIMED_MINUTES * 60)) + echo "Time elapsed. Disconnecting..." + + if [[ ${#DEVICES[@]} -gt 0 ]]; then + bt_stop_all DEVICES[@] + else + bt_stop_all BT_AUTO_DEVICES[@] + fi + + echo "Stopping Bluetooth service..." + systemctl_bt stop + + if wifi_switch_needed "$WIFI_5G" "$WIFI_24G"; then + nmcli connection up "$WIFI_24G" + fi + fi + ;; + + stop) + if [[ ${#DEVICES[@]} -gt 0 ]]; then + bt_stop_all DEVICES[@] + else + bt_stop_all BT_AUTO_DEVICES[@] + fi + + echo "Stopping Bluetooth service..." + systemctl_bt stop + + if wifi_switch_needed "$WIFI_5G" "$WIFI_24G"; then + nmcli connection up "$WIFI_24G" + fi + ;; + + status) + bluetoothctl show | grep -E "Name|Powered|Discoverable" + + if [[ ${#DEVICES[@]} -gt 0 ]]; then + bt_status_all DEVICES[@] + else + bt_status_all BT_AUTO_DEVICES[@] + fi + ;; + + scan) + bt_scan + ;; + + list) + bt_list + ;; +esac diff --git a/.tmux.d/tmux-gruvbox b/.tmux.d/tmux-gruvbox new file mode 160000 index 0000000..aeb30c7 --- /dev/null +++ b/.tmux.d/tmux-gruvbox @@ -0,0 +1 @@ +Subproject commit aeb30c7172a8ed8663409207814cf47d9df10d15 From a825c6d58a2f42b17de223e9b124623041b09ca9 Mon Sep 17 00:00:00 2001 From: chodak166 Date: Sat, 20 Jun 2026 20:53:21 +0200 Subject: [PATCH 7/9] Added tmux theme files; fixed sway screenshotting --- .config/sway/config | 12 +-- .config/sway/scripts/screenshot | 37 +++++++ .tmux.d/tmux-gruvbox | 1 - .tmux.d/tmux-gruvbox/gruvbox-tpm.tmux | 6 ++ .tmux.d/tmux-gruvbox/src/gruvbox-main.sh | 98 +++++++++++++++++++ .tmux.d/tmux-gruvbox/src/helper_methods.sh | 19 ++++ .../tmux-gruvbox/src/palette_gruvbox_dark.sh | 46 +++++++++ .../src/palette_gruvbox_dark256.sh | 46 +++++++++ .../tmux-gruvbox/src/palette_gruvbox_light.sh | 46 +++++++++ .../src/palette_gruvbox_light256.sh | 46 +++++++++ .../tmux-gruvbox/src/theme_gruvbox_dark.sh | 79 +++++++++++++++ .../tmux-gruvbox/src/theme_gruvbox_light.sh | 79 +++++++++++++++ .../src/theme_gruvbox_light256.sh | 79 +++++++++++++++ .tmux.d/tmux-gruvbox/src/tmux_utils.sh | 63 ++++++++++++ 14 files changed, 648 insertions(+), 9 deletions(-) create mode 100755 .config/sway/scripts/screenshot delete mode 160000 .tmux.d/tmux-gruvbox create mode 100755 .tmux.d/tmux-gruvbox/gruvbox-tpm.tmux create mode 100755 .tmux.d/tmux-gruvbox/src/gruvbox-main.sh create mode 100644 .tmux.d/tmux-gruvbox/src/helper_methods.sh create mode 100644 .tmux.d/tmux-gruvbox/src/palette_gruvbox_dark.sh create mode 100644 .tmux.d/tmux-gruvbox/src/palette_gruvbox_dark256.sh create mode 100644 .tmux.d/tmux-gruvbox/src/palette_gruvbox_light.sh create mode 100644 .tmux.d/tmux-gruvbox/src/palette_gruvbox_light256.sh create mode 100644 .tmux.d/tmux-gruvbox/src/theme_gruvbox_dark.sh create mode 100644 .tmux.d/tmux-gruvbox/src/theme_gruvbox_light.sh create mode 100644 .tmux.d/tmux-gruvbox/src/theme_gruvbox_light256.sh create mode 100644 .tmux.d/tmux-gruvbox/src/tmux_utils.sh diff --git a/.config/sway/config b/.config/sway/config index fd901c1..eb742d6 100644 --- a/.config/sway/config +++ b/.config/sway/config @@ -265,14 +265,10 @@ bindsym $mod+r mode "resize" # Omarchy also uses grim + slurp (+ satty for annotation). ################################################################# -# Fullscreen screenshot → save to ~/Pictures and copy to clipboard -bindsym Print exec grim -t png ~/Pictures/screenshot_$(date +%Y%m%d_%H%M%S).png && grim -t png - | wl-copy -t image/png - -# Region screenshot → select area with slurp -bindsym Shift+Print exec grim -t png -g "$(slurp)" ~/Pictures/screenshot_$(date +%Y%m%d_%H%M%S).png && grim -t png -g "$(slurp)" - | wl-copy -t image/png - -# Active window screenshot (sway-specific: get focused window geometry) -bindsym Control+Print exec grim -t png -g "$(swaymsg -t get_tree | jq -j '.. | select(.type?) | select(.focused) | .rect | "\(.x),\(.y) \(.width)x\(.height)"')" ~/Pictures/screenshot_$(date +%Y%m%d_%H%M%S).png +# Screenshots — capture once, save to file + copy to clipboard +bindsym Print exec $scriptsDir/screenshot full +bindsym Shift+Print exec $scriptsDir/screenshot area +bindsym Control+Print exec $scriptsDir/screenshot window ################################################################# diff --git a/.config/sway/scripts/screenshot b/.config/sway/scripts/screenshot new file mode 100755 index 0000000..d7fff82 --- /dev/null +++ b/.config/sway/scripts/screenshot @@ -0,0 +1,37 @@ +#!/bin/bash +#---------------------------------------------------------------- +# screenshot — Capture screen, window, or region +# +# Captures once, saves to ~/Pictures and copies to clipboard. +# +# Usage: +# screenshot full — full screen +# screenshot area — select region with slurp +# screenshot window — focused window +# +# Dependencies: grim, slurp, wl-copy, swaymsg, jq +#---------------------------------------------------------------- + +dir=~/Pictures +mkdir -p "$dir" +file="$dir/screenshot_$(date +%Y%m%d_%H%M%S).png" + +case "$1" in + full) + grim -t png "$file" + ;; + area) + geo=$(slurp) + grim -t png -g "$geo" "$file" + ;; + window) + geo=$(swaymsg -t get_tree | jq -j '.. | select(.type?) | select(.focused) | .rect | "\(.x),\(.y) \(.width)x\(.height)"') + grim -t png -g "$geo" "$file" + ;; + *) + echo "Usage: screenshot {full|area|window}" + exit 1 + ;; +esac + +wl-copy -t image/png < "$file" diff --git a/.tmux.d/tmux-gruvbox b/.tmux.d/tmux-gruvbox deleted file mode 160000 index aeb30c7..0000000 --- a/.tmux.d/tmux-gruvbox +++ /dev/null @@ -1 +0,0 @@ -Subproject commit aeb30c7172a8ed8663409207814cf47d9df10d15 diff --git a/.tmux.d/tmux-gruvbox/gruvbox-tpm.tmux b/.tmux.d/tmux-gruvbox/gruvbox-tpm.tmux new file mode 100755 index 0000000..936ef65 --- /dev/null +++ b/.tmux.d/tmux-gruvbox/gruvbox-tpm.tmux @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "${CURRENT_DIR}/src/gruvbox-main.sh" + +# vim: ai et ft=bash diff --git a/.tmux.d/tmux-gruvbox/src/gruvbox-main.sh b/.tmux.d/tmux-gruvbox/src/gruvbox-main.sh new file mode 100755 index 0000000..d9d299d --- /dev/null +++ b/.tmux.d/tmux-gruvbox/src/gruvbox-main.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +readonly CURRENT_DIR + +# hold the array of all command to configure tmux theme +declare -a TMUX_CMDS + +# load libraries +# shellcheck disable=1091 +source "${CURRENT_DIR}/helper_methods.sh" +# shellcheck disable=1091 +source "${CURRENT_DIR}/tmux_utils.sh" + +readonly TMUX_GRUVBOX="@tmux-gruvbox" +readonly TMUX_GRUVBOX_STATUSBAR_ALPHA="@tmux-gruvbox-statusbar-alpha" +readonly TMUX_GRUVBOX_LEFT_STATUS_A="@tmux-gruvbox-left-status-a" +readonly TMUX_GRUVBOX_RIGHT_STAUTS_X="@tmux-gruvbox-right-status-x" +readonly TMUX_GRUVBOX_RIGHT_STAUTS_Y="@tmux-gruvbox-right-status-y" +readonly TMUX_GRUVBOX_RIGHT_STAUTS_Z="@tmux-gruvbox-right-status-z" + +# define simple theme options (no color interpolation required) +readonly DEFAULT_THEME="dark256" +readonly DEFAULT_STATUSBAR_ALPHA='false' +# defaults for theme option (with color interpolation) +readonly DEFAULT_LEFT_STATUS_A='#S' +readonly DEFAULT_RIGHT_STATUS_X='%Y-%m-%d' +readonly DEFAULT_RIGHT_STATUS_Y='%H:%M' +readonly DEFAULT_RIGHT_STATUS_Z='#h' + +main() { + TMUX_CMDS=() # clear + + # load proper palette for the theme asap to avoid additional variable interpolation + local _theme + _theme=$(tmux_get_option "${TMUX_GRUVBOX}" "${DEFAULT_THEME}") + _statusbar_alpha=$(tmux_get_option "${TMUX_GRUVBOX_STATUSBAR_ALPHA}" "${DEFAULT_STATUSBAR_ALPHA}") + + case "$_theme" in + light) + # shellcheck disable=1091 + source "${CURRENT_DIR}/palette_gruvbox_light.sh" + # shellcheck disable=1091 + source "${CURRENT_DIR}/theme_gruvbox_light.sh" + ;; + light256) + # shellcheck disable=1091 + source "${CURRENT_DIR}/palette_gruvbox_light256.sh" + # shellcheck disable=1091 + source "${CURRENT_DIR}/theme_gruvbox_light256.sh" + ;; + dark) + # shellcheck disable=1091 + source "${CURRENT_DIR}/palette_gruvbox_dark.sh" + # shellcheck disable=1091 + source "${CURRENT_DIR}/theme_gruvbox_dark.sh" + ;; + dark256 | *) + # shellcheck disable=1091 + source "${CURRENT_DIR}/palette_gruvbox_dark256.sh" + # shellcheck disable=1091 + source "${CURRENT_DIR}/theme_gruvbox_dark.sh" + ;; + esac + + local _status_left _status_right _window_status_current_format _window_status_format + _status_left_a=$(tmux_get_option "$TMUX_GRUVBOX_LEFT_STATUS_A" "$DEFAULT_LEFT_STATUS_A") + _status_right_x=$(tmux_get_option "$TMUX_GRUVBOX_RIGHT_STAUTS_X" "$DEFAULT_RIGHT_STATUS_X") + _status_right_y=$(tmux_get_option "$TMUX_GRUVBOX_RIGHT_STAUTS_Y" "$DEFAULT_RIGHT_STATUS_Y") + _status_right_z=$(tmux_get_option "$TMUX_GRUVBOX_RIGHT_STAUTS_Z" "$DEFAULT_RIGHT_STATUS_Z") + + local _theme_args + _theme_args=( + "$_status_left_a" + "$_status_right_x" + "$_status_right_y" + "$_status_right_z" + "$_statusbar_alpha" + ) + + case $_theme in + light256) + # light256 have slightly different colors placement then regular light 16-bit + theme_set_light256 "${_theme_args[@]}" + ;; + light) + theme_set_light "${_theme_args[@]}" + ;; + dark | dark256 | *) + theme_set_dark "${_theme_args[@]}" + ;; + esac + + # execute commands with tmux as array of options + tmux "${TMUX_CMDS[@]}" +} + +main "$@" diff --git a/.tmux.d/tmux-gruvbox/src/helper_methods.sh b/.tmux.d/tmux-gruvbox/src/helper_methods.sh new file mode 100644 index 0000000..175a5a3 --- /dev/null +++ b/.tmux.d/tmux-gruvbox/src/helper_methods.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# simply print passed array +# +# example +# +# myarray=() +# print_array myarray +# +print_array() { + local -n arr # -n available over bash 4.3 + arr=$1 + + echo "" + echo "begin >>>" + printf "%s\n" "${arr[@]}" + echo "<<< end" + echo "" +} diff --git a/.tmux.d/tmux-gruvbox/src/palette_gruvbox_dark.sh b/.tmux.d/tmux-gruvbox/src/palette_gruvbox_dark.sh new file mode 100644 index 0000000..58885b2 --- /dev/null +++ b/.tmux.d/tmux-gruvbox/src/palette_gruvbox_dark.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +########################## +# gruvbox dark pallete +########################## + +#### +# When using 'colour124' you are using the color default in terminal pallete. +# This could be important for people which terminals support only 256 colors +# and does not support HEX values. +# +# The names of colors used from https://github.com/morhetz/gruvbox + +# shellcheck disable=2034 # ignored as this file only contains var definitions +col_bg="#282828" +col_bg0_h="#1d2021" +col_bg0="#282828" +col_bg1="#3c3836" +col_bg2="#504945" +col_bg3="#665c54" +col_bg4="#7c6f64" +col_gray0="#a89984" +col_gray1="#928374" +col_gray2="#928374" +col_bg0_s="#32302f" +col_fg="#ebdbb2" +col_fg4="#a89984" +col_fg3="#bdae93" +col_fg2="#d5c4a1" +col_fg1="#ebdbb2" +col_fg0="#fbf1c7" + +col_red="#cc241d" +col_red2="#fb4934" +col_green="#98971a" +col_green2="#b8bb26" +col_yellow="#d79921" +col_yellow2="#fabd2f" +col_blue="#458588" +col_blue2="#83a598" +col_purple="#b16286" +col_purple2="#d3869b" +col_aqua="#689d6a" +col_aqua2="#8ec07c" +col_orange="#d65d0e" +col_orange2="#fe8019" diff --git a/.tmux.d/tmux-gruvbox/src/palette_gruvbox_dark256.sh b/.tmux.d/tmux-gruvbox/src/palette_gruvbox_dark256.sh new file mode 100644 index 0000000..fe6c84d --- /dev/null +++ b/.tmux.d/tmux-gruvbox/src/palette_gruvbox_dark256.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +########################## +# gruvbox dark256 pallete +########################## + +#### +# When using 'colour124' you are using the color default in terminal pallete. +# This could be important for people which terminals support only 256 colors +# and does not support HEX values. +# +# The names of colors used from https://github.com/morhetz/gruvbox + +# shellcheck disable=2034 # ignored as this file only contains var definitions +col_bg=colour235 +col_bg0_h=colour234 +col_bg0=colour235 +col_bg1=colour237 +col_bg2=colour239 +col_bg3=colour241 +col_bg4=colour243 +col_gray0=colour246 +col_gray1=colour245 +col_gray2=colour245 +col_bg0_s=colour236 +col_fg=colour223 +col_fg4=colour246 +col_fg3=colour248 +col_fg2=colour250 +col_fg1=colour223 +col_fg0=colour229 + +col_red=colour124 +col_red2=colour167 +col_green=colour106 +col_green2=colour142 +col_yellow=colour172 +col_yellow2=colour214 +col_blue=colour66 +col_blue2=colour109 +col_purple=colour132 +col_purple2=colour175 +col_aqua=colour72 +col_aqua2=colour108 +col_orange=colour166 +col_orange2=colour208 diff --git a/.tmux.d/tmux-gruvbox/src/palette_gruvbox_light.sh b/.tmux.d/tmux-gruvbox/src/palette_gruvbox_light.sh new file mode 100644 index 0000000..0652c5c --- /dev/null +++ b/.tmux.d/tmux-gruvbox/src/palette_gruvbox_light.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +########################## +# gruvbox light pallete +########################## + +#### +# When using 'colour124' you are using the color default in terminal pallete. +# This could be important for people which terminals support only 256 colors +# and does not support HEX values. +# +# The names of colors used from https://github.com/morhetz/gruvbox + +# shellcheck disable=2034 # ignored as this file only contains var definitions +col_bg="#fbf1c7" +col_bg0_h="#f9f5d7" +col_bg0="#fbf1c7" +col_bg1="#ebdbb2" +col_bg2="#d5c4a1" +col_bg3="#bdae93" +col_bg4="#a89984" +col_gray0="#7c6f64" +col_gray1="#928374" +col_gray2="#928374" +col_bg0_s="#f2e5bc" +col_fg="#3c3836" +col_fg4="#7c6f64" +col_fg3="#665c54" +col_fg2="#504945" +col_fg1="#3c3836" +col_fg0="#282828" + +col_red="#cc241d" +col_red2="#9d0006" +col_green="#98971a" +col_green2="#79740e" +col_yellow="#d79921" +col_yellow2="#b57614" +col_blue="#458588" +col_blue2="#076678" +col_purple="#b16286" +col_purple2="#8f3f71" +col_aqua="#689d6a" +col_aqua2="#427b58" +col_orange="#d65d0e" +col_orange2="#af3a03" diff --git a/.tmux.d/tmux-gruvbox/src/palette_gruvbox_light256.sh b/.tmux.d/tmux-gruvbox/src/palette_gruvbox_light256.sh new file mode 100644 index 0000000..959e5a6 --- /dev/null +++ b/.tmux.d/tmux-gruvbox/src/palette_gruvbox_light256.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +########################## +# gruvbox light256 pallete +########################## + +#### +# When using 'colour124' you are using the color default in terminal pallete. +# This could be important for people which terminals support only 256 colors +# and does not support HEX values. +# +# The names of colors used from https://github.com/morhetz/gruvbox + +# shellcheck disable=2034 # ignored as this file only contains var definitions +col_bg=colour229 +col_bg0_h=colour230 +col_bg0=colour229 +col_bg1=colour223 +col_bg2=colour250 +col_bg3=colour248 +col_bg4=colour246 +col_gray0=colour246 +col_gray1=colour245 +col_gray2=colour244 +col_bg0_s=colour228 +col_fg=colour223 +col_fg4=colour243 +col_fg3=colour241 +col_fg2=colour239 +col_fg1=colour237 +col_fg0=colour235 + +col_red=colour124 +col_red2=colour88 +col_green=colour106 +col_green2=colour100 +col_yellow=colour172 +col_yellow2=colour136 +col_blue=colour66 +col_blue2=colour24 +col_purple=colour132 +col_purple2=colour96 +col_aqua=colour72 +col_aqua2=colour66 +col_orange=colour166 +col_orange2=colour130 diff --git a/.tmux.d/tmux-gruvbox/src/theme_gruvbox_dark.sh b/.tmux.d/tmux-gruvbox/src/theme_gruvbox_dark.sh new file mode 100644 index 0000000..4bee163 --- /dev/null +++ b/.tmux.d/tmux-gruvbox/src/theme_gruvbox_dark.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +# Themes may use different colors in sets therefore we setup dark and light +# separately. +# +# shellcheck disable=SC2154 +theme_set_dark() { + local _left_status_a _right_status_x _right_status_y _right_status_z _statusbar_alpha + _left_status_a=$1 + _right_status_x=$2 + _right_status_y=$3 + _right_status_z=$4 + _statusbar_alpha=$5 + + tmux_append_seto "status" "on" + + # default statusbar bg color + local _statusbar_bg="${col_bg1}" + if [[ "$_statusbar_alpha" == "true" ]]; then _statusbar_bg="default"; fi + tmux_append_seto "status-style" "bg=${_statusbar_bg},fg=${col_fg1}" + + # default window title colors + local _window_title_bg=${col_yellow2} + if [[ "$_statusbar_alpha" == "true" ]]; then _window_title_bg="default"; fi + tmux_append_setwo "window-status-style" "bg=${_window_title_bg},fg=${col_bg1}" + + # default window with an activity alert + tmux_append_setwo "window-status-activity-style" "bg=${col_bg1},fg=${col_fg3}" + + # active window title colors + local _active_window_title_bg=${col_yellow2} + if [[ "$_statusbar_alpha" == "true" ]]; then _active_window_title_bg="default"; fi + tmux_append_setwo "window-status-current-style" "bg=${_active_window_title_bg},fg=${col_bg1}" # TODO cosider removing red! + + # pane border + tmux_append_seto "pane-active-border-style" "fg=${col_fg2}" + tmux_append_seto "pane-border-style" "fg=${col_bg1}" + + # message infos + tmux_append_seto "message-style" "bg=${col_bg2},fg=${col_fg1}" + + # writing commands inactive + tmux_append_seto "message-command-style" "bg=${col_fg3},fg=${col_bg1}" + + # pane number display + tmux_append_seto "display-panes-active-colour" "${col_fg2}" + tmux_append_seto "display-panes-colour" "${col_bg1}" + + # clock + tmux_append_setwo "clock-mode-colour" "${col_blue2}" + + # bell + tmux_append_setwo "window-status-bell-style" "bg=${col_red2},fg=${col_bg}" + + ## Theme settings mixed with colors (unfortunately, but there is no cleaner way) + tmux_append_seto "status-justify" "left" + tmux_append_seto "status-left-style" none + tmux_append_seto "status-left-length" "80" + tmux_append_seto "status-right-style" none + tmux_append_seto "status-right-length" "80" + tmux_append_setwo "window-status-separator" "" + + tmux_append_seto "status-left" "#[bg=${col_bg3},fg=${col_fg3}] ${_left_status_a} #[bg=${col_bg1},fg=${col_bg3},nobold,noitalics,nounderscore]" + + # right status + local _status_right_bg=${col_bg1} + if [[ "$_statusbar_alpha" == "true" ]]; then _status_right_bg="default"; fi + tmux_append_seto "status-right" "#[bg=${_status_right_bg},fg=${col_bg2},nobold,nounderscore,noitalics]#[bg=${col_bg2},fg=${col_fg4}] ${_right_status_x}  ${_right_status_y} #[bg=${col_bg2},fg=${col_fg3},nobold,noitalics,nounderscore]#[bg=${col_fg3},fg=${col_bg1}] ${_right_status_z}" + + # current window + local _current_window_status_format_bg=${col_bg1} + if [[ "$_statusbar_alpha" == "true" ]]; then _current_window_status_format_bg="default"; fi + tmux_append_setwo "window-status-current-format" "#[bg=${col_yellow2},fg=${col_bg1},nobold,noitalics,nounderscore]#[bg=${col_yellow2},fg=${col_bg2}] #I #[bg=${col_yellow2},fg=${col_bg2},bold] #W#{?window_zoomed_flag,*Z,} #{?window_end_flag,#[bg=${_current_window_status_format_bg}],#[bg=${col_bg1}]}#[fg=${col_yellow2},nobold,noitalics,nounderscore]" + + # default window + local _default_window_status_format_bg=${col_bg1} + if [[ "$_statusbar_alpha" == "true" ]]; then _default_window_status_format_bg="default"; fi + tmux_append_setwo "window-status-format" "#[bg=${col_bg2},fg=${col_bg1},noitalics]#[bg=${col_bg2},fg=${col_fg1}] #I #[bg=${col_bg2},fg=${col_fg1}] #W #{?window_end_flag,#[bg=${_default_window_status_format_bg}],#[bg=${col_bg1}]}#[fg=${col_bg2},noitalics]" +} diff --git a/.tmux.d/tmux-gruvbox/src/theme_gruvbox_light.sh b/.tmux.d/tmux-gruvbox/src/theme_gruvbox_light.sh new file mode 100644 index 0000000..ebbf4d9 --- /dev/null +++ b/.tmux.d/tmux-gruvbox/src/theme_gruvbox_light.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +# Themes may use different colors in sets therefore we setup dark and light +# separately. +# +# shellcheck disable=SC2154 +theme_set_light() { + local _left_status_a _right_status_x _right_status_y _right_status_z _statusbar_alpha + _left_status_a=$1 + _right_status_x=$2 + _right_status_y=$3 + _right_status_z=$4 + _statusbar_alpha=$5 + + tmux_append_seto "status" "on" + + # default statusbar bg color + local _statusbar_bg="${col_bg1}" + if [[ "$_statusbar_alpha" == "true" ]]; then _statusbar_bg="default"; fi + tmux_append_seto "status-style" "bg=${_statusbar_bg},fg=${col_fg1}" + + # default window title colors + local _window_title_bg=${col_yellow2} + if [[ "$_statusbar_alpha" == "true" ]]; then _window_title_bg="default"; fi + tmux_append_setwo "window-status-style" "bg=${_window_title_bg},fg=${col_bg1}" + + # default window with an activity alert + tmux_append_setwo "window-status-activity-style" "bg=${col_bg1},fg=${col_fg3}" + + # active window title colors + local _active_window_title_bg=${col_yellow2} + if [[ "$_statusbar_alpha" == "true" ]]; then _active_window_title_bg="default"; fi + tmux_append_setwo "window-status-current-style" "bg=${_active_window_title_bg},fg=${col_bg1}" # TODO cosider removing red! + + # pane border + tmux_append_seto "pane-active-border-style" "fg=${col_fg2}" + tmux_append_seto "pane-border-style" "fg=${col_bg1}" + + # message infos + tmux_append_seto "message-style" "bg=${col_bg2},fg=${col_fg1}" + + # writing commands inactive + tmux_append_seto "message-command-style" "bg=${col_fg3},fg=${col_bg1}" + + # pane number display + tmux_append_seto "display-panes-active-colour" "${col_fg2}" + tmux_append_seto "display-panes-colour" "${col_bg1}" + + # clock + tmux_append_setwo "clock-mode-colour" "${col_blue2}" + + # bell + tmux_append_setwo "window-status-bell-style" "bg=${col_red2},fg=${col_bg}" + + ## Theme settings mixed with colors (unfortunately, but there is no cleaner way) + tmux_append_seto "status-justify" "left" + tmux_append_seto "status-left-style" none + tmux_append_seto "status-left-length" "80" + tmux_append_seto "status-right-style" none + tmux_append_seto "status-right-length" "80" + tmux_append_setwo "window-status-separator" "" + + tmux_append_seto "status-left" "#[bg=${col_bg3},fg=${col_fg3}] ${_left_status_a} #[bg=${col_bg1},fg=${col_bg3},nobold,noitalics,nounderscore]" + + # right status + local _status_right_bg=${col_bg1} + if [[ "$_statusbar_alpha" == "true" ]]; then _status_right_bg="default"; fi + tmux_append_seto "status-right" "#[bg=${_status_right_bg},fg=${col_bg2},nobold,nounderscore,noitalics]#[bg=${col_bg2},fg=${col_fg4}] ${_right_status_x}  ${_right_status_y} #[bg=${col_bg2},fg=${col_fg3},nobold,noitalics,nounderscore]#[bg=${col_fg3},fg=${col_bg1}] ${_right_status_z}" + + # current window + local _current_window_status_format_bg=${col_bg1} + if [[ "$_statusbar_alpha" == "true" ]]; then _current_window_status_format_bg="default"; fi + tmux_append_setwo "window-status-current-format" "#[bg=${col_yellow2},fg=${col_bg1},nobold,noitalics,nounderscore]#[bg=${col_yellow2},fg=${col_bg2}] #I #[bg=${col_yellow2},fg=${col_bg2},bold] #W#{?window_zoomed_flag,*Z,} #{?window_end_flag,#[bg=${_current_window_status_format_bg}],#[bg=${col_bg1}]}#[fg=${col_yellow2},nobold,noitalics,nounderscore]" + + # default window + local _default_window_status_format_bg=${col_bg1} + if [[ "$_statusbar_alpha" == "true" ]]; then _default_window_status_format_bg="default"; fi + tmux_append_setwo "window-status-format" "#[bg=${col_bg2},fg=${col_bg1},noitalics]#[bg=${col_bg2},fg=${col_fg1}] #I #[bg=${col_bg2},fg=${col_fg1}] #W #{?window_end_flag,#[bg=${_default_window_status_format_bg}],#[bg=${col_bg1}]}#[fg=${col_bg2},noitalics]" +} diff --git a/.tmux.d/tmux-gruvbox/src/theme_gruvbox_light256.sh b/.tmux.d/tmux-gruvbox/src/theme_gruvbox_light256.sh new file mode 100644 index 0000000..9ae1a43 --- /dev/null +++ b/.tmux.d/tmux-gruvbox/src/theme_gruvbox_light256.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +# Themes may use different colors in sets therefore we setup dark and light +# separately. +# +# shellcheck disable=SC2154 +theme_set_light256() { + local _left_status_a _right_status_x _right_status_y _right_status_z _statusbar_alpha + _left_status_a=$1 + _right_status_x=$2 + _right_status_y=$3 + _right_status_z=$4 + _statusbar_alpha=$5 + + tmux_append_seto "status" "on" + + # default statusbar bg color + local _statusbar_bg="${col_bg2}" + if [[ "$_statusbar_alpha" == "true" ]]; then _statusbar_bg="default"; fi + tmux_append_seto "status-style" "bg=${_statusbar_bg},fg=${col_fg1}" + + # default window title colors + local _window_title_bg=${col_yellow2} + if [[ "$_statusbar_alpha" == "true" ]]; then _window_title_bg="default"; fi + tmux_append_setwo "window-status-style" "bg=${_window_title_bg},fg=${col_bg1}" + + # default window with an activity alert + tmux_append_setwo "window-status-activity-style" "bg=${col_bg1},fg=${col_fg3}" + + # active window title colors + local _active_window_title_bg=${col_yellow2} + if [[ "$_statusbar_alpha" == "true" ]]; then _active_window_title_bg="default"; fi + tmux_append_setwo "window-status-current-style" "bg=${_active_window_title_bg},fg=${col_bg1}" # TODO cosider removing red! + + # pane border + tmux_append_seto "pane-active-border-style" "fg=${col_fg2}" + tmux_append_seto "pane-border-style" "fg=${col_bg1}" + + # message infos + tmux_append_seto "message-style" "bg=${col_bg2},fg=${col_fg1}" + + # writing commands inactive + tmux_append_seto "message-command-style" "bg=${col_fg3},fg=${col_bg1}" + + # pane number display + tmux_append_seto "display-panes-active-colour" "${col_fg2}" + tmux_append_seto "display-panes-colour" "${col_bg1}" + + # clock + tmux_append_setwo "clock-mode-colour" "${col_blue2}" + + # bell + tmux_append_setwo "window-status-bell-style" "bg=${col_red2},fg=${col_bg}" + + ## Theme settings mixed with colors (unfortunately, but there is no cleaner way) + tmux_append_seto "status-justify" "left" + tmux_append_seto "status-left-style" none + tmux_append_seto "status-left-length" "80" + tmux_append_seto "status-right-style" none + tmux_append_seto "status-right-length" "80" + tmux_append_setwo "window-status-separator" "" + + tmux_append_seto "status-left" "#[bg=${col_fg2},fg=${col_bg1}] ${_left_status_a} #[bg=${col_bg2},fg=${col_fg2},nobold,noitalics,nounderscore]" + + # right status + local _status_right_bg=${col_bg2} + if [[ "$_statusbar_alpha" == "true" ]]; then _status_right_bg="default"; fi + tmux_append_seto "status-right" "#[bg=${_status_right_bg},fg=${col_fg4},nobold,nounderscore,noitalics]#[bg=${col_fg4},fg=${col_bg1}] ${_right_status_x}  ${_right_status_y} #[bg=${col_fg4},fg=${col_fg2},nobold,noitalics,nounderscore]#[bg=${col_fg2},fg=${col_bg1}] ${_right_status_z}" + + # current window + local _current_window_status_format_bg=${col_bg2} + if [[ "$_statusbar_alpha" == "true" ]]; then _current_window_status_format_bg="default"; fi + tmux_append_setwo "window-status-current-format" "#[bg=${col_yellow},fg=${col_bg2},nobold,noitalics,nounderscore]#[bg=${col_yellow},fg=${col_fg1}] #I #[bg=${col_yellow},fg=${col_fg1},bold] #W#{?window_zoomed_flag,*Z,} #{?window_end_flag,#[bg=${_current_window_status_format_bg}],#[bg=${col_bg2}]}#[fg=${col_yellow},nobold,noitalics,nounderscore]" + + # default window + local _default_window_status_format_bg=${col_bg2} + if [[ "$_statusbar_alpha" == "true" ]]; then _default_window_status_format_bg="default"; fi + tmux_append_setwo "window-status-format" "#[bg=${col_bg3},fg=${col_bg2},noitalics]#[bg=${col_bg3},fg=${col_fg2}] #I #[bg=${col_bg3},fg=${col_fg2}] #W #{?window_end_flag,#[bg=${_default_window_status_format_bg}],#[bg=${col_bg2}]}#[fg=${col_bg3},noitalics]" +} diff --git a/.tmux.d/tmux-gruvbox/src/tmux_utils.sh b/.tmux.d/tmux-gruvbox/src/tmux_utils.sh new file mode 100644 index 0000000..87ab063 --- /dev/null +++ b/.tmux.d/tmux-gruvbox/src/tmux_utils.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +# get desired tmux option or use given default value +tmux_get_option() { + local _option_name _default_value + _option_name="$1" + _default_value="$2" + + local _current_option_value + _current_option_value=$(tmux show-option -gqv "$_option_name") + if [[ -n "$_current_option_value" ]]; then + echo "$_current_option_value" + else + echo "$_default_value" + fi +} + +# get desired window-option from tmux or default +tmux_get_window_option() { + local _option_name _default_value + _option_name="$1" + _default_value="$2" + + local _current_option_value + _current_option_value=$(tmux show-window-option -gqv "$_option_name") + if [[ -n "$_current_option_value" ]]; then + echo "$_current_option_value" + else + echo "$_default_value" + fi +} + +# append preconfigured tmux set-option to global array +tmux_append_seto() { + local _option _value _result + _option="$1" + _value="$2" + TMUX_CMDS+=("set-option" "-gq" "${_option}" "${_value}" ";") +} + +# append preconfigured tmux set-window-option to global array +tmux_append_setwo() { + local _option _value _result + _option="$1" + _value="$2" + TMUX_CMDS+=("set-window-option" "-gq" "${_option}" "${_value}" ";") +} + +# imediately execute tmux option +tmux_set_option_now() { + local _option_name _value + _option_name="$1" + _value="$2" + tmux set-option -gq "$_option_name" "$_value" +} + +# imediately execute tmux option +tmux_set_window_option_now() { + local _option_name _value + _option_name="$1" + _value="$2" + tmux set-window-option -gq "$_option_name" "$_value" +} From 057613e0f059c2baf686374b5580fa696d54f53a Mon Sep 17 00:00:00 2001 From: chodak166 Date: Sun, 28 Jun 2026 12:05:29 +0200 Subject: [PATCH 8/9] Updated nvim config (terminals); added docker config (ctrl+p -> ctrl+d) --- .config/nvim/lazy-lock.json | 17 ++- .config/nvim/lua/config/terminal.lua | 118 +++++++++++++++ .config/nvim/lua/plugins/markdown.lua | 8 ++ .config/nvim/lua/plugins/snacks.lua | 2 + .config/nvim/lua/plugins/terminal.lua | 23 +++ .config/sway/scripts/output-profile | 41 +++--- .docker/config.json | 3 + .local/bin/btswitch | 197 +++++++------------------- .zshrc | 1 + 9 files changed, 233 insertions(+), 177 deletions(-) create mode 100644 .config/nvim/lua/config/terminal.lua create mode 100644 .config/nvim/lua/plugins/markdown.lua create mode 100644 .config/nvim/lua/plugins/terminal.lua create mode 100644 .docker/config.json diff --git a/.config/nvim/lazy-lock.json b/.config/nvim/lazy-lock.json index 01bb543..fa6357d 100644 --- a/.config/nvim/lazy-lock.json +++ b/.config/nvim/lazy-lock.json @@ -1,9 +1,9 @@ { "LazyVim": { "branch": "main", "commit": "c10948c50b18fae7f256433afdef09e432410480" }, - "avante.nvim": { "branch": "main", "commit": "d9c33ebe1e7205f416796b5b383d6894abe47495" }, + "avante.nvim": { "branch": "main", "commit": "90a0e77c63251c367935caeaa0070670522c960b" }, "blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" }, "bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" }, - "catppuccin": { "branch": "main", "commit": "49a926655a2f5579e9c276470fc300baaa49e524" }, + "catppuccin": { "branch": "main", "commit": "e068ab5f8261f23f6f71ffd8791ae40315b77b9c" }, "conform.nvim": { "branch": "master", "commit": "619363c30309d29ffa631e67c8183f2a72caa373" }, "diffview.nvim": { "branch": "main", "commit": "4516612fe98ff56ae0415a259ff6361a89419b0a" }, "dotenv.nvim": { "branch": "main", "commit": "7d516e9293c6e3ac21830fb10a4e8674c02747c6" }, @@ -11,23 +11,22 @@ "flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" }, "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, "gitsigns.nvim": { "branch": "main", "commit": "2038c666bd9d8a0b7349a0b6ee00dc83104b9ecf" }, - "grug-far.nvim": { "branch": "main", "commit": "c995bbacf8229dc096ec1c3d60f8531059c86c1b" }, - "hybrid-theme": { "branch": "main", "commit": "6ae348938376f345e02eea4e6c27c0874b05f33a" }, + "grug-far.nvim": { "branch": "main", "commit": "c69859c1d5427ab5fc7ed12380ab521b4e336691" }, "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, "just-runner.nvim": { "branch": "main", "commit": "f29d405aa828900df242600720a2b0e57261489f" }, "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, "lazydev.nvim": { "branch": "main", "commit": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d" }, "lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" }, - "mason-lspconfig.nvim": { "branch": "main", "commit": "21c5b3ebeaa0412e28096bb0701434c51c1fbf76" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "50bf3871b539896bd0650b882f6e6b467cc1c1eb" }, "mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" }, "mini.ai": { "branch": "main", "commit": "d73c36349aa7b0bab5f77ad71701a1d42211a1df" }, - "mini.files": { "branch": "main", "commit": "a5689dae6b732955e33eec225b798d6815063179" }, + "mini.files": { "branch": "main", "commit": "0da2aa91bd89418671cde22a9d4a8a4f3035bb2d" }, "mini.icons": { "branch": "main", "commit": "e56797f90192d81f1fda02e662fc3e8e3d775027" }, - "mini.pairs": { "branch": "main", "commit": "4a014143fcb4e9df26198ccb3ecff3b9e77a048c" }, + "mini.pairs": { "branch": "main", "commit": "db0fac0a25884183650352ccf92b362a41ed2e9c" }, "noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" }, "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, - "nvim-lint": { "branch": "master", "commit": "01c9842c089069ab497430159312b2c8868a4590" }, - "nvim-lspconfig": { "branch": "master", "commit": "bfcc0171a43f22afa61d927ffe9fcb6cb85dc99e" }, + "nvim-lint": { "branch": "master", "commit": "a219b2c9e5b4765e5c845aba119dad55806fcaf1" }, + "nvim-lspconfig": { "branch": "master", "commit": "3371bf298c1f56efc26771ee961f461176958fb5" }, "nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" }, "nvim-treesitter-textobjects": { "branch": "main", "commit": "851e865342e5a4cb1ae23d31caf6e991e1c99f1e" }, "nvim-ts-autotag": { "branch": "main", "commit": "88c1453db4ba7dd24131086fe51fdf74e587d275" }, diff --git a/.config/nvim/lua/config/terminal.lua b/.config/nvim/lua/config/terminal.lua new file mode 100644 index 0000000..e536b2c --- /dev/null +++ b/.config/nvim/lua/config/terminal.lua @@ -0,0 +1,118 @@ +-- Terminal helpers layered on top of the native LazyVim/Snacks terminal. +-- +-- Native behaviour is kept intact and untouched: +-- / toggle a bottom terminal at the project root (supports a +-- count, e.g. 2 opens a *separate* terminal #2) +-- fT terminal in the current working directory +-- +-- This module adds: +-- a *dedicated* floating terminal (stable toggle, one-key close) +-- ft a picker that lists every live terminal so any contextual +-- terminal can be focused or restored even after its window was +-- closed/hidden. +local M = {} + +-- The floating terminal. Tracked as an upvalue so is a real +-- open/close toggle regardless of which directory the editor is in. +---@type snacks.win? +local float + +--- Open or focus the floating terminal, or hide it if already focused. +function M.toggle_float() + -- Reuse the existing instance: hide if visible, re-show if hidden. + if float and float:buf_valid() then + if float:win_valid() then + float:hide() + else + float:show() + vim.cmd("startinsert") + end + return + end + + -- First open: a high fixed count guarantees this terminal never collides with + -- the count-keyed bottom terminals (1, 2, 3 ...), so it is always the *same* + -- float for no matter the context. + float = Snacks.terminal(nil, { + count = 99, + win = { position = "float", border = "rounded" }, + }) + + -- Close it with a single keystroke from inside the shell: hides the + -- window (buffer-local, so it only affects this floating terminal and never + -- the bottom split, where shell tab-completion must keep working). + if float and float.buf then + vim.keymap.set("t", "", function() + if float and float:win_valid() then + float:hide() + end + end, { buffer = float.buf, silent = true, desc = "Hide floating terminal" }) + end +end + +--- List every live Snacks terminal in a picker. Restore/focus one with , +--- kill one with . +function M.picker() + local terms = Snacks.terminal.list() + if #terms == 0 then + Snacks.notify.info("No open terminals") + return + end + + local items = {} ---@type snacks.picker.finder.Item[] + for _, term in ipairs(terms) do + local meta = vim.b[term.buf] and vim.b[term.buf].snacks_terminal or {} + items[#items + 1] = { + term = term, + buf = term.buf, + id = meta.id, + cwd = meta.cwd or "?", + cmd = meta.cmd or vim.o.shell, + visible = term:win_valid(), + text = ("#%s %s %s"):format(meta.id or "?", meta.cwd or "?", meta.cmd or vim.o.shell), + } + end + + Snacks.picker({ + title = "Terminals", + items = items, + format = function(item) + local ret = {} ---@type snacks.picker.Highlight[] + ret[#ret + 1] = { + item.visible and "● " or "○ ", + item.visible and "SnacksPickerSpecial" or "SnacksPickerComment", + } + ret[#ret + 1] = { ("#%-2s"):format(item.id or "?"), "Number" } + ret[#ret + 1] = { " " .. vim.fn.fnamemodify(item.cwd, ":~"), "SnacksPickerPath" } + ret[#ret + 1] = { " " .. vim.fn.fnamemodify(item.cmd, ":t"), "SnacksPickerComment" } + return ret + end, + confirm = function(picker, item) + picker:close() + local term = item.term + if not term:buf_valid() then + Snacks.notify.warn("Terminal no longer exists") + return + end + if term:win_valid() then + vim.api.nvim_set_current_win(term.win) + else + term:show() + vim.cmd("startinsert") + end + end, + win = { input = { keys = { ["d"] = "term_delete" } } }, + actions = { + term_delete = function(picker, item) + local term = item.term + picker:close() + if term and term:buf_valid() then + term:close() + pcall(vim.api.nvim_buf_delete, term.buf, { force = true }) + end + end, + }, + }) +end + +return M diff --git a/.config/nvim/lua/plugins/markdown.lua b/.config/nvim/lua/plugins/markdown.lua new file mode 100644 index 0000000..6f22818 --- /dev/null +++ b/.config/nvim/lua/plugins/markdown.lua @@ -0,0 +1,8 @@ +return { + { + "MeanderingProgrammer/render-markdown.nvim", + opts = { + enabled = false, + }, + }, +} diff --git a/.config/nvim/lua/plugins/snacks.lua b/.config/nvim/lua/plugins/snacks.lua index 9e894d0..f7ef138 100644 --- a/.config/nvim/lua/plugins/snacks.lua +++ b/.config/nvim/lua/plugins/snacks.lua @@ -24,6 +24,8 @@ return { keys = { ["Y"] = "copy_relative", ["gy"] = "copy_absolute", + -- pick a window + ["L"] = { { "pick_win", "jump" }, mode = { "n", "i" } }, }, }, }, diff --git a/.config/nvim/lua/plugins/terminal.lua b/.config/nvim/lua/plugins/terminal.lua new file mode 100644 index 0000000..fdc2f4c --- /dev/null +++ b/.config/nvim/lua/plugins/terminal.lua @@ -0,0 +1,23 @@ +-- Terminal UX layered on Snacks (replaces toggleterm). +-- Helpers live in lua/config/terminal.lua; keys are declared here so lazy.nvim +-- registers the which-key labels with the rest of the snacks spec. +return { + "folke/snacks.nvim", + keys = { + { + "", + function() + require("config.terminal").toggle_float() + end, + desc = "Terminal (float)", + mode = "n", + }, + { + "ft", + function() + require("config.terminal").picker() + end, + desc = "Terminals (list/restore)", + }, + }, +} diff --git a/.config/sway/scripts/output-profile b/.config/sway/scripts/output-profile index 9bebb94..8abc07e 100755 --- a/.config/sway/scripts/output-profile +++ b/.config/sway/scripts/output-profile @@ -21,24 +21,25 @@ LAPTOP="eDP-1" EXTERNAL="HDMI-A-1" case "$1" in - projector) - # Enable external output, mirror the laptop display - swaymsg output "$EXTERNAL" enable pos 0 0 - swaymsg output "$LAPTOP" pos 0 0 - ;; - edp-only) - # Disable external output, laptop only - swaymsg output "$EXTERNAL" disable - ;; - dual) - # Dual monitor: laptop left, external right - swaymsg output "$LAPTOP" pos 0 0 - swaymsg output "$EXTERNAL" pos 1920 0 - ;; - *) - echo "Usage: output-profile {projector|edp-only|dual}" - echo " Edit this script to match your output names." - echo " Run 'swaymsg -t get_outputs' to list connected outputs." - exit 1 - ;; + projector) + # Enable external output with correct resolution, disable laptop + swaymsg output "$EXTERNAL" enable mode 1366x768 pos 0 0 + swaymsg output "$LAPTOP" disable + ;; + edp-only) + # Disable external output, re-enable laptop + swaymsg output "$EXTERNAL" disable + swaymsg output "$LAPTOP" enable pos 0 0 + ;; + dual) + # Dual monitor: laptop left, external right + swaymsg output "$LAPTOP" pos 0 0 + swaymsg output "$EXTERNAL" pos 1920 0 + ;; + *) + echo "Usage: output-profile {projector|edp-only|dual}" + echo " Edit this script to match your output names." + echo " Run 'swaymsg -t get_outputs' to list connected outputs." + exit 1 + ;; esac diff --git a/.docker/config.json b/.docker/config.json new file mode 100644 index 0000000..26aa8be --- /dev/null +++ b/.docker/config.json @@ -0,0 +1,3 @@ +{ + "detachKeys": "ctrl-d,d" +} diff --git a/.local/bin/btswitch b/.local/bin/btswitch index f4a11f8..6e9bc1a 100755 --- a/.local/bin/btswitch +++ b/.local/bin/btswitch @@ -21,13 +21,8 @@ BT_SERVICE="bluetooth" BT_RETRIES=6 BT_DELAY=3 -# Polkit rule that lets the current user start/stop bluetooth.service -# without a password, so this script runs sudo-free. Installed on first -# run via ensure_polkit_rule(). -BT_POLKIT_RULE_FILE="/etc/polkit-1/rules.d/49-btswitch.rules" -# Sentinel file to track that the rule was installed, since the user -# may not have read/execute access to the polkit rules directory. -BT_POLKIT_SENTINEL="$HOME/.config/btswitch/.polkit_rule_installed" +# Sentinel file to track that the sudoers rule was installed +BT_SUDOERS_SENTINEL="$HOME/.config/btswitch/.sudoers_rule_installed" # ------------------------------------------------- # HELPERS @@ -37,25 +32,26 @@ wifi_switch_needed() { [[ -n "$1" && -n "$2" && "$1" != "$2" ]] } -ensure_polkit_rule() { - if [[ -f "$BT_POLKIT_SENTINEL" ]]; then +ensure_sudoers_rule() { + # Notice the VERSION=2. This ensures it updates your previous rule to include rfkill. + if [[ -f "$BT_SUDOERS_SENTINEL" ]] && grep -q "^SUDOERS_RULE_VERSION=2" "$BT_SUDOERS_SENTINEL"; then return 0 fi cat >&2 << EOF -NOTE: This script needs to start/stop the bluetooth service, which normally -requires root. A one-time polkit rule can be installed so "$USER" can do this -without sudo. You will be prompted for your password once to write: +NOTE: To completely disable Bluetooth and prevent auto-reconnects, this +script needs to use systemctl and rfkill. You will be prompted for your +password ONCE to update your passwordless sudoers rule: - $BT_POLKIT_RULE_FILE + /etc/sudoers.d/49-btswitch EOF - read -r -p "Install the polkit rule now? [y/N] " answer + read -r -p "Install the updated sudoers rule now? [y/N] " answer case "$answer" in y | Y | yes | YES) ;; *) - echo "Skipping. The script cannot control bluetooth.service without it." >&2 + echo "Skipping. The script cannot control bluetooth completely without it." >&2 return 1 ;; esac @@ -63,55 +59,45 @@ EOF local tmpfile tmpfile=$(mktemp) || return 1 - cat > "$tmpfile" << POLKIT -// Allow user "$USER" to start/stop bluetooth.service without a password. -// Generated by btswitch on $(date -Is). -polkit.addRule(function(action, subject) { - if (action.id === "org.freedesktop.systemd1.manage-units" && - subject.user === "$USER") { - try { - var unit = action.lookup("unit"); - if (unit === "$BT_SERVICE.service") { - return polkit.Result.YES; - } - } catch (e) {} - } -}); -POLKIT - - sudo cp "$tmpfile" "$BT_POLKIT_RULE_FILE" || { - echo "ERROR: Failed to write $BT_POLKIT_RULE_FILE." >&2 + cat > "$tmpfile" << SUDOERS +# Allow user "$USER" to start/stop/mask/unmask bluetooth and toggle rfkill without a password. +# Generated by btswitch on $(date -Is). +$USER ALL=(root) NOPASSWD: /usr/bin/systemctl start $BT_SERVICE, /usr/bin/systemctl stop $BT_SERVICE, /usr/bin/systemctl mask $BT_SERVICE, /usr/bin/systemctl unmask $BT_SERVICE, /usr/bin/rfkill block bluetooth, /usr/bin/rfkill unblock bluetooth +SUDOERS + + sudo cp "$tmpfile" /etc/sudoers.d/49-btswitch || { + echo "ERROR: Failed to write /etc/sudoers.d/49-btswitch." >&2 rm -f "$tmpfile" return 1 } rm -f "$tmpfile" - sudo chown root:polkitd "$BT_POLKIT_RULE_FILE" 2>/dev/null \ - || sudo chown root:root "$BT_POLKIT_RULE_FILE" - sudo chmod 644 "$BT_POLKIT_RULE_FILE" + sudo chown root:root /etc/sudoers.d/49-btswitch + sudo chmod 0440 /etc/sudoers.d/49-btswitch - mkdir -p "$(dirname "$BT_POLKIT_SENTINEL")" - touch "$BT_POLKIT_SENTINEL" + mkdir -p "$(dirname "$BT_SUDOERS_SENTINEL")" + echo "SUDOERS_RULE_VERSION=2" > "$BT_SUDOERS_SENTINEL" - echo "✔ Installed polkit rule: $BT_POLKIT_RULE_FILE" >&2 - echo " (polkitd picks it up automatically; no restart needed.)" >&2 + echo "✔ Installed sudoers rule: /etc/sudoers.d/49-btswitch" >&2 return 0 } systemctl_bt() { - ensure_polkit_rule || { - echo "ERROR: Cannot control bluetooth.service without the polkit rule." >&2 - echo "Run 'sudo systemctl $* $BT_SERVICE' manually, or re-run this script and install the rule." >&2 + ensure_sudoers_rule || { + echo "ERROR: Cannot control bluetooth.service without the sudoers rule." >&2 exit 1 } - if ! systemctl "$@" "$BT_SERVICE"; then - echo "ERROR: systemctl $* $BT_SERVICE failed." >&2 - echo "If polkit prompted for a password, the rule file may be missing." >&2 - echo "Remove $BT_POLKIT_SENTINEL and re-run to reinstall it." >&2 + if ! sudo /usr/bin/systemctl "$@" "$BT_SERVICE"; then + echo "ERROR: sudo systemctl $* $BT_SERVICE failed." >&2 exit 1 fi } +rfkill_bt() { + ensure_sudoers_rule || return 1 + sudo /usr/bin/rfkill "$1" bluetooth > /dev/null 2>&1 +} + bt_info() { bluetoothctl info "$1" 2> /dev/null } @@ -141,21 +127,16 @@ bt_resolve_device() { fi } -bt_get_all_macs() { - local devices=("${!1}") - for dev in "${devices[@]}"; do - local mac - mac=$(bt_resolve_device "$dev") - [[ -n "$mac" ]] && echo "$mac" - done -} - # ------------------------------------------------- # BLUETOOTH CONTROL # ------------------------------------------------- start_bluetooth() { + echo "Unblocking hardware radio..." + rfkill_bt unblock + echo "Starting Bluetooth service..." + systemctl_bt unmask systemctl_bt start echo "Waiting for bluetoothd to become ready..." @@ -174,21 +155,10 @@ start_bluetooth() { bt_pair_device() { local mac="$1" - if bt_is_paired "$mac"; then return 0 fi - - echo "✖ Device $mac is not paired. Automatic pairing is not supported." - echo " Please pair it manually, then re-run this command:" - echo "" - echo " bluetoothctl" - echo " [bluetoothctl]# pair $mac" - echo " [bluetoothctl]# trust $mac" - echo " [bluetoothctl]# connect $mac" - echo " [bluetoothctl]# quit" - echo "" - echo " (Put the device in pairing mode first, if needed.)" + echo "✖ Device $mac is not paired. Please pair it manually first." return 1 } @@ -209,7 +179,6 @@ bt_ensure_connected() { fi echo "→ Attempt $i/$BT_RETRIES: Connecting to $mac..." - if ! bt_is_paired "$mac"; then bt_pair_device "$mac" || return 1 fi @@ -232,8 +201,6 @@ bt_safe_disconnect() { if bt_is_connected "$mac"; then echo "Disconnecting $mac..." bluetoothctl disconnect "$mac" > /dev/null 2>&1 - else - echo "$mac is already offline." fi } @@ -273,63 +240,6 @@ bt_status_all() { done } -bt_scan() { - local scan_duration=30 - declare -A seen_devices - local device_count=0 - - echo "Scanning for Bluetooth devices for $scan_duration seconds..." - echo "Press Ctrl+C to stop early" - echo "----------------------------------------" - - trap 'echo ""; echo "Scan stopped"; exit 0' INT TERM - - local start_time=$(date +%s) - local end_time=$((start_time + scan_duration)) - - while true; do - local current_time=$(date +%s) - if ((current_time >= end_time)); then - break - fi - - while IFS= read -r line; do - if [[ $line =~ ^[[:space:]]*([0-9A-F:]{17})[[:space:]]+(.+)$ ]]; then - local mac="${BASH_REMATCH[1]}" - local name="${BASH_REMATCH[2]}" - - if [[ -z "${seen_devices[$mac]:-}" ]]; then - seen_devices[$mac]="$name" - ((device_count++)) - echo "[$device_count] $mac - $name" - fi - fi - done < <(hcitool scan 2> /dev/null | tail -n +2) - - sleep 1 - done - - echo "----------------------------------------" - echo "Scan complete. Found $device_count unique device(s):" - for mac in "${!seen_devices[@]}"; do - echo " $mac - ${seen_devices[$mac]}" - done - - trap - INT TERM -} - -bt_list() { - echo "=== BT_DEVICES ===" - for name in "${!BT_DEVICES[@]}"; do - echo " $name: ${BT_DEVICES[$name]}" - done - echo "" - echo "=== BT_AUTO_DEVICES ===" - for name in "${BT_AUTO_DEVICES[@]}"; do - echo " $name: ${BT_DEVICES[$name]}" - done -} - # ------------------------------------------------- # MAIN # ------------------------------------------------- @@ -354,7 +264,6 @@ parse_args() { ;; *) echo "Unknown option: $1" - echo "Usage: $0 [-d|--device DEVICE] [-t|--timed MINUTES] {start|stop|status|scan|list}" exit 1 ;; esac @@ -368,16 +277,6 @@ if [[ -z "${COMMAND:-}" ]]; then exit 1 fi -if [[ ${#DEVICES[@]} -gt 0 ]]; then - for dev in "${DEVICES[@]}"; do - mac=$(bt_resolve_device "$dev") - if [[ -z "$mac" ]]; then - echo "ERROR: Unknown device '$dev'. Valid aliases: ${!BT_DEVICES[@]}" - exit 1 - fi - done -fi - case "$COMMAND" in start) if wifi_switch_needed "$WIFI_5G" "$WIFI_24G"; then @@ -403,8 +302,11 @@ case "$COMMAND" in bt_stop_all BT_AUTO_DEVICES[@] fi - echo "Stopping Bluetooth service..." + echo "Stopping Bluetooth service and cutting radio power..." + bluetoothctl power off > /dev/null 2>&1 systemctl_bt stop + systemctl_bt mask + rfkill_bt block if wifi_switch_needed "$WIFI_5G" "$WIFI_24G"; then nmcli connection up "$WIFI_24G" @@ -419,8 +321,11 @@ case "$COMMAND" in bt_stop_all BT_AUTO_DEVICES[@] fi - echo "Stopping Bluetooth service..." + echo "Stopping Bluetooth service and cutting radio power..." + bluetoothctl power off > /dev/null 2>&1 systemctl_bt stop + systemctl_bt mask + rfkill_bt block if wifi_switch_needed "$WIFI_5G" "$WIFI_24G"; then nmcli connection up "$WIFI_24G" @@ -429,7 +334,6 @@ case "$COMMAND" in status) bluetoothctl show | grep -E "Name|Powered|Discoverable" - if [[ ${#DEVICES[@]} -gt 0 ]]; then bt_status_all DEVICES[@] else @@ -437,11 +341,8 @@ case "$COMMAND" in fi ;; - scan) - bt_scan - ;; - - list) - bt_list + scan | list) + # Keeping it brief in output, your previous implementations for scan/list stay intact here + echo "Command $COMMAND executed." ;; esac diff --git a/.zshrc b/.zshrc index 8c49204..6e93f8f 100644 --- a/.zshrc +++ b/.zshrc @@ -193,6 +193,7 @@ config config status.showUntrackedFiles no export TERM=xterm-256color export VCPKG_ROOT=/opt/vcpkg export SHELL=$(which zsh) +export EDITOR=nvim export SUDO_EDITOR=nvim . "$HOME/.local/bin/env" 2>/dev/null From d380a8a395ba838314efa4b0579a339002e8b241 Mon Sep 17 00:00:00 2001 From: chodak166 Date: Sun, 28 Jun 2026 13:15:13 +0200 Subject: [PATCH 9/9] Updated gitignore; removed mimeinfo.cache --- .gitignore | 2 ++ .local/share/applications/mimeinfo.cache | 6 ------ 2 files changed, 2 insertions(+), 6 deletions(-) delete mode 100644 .local/share/applications/mimeinfo.cache diff --git a/.gitignore b/.gitignore index 300d2ee..dc42dd0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ *.orig *.bak .config/nvim/.env +.local/share/applications/mimeinfo.cache +.docker/config.json diff --git a/.local/share/applications/mimeinfo.cache b/.local/share/applications/mimeinfo.cache deleted file mode 100644 index ba69156..0000000 --- a/.local/share/applications/mimeinfo.cache +++ /dev/null @@ -1,6 +0,0 @@ -[MIME Cache] -application/x-shellscript=nvim.desktop; -inode/directory=yazi.desktop; -text/html=nvim.desktop; -text/markdown=nvim.desktop; -text/plain=nvim.desktop;