├── apps ├── roxide │ ├── hooks │ │ ├── rebase.sh │ │ ├── typos.sh │ │ ├── cargo-init.sh │ │ └── go-init.sh │ ├── remotes │ │ ├── docs.toml │ │ ├── ucloud.toml.secret │ │ ├── test.toml │ │ └── github.toml │ └── config.toml ├── sddm │ ├── sddm.conf │ ├── README.md │ └── theme.conf ├── k9s │ ├── config.yaml │ ├── aliases.yaml │ └── skins │ │ └── catppuccin-mocha.yaml ├── grub │ ├── archlinux.tar │ └── README.md ├── kubewrap │ └── config.toml ├── csync │ ├── client.toml.secret │ └── pki │ │ ├── token_public.pem.secret │ │ └── token_private.pem.secret ├── flameshot │ └── flameshot.ini ├── fcitx5 │ ├── README.md │ └── classicui.conf ├── lazygit │ └── config.yml ├── starship.toml ├── vscode │ └── settings.json └── otree.toml ├── typos.toml ├── term ├── zsh │ ├── secrets.sh.secret │ ├── lib │ │ ├── history.zsh │ │ ├── welcome.zsh │ │ ├── completion.zsh │ │ └── tools.zsh │ ├── zshenv │ └── zshrc ├── wezterm │ ├── config │ │ ├── custom.lua │ │ ├── utils.lua │ │ └── keys.lua │ ├── README.md │ ├── wezterm.lua │ └── plugin │ │ ├── catppuccin.lua │ │ └── bar.lua ├── kitty │ ├── kitty.conf │ └── mocha.conf ├── alacritty │ ├── alacritty.toml │ └── mocha.toml └── tmux │ └── tmux.conf.local ├── hyprland ├── rofi │ ├── bin │ │ ├── rofi-csync │ │ └── rofi-powermenu │ ├── config.rasi │ └── themes │ │ ├── rounded-common.rasi │ │ └── powermenu.rasi ├── hypr │ ├── conf.d │ │ ├── colors.conf │ │ ├── custom.conf │ │ ├── exec.conf │ │ ├── env.conf │ │ ├── rules.conf │ │ ├── README.md │ │ ├── general.conf │ │ └── keybind.conf │ ├── hyprpaper.conf │ ├── hyprland.conf │ ├── hyprlock │ │ └── status.sh │ ├── themes │ │ └── mocha.conf │ └── hyprlock.conf ├── mako │ └── config └── waybar │ ├── mocha.css │ ├── style.css │ └── config.jsonc ├── .dockerignore ├── .gitignore ├── Makefile ├── guides ├── GPU.md └── installation.md ├── scripts ├── proxy.sh ├── topng.py ├── rolling.sh ├── bootstrap.sh ├── syncpkg.py ├── updpkg.sh └── setup.sh ├── Dockerfile ├── packages ├── macos.json └── archlinux.json └── README.md /apps/roxide/hooks/rebase.sh: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/roxide/hooks/typos.sh: -------------------------------------------------------------------------------- 1 | typos . 2 | -------------------------------------------------------------------------------- /apps/roxide/hooks/cargo-init.sh: -------------------------------------------------------------------------------- 1 | cargo init 2 | -------------------------------------------------------------------------------- /apps/roxide/remotes/docs.toml: -------------------------------------------------------------------------------- 1 | icon = "󰈙" 2 | -------------------------------------------------------------------------------- /apps/sddm/sddm.conf: -------------------------------------------------------------------------------- 1 | [Theme] 2 | Current=sddm-astronaut-theme 3 | -------------------------------------------------------------------------------- /apps/k9s/config.yaml: -------------------------------------------------------------------------------- 1 | k9s: 2 | ui: 3 | skin: catppuccin-mocha 4 | -------------------------------------------------------------------------------- /typos.toml: -------------------------------------------------------------------------------- 1 | [default.extend-words] 2 | ba = "ba" 3 | BA = "BA" 4 | daed = "daed" 5 | -------------------------------------------------------------------------------- /apps/grub/archlinux.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fioncat/dotfiles/HEAD/apps/grub/archlinux.tar -------------------------------------------------------------------------------- /apps/kubewrap/config.toml: -------------------------------------------------------------------------------- 1 | [nodeshell] 2 | image = "uhub.service.ucloud.cn/library/alpine:latest" 3 | -------------------------------------------------------------------------------- /term/zsh/secrets.sh.secret: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fioncat/dotfiles/HEAD/term/zsh/secrets.sh.secret -------------------------------------------------------------------------------- /apps/csync/client.toml.secret: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fioncat/dotfiles/HEAD/apps/csync/client.toml.secret -------------------------------------------------------------------------------- /apps/flameshot/flameshot.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | contrastOpacity=188 3 | savePath=/home/wenqian 4 | useGrimAdapter=true 5 | -------------------------------------------------------------------------------- /apps/csync/pki/token_public.pem.secret: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fioncat/dotfiles/HEAD/apps/csync/pki/token_public.pem.secret -------------------------------------------------------------------------------- /apps/roxide/remotes/ucloud.toml.secret: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fioncat/dotfiles/HEAD/apps/roxide/remotes/ucloud.toml.secret -------------------------------------------------------------------------------- /apps/csync/pki/token_private.pem.secret: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fioncat/dotfiles/HEAD/apps/csync/pki/token_private.pem.secret -------------------------------------------------------------------------------- /hyprland/rofi/bin/rofi-csync: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | csynctl select -dr 'rofi -i -dmenu -p "󰅍 Clipboard"' 6 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | apps/roxide/remotes/* 2 | 3 | !apps/roxide/remotes/github.toml 4 | !apps/roxide/remotes/test.toml 5 | 6 | apps/polybar/interface.ini 7 | -------------------------------------------------------------------------------- /apps/roxide/remotes/test.toml: -------------------------------------------------------------------------------- 1 | icon = "" 2 | 3 | [owners."golang"] 4 | on_create = ["go-init"] 5 | 6 | [owners."rust"] 7 | on_create = ["cargo-init"] 8 | -------------------------------------------------------------------------------- /hyprland/hypr/conf.d/colors.conf: -------------------------------------------------------------------------------- 1 | source=~/.config/hypr/themes/mocha.conf 2 | 3 | general { 4 | col.active_border = $pink 5 | col.inactive_border = $surface0 6 | } 7 | -------------------------------------------------------------------------------- /hyprland/hypr/conf.d/custom.conf: -------------------------------------------------------------------------------- 1 | # Add custom setting here 2 | # You should ignore this file in local workspace: 3 | # git update-index --skip-worktree hyprland/hypr/conf.d/custom.conf 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | apps/polybar/interface.ini 2 | rolling_clash 3 | 4 | # rox:secrets 5 | apps/roxide/remotes/ucloud.toml 6 | apps/csync/client.toml 7 | apps/csync/pki/*.pem 8 | term/zsh/secrets.sh 9 | -------------------------------------------------------------------------------- /hyprland/hypr/hyprpaper.conf: -------------------------------------------------------------------------------- 1 | preload = ~/Pictures/wallpaper.png 2 | 3 | wallpaper = HDMI-A-2,~/Pictures/wallpaper.png 4 | wallpaper = DP-2,~/Pictures/wallpaper.png 5 | wallpaper = , ~/Pictures/wallpaper.png 6 | -------------------------------------------------------------------------------- /apps/k9s/aliases.yaml: -------------------------------------------------------------------------------- 1 | aliases: 2 | dp: deployments 3 | sec: v1/secrets 4 | jo: jobs 5 | cr: clusterroles 6 | crb: clusterrolebindings 7 | ro: roles 8 | rb: rolebindings 9 | np: networkpolicies 10 | -------------------------------------------------------------------------------- /hyprland/hypr/conf.d/exec.conf: -------------------------------------------------------------------------------- 1 | # Bar, wallpaper 2 | exec-once = waybar 3 | exec-once = hyprpaper 4 | 5 | # Input method 6 | exec-once = fcitx5 7 | 8 | # Notification 9 | exec-once = mako 10 | 11 | # Clipboard history 12 | exec-once = wl-copy -c && csyncd restart 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DOCKER_CMD:=$(if $(DOCKER_CMD),$(DOCKER_CMD),docker) 2 | DOCKER_BUCKET:=$(if $(DOCKER_BUCKET),$(DOCKER_BUCKET),fioncat) 3 | 4 | BASE_IMAGE:=$(if $(BASE_IMAGE),$(BASE_IMAGE),archlinux:latest) 5 | 6 | .PHONY: build 7 | build: 8 | $(DOCKER_CMD) build --build-arg BASE_IMAGE=$(BASE_IMAGE) -t $(DOCKER_BUCKET)/dev:archlinux . 9 | -------------------------------------------------------------------------------- /hyprland/hypr/hyprland.conf: -------------------------------------------------------------------------------- 1 | source=~/.config/hypr/conf.d/env.conf 2 | source=~/.config/hypr/conf.d/colors.conf 3 | source=~/.config/hypr/conf.d/general.conf 4 | source=~/.config/hypr/conf.d/exec.conf 5 | source=~/.config/hypr/conf.d/keybind.conf 6 | source=~/.config/hypr/conf.d/rules.conf 7 | source=~/.config/hypr/conf.d/custom.conf 8 | -------------------------------------------------------------------------------- /term/wezterm/config/custom.lua: -------------------------------------------------------------------------------- 1 | ---@type wezterm 2 | local wezterm = require("wezterm") 3 | local M = {} 4 | 5 | M.apply = function(c) 6 | -- Add custom setting here 7 | -- You should ignore this file in local workspace: 8 | -- git update-index --skip-worktree term/wezterm/config/custom.lua 9 | end 10 | 11 | return M 12 | -------------------------------------------------------------------------------- /apps/fcitx5/README.md: -------------------------------------------------------------------------------- 1 | # Fcitx5 2 | 3 | Install themes: 4 | 5 | ```bash 6 | git clone https://github.com/catppuccin/fcitx5.git /tmp/fcitx5 7 | mkdir -p ~/.local/share/fcitx5/themes/ 8 | cp -r /tmp/fcitx5/src/* ~/.local/share/fcitx5/themes 9 | rm -rf /tmp/fcitx5 10 | ``` 11 | 12 | Replace file `~/.config/fcitx5/conf/classicui.conf`. 13 | -------------------------------------------------------------------------------- /term/kitty/kitty.conf: -------------------------------------------------------------------------------- 1 | include mocha.conf 2 | 3 | background_opacity 1 4 | 5 | font_family SauceCodePro Nerd Font 6 | bold_font auto 7 | italic_font auto 8 | bold_italic_font auto 9 | 10 | font_size 14.0 11 | 12 | copy_on_select yes 13 | 14 | cursor_shape block 15 | cursor_blink_interval 0 16 | shell_integration no-cursor 17 | -------------------------------------------------------------------------------- /apps/roxide/remotes/github.toml: -------------------------------------------------------------------------------- 1 | clone = "github.com" 2 | icon = "" 3 | 4 | [api] 5 | provider = "github" 6 | token = "${GITHUB_TOKEN}" 7 | 8 | [default] 9 | user = "fioncat" 10 | email = "lazycat7706@gmail.com" 11 | 12 | [owners."fioncat"] 13 | sync = true 14 | pin = true 15 | ssh = true 16 | 17 | [owners."ucloud"] 18 | sync = true 19 | pin = true 20 | ssh = true 21 | -------------------------------------------------------------------------------- /hyprland/hypr/conf.d/env.conf: -------------------------------------------------------------------------------- 1 | # Input Method 2 | # See https://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland 3 | env = XIM,fcitx 4 | env = XIM_PROGRAM,fcitx 5 | env = INPUT_METHOD,fcitx 6 | env = GTK_IM_MODULE,fcitx 7 | env = QT_IM_MODULE,fcitx 8 | env = XMODIFIERS,@im=fcitx 9 | 10 | # Application Themes 11 | env = QT_QPA_PLATFORM, wayland 12 | env = QT_QPA_PLATFORMTHEME, qt5ct 13 | 14 | env = XCURSOR_SIZE,24 15 | -------------------------------------------------------------------------------- /term/alacritty/alacritty.toml: -------------------------------------------------------------------------------- 1 | import = [ 2 | "~/.config/alacritty/mocha.toml" 3 | ] 4 | 5 | [window] 6 | opacity = 1.0 7 | 8 | [font] 9 | size = 14.0 10 | normal = { family = "SauceCodePro Nerd Font" } 11 | bold = { family = "SauceCodePro Nerd Font" } 12 | italic = { family = "SauceCodePro Nerd Font" } 13 | 14 | [mouse] 15 | hide_when_typing = true 16 | 17 | [selection] 18 | save_to_clipboard = true 19 | -------------------------------------------------------------------------------- /hyprland/mako/config: -------------------------------------------------------------------------------- 1 | font="SauceCodePro Nerd Font 14" 2 | 3 | padding=10 4 | 5 | margin=0,20,20 6 | border-size=2 7 | border-radius=5 8 | default-timeout=10000 9 | group-by=summary 10 | 11 | background-color=#1e1e2e 12 | text-color=#cdd6f4 13 | border-color=#89b4fa 14 | progress-color=over #313244 15 | 16 | [urgency=high] 17 | border-color=#fab387 18 | 19 | [flameshot] 20 | ignore=1 21 | 22 | [fcitx5] 23 | ignore=1 24 | -------------------------------------------------------------------------------- /term/wezterm/README.md: -------------------------------------------------------------------------------- 1 | # wezterm-config 2 | 3 | My config files for wezterm 4 | 5 | Doc: [wezterm Config struct](https://wezfurlong.org/wezterm/config/lua/config/index.html) 6 | 7 | Plugins: 8 | 9 | - [bar](https://github.com/nekowinston/wezterm-bar) 10 | - [catppuccin](https://github.com/catppuccin/wezterm) 11 | 12 | Install: 13 | 14 | ```bash 15 | git clone https://github.com/fioncat/wezterm-config.git ~/.config/wezterm 16 | ``` 17 | -------------------------------------------------------------------------------- /apps/grub/README.md: -------------------------------------------------------------------------------- 1 | # Grub Theme 2 | 3 | Install the theme: 4 | 5 | ```bash 6 | mkdir Distro 7 | tar -xf archlinux.tar -C ./Distro 8 | sudo mv ./Distro /usr/share/grub/themes 9 | ``` 10 | 11 | Change the theme: 12 | 13 | ```bash 14 | sudo vim /etc/default/grub 15 | ``` 16 | 17 | Add the line: 18 | 19 | ```ini 20 | GRUB_THEME="/usr/share/grub/themes/Distro/theme.txt" 21 | ``` 22 | 23 | Flush grub: 24 | 25 | ```bash 26 | sudo grub-mkconfig -o /boot/grub/grub.cfg 27 | ``` 28 | -------------------------------------------------------------------------------- /guides/GPU.md: -------------------------------------------------------------------------------- 1 | # GPU 2 | 3 | References: 4 | 5 | - [archlinux 显卡驱动](https://arch.icekylin.online/guide/rookie/graphic-driver.html). 6 | 7 | ## Intel 8 | 9 | ```bash 10 | sudo pacman -S mesa lib32-mesa vulkan-intel lib32-vulkan-intel 11 | ``` 12 | 13 | ## NVIDIA 14 | 15 | ```bash 16 | sudo pacman -S nvidia-open nvidia-settings lib32-nvidia-utils 17 | ``` 18 | 19 | ## AMD 20 | 21 | ```bash 22 | sudo pacman -S mesa lib32-mesa xf86-video-amdgpu vulkan-radeon lib32-vulkan-radeon 23 | ``` 24 | -------------------------------------------------------------------------------- /apps/roxide/hooks/go-init.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | if [[ -n "${REMOTE_CLONE}" ]]; then 4 | mod_name="${REMOTE_CLONE}/${OWNER_NAME}/${REPO_NAME}" 5 | else 6 | mod_name="test/${REPO_NAME}" 7 | fi 8 | 9 | echo "Go module name: ${mod_name}" 10 | go mod init "${mod_name}" 11 | touch main.go 12 | 13 | echo 'package main' >>main.go 14 | echo '' >>main.go 15 | echo 'import "fmt"' >>main.go 16 | echo '' >>main.go 17 | echo 'func main() {' >>main.go 18 | echo ' fmt.Println("Hello, World!")' >>main.go 19 | echo '}' >>main.go 20 | -------------------------------------------------------------------------------- /apps/roxide/config.toml: -------------------------------------------------------------------------------- 1 | stats_ignore = [ 2 | "vendor", 3 | "target", 4 | "tests", 5 | "bin", 6 | ] 7 | 8 | mirror_icon = "" 9 | 10 | edit_allow_fail = false 11 | 12 | [[hooks]] 13 | name = "go-init" 14 | when = ["created"] 15 | run = ["go-init"] 16 | on = [ 17 | "test golang", 18 | ] 19 | 20 | [[hooks]] 21 | name = "cargo-init" 22 | when = ["created"] 23 | run = ["cargo-init"] 24 | on = [ 25 | "test rust", 26 | ] 27 | 28 | [[hooks]] 29 | name = "spell-check" 30 | when = ["updated"] 31 | run = ["typos"] 32 | on = [ 33 | "github fioncat", 34 | ] 35 | -------------------------------------------------------------------------------- /scripts/proxy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | os_type=$(uname -s) 6 | if [[ "$os_type" != "Linux" ]]; then 7 | echo "Unsupported OS: $os_type" 8 | exit 1 9 | fi 10 | 11 | if [[ ! -f /etc/arch-release ]]; then 12 | echo "Not an Arch Linux distribution" 13 | exit 1 14 | fi 15 | 16 | if [ "$(id -u)" -eq 0 ]; then 17 | echo "Running as root is forbidden" 18 | exit 1 19 | fi 20 | 21 | sudo pacman -S daed 22 | sudo systemctl enable --now daed 23 | 24 | echo "Congratulations! The daed has already been installed." 25 | echo " * Please open this in your browser: http://localhost:2023" 26 | -------------------------------------------------------------------------------- /apps/lazygit/config.yml: -------------------------------------------------------------------------------- 1 | gui: 2 | # Use the mocha catppuccin theme 3 | theme: 4 | activeBorderColor: 5 | - '#89b4fa' 6 | - bold 7 | inactiveBorderColor: 8 | - '#a6adc8' 9 | optionsTextColor: 10 | - '#89b4fa' 11 | selectedLineBgColor: 12 | - '#313244' 13 | selectedRangeBgColor: 14 | - '#313244' 15 | cherryPickedCommitBgColor: 16 | - '#45475a' 17 | cherryPickedCommitFgColor: 18 | - '#89b4fa' 19 | unstagedChangesColor: 20 | - '#f38ba8' 21 | defaultFgColor: 22 | - '#cdd6f4' 23 | searchingActiveBorderColor: 24 | - '#f9e2af' 25 | -------------------------------------------------------------------------------- /apps/sddm/README.md: -------------------------------------------------------------------------------- 1 | # Install sddm theme 2 | 3 | Install dependencies: 4 | 5 | ```bash 6 | sudo pacman -S qt6-5compat qt6-declarative qt6-svg 7 | ``` 8 | 9 | Install theme: 10 | 11 | ```bash 12 | sudo git clone https://github.com/keyitdev/sddm-astronaut-theme.git /usr/share/sddm/themes/sddm-astronaut-theme 13 | sudo cp /usr/share/sddm/themes/sddm-astronaut-theme/Fonts/* /usr/share/fonts/ 14 | ``` 15 | 16 | Replace config: 17 | 18 | ```bash 19 | sudo cp ~/dotfiles/apps/sddm/sddm.conf /etc/sddm.conf 20 | sudo cp ~/dotfiles/apps/sddm/theme.conf /usr/share/sddm/themes/sddm-astronaut-theme/theme.conf 21 | ``` 22 | -------------------------------------------------------------------------------- /apps/starship.toml: -------------------------------------------------------------------------------- 1 | # ~/.config/starship.toml 2 | 3 | format = "$all$character" 4 | 5 | [rust] 6 | symbol = "󱘗 " 7 | 8 | [golang] 9 | symbol = " " 10 | 11 | [lua] 12 | symbol = "󰢱 " 13 | 14 | [python] 15 | symbol = "󰌠 " 16 | 17 | [c] 18 | symbol = " " 19 | 20 | [nodejs] 21 | symbol = "󰎙 " 22 | 23 | [custom.hello] 24 | command = '''ROXIDE_WRAP="true" roxide which''' 25 | when = ''' test "$(ROXIDE_WRAP=true roxide which)" ''' 26 | require_repo = true 27 | style = "fg:#fab387" 28 | format = "rox [$output]($style) " 29 | 30 | [custom.kubewrap] 31 | command = 'kubewrap show' 32 | when = ''' test "$(kubewrap show)" ''' 33 | symbol = '󱃾' 34 | style = "fg:#74c7ec" 35 | format = "\n[$symbol $output]($style) " 36 | -------------------------------------------------------------------------------- /hyprland/rofi/bin/rofi-powermenu: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | config="~/.config/rofi/themes/powermenu.rasi" 4 | script_dir="$(cd "$(dirname "$0")" >/dev/null 2>&1 && pwd)" 5 | 6 | shutdown="⏻" 7 | reboot="" 8 | lock="" 9 | suspend="󰤄" 10 | logout="󰗽" 11 | 12 | # sh "$script_dir/accent.sh" 13 | 14 | chosen="$(printf "%s\n%s\n%s\n%s\n%s\n" "$shutdown" "$reboot" "$lock" "$suspend" "$logout" | rofi -theme "$config" -p "$(uptime -p)" -dmenu -selected-row 2)" 15 | 16 | case "$chosen" in 17 | "$shutdown") 18 | poweroff 19 | ;; 20 | "$reboot") 21 | reboot 22 | ;; 23 | "$lock") 24 | hyprlock 25 | ;; 26 | "$suspend") 27 | systemctl suspend 28 | ;; 29 | "$logout") 30 | killall Hyprland 31 | ;; 32 | esac 33 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # NOTE: BASE_IMAGE only supports ArchLinux 2 | ARG BASE_IMAGE="archlinux:latest" 3 | FROM ${BASE_IMAGE} 4 | 5 | MAINTAINER "Wenqian lazycat7706@gmail.com" 6 | 7 | RUN pacman-key --init && pacman -Syu --noconfirm && pacman -S --noconfirm sudo 8 | 9 | RUN useradd -m -G wheel -s /bin/bash wenqian && \ 10 | echo "wenqian ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \ 11 | chown -R wenqian:wenqian /home/wenqian 12 | 13 | USER wenqian 14 | WORKDIR /home/wenqian 15 | 16 | COPY . dotfiles 17 | RUN sudo pacman -S --noconfirm git base-devel go && git clone https://aur.archlinux.org/yay.git && cd yay && makepkg -si --noconfirm && cd .. && rm -rf yay 18 | RUN USER="wenqian" dotfiles/scripts/setup.sh --nodocker 19 | 20 | ENTRYPOINT ["/usr/bin/zsh"] 21 | -------------------------------------------------------------------------------- /hyprland/rofi/config.rasi: -------------------------------------------------------------------------------- 1 | /******************************************************* 2 | * ROFI configs i3 Apps menu for EndeavourOS 3 | * Maintainer: joekamprad 4 | *******************************************************/ 5 | 6 | configuration { 7 | font: "Sans 16"; 8 | 9 | modi: "run,drun,window"; 10 | icon-theme: "Oranchelo"; 11 | show-icons: true; 12 | terminal: "wezterm"; 13 | drun-display-format: "{icon} {name}"; 14 | location: 0; 15 | disable-history: false; 16 | hide-scrollbar: true; 17 | display-drun: " 󰘳 Apps "; 18 | display-run: "  Run "; 19 | display-window: "  Window"; 20 | display-Network: " 󰤨 Network"; 21 | display-clipboard: "󰅍 Clipboard"; 22 | } 23 | 24 | @theme "rounded-common" 25 | -------------------------------------------------------------------------------- /hyprland/hypr/hyprlock/status.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############ Variables ############ 4 | enable_battery=false 5 | battery_charging=false 6 | 7 | ####### Check availability ######## 8 | for battery in /sys/class/power_supply/*BAT*; do 9 | if [[ -f "$battery/uevent" ]]; then 10 | enable_battery=true 11 | if [[ $(cat /sys/class/power_supply/*/status | head -1) == "Charging" ]]; then 12 | battery_charging=true 13 | fi 14 | break 15 | fi 16 | done 17 | 18 | ############# Output ############# 19 | if [[ $enable_battery == true ]]; then 20 | if [[ $battery_charging == true ]]; then 21 | echo -n "(+) " 22 | fi 23 | echo -n "$(cat /sys/class/power_supply/*/capacity | head -1)"% 24 | if [[ $battery_charging == false ]]; then 25 | echo -n " remaining" 26 | fi 27 | fi 28 | 29 | echo '' 30 | -------------------------------------------------------------------------------- /apps/vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.fontSize": 16, 3 | "editor.fontFamily": "'SauceCodePro Nerd Font'", 4 | "editor.cursorBlinking": "solid", 5 | "editor.lineNumbers": "relative", 6 | "workbench.colorTheme": "Catppuccin Mocha", 7 | "debug.console.fontSize": 16, 8 | "chat.editor.fontSize": 16, 9 | "markdown.preview.fontSize": 16, 10 | "window.zoomLevel": 1, 11 | "editor.fontLigatures": false, 12 | "vim.leader": "", 13 | "vim.normalModeKeyBindingsNonRecursive": [ 14 | { 15 | "before": ["", "w", "/"], 16 | "commands": [":vs"] 17 | }, 18 | { 19 | "before": [""], 20 | "after": ["^"] 21 | }, 22 | { 23 | "before": [""], 24 | "after": ["$"] 25 | } 26 | ], 27 | "security.workspace.trust.untrustedFiles": "open" 28 | } 29 | -------------------------------------------------------------------------------- /hyprland/hypr/conf.d/rules.conf: -------------------------------------------------------------------------------- 1 | windowrulev2 = noblur, class:.* 2 | 3 | # Window rules 4 | windowrulev2 = float, class:^(steam)$ 5 | windowrulev2 = float, class:^(wechat)$ 6 | windowrulev2 = float, class:^(QQ)$ 7 | 8 | # Dialogs 9 | windowrulev2 = center, title:^(Open File)(.*)$ 10 | windowrulev2 = center, title:^(Select a File)(.*)$ 11 | windowrulev2 = center, title:^(Choose wallpaper)(.*)$ 12 | windowrulev2 = center, title:^(Open Folder)(.*)$ 13 | windowrulev2 = center, title:^(Save As)(.*)$ 14 | windowrulev2 = center, title:^(Library)(.*)$ 15 | windowrulev2 = center, title:^(File Upload)(.*)$ 16 | windowrulev2 = float, title:^(Open File)(.*)$ 17 | windowrulev2 = float, title:^(Select a File)(.*)$ 18 | windowrulev2 = float, title:^(Choose wallpaper)(.*)$ 19 | windowrulev2 = float, title:^(Open Folder)(.*)$ 20 | windowrulev2 = float, title:^(Save As)(.*)$ 21 | windowrulev2 = float, title:^(Library)(.*)$ 22 | windowrulev2 = float, title:^(File Upload)(.*)$ 23 | windowrulev2 = float, title:^(微信)(.*)$ 24 | -------------------------------------------------------------------------------- /hyprland/hypr/conf.d/README.md: -------------------------------------------------------------------------------- 1 | # Hyprland Configuration 2 | 3 | Useful for non-HHKB keyboard: 4 | 5 | ``` 6 | input { 7 | kb_options = caps:ctrl_shifted_capslock,altwin:swap_alt_win 8 | } 9 | ``` 10 | 11 | Multiple monitors configuration: 12 | 13 | ``` 14 | # The main monitor, on the left 15 | monitorv2 { 16 | output = DP-2 17 | mode = 2560x1440@100.00 18 | position = 0x0 19 | scale = 1 20 | } 21 | 22 | # The secondary monitor, on the right 23 | monitorv2 { 24 | output = HDMI-A-2 25 | mode = 2560x1440@59.95 26 | position = 2560x0 27 | scale = 1 28 | } 29 | ``` 30 | 31 | Assign workspaces to monitors: 32 | 33 | ``` 34 | # Main workspaces 35 | workspace = 1, monitor:DP-2 36 | workspace = 2, monitor:DP-1 37 | workspace = 3, monitor:DP-2 38 | 39 | # Secondary workspaces 40 | workspace = 4, monitor:HDMI-A-2 41 | workspace = 5, monitor:HDMI-A-2 42 | workspace = 6, monitor:HDMI-A-2 43 | workspace = 7, monitor:HDMI-A-2 44 | workspace = 8, monitor:HDMI-A-2 45 | workspace = 9, monitor:HDMI-A-2 46 | ``` 47 | -------------------------------------------------------------------------------- /apps/fcitx5/classicui.conf: -------------------------------------------------------------------------------- 1 | # Vertical Candidate List 2 | Vertical Candidate List=False 3 | # Use mouse wheel to go to prev or next page 4 | WheelForPaging=True 5 | # Font 6 | Font="Sans 15" 7 | # Menu Font 8 | MenuFont="Sans 15" 9 | # Tray Font 10 | TrayFont="Sans Bold 10" 11 | # Tray Label Outline Color 12 | TrayOutlineColor=#000000 13 | # Tray Label Text Color 14 | TrayTextColor=#ffffff 15 | # Prefer Text Icon 16 | PreferTextIcon=True 17 | # Show Layout Name In Icon 18 | ShowLayoutNameInIcon=True 19 | # Use input method language to display text 20 | UseInputMethodLanguageToDisplayText=True 21 | # Theme 22 | Theme=catppuccin-mocha 23 | # Dark Theme 24 | DarkTheme=catppuccin-mocha 25 | # Follow system light/dark color scheme 26 | UseDarkTheme=False 27 | # Follow system accent color if it is supported by theme and desktop 28 | UseAccentColor=True 29 | # Use Per Screen DPI on X11 30 | PerScreenDPI=False 31 | # Force font DPI on Wayland 32 | ForceWaylandDPI=0 33 | # Enable fractional scale under Wayland 34 | EnableFractionalScale=True 35 | -------------------------------------------------------------------------------- /hyprland/waybar/mocha.css: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Catppuccin Mocha palette 4 | * Maintainer: rubyowo 5 | * 6 | */ 7 | 8 | @define-color base #1e1e2e; 9 | @define-color mantle #181825; 10 | @define-color crust #11111b; 11 | 12 | @define-color text #cdd6f4; 13 | @define-color subtext0 #a6adc8; 14 | @define-color subtext1 #bac2de; 15 | 16 | @define-color surface0 #313244; 17 | @define-color surface1 #45475a; 18 | @define-color surface2 #585b70; 19 | 20 | @define-color overlay0 #6c7086; 21 | @define-color overlay1 #7f849c; 22 | @define-color overlay2 #9399b2; 23 | 24 | @define-color blue #89b4fa; 25 | @define-color lavender #b4befe; 26 | @define-color sapphire #74c7ec; 27 | @define-color sky #89dceb; 28 | @define-color teal #94e2d5; 29 | @define-color green #a6e3a1; 30 | @define-color yellow #f9e2af; 31 | @define-color peach #fab387; 32 | @define-color maroon #eba0ac; 33 | @define-color red #f38ba8; 34 | @define-color mauve #cba6f7; 35 | @define-color pink #f5c2e7; 36 | @define-color flamingo #f2cdcd; 37 | @define-color rosewater #f5e0dc; 38 | -------------------------------------------------------------------------------- /term/wezterm/config/utils.lua: -------------------------------------------------------------------------------- 1 | ---@type wezterm 2 | local wezterm = require("wezterm") 3 | local M = {} 4 | 5 | ---merge two tables, t2 overwriting t1 6 | ---@param t1 table 7 | ---@param t2 table 8 | ---@return table 9 | M.tableMerge = function(t1, t2) 10 | for k, v in pairs(t2) do 11 | if type(v) == "table" then 12 | if type(t1[k] or false) == "table" then 13 | M.tableMerge(t1[k] or {}, t2[k] or {}) 14 | else 15 | t1[k] = v 16 | end 17 | else 18 | t1[k] = v 19 | end 20 | end 21 | return t1 22 | end 23 | 24 | ---check if a table contains a value 25 | ---@param t table 26 | ---@param val any 27 | ---@return boolean 28 | M.tableContains = function(t, val) 29 | for _, v in ipairs(t) do 30 | if v == val then 31 | return true 32 | end 33 | end 34 | return false 35 | end 36 | 37 | ---check if we're on Linux 38 | ---@return boolean 39 | M.is_linux = function() 40 | return wezterm.target_triple:find("linux") ~= nil 41 | end 42 | 43 | ---check if we're on macOS 44 | ---@return boolean 45 | M.is_darwin = function() 46 | return wezterm.target_triple:find("darwin") ~= nil 47 | end 48 | 49 | return M 50 | -------------------------------------------------------------------------------- /term/wezterm/wezterm.lua: -------------------------------------------------------------------------------- 1 | local wezterm = require("wezterm") 2 | local config = wezterm.config_builder() 3 | 4 | config.font = wezterm.font_with_fallback({ 5 | { family = "SauceCodePro Nerd Font", weight = "Medium" }, 6 | "Noto Sans CJK SC", -- Require: noto-fonts-cjk 7 | }) 8 | config.font_size = 14 9 | config.command_palette_font_size = config.font_size * 1.1 10 | config.freetype_load_target = "Light" 11 | 12 | config.window_padding = { left = 0, right = 0, top = 10, bottom = 0 } 13 | 14 | config.window_background_opacity = 0.97 15 | 16 | config.native_macos_fullscreen_mode = true 17 | 18 | -- This require: yay -S wezterm-git 19 | -- TODO: Wait for https://github.com/wez/wezterm/pull/5264 to be released 20 | config.enable_wayland = true 21 | 22 | -- https://github.com/nekowinston/wezterm-bar 23 | require("plugin.bar").apply_to_config(config, { 24 | position = "top", 25 | }) 26 | 27 | -- https://github.com/catppuccin/wezterm 28 | require("plugin.catppuccin").apply_to_config(config, { 29 | sync = true, 30 | sync_flavors = { light = "mocha", dark = "mocha" }, 31 | }) 32 | 33 | require("config.keys").apply(config) 34 | require("config.custom").apply(config) 35 | 36 | return config 37 | -------------------------------------------------------------------------------- /packages/macos.json: -------------------------------------------------------------------------------- 1 | { 2 | "list": [ 3 | "brew list -1 --formula --full-name", 4 | "brew list -1 --cask" 5 | ], 6 | "install": { 7 | "default": "brew install %pkg", 8 | "cask": "brew install --cask %pkg" 9 | }, 10 | "packages": [ 11 | "cask:cursor", 12 | "cask:docker", 13 | "cask:feishu", 14 | "cask:font-sauce-code-pro-nerd-font", 15 | "cask:google-chrome", 16 | "cask:qqmusic", 17 | "cask:studio-3t", 18 | "cask:tableplus", 19 | "cask:tencent-lemon", 20 | "cask:tencent-meeting", 21 | "cask:wechat", 22 | "cask:wechatwork", 23 | "cask:wezterm", 24 | "cask:wpsoffice-cn", 25 | "cask:xmind", 26 | 27 | "fioncat/apps/csync", 28 | "fioncat/apps/filewarden", 29 | "fioncat/apps/kubewrap", 30 | "fioncat/apps/otree", 31 | "fioncat/apps/roxide", 32 | 33 | "bottom", 34 | "bruno", 35 | "duf", 36 | "eza", 37 | "fastfetch", 38 | "fd", 39 | "fzf", 40 | "go", 41 | "k9s", 42 | "kubernetes-cli", 43 | "lazygit", 44 | "make", 45 | "make", 46 | "neovim", 47 | "node", 48 | "ripgrep", 49 | "rustup", 50 | "starship", 51 | "stylua", 52 | "tree-sitter", 53 | "tree-sitter-cli", 54 | "unzip", 55 | "wget", 56 | "yarn", 57 | "zsh-autosuggestions", 58 | "zsh-syntax-highlighting" 59 | ] 60 | } 61 | -------------------------------------------------------------------------------- /hyprland/hypr/themes/mocha.conf: -------------------------------------------------------------------------------- 1 | $rosewaterAlpha = f5e0dc 2 | $flamingoAlpha = f2cdcd 3 | $pinkAlpha = f5c2e7 4 | $mauveAlpha = cba6f7 5 | $redAlpha = f38ba8 6 | $maroonAlpha = eba0ac 7 | $peachAlpha = fab387 8 | $yellowAlpha = f9e2af 9 | $greenAlpha = a6e3a1 10 | $tealAlpha = 94e2d5 11 | $skyAlpha = 89dceb 12 | $sapphireAlpha = 74c7ec 13 | $blueAlpha = 89b4fa 14 | $lavenderAlpha = b4befe 15 | 16 | $textAlpha = cdd6f4 17 | $subtext1Alpha = bac2de 18 | $subtext0Alpha = a6adc8 19 | 20 | $overlay2Alpha = 9399b2 21 | $overlay1Alpha = 7f849c 22 | $overlay0Alpha = 6c7086 23 | 24 | $surface2Alpha = 585b70 25 | $surface1Alpha = 45475a 26 | $surface0Alpha = 313244 27 | 28 | $baseAlpha = 1e1e2e 29 | $mantleAlpha = 181825 30 | $crustAlpha = 11111b 31 | 32 | $rosewater = 0xfff5e0dc 33 | $flamingo = 0xfff2cdcd 34 | $pink = 0xfff5c2e7 35 | $mauve = 0xffcba6f7 36 | $red = 0xfff38ba8 37 | $maroon = 0xffeba0ac 38 | $peach = 0xfffab387 39 | $yellow = 0xfff9e2af 40 | $green = 0xffa6e3a1 41 | $teal = 0xff94e2d5 42 | $sky = 0xff89dceb 43 | $sapphire = 0xff74c7ec 44 | $blue = 0xff89b4fa 45 | $lavender = 0xffb4befe 46 | 47 | $text = 0xffcdd6f4 48 | $subtext1 = 0xffbac2de 49 | $subtext0 = 0xffa6adc8 50 | 51 | $overlay2 = 0xff9399b2 52 | $overlay1 = 0xff7f849c 53 | $overlay0 = 0xff6c7086 54 | 55 | $surface2 = 0xff585b70 56 | $surface1 = 0xff45475a 57 | $surface0 = 0xff313244 58 | 59 | $base = 0xff1e1e2e 60 | $mantle = 0xff181825 61 | $crust = 0xff11111b 62 | -------------------------------------------------------------------------------- /term/alacritty/mocha.toml: -------------------------------------------------------------------------------- 1 | [colors.primary] 2 | background = "#1e1e2e" 3 | foreground = "#cdd6f4" 4 | dim_foreground = "#7f849c" 5 | bright_foreground = "#cdd6f4" 6 | 7 | [colors.cursor] 8 | text = "#1e1e2e" 9 | cursor = "#f5e0dc" 10 | 11 | [colors.vi_mode_cursor] 12 | text = "#1e1e2e" 13 | cursor = "#b4befe" 14 | 15 | [colors.search.matches] 16 | foreground = "#1e1e2e" 17 | background = "#a6adc8" 18 | 19 | [colors.search.focused_match] 20 | foreground = "#1e1e2e" 21 | background = "#a6e3a1" 22 | 23 | [colors.footer_bar] 24 | foreground = "#1e1e2e" 25 | background = "#a6adc8" 26 | 27 | [colors.hints.start] 28 | foreground = "#1e1e2e" 29 | background = "#f9e2af" 30 | 31 | [colors.hints.end] 32 | foreground = "#1e1e2e" 33 | background = "#a6adc8" 34 | 35 | [colors.selection] 36 | text = "#1e1e2e" 37 | background = "#f5e0dc" 38 | 39 | [colors.normal] 40 | black = "#45475a" 41 | red = "#f38ba8" 42 | green = "#a6e3a1" 43 | yellow = "#f9e2af" 44 | blue = "#89b4fa" 45 | magenta = "#f5c2e7" 46 | cyan = "#94e2d5" 47 | white = "#bac2de" 48 | 49 | [colors.bright] 50 | black = "#585b70" 51 | red = "#f38ba8" 52 | green = "#a6e3a1" 53 | yellow = "#f9e2af" 54 | blue = "#89b4fa" 55 | magenta = "#f5c2e7" 56 | cyan = "#94e2d5" 57 | white = "#a6adc8" 58 | 59 | [colors.dim] 60 | black = "#45475a" 61 | red = "#f38ba8" 62 | green = "#a6e3a1" 63 | yellow = "#f9e2af" 64 | blue = "#89b4fa" 65 | magenta = "#f5c2e7" 66 | cyan = "#94e2d5" 67 | white = "#bac2de" 68 | 69 | [[colors.indexed_colors]] 70 | index = 16 71 | color = "#fab387" 72 | 73 | [[colors.indexed_colors]] 74 | index = 17 75 | color = "#f5e0dc" 76 | -------------------------------------------------------------------------------- /term/zsh/lib/history.zsh: -------------------------------------------------------------------------------- 1 | ## History wrapper 2 | function omz_history { 3 | # parse arguments and remove from $@ 4 | local clear list stamp REPLY 5 | zparseopts -E -D c=clear l=list f=stamp E=stamp i=stamp t:=stamp 6 | 7 | if [[ -n "$clear" ]]; then 8 | # if -c provided, clobber the history file 9 | 10 | # confirm action before deleting history 11 | print -nu2 "This action will irreversibly delete your command history. Are you sure? [y/N] " 12 | builtin read -E 13 | [[ "$REPLY" = [yY] ]] || return 0 14 | 15 | print -nu2 >| "$HISTFILE" 16 | fc -p "$HISTFILE" 17 | 18 | print -u2 History file deleted. 19 | elif [[ $# -eq 0 ]]; then 20 | # if no arguments provided, show full history starting from 1 21 | builtin fc $stamp -l 1 22 | else 23 | # otherwise, run `fc -l` with a custom format 24 | builtin fc $stamp -l "$@" 25 | fi 26 | } 27 | 28 | alias history='omz_history -i' 29 | 30 | ## History file configuration 31 | [ -z "$HISTFILE" ] && HISTFILE="$HOME/.zsh_history" 32 | [ "$HISTSIZE" -lt 50000 ] && HISTSIZE=50000 33 | [ "$SAVEHIST" -lt 10000 ] && SAVEHIST=10000 34 | 35 | ## History command configuration 36 | setopt extended_history # record timestamp of command in HISTFILE 37 | setopt hist_expire_dups_first # delete duplicates first when HISTFILE size exceeds HISTSIZE 38 | setopt hist_ignore_dups # ignore duplicated commands history list 39 | setopt hist_ignore_space # ignore commands that start with space 40 | setopt hist_verify # show command with history expansion to user before running it 41 | setopt share_history # share command history data 42 | -------------------------------------------------------------------------------- /scripts/topng.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import os 5 | from PIL import Image 6 | 7 | 8 | def convert_to_png(input_path): 9 | # Create a temporary PNG file path 10 | temp_png_path = input_path + '.tmp.png' 11 | try: 12 | # Check if input file exists 13 | if not os.path.exists(input_path): 14 | print(f"Error: File '{input_path}' does not exist") 15 | return False 16 | 17 | # Convert image to PNG 18 | with Image.open(input_path) as img: 19 | img.save(temp_png_path, 'PNG') 20 | 21 | # Remove the original file 22 | os.remove(input_path) 23 | 24 | # Get the new filename (replace jpg extension with png) 25 | new_path = os.path.splitext(input_path)[0] + '.png' 26 | 27 | # Rename the temporary file to the final name 28 | os.rename(temp_png_path, new_path) 29 | 30 | print(f"Conversion successful: '{input_path}' -> '{new_path}'") 31 | return True 32 | 33 | except Exception as e: 34 | print(f"Conversion failed: {str(e)}") 35 | # Clean up temporary file if it exists 36 | if os.path.exists(temp_png_path): 37 | os.remove(temp_png_path) 38 | return False 39 | 40 | 41 | def main(): 42 | # Check command line arguments 43 | if len(sys.argv) != 2: 44 | print("Usage: topng.py ") 45 | sys.exit(1) 46 | 47 | # Get input file path 48 | input_path = sys.argv[1] 49 | 50 | # Execute conversion 51 | if not convert_to_png(input_path): 52 | sys.exit(1) 53 | 54 | 55 | if __name__ == "__main__": 56 | main() 57 | -------------------------------------------------------------------------------- /term/kitty/mocha.conf: -------------------------------------------------------------------------------- 1 | # vim:ft=kitty 2 | 3 | ## name: Catppuccin Kitty Mocha 4 | ## author: Catppuccin Org 5 | ## license: MIT 6 | ## upstream: https://github.com/catppuccin/kitty/blob/main/themes/mocha.conf 7 | ## blurb: Soothing pastel theme for the high-spirited! 8 | 9 | 10 | 11 | # The basic colors 12 | foreground #CDD6F4 13 | background #1E1E2E 14 | selection_foreground #1E1E2E 15 | selection_background #F5E0DC 16 | 17 | # Cursor colors 18 | cursor #F5E0DC 19 | cursor_text_color #1E1E2E 20 | 21 | # URL underline color when hovering with mouse 22 | url_color #F5E0DC 23 | 24 | # Kitty window border colors 25 | active_border_color #F2C2E7 26 | inactive_border_color #6C7086 27 | bell_border_color #F9E2AF 28 | 29 | # OS Window titlebar colors 30 | wayland_titlebar_color #1E1E2E 31 | macos_titlebar_color #1E1E2E 32 | 33 | # Tab bar colors 34 | active_tab_foreground #11111B 35 | active_tab_background #CBA6F7 36 | inactive_tab_foreground #CDD6F4 37 | inactive_tab_background #181825 38 | tab_bar_background #11111B 39 | 40 | # Colors for marks (marked text in the terminal) 41 | mark1_foreground #1E1E2E 42 | mark1_background #B4BEFE 43 | mark2_foreground #1E1E2E 44 | mark2_background #CBA6F7 45 | mark3_foreground #1E1E2E 46 | mark3_background #74C7EC 47 | 48 | # The 16 terminal colors 49 | 50 | # black 51 | color0 #45475A 52 | color8 #585B70 53 | 54 | # red 55 | color1 #F38BA8 56 | color9 #F38BA8 57 | 58 | # green 59 | color2 #A6E3A1 60 | color10 #A6E3A1 61 | 62 | # yellow 63 | color3 #F9E2AF 64 | color11 #F9E2AF 65 | 66 | # blue 67 | color4 #89B4FA 68 | color12 #89B4FA 69 | 70 | # magenta 71 | color5 #F5C2E7 72 | color13 #F5C2E7 73 | 74 | # cyan 75 | color6 #94E2D5 76 | color14 #94E2D5 77 | 78 | # white 79 | color7 #BAC2DE 80 | color15 #A6ADC8 81 | -------------------------------------------------------------------------------- /packages/archlinux.json: -------------------------------------------------------------------------------- 1 | { 2 | "list": [ 3 | "yay -Qq" 4 | ], 5 | "install": { 6 | "default": "sudo pacman -S --noconfirm %pkg", 7 | "yay": "yay -S --noconfirm %pkg" 8 | }, 9 | "packages": [ 10 | "yay:csync-release", 11 | "yay:downgrade", 12 | "yay:filewarden-release", 13 | "yay:kubewrap-release", 14 | "yay:otree-release", 15 | "yay:roxide-release", 16 | 17 | "appmenu-gtk-module", 18 | "bat", 19 | "bc", 20 | "bottom", 21 | "clang", 22 | "cpu-x", 23 | "curl", 24 | "docker", 25 | "docker-compose", 26 | "duf", 27 | "dust", 28 | "eza", 29 | "fastfetch", 30 | "fd", 31 | "fzf", 32 | "gcc", 33 | "git", 34 | "github-cli", 35 | "go", 36 | "inetutils", 37 | "jq", 38 | "k9s", 39 | "kubectl", 40 | "lazygit", 41 | "less", 42 | "libappindicator-gtk3", 43 | "librsvg", 44 | "lldb", 45 | "lsof", 46 | "lua", 47 | "luajit", 48 | "make", 49 | "mkcert", 50 | "neovim", 51 | "net-tools", 52 | "nodejs", 53 | "npm", 54 | "openssh", 55 | "openssl", 56 | "pacman-contrib", 57 | "perf", 58 | "pkgconf", 59 | "procs", 60 | "python-pillow", 61 | "python-pynvim", 62 | "ripgrep", 63 | "rsync", 64 | "rustup", 65 | "skopeo", 66 | "starship", 67 | "sysstat", 68 | "tcpdump", 69 | "typos", 70 | "unzip", 71 | "webkit2gtk-4.1", 72 | "wget", 73 | "wireshark-qt", 74 | "yapf", 75 | "yarn", 76 | "zip", 77 | "zsh", 78 | "zsh-autosuggestions", 79 | "zsh-completions", 80 | "zsh-syntax-highlighting" 81 | ] 82 | } 83 | -------------------------------------------------------------------------------- /term/tmux/tmux.conf.local: -------------------------------------------------------------------------------- 1 | tmux_conf_new_window_retain_current_path=false 2 | tmux_conf_new_pane_retain_current_path=true 3 | tmux_conf_new_pane_reconnect_ssh=false 4 | tmux_conf_new_session_prompt=false 5 | 6 | tmux_conf_update_plugins_on_launch=false 7 | 8 | tmux_conf_update_plugins_on_reload=false 9 | 10 | set -g @plugin 'catppuccin/tmux' 11 | set -g @plugin 'niksingh710/minimal-tmux-status' 12 | 13 | set -g @minimal-tmux-status "top" 14 | 15 | set -g @catppuccin_pane_border_style "fg=#f5c2e7" 16 | set -g @catppuccin_pane_active_border_style "fg=#f5c2e7" 17 | set -g @catppuccin_status_background "#181825" 18 | set -g @minimal-tmux-bg "#f38ba8" 19 | 20 | set -g window-style 'fg=#f5c2e7' 21 | set -g window-active-style 'fg=#f5c2e7' 22 | 23 | set -g focus-events on 24 | set-hook -g pane-focus-out 'select-pane -P bg=#181825,fg=default' 25 | set-hook -g pane-focus-in 'select-pane -P bg=default,fg=default' 26 | 27 | set -g mouse on 28 | set -g status-position top 29 | 30 | set -g default-terminal "tmux-256color" 31 | set-option -ga terminal-overrides ",xterm-256color:Tc" 32 | 33 | set -s escape-time 0 34 | set -sg repeat-time 0 35 | 36 | unbind C-a 37 | unbind C-s 38 | unbind C-c 39 | unbind C-f 40 | unbind - 41 | unbind _ 42 | unbind C-h 43 | unbind C-l 44 | unbind f 45 | unbind \; 46 | 47 | set-option -g prefix C-s 48 | set-option -g prefix2 C-s 49 | bind C-s send-prefix 50 | 51 | bind . run -b 'tmux rename-window "`basename \"#{pane_current_path}\"`"' 52 | bind \; run -b 'tmux rename-window "`roxide display #{pane_current_path}`"' 53 | bind x kill-pane 54 | 55 | bind b set-option status 56 | 57 | bind / split-pane -h 58 | bind - split-pane -v 59 | 60 | bind q display-panes -d 0 61 | 62 | bind -T copy-mode-vi y send -X copy-selection-no-clear 63 | bind -T copy-mode-vi MouseDragEnd1Pane send -X copy-selection-no-clear 64 | bind -T copy-mode-vi DoubleClick1Pane send -X copy-selection-no-clear 65 | 66 | bind -T copy-mode MouseDragEnd1Pane send -X copy-selection-no-clear 67 | bind -T copy-mode DoubleClick1Pane send -X copy-selection-no-clear 68 | -------------------------------------------------------------------------------- /apps/otree.toml: -------------------------------------------------------------------------------- 1 | [filter] 2 | ignore_case = true 3 | 4 | [header] 5 | format = " {version} - {data_source} ({content_type}) - {data_size} " 6 | 7 | [data] 8 | wrap = true 9 | 10 | [palette] 11 | base = "#1e1e2e" 12 | mantle = "#181825" 13 | crust = "#11111b" 14 | 15 | text = "#cdd6f4" 16 | subtext0 = "#a6adc8" 17 | subtext1 = "#bac2de" 18 | 19 | surface0 = "#313244" 20 | surface1 = "#45475a" 21 | surface2 = "#585b70" 22 | 23 | overlay0 = "#6c7086" 24 | overlay1 = "#7f849c" 25 | overlay2 = "#9399b2" 26 | 27 | blue = "#89b4fa" 28 | lavender = "#b4befe" 29 | sapphire = "#74c7ec" 30 | sky = "#89dceb" 31 | teal = "#94e2d5" 32 | green = "#a6e3a1" 33 | yellow = "#f9e2af" 34 | peach = "#fab387" 35 | maroon = "#eba0ac" 36 | red = "#f38ba8" 37 | mauve = "#cba6f7" 38 | pink = "#f5c2e7" 39 | flamingo = "#f2cdcd" 40 | rosewater = "#f5e0dc" 41 | 42 | [colors] 43 | header = { fg = "base", bg = "lavender", bold = true } 44 | focus_border = { fg = "lavender", bold = true } 45 | 46 | [colors.data] 47 | text = { fg = "text" } 48 | border = { fg = "blue" } 49 | symbol = { fg = "text" } 50 | name = { fg = "flamingo" } 51 | str = { fg = "green" } 52 | num = { fg = "peach" } 53 | null = { fg = "blue", italic = true } 54 | bool = { fg = "peach", bold = true, italic = true } 55 | section = { fg = "blue", bold = true } 56 | 57 | [colors.tree] 58 | border = { fg = "blue" } 59 | filter_keyword = { fg = "maroon", bg = "surface2" } 60 | selected = { bg = "surface0" } 61 | type_str = { fg = "green", bold = true, italic = true } 62 | type_null = { fg = "blue", bold = true, italic = true } 63 | type_bool = { fg = "peach", bold = true, italic = true } 64 | type_num = { fg = "peach", bold = true, italic = true } 65 | type_arr = { fg = "blue", bold = true, italic = true } 66 | type_obj = { fg = "blue", bold = true, italic = true } 67 | value = { fg = "dark_gray" } 68 | 69 | [colors.footer] 70 | root = { fg = "base", bg = "sky", bold = true } 71 | identify = { fg = "base", bg = "peach", bold = true } 72 | message = { fg = "green", bold = true } 73 | 74 | [colors.popup] 75 | error_text = { fg = "red" } 76 | -------------------------------------------------------------------------------- /hyprland/hypr/hyprlock.conf: -------------------------------------------------------------------------------- 1 | $text_color = rgba(F7DCDEFF) 2 | $entry_background_color = rgba(1D101111) 3 | $entry_border_color = rgba(A58A8D55) 4 | $entry_color = rgba(DEBFC2FF) 5 | $check_color = rgba(89B4FA55) 6 | $fail_color = rgba(F38BA855) 7 | $font_family = Noto Sans CJK SC 8 | $font_family_clock = Noto Sans CJK SC 9 | $font_material_symbols = Material Symbols Rounded 10 | 11 | background { 12 | color = rgba(1D101177) 13 | path = ~/Pictures/lock.png 14 | blur_size = 3 15 | blur_passes = 3 16 | } 17 | 18 | input-field { 19 | monitor = 20 | size = 250, 50 21 | outline_thickness = 2 22 | dots_size = 0.1 23 | dots_spacing = 0.3 24 | 25 | outer_color = $entry_border_color 26 | inner_color = $entry_background_color 27 | font_color = $entry_color 28 | 29 | check_color = $check_color 30 | fail_color = $fail_color 31 | 32 | placeholder_text = 33 | fail_text = 34 | 35 | # fade_on_empty = true 36 | 37 | position = 0, 20 38 | halign = center 39 | valign = center 40 | } 41 | 42 | label { # Clock 43 | monitor = 44 | text = $TIME 45 | shadow_passes = 1 46 | shadow_boost = 0.5 47 | color = $text_color 48 | font_size = 65 49 | font_family = $font_family_clock 50 | 51 | position = 0, 300 52 | halign = center 53 | valign = center 54 | } 55 | 56 | label { # Date 57 | monitor = 58 | text = cmd[update:5000] date +'%a %b %e %Y' 59 | shadow_passes = 1 60 | shadow_boost = 0.5 61 | color = $text_color 62 | font_size = 20 63 | font_family = $font_family 64 | 65 | position = 0, 200 66 | halign = center 67 | valign = center 68 | } 69 | 70 | label { # lock icon 71 | monitor = 72 | text = Locked 73 | shadow_passes = 1 74 | shadow_boost = 0.5 75 | color = $text_color 76 | font_size = 21 77 | font_family = $font_material_symbols 78 | 79 | position = 0, 65 80 | halign = center 81 | valign = bottom 82 | } 83 | 84 | label { # Status 85 | monitor = 86 | text = cmd[update:5000] ~/.config/hypr/hyprlock/status.sh 87 | shadow_passes = 1 88 | shadow_boost = 0.5 89 | color = $text_color 90 | font_size = 14 91 | font_family = $font_family 92 | 93 | position = 30, -30 94 | halign = left 95 | valign = top 96 | } 97 | -------------------------------------------------------------------------------- /hyprland/rofi/themes/rounded-common.rasi: -------------------------------------------------------------------------------- 1 | /*******r*********************************************************************** 2 | * ROUNDED THEME FOR ROFI 3 | * User : LR-Tech 4 | * Theme Repo : https://github.com/lr-tech/rofi-themes-collection 5 | *******************************************************************************/ 6 | 7 | * { 8 | font: "Sans 16"; 9 | 10 | background-color: transparent; 11 | text-color: @fg0; 12 | 13 | margin: 0px; 14 | padding: 0px; 15 | spacing: 0px; 16 | 17 | bg0: #212121F2; 18 | bg1: #2A2A2A; 19 | bg2: #3D3D3D80; 20 | bg3: #1A73E8F2; 21 | fg0: #E6E6E6; 22 | fg1: #FFFFFF; 23 | fg2: #969696; 24 | fg3: #3D3D3D; 25 | } 26 | 27 | window { 28 | location: center; 29 | width: 1200; 30 | border-radius: 24px; 31 | 32 | background-color: @bg0; 33 | } 34 | 35 | mainbox { 36 | padding: 12px; 37 | } 38 | 39 | inputbar { 40 | background-color: @bg1; 41 | border-color: @bg3; 42 | 43 | border: 2px; 44 | border-radius: 16px; 45 | 46 | padding: 8px 16px; 47 | spacing: 8px; 48 | children: [ prompt, entry ]; 49 | } 50 | 51 | prompt { 52 | text-color: @fg2; 53 | } 54 | 55 | entry { 56 | placeholder: "Search"; 57 | placeholder-color: @fg3; 58 | } 59 | 60 | message { 61 | margin: 12px 0 0; 62 | border-radius: 16px; 63 | border-color: @bg2; 64 | background-color: @bg2; 65 | } 66 | 67 | textbox { 68 | padding: 8px 24px; 69 | } 70 | 71 | listview { 72 | background-color: transparent; 73 | 74 | margin: 12px 0 0; 75 | lines: 15; 76 | columns: 1; 77 | 78 | fixed-height: false; 79 | } 80 | 81 | element { 82 | padding: 8px 16px; 83 | spacing: 8px; 84 | border-radius: 16px; 85 | } 86 | 87 | element normal active { 88 | text-color: @bg3; 89 | } 90 | 91 | element selected normal, element selected active { 92 | background-color: @bg3; 93 | } 94 | 95 | element-icon { 96 | size: 1em; 97 | vertical-align: 0.5; 98 | } 99 | 100 | element-text { 101 | text-color: inherit; 102 | } 103 | -------------------------------------------------------------------------------- /scripts/rolling.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | # Parse command line arguments 6 | SKIP_SYSTEM=false 7 | SKIP_RUST=false 8 | SKIP_NVIM=false 9 | SKIP_ROXIDE=false 10 | 11 | while [[ $# -gt 0 ]]; do 12 | case $1 in 13 | --skip-system) 14 | SKIP_SYSTEM=true 15 | shift 16 | ;; 17 | --skip-rust) 18 | SKIP_RUST=true 19 | shift 20 | ;; 21 | --skip-nvim) 22 | SKIP_NVIM=true 23 | shift 24 | ;; 25 | --skip-roxide) 26 | SKIP_ROXIDE=true 27 | shift 28 | ;; 29 | -h | --help) 30 | echo "Usage: $0 [options]" 31 | echo "Options:" 32 | echo " --skip-system Skip system update" 33 | echo " --skip-rust Skip rust update" 34 | echo " --skip-nvim Skip neovim config update" 35 | echo " --skip-roxide Skip roxide sync" 36 | echo " -h, --help Show this help message" 37 | exit 0 38 | ;; 39 | *) 40 | echo "Unknown option: $1" 41 | echo "Use -h or --help for usage information" 42 | exit 1 43 | ;; 44 | esac 45 | done 46 | 47 | MARK_DIR="$HOME/.local/share" 48 | mkdir -p "$MARK_DIR" 49 | 50 | MARK_FILE="$MARK_DIR/rolling" 51 | 52 | TODAY=$(date +%Y-%m-%d) 53 | 54 | if [ -f "$MARK_FILE" ] && [ "$(cat "$MARK_FILE")" == "$TODAY" ]; then 55 | exit 0 56 | fi 57 | 58 | if ! command -v flock &>/dev/null; then 59 | # If flock not found, it means we are on macOS, use brew to install it 60 | brew install flock 61 | fi 62 | 63 | LOCK_FILE="/tmp/rolling.lock" 64 | exec 299>"$LOCK_FILE" 65 | flock 299 66 | 67 | # After acquiring the lock, check again to avoid another process has already done the update 68 | if [ -f "$MARK_FILE" ] && [ "$(cat "$MARK_FILE")" == "$TODAY" ]; then 69 | exit 0 70 | fi 71 | 72 | CLASH_FLAG_FILE="$HOME/dotfiles/rolling_clash" 73 | if [ -f "$CLASH_FLAG_FILE" ]; then 74 | clash on 75 | fi 76 | 77 | if [ "$SKIP_SYSTEM" = false ]; then 78 | echo "Rolling update your system" 79 | 80 | OS_TYPE=$(uname -s) 81 | case "$OS_TYPE" in 82 | Darwin) 83 | brew update && brew upgrade --force 84 | brew cleanup 85 | ;; 86 | Linux) 87 | # yay -Fy downloads database files to local so that we can search packages 88 | yay -Fy && yay --noconfirm 89 | yay -Sc --noconfirm 90 | ;; 91 | *) 92 | echo "Unsupported OS: $OS_TYPE" 93 | exit 1 94 | ;; 95 | esac 96 | fi 97 | 98 | if [ "$SKIP_ROXIDE" = false ]; then 99 | echo "Updating all git repositories" 100 | ROXIDE_NO_CONFIRM="true" ROXIDE_WRAP="true" roxide sync -r 101 | else 102 | echo "Skipping roxide sync" 103 | fi 104 | 105 | if [ "$SKIP_RUST" = false ]; then 106 | echo "Updating rust" 107 | rustup update 108 | else 109 | echo "Skipping rust update" 110 | fi 111 | 112 | echo "Rolling done" 113 | echo "$TODAY" >"$MARK_FILE" 114 | -------------------------------------------------------------------------------- /scripts/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | os_type=$(uname -s) 6 | if [[ "$os_type" != "Linux" ]]; then 7 | echo "Unsupported OS: $os_type" 8 | exit 1 9 | fi 10 | 11 | if [[ ! -f /etc/arch-release ]]; then 12 | echo "Not an Arch Linux distribution" 13 | exit 1 14 | fi 15 | 16 | if [ "$(id -u)" -eq 0 ]; then 17 | echo "Running as root is forbidden" 18 | exit 1 19 | fi 20 | 21 | pacman="sudo pacman --noconfirm" 22 | yay="yay --noconfirm" 23 | 24 | if ! command -v yay &> /dev/null; then 25 | echo "Begin to install archlinuxcn and yay" 26 | 27 | sudo tee -a /etc/pacman.conf > /dev/null << EOF 28 | [multilib] 29 | Include = /etc/pacman.d/mirrorlist 30 | 31 | [archlinuxcn] 32 | Server = https://mirrors.ustc.edu.cn/archlinuxcn/\$arch 33 | EOF 34 | 35 | $pacman -Syyu 36 | $pacman -S archlinuxcn-keyring 37 | $pacman -S yay 38 | else 39 | echo "archlinuxcn and yay already installed, skip" 40 | fi 41 | 42 | if [[ ! -d $HOME/Downloads ]]; then 43 | $pacman -S xdg-user-dirs 44 | echo "Ensure some default directories" 45 | cd $HOME 46 | xdg-user-dirs-update 47 | fi 48 | 49 | basic_packages=( 50 | hyprland hyprpaper hyprlock waybar mako rofi-wayland xorg-xwayland 51 | kitty nm-connection-editor 52 | xdg-desktop-portal-hyprland grim 53 | 54 | # Fonts 55 | ttf-sourcecodepro-nerd adobe-source-han-serif-cn-fonts wqy-zenhei 56 | noto-fonts noto-fonts-cjk noto-fonts-emoji noto-fonts-extra 57 | 58 | # Audio 59 | pulseaudio sof-firmware alsa-firmware alsa-ucm-conf pavucontrol 60 | 61 | # Bluetooth 62 | bluez bluez-utils blueman 63 | 64 | # Input method 65 | fcitx5-im fcitx5-chinese-addons fcitx5-material-color 66 | 67 | # Clipboard 68 | wl-clipboard cliphist 69 | 70 | # Some GUI software 71 | thunar ristretto thunderbird okular 72 | 73 | sddm 74 | ) 75 | 76 | yay_packages=( 77 | google-chrome wezterm-git flameshot-git 78 | ) 79 | 80 | if ! command -v Hyprland &> /dev/null; then 81 | echo "Begin to install basic packages" 82 | $pacman -S ${basic_packages[@]} 83 | $yay -S ${yay_packages[@]} 84 | 85 | mkdir -p $HOME/.config 86 | ln -s $HOME/dotfiles/hyprland/hypr $HOME/.config 87 | ln -s $HOME/dotfiles/hyprland/rofi $HOME/.config 88 | ln -s $HOME/dotfiles/hyprland/mako $HOME/.config 89 | ln -s $HOME/dotfiles/hyprland/waybar $HOME/.config 90 | ln -s $HOME/dotfiles/term/wezterm $HOME/.config 91 | ln -s $HOME/dotfiles/term/kitty $HOME/.config 92 | 93 | sudo systemctl enable sddm 94 | sudo systemctl enable --now bluetooth 95 | 96 | echo "Bootstrap completed, you can reboot to enter Hyprland." 97 | echo "Next steps: 1) install proxy. 2) install dev." 98 | 99 | else 100 | echo "Hyprland already installed, skip" 101 | fi 102 | -------------------------------------------------------------------------------- /apps/k9s/skins/catppuccin-mocha.yaml: -------------------------------------------------------------------------------- 1 | k9s: 2 | body: 3 | fgColor: '#cdd6f4' 4 | bgColor: '#1e1e2e' 5 | logoColor: '#cba6f7' 6 | prompt: 7 | fgColor: '#cdd6f4' 8 | bgColor: '#181825' 9 | suggestColor: '#89b4fa' 10 | help: 11 | fgColor: '#cdd6f4' 12 | bgColor: '#1e1e2e' 13 | sectionColor: '#a6e3a1' 14 | keyColor: '#89b4fa' 15 | numKeyColor: '#eba0ac' 16 | frame: 17 | title: 18 | fgColor: '#94e2d5' 19 | bgColor: '#1e1e2e' 20 | highlightColor: '#f5c2e7' 21 | counterColor: '#f9e2af' 22 | filterColor: '#a6e3a1' 23 | border: 24 | fgColor: '#cba6f7' 25 | focusColor: '#b4befe' 26 | menu: 27 | fgColor: '#cdd6f4' 28 | keyColor: '#89b4fa' 29 | numKeyColor: '#eba0ac' 30 | crumbs: 31 | fgColor: '#1e1e2e' 32 | bgColor: '#eba0ac' 33 | activeColor: '#f2cdcd' 34 | status: 35 | newColor: '#89b4fa' 36 | modifyColor: '#b4befe' 37 | addColor: '#a6e3a1' 38 | pendingColor: '#fab387' 39 | errorColor: '#f38ba8' 40 | highlightColor: '#89dceb' 41 | killColor: '#cba6f7' 42 | completedColor: '#6c7086' 43 | info: 44 | fgColor: '#fab387' 45 | sectionColor: '#cdd6f4' 46 | views: 47 | table: 48 | fgColor: '#cdd6f4' 49 | bgColor: '#1e1e2e' 50 | cursorFgColor: '#313244' 51 | cursorBgColor: '#45475a' 52 | markColor: '#f5e0dc' 53 | header: 54 | fgColor: '#f9e2af' 55 | bgColor: '#1e1e2e' 56 | sorterColor: '#89dceb' 57 | xray: 58 | fgColor: '#cdd6f4' 59 | bgColor: '#1e1e2e' 60 | cursorColor: '#45475a' 61 | cursorTextColor: '#1e1e2e' 62 | graphicColor: '#f5c2e7' 63 | charts: 64 | bgColor: '#1e1e2e' 65 | chartBgColor: '#1e1e2e' 66 | dialBgColor: '#1e1e2e' 67 | defaultDialColors: 68 | - '#a6e3a1' 69 | - '#f38ba8' 70 | defaultChartColors: 71 | - '#a6e3a1' 72 | - '#f38ba8' 73 | resourceColors: 74 | cpu: 75 | - '#cba6f7' 76 | - '#89b4fa' 77 | mem: 78 | - '#f9e2af' 79 | - '#fab387' 80 | yaml: 81 | keyColor: '#89b4fa' 82 | valueColor: '#cdd6f4' 83 | colonColor: '#a6adc8' 84 | logs: 85 | fgColor: '#cdd6f4' 86 | bgColor: '#1e1e2e' 87 | indicator: 88 | fgColor: '#b4befe' 89 | bgColor: '#1e1e2e' 90 | toggleOnColor: '#a6e3a1' 91 | toggleOffColor: '#a6adc8' 92 | dialog: 93 | fgColor: '#f9e2af' 94 | bgColor: '#9399b2' 95 | buttonFgColor: '#1e1e2e' 96 | buttonBgColor: '#7f849c' 97 | buttonFocusFgColor: '#1e1e2e' 98 | buttonFocusBgColor: '#f5c2e7' 99 | labelFgColor: '#f5e0dc' 100 | fieldFgColor: '#cdd6f4' 101 | -------------------------------------------------------------------------------- /term/zsh/zshenv: -------------------------------------------------------------------------------- 1 | typeset -U path PATH 2 | path=( 3 | ~/bin 4 | ~/go/bin 5 | ~/.cargo/bin 6 | ~/nvim/bin 7 | ~/.local/share/go/bin 8 | /opt/nvim/bin 9 | /opt/homebrew/bin 10 | $path 11 | ) 12 | export PATH 13 | export ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=#6a687a" 14 | export TERM=xterm-256color 15 | export EDITOR='nvim' 16 | export GIT_EDITOR='nvim' 17 | export BAT_THEME="catppuccin-mocha" 18 | export FZF_DEFAULT_OPTS=" \ 19 | --height 80% \ 20 | --reverse \ 21 | --border \ 22 | --color=bg+:#313244,bg:#1e1e2e,spinner:#f5e0dc,hl:#f38ba8 \ 23 | --color=fg:#cdd6f4,header:#f38ba8,info:#cba6f7,pointer:#f5e0dc \ 24 | --color=marker:#f5e0dc,fg+:#cdd6f4,prompt:#cba6f7,hl+:#f38ba8" 25 | export BROWSER='google-chrome-stable' 26 | export LS_COLORS="rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=00:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.7z=01;31:*.ace=01;31:*.alz=01;31:*.apk=01;31:*.arc=01;31:*.arj=01;31:*.bz=01;31:*.bz2=01;31:*.cab=01;31:*.cpio=01;31:*.crate=01;31:*.deb=01;31:*.drpm=01;31:*.dwm=01;31:*.dz=01;31:*.ear=01;31:*.egg=01;31:*.esd=01;31:*.gz=01;31:*.jar=01;31:*.lha=01;31:*.lrz=01;31:*.lz=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.lzo=01;31:*.pyz=01;31:*.rar=01;31:*.rpm=01;31:*.rz=01;31:*.sar=01;31:*.swm=01;31:*.t7z=01;31:*.tar=01;31:*.taz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tgz=01;31:*.tlz=01;31:*.txz=01;31:*.tz=01;31:*.tzo=01;31:*.tzst=01;31:*.udeb=01;31:*.war=01;31:*.whl=01;31:*.wim=01;31:*.xz=01;31:*.z=01;31:*.zip=01;31:*.zoo=01;31:*.zst=01;31:*.avif=01;35:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:*~=00;90:*#=00;90:*.bak=00;90:*.crdownload=00;90:*.dpkg-dist=00;90:*.dpkg-new=00;90:*.dpkg-old=00;90:*.dpkg-tmp=00;90:*.old=00;90:*.orig=00;90:*.part=00;90:*.rej=00;90:*.rpmnew=00;90:*.rpmorig=00;90:*.rpmsave=00;90:*.swp=00;90:*.tmp=00;90:*.ucf-dist=00;90:*.ucf-new=00;90:*.ucf-old=00;90:" 27 | export NVM_DIR="$HOME/.nvm" 28 | export GITHUB_TOKEN="" 29 | export HOMEBREW_BREW_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git" 30 | export HOMEBREW_CORE_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git" 31 | export HOMEBREW_INSTALL_FROM_API=1 32 | -------------------------------------------------------------------------------- /hyprland/hypr/conf.d/general.conf: -------------------------------------------------------------------------------- 1 | monitor=,preferred,auto,auto 2 | 3 | # HDMI port: mirror display. To see device name, use `hyprctl monitors` 4 | # monitor=HDMI-A-1,1920x1080@60,1920x0,1,mirror,eDP-1 5 | 6 | input { 7 | kb_layout = us 8 | kb_variant = 9 | kb_model = 10 | # View all options: localectl list-x11-keymap-options 11 | kb_options = caps:numlock 12 | kb_rules = 13 | 14 | follow_mouse = 1 15 | 16 | touchpad { 17 | natural_scroll = no 18 | } 19 | 20 | sensitivity = 0 # -1.0 - 1.0, 0 means no modification. 21 | } 22 | 23 | binds { 24 | workspace_back_and_forth = false 25 | allow_workspace_cycles = true 26 | } 27 | 28 | general { 29 | gaps_in = 5 30 | gaps_out = 0 31 | border_size = 2 32 | 33 | col.active_border = $pink 34 | col.inactive_border = $surface0 35 | 36 | layout = dwindle 37 | 38 | allow_tearing = false 39 | } 40 | 41 | dwindle { 42 | pseudotile = yes 43 | preserve_split = yes 44 | } 45 | 46 | master { 47 | new_status = master 48 | } 49 | 50 | decoration { 51 | rounding = 10 52 | 53 | blur { 54 | enabled = true 55 | xray = true 56 | special = false 57 | new_optimizations = true 58 | size = 7 59 | passes = 4 60 | brightness = 1 61 | noise = 0.01 62 | contrast = 1 63 | popups = true 64 | popups_ignorealpha = 0.6 65 | } 66 | 67 | # Dim 68 | dim_inactive = false 69 | dim_strength = 0.1 70 | dim_special = 0 71 | } 72 | 73 | animations { 74 | enabled = true 75 | 76 | bezier = linear, 0, 0, 1, 1 77 | bezier = md3_standard, 0.2, 0, 0, 1 78 | bezier = md3_decel, 0.05, 0.7, 0.1, 1 79 | bezier = md3_accel, 0.3, 0, 0.8, 0.15 80 | bezier = overshot, 0.05, 0.9, 0.1, 1.1 81 | bezier = crazyshot, 0.1, 1.5, 0.76, 0.92 82 | bezier = hyprnostretch, 0.05, 0.9, 0.1, 1.0 83 | bezier = menu_decel, 0.1, 1, 0, 1 84 | bezier = menu_accel, 0.38, 0.04, 1, 0.07 85 | bezier = easeInOutCirc, 0.85, 0, 0.15, 1 86 | bezier = easeOutCirc, 0, 0.55, 0.45, 1 87 | bezier = easeOutExpo, 0.16, 1, 0.3, 1 88 | bezier = softAcDecel, 0.26, 0.26, 0.15, 1 89 | bezier = md2, 0.4, 0, 0.2, 1 90 | animation = windows, 1, 3, md3_decel, popin 60% 91 | animation = windowsIn, 1, 3, md3_decel, popin 60% 92 | animation = windowsOut, 1, 3, md3_accel, popin 60% 93 | animation = border, 1, 10, default 94 | animation = fade, 1, 3, md3_decel 95 | animation = layersIn, 1, 3, menu_decel, slide 96 | animation = layersOut, 1, 1.6, menu_accel 97 | animation = fadeLayersIn, 1, 3, menu_decel 98 | animation = fadeLayersOut, 1, 1.6, menu_accel 99 | animation = workspaces, 1, 7, menu_decel, slide 100 | animation = specialWorkspace, 1, 3, md3_decel, slidevert 101 | } 102 | 103 | misc { 104 | vfr = 1 105 | vrr = 1 106 | focus_on_activate = true 107 | animate_manual_resizes = false 108 | enable_swallow = false 109 | swallow_regex = (foot|kitty|alacritty|Alacritty) 110 | 111 | disable_hyprland_logo = true 112 | force_default_wallpaper = 0 113 | new_window_takes_over_fullscreen = 2 114 | } 115 | -------------------------------------------------------------------------------- /guides/installation.md: -------------------------------------------------------------------------------- 1 | # Installation Guide 2 | 3 | References: 4 | 5 | - [Arch Wiki](https://wiki.archlinux.org/title/Installation_guide). 6 | - [archlinux 简明指南](https://arch.icekylin.online/) 7 | 8 | ## Boot from live environment 9 | 10 | Download archlinux iso file from: [Download page](https://archlinux.org/download/). 11 | 12 | You can use [etcher](https://etcher.balena.io/) to create USB flash device. 13 | 14 | ## Disable reflector 15 | 16 | Disable the reflector to prevent the mirror from auto-updating: 17 | 18 | ```bash 19 | systemctl stop reflector 20 | ``` 21 | 22 | ## Ensure Internet connected 23 | 24 | ```bash 25 | curl http://baidu.com 26 | ``` 27 | 28 | ## Update the system clock 29 | 30 | ```bash 31 | timedatectl set-ntp true 32 | timedatectl status 33 | ``` 34 | 35 | ## Update pacman mirror 36 | 37 | Edit `/etc/pacman.d/mirrorlist`: 38 | 39 | ``` 40 | Server = https://mirrors.ustc.edu.cn/archlinux/$repo/os/$arch 41 | ``` 42 | 43 | ## Partition the disks 44 | 45 | Please refer to: [Example layouts](https://wiki.archlinux.org/title/Installation_guide#Example_layouts). 46 | 47 | ```bash 48 | lsblk 49 | cfdisk /dev/your_main_disk 50 | ``` 51 | 52 | ## Format the partitions 53 | 54 | ```bash 55 | mkfs.fat -F32 /dev/boot_partition 56 | mkfs.ext4 /dev/root_partition 57 | mkswap /dev/swap_partition # Optional 58 | mkfs.ext4 /dev/home_partition # Optional 59 | ``` 60 | 61 | ## Mount the file systems 62 | 63 | ```bash 64 | mount /dev/root_partition /mnt 65 | mount --mkdir /dev/boot_partition /mnt/boot 66 | swapon /dev/swap_partition # Optional 67 | mount --mkdir /dev/home_partition /mnt/home # Optional 68 | ``` 69 | 70 | ## Installation 71 | 72 | ```bash 73 | pacstrap /mnt base base-devel linux linux-firmware 74 | pacstrap /mnt networkmanager vim sudo zsh zsh-completions 75 | ``` 76 | 77 | If pacstrap reports GPG error, execute: 78 | 79 | ```bash 80 | pacman -S archlinux-keyring 81 | ``` 82 | 83 | ## Generate fstab 84 | 85 | ```bash 86 | genfstab -U /mnt > /mnt/etc/fstab 87 | cat /mnt/etc/fstab 88 | ``` 89 | 90 | ## Configure the system 91 | 92 | ```bash 93 | arch-chroot /mnt 94 | 95 | # Set hostname 96 | vim /etc/hostname 97 | # 127.0.0.1 localhost 98 | # ::1 localhost 99 | # 127.0.0.1 your_hostname.localdomain your_hostname 100 | vim /etc/hosts 101 | 102 | # time zone 103 | ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 104 | 105 | hwclock --systohc 106 | 107 | # Uncomment: en_US.UTF-8 UTF-8 108 | vim /etc/locale.gen 109 | locale-gen 110 | echo "LANG=en_US.UTF-8" > /etc/locale.conf 111 | 112 | # Set password for root 113 | passwd root 114 | 115 | # Install ucode 116 | pacman -S intel-ucode # Intel 117 | pacman -S amd-ucode # AMD 118 | 119 | # Install boot loader 120 | pacman -S grub efibootmgr os-prober 121 | grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=ARCH 122 | # GRUB_CMDLINE_LINUX_DEFAULT="loglevel=5 nowatchdog" 123 | # GRUB_DISABLE_OS_PROBER=false (Optional, if you need to boot Windows) 124 | vim /etc/default/grub 125 | grub-mkconfig -o /boot/grub/grub.cfg 126 | 127 | # Normal user 128 | useradd -m -G wheel -s /bin/bash your_user 129 | passwd your_user 130 | # Uncomment: %wheel ALL=(ALL:ALL) ALL 131 | EDITOR=vim visudo 132 | 133 | # Complete installation 134 | exit 135 | umount -R /mnt 136 | reboot 137 | ``` 138 | -------------------------------------------------------------------------------- /term/zsh/lib/welcome.zsh: -------------------------------------------------------------------------------- 1 | print_welcome() { 2 | echo "\033[38;5;213m" 3 | echo ",--. ,-----. ,--. " 4 | echo "| | ,--,--.,-----.,--. ,--.' .--./ ,--,--.,-' '-. " 5 | echo "| | ' ,-. |\`-. / \ ' / | | ' ,-. |'-. .-' " 6 | echo "| '--.\\ '-' | / \`-. \ ' ' '--'\\ '-' | | | " 7 | echo "\`-----' \`--\`--'\`-----'.-' / \`-----' \`--\`--' \`--' " 8 | echo " \`---' " 9 | echo "\033[0m" 10 | 11 | # Get system information 12 | echo "\033[36mSystem Information:\033[0m" 13 | echo " \033[35mOperating System:\033[0m $os_name" 14 | echo " \033[35mHostname:\033[0m $(hostname)" 15 | echo " \033[35mCurrent User:\033[0m $USER" 16 | echo " \033[35mKernel Version:\033[0m $(uname -r)" 17 | echo " \033[35mSystem Time:\033[0m $(date '+%Y-%m-%d %H:%M:%S')" 18 | 19 | if [[ $os_name == "Linux" ]]; then 20 | # Get Linux system information 21 | cpu_cores=$(nproc) 22 | cpu_model=$(cat /proc/cpuinfo | grep "model name" | head -n1 | cut -d':' -f2 | xargs) 23 | mem_total=$(free -h | awk '/^Mem:/ {print $2}') 24 | mem_used=$(free -h | awk '/^Mem:/ {print $3}') 25 | disk_info=$(df -h / | awk 'NR==2 {print $2 " total, " $3 " used (" $5 ")"}') 26 | uptime_info=$(uptime -p | sed 's/^up //') 27 | 28 | echo " \033[35mCPU Model:\033[0m $cpu_model" 29 | echo " \033[35mCPU Cores:\033[0m $cpu_cores" 30 | echo " \033[35mMemory Usage:\033[0m $mem_used / $mem_total" 31 | echo " \033[35mDisk Usage:\033[0m $disk_info" 32 | echo " \033[35mSystem Uptime:\033[0m $uptime_info" 33 | elif [[ $os_name == "Darwin" ]]; then 34 | # Get macOS system information 35 | cpu_cores=$(sysctl -n hw.ncpu) 36 | cpu_model=$(sysctl -n machdep.cpu.brand_string) 37 | mem_total=$(sysctl -n hw.memsize | awk '{ printf "%.1fG\n", $1/1024/1024/1024 }') 38 | mem_used=$(ps -A -o rss | awk '{sum+=$1} END {printf "%.1fG\n", sum/1024/1024}') 39 | disk_info=$(df -h / | awk 'NR==2 {print $2 " total, " $3 " used (" $5 ")"}') 40 | boot_time=$(sysctl -n kern.boottime | awk -F'[{ ,}]' '{print $4}') 41 | current_time=$(date +%s) 42 | uptime_seconds=$((current_time - boot_time)) 43 | uptime_info=$(printf '%d days %d hours %d minutes\n' $((uptime_seconds/86400)) $((uptime_seconds%86400/3600)) $((uptime_seconds%3600/60))) 44 | 45 | echo " \033[35mCPU Model:\033[0m $cpu_model" 46 | echo " \033[35mCPU Cores:\033[0m $cpu_cores" 47 | echo " \033[35mMemory Usage:\033[0m $mem_used / $mem_total" 48 | echo " \033[35mDisk Usage:\033[0m $disk_info" 49 | echo " \033[35mSystem Uptime:\033[0m $uptime_info" 50 | fi 51 | echo 52 | 53 | if [[ $os_name == "Linux" ]]; then 54 | if command -v pacman &> /dev/null; then 55 | updates=$(pacman -Qu | wc -l) 56 | if [ $updates -gt 0 ]; then 57 | echo "\033[33mYou have $updates package(s) to update\033[0m" 58 | else 59 | echo "\033[32mGreat! Your system is up to date\033[0m" 60 | fi 61 | fi 62 | elif [[ $os_name == "Darwin" ]]; then 63 | if command -v brew &> /dev/null; then 64 | brew update &> /dev/null 65 | updates=$(brew outdated | wc -l) 66 | if [ $updates -gt 0 ]; then 67 | echo "\033[33mYou have $updates package(s) to update\033[0m" 68 | else 69 | echo "\033[32mGreat! Your system is up to date\033[0m" 70 | fi 71 | fi 72 | fi 73 | } 74 | -------------------------------------------------------------------------------- /term/zsh/lib/completion.zsh: -------------------------------------------------------------------------------- 1 | # fixme - the load process here seems a bit bizarre 2 | zmodload -i zsh/complist 3 | 4 | WORDCHARS='' 5 | 6 | unsetopt menu_complete # do not autoselect the first completion entry 7 | unsetopt flowcontrol 8 | setopt auto_menu # show completion menu on successive tab press 9 | setopt complete_in_word 10 | setopt always_to_end 11 | 12 | # should this be in keybindings? 13 | bindkey -M menuselect '^o' accept-and-infer-next-history 14 | zstyle ':completion:*:*:*:*:*' menu select 15 | 16 | # case insensitive (all), partial-word and substring completion 17 | if [[ "$CASE_SENSITIVE" = true ]]; then 18 | zstyle ':completion:*' matcher-list 'r:|=*' 'l:|=* r:|=*' 19 | else 20 | if [[ "$HYPHEN_INSENSITIVE" = true ]]; then 21 | zstyle ':completion:*' matcher-list 'm:{[:lower:][:upper:]-_}={[:upper:][:lower:]_-}' 'r:|=*' 'l:|=* r:|=*' 22 | else 23 | zstyle ':completion:*' matcher-list 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' 'r:|=*' 'l:|=* r:|=*' 24 | fi 25 | fi 26 | unset CASE_SENSITIVE HYPHEN_INSENSITIVE 27 | 28 | # Complete . and .. special directories 29 | zstyle ':completion:*' special-dirs true 30 | 31 | zstyle ':completion:*' list-colors '' 32 | zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#) ([0-9a-z-]#)*=01;34=0=01' 33 | 34 | if [[ "$OSTYPE" = solaris* ]]; then 35 | zstyle ':completion:*:*:*:*:processes' command "ps -u $USERNAME -o pid,user,comm" 36 | else 37 | zstyle ':completion:*:*:*:*:processes' command "ps -u $USERNAME -o pid,user,comm -w -w" 38 | fi 39 | 40 | # disable named-directories autocompletion 41 | zstyle ':completion:*:cd:*' tag-order local-directories directory-stack path-directories 42 | 43 | # Use caching so that commands like apt and dpkg complete are useable 44 | zstyle ':completion:*' use-cache yes 45 | zstyle ':completion:*' cache-path $ZSH_CACHE_DIR 46 | 47 | # Don't complete uninteresting users 48 | zstyle ':completion:*:*:*:users' ignored-patterns \ 49 | adm amanda apache at avahi avahi-autoipd beaglidx bin cacti canna \ 50 | clamav daemon dbus distcache dnsmasq dovecot fax ftp games gdm \ 51 | gkrellmd gopher hacluster haldaemon halt hsqldb ident junkbust kdm \ 52 | ldap lp mail mailman mailnull man messagebus mldonkey mysql nagios \ 53 | named netdump news nfsnobody nobody nscd ntp nut nx obsrun openvpn \ 54 | operator pcap polkitd postfix postgres privoxy pulse pvm quagga radvd \ 55 | rpc rpcuser rpm rtkit scard shutdown squid sshd statd svn sync tftp \ 56 | usbmux uucp vcsa wwwrun xfs '_*' 57 | 58 | # ... unless we really want to. 59 | zstyle '*' single-ignored show 60 | 61 | if [[ ${COMPLETION_WAITING_DOTS:-false} != false ]]; then 62 | expand-or-complete-with-dots() { 63 | # use $COMPLETION_WAITING_DOTS either as toggle or as the sequence to show 64 | [[ $COMPLETION_WAITING_DOTS = true ]] && COMPLETION_WAITING_DOTS="%F{red}…%f" 65 | # turn off line wrapping and print prompt-expanded "dot" sequence 66 | printf '\e[?7l%s\e[?7h' "${(%)COMPLETION_WAITING_DOTS}" 67 | zle expand-or-complete 68 | zle redisplay 69 | } 70 | zle -N expand-or-complete-with-dots 71 | # Set the function as the default tab completion widget 72 | bindkey -M emacs "^I" expand-or-complete-with-dots 73 | bindkey -M viins "^I" expand-or-complete-with-dots 74 | bindkey -M vicmd "^I" expand-or-complete-with-dots 75 | fi 76 | 77 | # automatically load bash completion functions 78 | autoload -U +X bashcompinit && bashcompinit 79 | -------------------------------------------------------------------------------- /hyprland/hypr/conf.d/keybind.conf: -------------------------------------------------------------------------------- 1 | # Terminal 2 | bind=SUPER, RETURN, exec, kitty 3 | bind=SUPER, W, exec, wezterm 4 | 5 | bind=SUPER, Q, killactive, 6 | bind=SUPER, F, fullscreen, 0, 7 | 8 | # Applications 9 | bind=SUPER, D, exec, rofi -show drun 10 | bind=SUPER, U, exec, google-chrome-stable 11 | # bind=SUPER, G, exec, google-chrome-stable --ozone-platform=wayland --gtk-version=4 --enable-features=UseOzonePlatform --enable-wayland-ime 12 | bind=SUPER, V, exec, ~/.config/rofi/bin/rofi-csync 13 | bind=SUPER, M, exec, ~/.config/rofi/bin/rofi-powermenu 14 | bind=SUPER, E, exec, thunar 15 | bind=SUPER, X, exec, hyprlock 16 | bind=SUPER, C, exec, cursor 17 | 18 | bind=SUPERSHIFT, SPACE, togglefloating, 19 | 20 | # Screenshot, recommended to use flameshot, only the AUR package supports Hyprland. 21 | # Install: 22 | # sudo pacman -S xdg-desktop-portal-hyprland grim 23 | # yay -S flameshot-git 24 | # 25 | # If the flameshot has problem, you could use swappy instead: 26 | # grim -g "$(slurp)" - | swappy -f - 27 | bind=SUPER, O, exec, flameshot gui 28 | bind=SUPER, P, exec, flameshot gui -r | csynctl put blob 29 | 30 | # Audio buttons 31 | bind=, XF86AudioRaiseVolume, exec, pactl set-sink-volume @DEFAULT_SINK@ +5% 32 | bind=, XF86AudioLowerVolume, exec, pactl set-sink-volume @DEFAULT_SINK@ -5% 33 | bind=, XF86AudioMute, exec, pactl set-sink-mute @DEFAULT_SINK@ toggle 34 | bind=, XF86AudioMicMute, exec, pactl set-source-mute @DEFAULT_SOURCE@ toggle 35 | 36 | # Resize mode 37 | bind=SUPER,R,submap,resize 38 | submap=resize 39 | 40 | binde=,h,resizeactive,-10 0 41 | binde=,l,resizeactive,10 0 42 | binde=,k,resizeactive,0 -10 43 | binde=,j,resizeactive,0 10 44 | 45 | bind=,escape,submap,reset 46 | submap=reset 47 | 48 | # Move focus with mainMod + arrow keys 49 | bind=SUPER,h,movefocus,l 50 | bind=SUPER,l,movefocus,r 51 | bind=SUPER,j,movefocus,d 52 | bind=SUPER,k,movefocus,u 53 | 54 | bind=SUPERSHIFT,h,movewindow,l 55 | bind=SUPERSHIFT,l,movewindow,r 56 | bind=SUPERSHIFT,j,movewindow,d 57 | bind=SUPERSHIFT,k,movewindow,u 58 | 59 | # Switch workspaces with mainMod + [0-9] 60 | bind = SUPER, 1, workspace, 1 61 | bind = SUPER, 2, workspace, 2 62 | bind = SUPER, 3, workspace, 3 63 | bind = SUPER, 4, workspace, 4 64 | bind = SUPER, 5, workspace, 5 65 | bind = SUPER, 6, workspace, 6 66 | bind = SUPER, 7, workspace, 7 67 | bind = SUPER, 8, workspace, 8 68 | bind = SUPER, 9, workspace, 9 69 | bind = SUPER, 0, workspace, 0 70 | bind = SUPER, TAB, workspace, previous 71 | 72 | # Move active window to a workspace with mainMod + SHIFT + [0-9] 73 | bind = SUPERSHIFT, 1, movetoworkspace, 1 74 | bind = SUPERSHIFT, 2, movetoworkspace, 2 75 | bind = SUPERSHIFT, 3, movetoworkspace, 3 76 | bind = SUPERSHIFT, 4, movetoworkspace, 4 77 | bind = SUPERSHIFT, 5, movetoworkspace, 5 78 | bind = SUPERSHIFT, 6, movetoworkspace, 6 79 | bind = SUPERSHIFT, 7, movetoworkspace, 7 80 | bind = SUPERSHIFT, 8, movetoworkspace, 8 81 | bind = SUPERSHIFT, 9, movetoworkspace, 9 82 | bind = SUPERSHIFT, 0, movetoworkspace, 0 83 | bind = SUPERSHIFT, TAB, movetoworkspace, previous 84 | 85 | # Example special workspace (scratchpad) 86 | bind = SUPER, S, togglespecialworkspace, magic 87 | bind = SUPER SHIFT, S, movetoworkspace, special:magic 88 | 89 | # Scroll through existing workspaces with mainMod + scroll 90 | bind = SUPER, mouse_down, workspace, e+1 91 | bind = SUPER, mouse_up, workspace, e-1 92 | 93 | # Move/resize windows with mainMod + LMB/RMB and dragging 94 | bindm = SUPER, mouse:272, movewindow 95 | bindm = SUPER, mouse:273, resizewindow 96 | -------------------------------------------------------------------------------- /term/zsh/lib/tools.zsh: -------------------------------------------------------------------------------- 1 | syncpkg() { 2 | if [[ $EUID -eq 0 ]]; then 3 | echo "Error: syncpkg should not be run as root" 4 | return 1 5 | fi 6 | python3 ~/dotfiles/scripts/syncpkg.py 7 | } 8 | 9 | clash() { 10 | if [[ "$1" == "on" ]]; then 11 | # Check if proxy port is accessible 12 | if ! nc -z 127.0.0.1 7890; then 13 | echo "Error: Clash proxy port 7890 is not accessible" 14 | return 1 15 | fi 16 | export https_proxy=http://127.0.0.1:7890 17 | export http_proxy=http://127.0.0.1:7890 18 | export all_proxy=socks5://127.0.0.1:7890 19 | echo "Proxy enabled" 20 | elif [[ "$1" == "off" ]]; then 21 | unset https_proxy 22 | unset http_proxy 23 | unset all_proxy 24 | echo "Proxy disabled" 25 | else 26 | echo "Usage: clash [on|off]" 27 | fi 28 | } 29 | 30 | ghproxy() { 31 | if [[ "$1" == "on" ]]; then 32 | # Check if proxy port is accessible 33 | if ! nc -z 127.0.0.1 7890; then 34 | echo "Error: Clash proxy port 7890 is not accessible" 35 | return 1 36 | fi 37 | git config --global http.proxy http://127.0.0.1:7890 38 | git config --global https.proxy https://127.0.0.1:7890 39 | echo "GitHub proxy enabled" 40 | elif [[ "$1" == "off" ]]; then 41 | git config --global --unset http.proxy 42 | git config --global --unset https.proxy 43 | echo "GitHub proxy disabled" 44 | else 45 | echo "Usage: ghproxy [on|off]" 46 | fi 47 | } 48 | 49 | clear_docker() { 50 | sudo docker rm -vf $(docker ps -aq) 51 | sudo docker rmi -f $(docker images -aq) 52 | } 53 | 54 | zsh_stats () { 55 | fc -l 1 | awk '{ CMD[$2]++; count++; } END { for (a in CMD) print CMD[a] " " CMD[a]*100/count "% " a }' | grep -v "./" | sort -nr | head -n 20 | column -c3 -s " " -t | nl 56 | } 57 | 58 | updpkg() { 59 | ~/dotfiles/scripts/updpkg.sh "$@" 60 | } 61 | 62 | command_not_found_handler() { 63 | local command="$1" 64 | local os_type="$(uname)" 65 | local output 66 | 67 | echo "Command '$command' not found" 68 | if [[ "$os_type" == "Linux" ]]; then 69 | command_not_found_archlinux "$command" 70 | elif [[ "$os_type" == "Darwin" ]]; then 71 | command_not_found_macos "$command" 72 | fi 73 | return 127 74 | } 75 | 76 | command_not_found_archlinux() { 77 | if ! command -v yay &> /dev/null; then 78 | return 79 | fi 80 | 81 | local command="$1" 82 | local output 83 | 84 | echo "Searching packages..." 85 | output=$(yay -F --color always "usr/bin/$command" 2> /dev/null | sed "s/usr\/bin\/$command is owned by / /g") 86 | if [[ -n "$output" ]]; then 87 | echo 88 | echo "Found packages:" 89 | echo "$output" 90 | echo 91 | echo "HINT: you can use 'yay -S ' to install one of them" 92 | else 93 | echo "Cannot find package contains this command" 94 | echo 95 | echo "HINT: You can try to search this in AUR: https://aur.archlinux.org/packages?K=${command}" 96 | fi 97 | } 98 | 99 | command_not_found_macos() { 100 | if ! command -v gh &> /dev/null; then 101 | return 102 | fi 103 | 104 | local command="$1" 105 | local output 106 | 107 | echo "Searching packages from homebrew-core" 108 | output=$(gh search code "$command path:Formula" --repo homebrew/homebrew-core --json path --jq '.[].path | sub("Formula/"; "") | sub(".rb$"; "") | split("/")[-1]') 109 | if [[ -n "$output" ]]; then 110 | echo 111 | echo "Found homebrew packages (contains this keyword):" 112 | echo "$output" 113 | echo 114 | echo "HINT: you can use 'brew install ' to install one of them" 115 | else 116 | echo "Cannot find package contains this keyword" 117 | fi 118 | } 119 | 120 | start-csyncd() { 121 | echo -n "" | pbcopy 122 | killall csyncd > /dev/null 2>&1 123 | sleep 1 124 | nohup csyncd > /tmp/csyncd.log 2>&1 & 125 | } 126 | 127 | meow() { 128 | $HOME/dotfiles/scripts/rolling.sh 129 | } 130 | -------------------------------------------------------------------------------- /term/zsh/zshrc: -------------------------------------------------------------------------------- 1 | autoload -U compinit 2 | compinit -u 3 | 4 | source $HOME/dotfiles/term/zsh/lib/completion.zsh 5 | source $HOME/dotfiles/term/zsh/lib/history.zsh 6 | source $HOME/dotfiles/term/zsh/lib/tools.zsh 7 | source $HOME/dotfiles/term/zsh/lib/welcome.zsh 8 | [[ -z "$LS_COLORS" ]] || zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}" 9 | 10 | os_name=$(uname -s) 11 | case $os_name in 12 | Linux) 13 | if [[ -d /usr/share/zsh/plugins ]]; then 14 | syntax_highlighting_path="/usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" 15 | autosuggestions_path="/usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh" 16 | else 17 | syntax_highlighting_path="/usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" 18 | autosuggestions_path="/usr/share/zsh-autosuggestions/zsh-autosuggestions.zsh" 19 | fi 20 | ;; 21 | Darwin) 22 | brew_path=$(brew --prefix) 23 | syntax_highlighting_path="$brew_path/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" 24 | autosuggestions_path="$brew_path/share/zsh-autosuggestions/zsh-autosuggestions.zsh" 25 | ;; 26 | *) 27 | echo "WARNING: Unsupported OS '$os_name'" 28 | ;; 29 | esac 30 | 31 | if [[ -f $syntax_highlighting_path ]]; then 32 | source $syntax_highlighting_path 33 | else 34 | echo "WATNING: zsh-syntax-highlighting not installed" 35 | fi 36 | 37 | if [[ -f $autosuggestions_path ]]; then 38 | source $autosuggestions_path 39 | bindkey '^E' end-of-line 40 | else 41 | echo "WATNING: zsh-autosuggestions not installed" 42 | fi 43 | 44 | if [ -f $HOME/dotfiles/term/zsh/secrets.sh ]; then 45 | source $HOME/dotfiles/term/zsh/secrets.sh 46 | else 47 | echo "WARNING: secrets file not found" 48 | fi 49 | 50 | if command -v nvim &> /dev/null; then 51 | alias vim='nvim' 52 | alias vi='NVIM_MINI="true" nvim' 53 | else 54 | echo "WARNING: neovim not installed" 55 | fi 56 | 57 | if command -v starship &> /dev/null; then 58 | eval "$(starship init zsh)" 59 | else 60 | echo "WARNING: starship not installed" 61 | fi 62 | 63 | if command -v fzf &> /dev/null; then 64 | source <(fzf --zsh) 65 | else 66 | echo "WARNING: fzf not installed" 67 | fi 68 | 69 | if command -v roxide &> /dev/null; then 70 | source <(ROXIDE_INIT='zsh' roxide) 71 | alias zz="rox home" 72 | alias zm="rox mirror" 73 | else 74 | echo "WARNING: roxide not installed" 75 | fi 76 | 77 | if command -v kubewrap &> /dev/null; then 78 | source <(kubewrap init zsh) 79 | else 80 | echo "WARNING: kubewrap not installed" 81 | fi 82 | 83 | if command -v eza &> /dev/null; then 84 | alias ls="eza" 85 | alias ll="ls -l" 86 | alias la="ls -a" 87 | alias lla="ls -la" 88 | else 89 | echo "WARNING: eza not installed" 90 | fi 91 | 92 | if command -v dust &> /dev/null; then 93 | alias du="dust -b" 94 | fi 95 | 96 | if command -v kubectl &> /dev/null; then 97 | alias k="kubectl" 98 | source <(kubectl completion zsh) 99 | else 100 | echo "WARNING: kubectl not installed" 101 | fi 102 | 103 | if command -v cargo &> /dev/null; then 104 | alias cg="cargo" 105 | else 106 | echo "WARNING: cargo not installed" 107 | fi 108 | 109 | if command -v git &> /dev/null; then 110 | alias gs="git status" 111 | alias gl="git pull" 112 | alias gp="git push" 113 | alias gpf="git push -f origin" 114 | alias gps="git push --set-upstream origin" 115 | alias gck="git checkout" 116 | alias gr="git restore" 117 | alias gm="git merge" 118 | alias gcb="git checkout -b" 119 | alias gd="git diff" 120 | alias ga="git add" 121 | alias gc="git commit" 122 | else 123 | echo "WARNING: git not installed" 124 | fi 125 | 126 | if [[ $os_name == "Linux" ]] && [[ $USER != "root" ]]; then 127 | alias docker="sudo docker" 128 | fi 129 | 130 | if [[ -f "$HOME/dotfiles/term/zsh/custom.sh" ]]; then 131 | source $HOME/dotfiles/term/zsh/custom.sh 132 | fi 133 | 134 | -------------------------------------------------------------------------------- /scripts/syncpkg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import subprocess 4 | import json 5 | import platform 6 | import os 7 | import sys 8 | 9 | 10 | def run_command(cmd, capture_output=False): 11 | try: 12 | if capture_output: 13 | output = subprocess.check_output(["bash", "-c", cmd], 14 | stderr=subprocess.STDOUT, 15 | universal_newlines=True) 16 | return {line for line in output.splitlines() if line.strip()} 17 | else: 18 | subprocess.check_call(["bash", "-c", cmd]) 19 | except subprocess.CalledProcessError as e: 20 | print(f"Command failed with exit code {e.returncode}") 21 | print(e.output) 22 | sys.exit(1) 23 | 24 | 25 | def load_config(): 26 | system = platform.system().lower() 27 | home = os.path.expanduser("~") 28 | 29 | if system == "linux": 30 | # Check if it's Arch Linux by checking /etc/os-release 31 | try: 32 | with open("/etc/os-release") as f: 33 | if "arch" in f.read().lower(): 34 | json_path = os.path.join( 35 | home, "dotfiles/packages/archlinux.json") 36 | else: 37 | print("Error: Only Arch Linux is supported on Linux") 38 | sys.exit(1) 39 | except FileNotFoundError: 40 | print("Error: Could not determine Linux distribution") 41 | sys.exit(1) 42 | elif system == "darwin": 43 | json_path = os.path.join(home, "dotfiles/packages/macos.json") 44 | else: 45 | print(f"Error: Unsupported system: {system}") 46 | sys.exit(1) 47 | 48 | try: 49 | with open(json_path) as f: 50 | return json.load(f) 51 | except FileNotFoundError: 52 | print(f"Error: Package list not found at {json_path}") 53 | sys.exit(1) 54 | except json.JSONDecodeError: 55 | print(f"Error: Invalid JSON file at {json_path}") 56 | sys.exit(1) 57 | 58 | 59 | def get_installed_packages(config): 60 | packages = set() 61 | for cmd in config["list"]: 62 | cmd_packages = run_command(cmd, capture_output=True) 63 | if cmd_packages is None: 64 | continue 65 | packages.update(cmd_packages) 66 | return packages 67 | 68 | 69 | if __name__ == "__main__": 70 | config = load_config() 71 | 72 | if "list" not in config: 73 | print("Error: list is missing or empty in config") 74 | sys.exit(1) 75 | if "install" not in config: 76 | print("Error: install is missing in config") 77 | sys.exit(1) 78 | if "packages" not in config: 79 | print("Error: packages is missing in config") 80 | sys.exit(1) 81 | 82 | install_cmds = config["install"] 83 | print("Searching for installed packages...") 84 | pkgs = get_installed_packages(config) 85 | expect_pkgs = set(config["packages"]) 86 | uninstalled = {} 87 | for expect_pkg in expect_pkgs: 88 | pkg_type = "" 89 | pkg_name = expect_pkg 90 | if ":" in expect_pkg: 91 | pkg_type, pkg_name = expect_pkg.split(":", 1) 92 | if pkg_type == "": 93 | pkg_type = "default" 94 | if pkg_name in pkgs: 95 | continue 96 | 97 | if pkg_type not in install_cmds: 98 | print( 99 | f"Error: No install command found for package type {pkg_type}") 100 | sys.exit(1) 101 | 102 | if pkg_type not in uninstalled: 103 | uninstalled[pkg_type] = [pkg_name] 104 | continue 105 | 106 | uninstalled[pkg_type].append(pkg_name) 107 | 108 | if not uninstalled: 109 | print("All packages are already installed") 110 | sys.exit(0) 111 | 112 | for cmd_name, pkgs in uninstalled.items(): 113 | print(f"Installing {', '.join(pkgs)}...") 114 | cmd = install_cmds[cmd_name] 115 | cmd = cmd.replace("%pkg", " ".join(pkgs)) 116 | run_command(cmd) 117 | 118 | print("All packages installed successfully") 119 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dotfiles 2 | 3 | Powered by: 4 | 5 | - OS: [Arch Linux](https://archlinux.org/) 6 | - WM: [Hyprland](https://hyprland.org/) 7 | - Terminal: [WezTerm](https://wezfurlong.org/wezterm/index.html) 8 | - Editor: [Neovim](https://neovim.io/) 9 | - Theme: [Catppuccin](https://github.com/catppuccin/catppuccin) 10 | 11 | Inspired by [end-4/dots-hyprland](https://github.com/end-4/dots-hyprland). 12 | 13 | ## Guides 14 | 15 | Arch Linux: 16 | 17 | 1. [Installation](guides/installation.md) 18 | 2. Ensure your network is available: `sudo systemctl enable --now NetworkManager` 19 | 3. Install git: `sudo pacman -S git` 20 | 4. Clone this repository to home directory: `git clone https://github.com/fioncat/dotfiles.git ~/dotfiles` 21 | 5. Run bootstrap script: `~/dotfiles/scripts/bootstrap.sh` 22 | 6. Install graphic driver, see: [GPU](guides/GPU.md) 23 | 7. Reboot your system to enter Hyprland 24 | 8. Run proxy script and config it (if you are in GWF): `~/dotfiles/scripts/proxy.sh` 25 | 9. Run setup script: `~/dotfiles/scripts/setup.sh` 26 | 27 | macOS: 28 | 29 | 1. Setup your proxy (if you are in GWF) 30 | 2. Install homebrew: `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"` 31 | 3. Add my homebrew tap: `brew tap fioncat/apps` 32 | 4. Clone this repository to home directory: `git clone https://github.com/fioncat/dotfiles.git ~/dotfiles` 33 | 5. Export homebrew bin path: `export PATH="/opt/homebrew/bin:$PATH"` 34 | 6. Run setup script: `~/dotfiles/scripts/setup.sh` 35 | 36 | Daily: 37 | 38 | - Install missing packages: `syncpkg` 39 | - Rolling update: `meow` 40 | - Update self maintained package: `updpkg ` 41 | - Enable or disable clash proxy in terminal: `clash on` and `clash off` 42 | - Remove all docker images: `clear_docker` 43 | 44 | ## Tips 45 | 46 | > [!TIP] 47 | > If you have a dual-boot system (Windows+Linux), the time might be out of sync between the two systems. In this case, you need to execute the following command in Linux: 48 | > 49 | > ```bash 50 | > sudo timedatectl set-local-rtc 1 51 | > ``` 52 | 53 | > [!TIP] 54 | > In some countries, accessing GitHub via SSH might be problematic, and by default, the SSH protocol doesn't use the global proxy. We need to add the following configuration to ~/.ssh/config to make GitHub's SSH protocol use HTTPS: 55 | > 56 | > ```ssh 57 | > Host github.com 58 | > Hostname ssh.github.com 59 | > Port 443 60 | > User git 61 | > ``` 62 | 63 | > [!TIP] 64 | > The `hyprpaper` and `hyprlock` cannot read `jpeg` image. You can use the following command to convert `jpeg` image to `png`: 65 | > 66 | > ```bash 67 | > ~/dotfiles/scripts/topng.py ~/Pictures/wallpaper.jpg 68 | > ``` 69 | > 70 | > This will generate `~/Pictures/wallpaper.png` file. 71 | 72 | > [!TIP] 73 | > In some scenarios, you may want to persist SSH connections, such as when logging into a jump server to avoid entering passwords repeatedly. You can add the following configuration to `~/.ssh/config`: 74 | > 75 | > ``` 76 | > Host 77 | > ControlMaster auto 78 | > COntrolPath ~/.ssh/%r@%h:%p.socket 79 | > ControlPersist 600m 80 | > ``` 81 | 82 | ## Docker 83 | 84 | If you are not on Arch Linux but want to experience this dotfiles, you can use Docker to achieve this: 85 | 86 | ```bash 87 | DOCKER_CMD="sudo docker" make 88 | docker run -it fioncat/dev:archlinux 89 | ``` 90 | 91 | Note that this Docker image is quite large, and I have not pushed it to DockerHub, so this method is only recommended for temporary experience and debugging. After you are done using it, it is advisable to delete this image. 92 | 93 | ## Update packages 94 | 95 | > [!IMPORTANT] 96 | > If you are using [daed](https://github.com/daeuniverse/daed) proxy, you need to configure `aur.archlinux.org` domain to not use proxy, otherwise AUR operations will fail: 97 | > 98 | > ``` 99 | > domain(aur.archlinux.org) -> direct 100 | > ``` 101 | 102 | Use the `updpkg` command to update [AUR](https://aur.archlinux.org/) and [Homebrew](https://brew.sh/) packages. Usage: 103 | 104 | ```bash 105 | updpkg 106 | NOAUR="true" updpkg # Update only Homebrew 107 | NOBREW="true" updpkg # Update only AUR 108 | updpkg --help # Show usage 109 | ``` 110 | 111 | This command can only be executed on Arch Linux. Before executing, you need to upload your ssh public key to AUR. Please refer to: [AUR submission guidelines](https://wiki.archlinux.org/title/AUR_submission_guidelines). 112 | -------------------------------------------------------------------------------- /hyprland/rofi/themes/powermenu.rasi: -------------------------------------------------------------------------------- 1 | * { 2 | font: "SauceCodePro Nerd Font 14"; 3 | 4 | accent: #b4befe; 5 | 6 | base: #1e1e2e; 7 | mantle: #181825; 8 | text: #cdd6f4; 9 | red: #f38ba8; 10 | green: #a6e3a1; 11 | pink: #f5c2ef; 12 | } 13 | 14 | window { 15 | enabled: true; 16 | transparency: "real"; 17 | location: center; 18 | anchor: center; 19 | fullscreen: false; 20 | width: 600px; 21 | border: 3px solid; 22 | border-color: @pink; 23 | border-radius: 8px; 24 | cursor: default; 25 | background-color: @base; 26 | } 27 | 28 | mainbox { 29 | enabled: true; 30 | padding: 25px; 31 | orientation: vertical; 32 | background-color: transparent; 33 | children: [ "inputbar", "listview" ]; 34 | } 35 | 36 | inputbar { 37 | enabled: true; 38 | padding: 0px 0px 25px; 39 | text-color: @text; 40 | orientation: horizontal; 41 | border-radius: 12px; 42 | background-color: transparent; 43 | children: [ "textbox-prompt-colon", "dummy", "prompt" ]; 44 | } 45 | 46 | dummy { 47 | background-color: transparent; 48 | } 49 | 50 | textbox-prompt-colon { 51 | enabled: true; 52 | expand: false; 53 | str: "System"; 54 | padding: 15px; 55 | border-radius: 100%; 56 | background-color: @mantle; 57 | text-color: @accent; 58 | } 59 | 60 | prompt { 61 | enabled: true; 62 | padding: 15px; 63 | border-radius: 100px; 64 | background-color: @accent; 65 | text-color: @mantle; 66 | } 67 | 68 | listview { 69 | enabled: true; 70 | columns: 5; 71 | lines: 1; 72 | cycle: true; 73 | dynamic: true; 74 | scrollbar: false; 75 | layout: vertical; 76 | reverse: false; 77 | fixed-height: true; 78 | fixed-columns: true; 79 | border-radius: 100%; 80 | background-color: @mantle; 81 | text-color: @text; 82 | cursor: default; 83 | } 84 | 85 | element { 86 | enabled: true; 87 | padding: 30px 15px; 88 | border-radius: 8px; 89 | background-color: transparent; 90 | text-color: @text; 91 | cursor: pointer; 92 | } 93 | 94 | element-text { 95 | font: "Phosphor\-Bold 20"; 96 | background-color: transparent; 97 | text-color: inherit; 98 | cursor: inherit; 99 | vertical-align: 0.5; 100 | horizontal-align: 0.5; 101 | } 102 | 103 | element selected.normal { 104 | background-color: @accent; 105 | text-color: @mantle; 106 | } 107 | 108 | message { 109 | enabled: true; 110 | padding: 15px; 111 | border: 0px; 112 | border-radius: 100%; 113 | border-color: @accent; 114 | background-color: @mantle; 115 | text-color: @text; 116 | } 117 | textbox { 118 | background-color: inherit; 119 | text-color: inherit; 120 | vertical-align: 0.5; 121 | horizontal-align: 0.5; 122 | placeholder-color: @text; 123 | blink: true; 124 | markup: true; 125 | } 126 | error-message { 127 | padding: 15px; 128 | border: 0px solid; 129 | border-radius: 100%; 130 | border-color: @red; 131 | background-color: @mantle; 132 | text-color: @red; 133 | } 134 | -------------------------------------------------------------------------------- /hyprland/waybar/style.css: -------------------------------------------------------------------------------- 1 | /* ============================================================================= 2 | * 3 | * Waybar configuration 4 | * 5 | * Configuration reference: https://github.com/Alexays/Waybar/wiki/Configuration 6 | * 7 | * =========================================================================== */ 8 | 9 | /* ----------------------------------------------------------------------------- 10 | * Keyframes 11 | * -------------------------------------------------------------------------- */ 12 | 13 | @import "mocha.css"; 14 | 15 | @keyframes blink-warning { 16 | 70% { 17 | color: white; 18 | } 19 | 20 | to { 21 | color: white; 22 | background-color: orange; 23 | } 24 | } 25 | 26 | @keyframes blink-critical { 27 | 70% { 28 | color: white; 29 | } 30 | 31 | to { 32 | color: white; 33 | background-color: @red; 34 | } 35 | } 36 | 37 | 38 | /* ----------------------------------------------------------------------------- 39 | * Base styles 40 | * -------------------------------------------------------------------------- */ 41 | 42 | /* Reset all styles */ 43 | * { 44 | border: none; 45 | border-radius: 0; 46 | min-height: 0; 47 | margin: 0; 48 | padding: 0; 49 | } 50 | 51 | /* The whole bar */ 52 | #waybar { 53 | background: @crust; 54 | color: @text; 55 | font-family: SauceCodePro Nerd Font; 56 | font-size: 17px; 57 | } 58 | 59 | 60 | /* Each module */ 61 | #battery, 62 | #cpu, 63 | #custom-keyboard-layout, 64 | #memory, 65 | #mode, 66 | #network, 67 | #pulseaudio, 68 | #temperature, 69 | #disk, 70 | #keyboard-state, 71 | #custom-fcitx5, 72 | #submap, 73 | #custom-icon, 74 | #bluetooth { 75 | margin: 5px; 76 | padding-left: 10px; 77 | padding-right: 10px; 78 | 79 | border-radius: 1rem; 80 | background: @surface0; 81 | } 82 | 83 | /* ----------------------------------------------------------------------------- 84 | * Module styles 85 | * -------------------------------------------------------------------------- */ 86 | 87 | #battery { 88 | animation-timing-function: linear; 89 | animation-iteration-count: infinite; 90 | animation-direction: alternate; 91 | } 92 | 93 | #battery.warning { 94 | color: orange; 95 | } 96 | 97 | #battery.critical { 98 | color: red; 99 | } 100 | 101 | #battery.warning.discharging { 102 | animation-name: blink-warning; 103 | animation-duration: 3s; 104 | } 105 | 106 | #battery.critical.discharging { 107 | animation-name: blink-critical; 108 | animation-duration: 2s; 109 | } 110 | 111 | #clock { 112 | padding-left: 10px; 113 | padding-right: 10px; 114 | 115 | font-weight: bold; 116 | } 117 | 118 | #cpu { 119 | color: @base; 120 | background-color: @blue; 121 | } 122 | 123 | #cpu.warning { 124 | /* color: @pink; */ 125 | background-color: @pink; 126 | } 127 | 128 | #cpu.critical { 129 | /* color: @red; */ 130 | background-color: @red; 131 | } 132 | 133 | #temperature { 134 | color: @base; 135 | background-color: @green; 136 | } 137 | 138 | #temperature.critical { 139 | background-color: @red; 140 | } 141 | 142 | #memory { 143 | color: @base; 144 | background-color: @sapphire; 145 | } 146 | 147 | #memory.warning { 148 | background-color: @pink; 149 | } 150 | 151 | #memory.critical { 152 | background-color: @red; 153 | } 154 | 155 | #mode { 156 | color: @red; 157 | border-top: 2px solid white; 158 | padding-bottom: 2px; 159 | } 160 | 161 | #network { 162 | color: @yellow; 163 | } 164 | 165 | #network.disconnected { 166 | color: @red; 167 | } 168 | 169 | #keyboard-state label { 170 | color: @blue; 171 | } 172 | 173 | #keyboard-state label.locked { 174 | color: @red; 175 | } 176 | 177 | #pulseaudio { 178 | color: @blue; 179 | } 180 | 181 | #pulseaudio.muted { 182 | color: @red; 183 | } 184 | 185 | #bluetooth { 186 | color: @blue; 187 | } 188 | 189 | #bluetooth.disabled { 190 | color: @red; 191 | } 192 | 193 | #bluetooth.connected { 194 | color: @green; 195 | } 196 | 197 | #disk { 198 | color: @sapphire; 199 | } 200 | 201 | #tray { 202 | margin: 5px; 203 | padding-left: 10px; 204 | padding-right: 10px; 205 | } 206 | 207 | #window { 208 | font-weight: bold; 209 | } 210 | 211 | #workspaces button { 212 | color: @text; 213 | 214 | /* border-top: 2px solid transparent; */ 215 | border-radius: 0.5rem; 216 | margin: 5px; 217 | 218 | padding-bottom: 2px; 219 | padding-left: 10px; 220 | padding-right: 10px; 221 | } 222 | 223 | #workspaces button.active { 224 | color: @base; 225 | background-color: @lavender; 226 | } 227 | 228 | button:hover { 229 | box-shadow: none; 230 | text-shadow: none; 231 | background: none; 232 | transition: none; 233 | } 234 | 235 | #workspaces button.urgent { 236 | color: @base; 237 | background-color: @red; 238 | } 239 | 240 | #submap { 241 | color: @base; 242 | background-color: @red; 243 | } 244 | 245 | tooltip { 246 | background: @base; 247 | border: 1px solid @pink; 248 | border-radius: 0.5rem; 249 | } 250 | 251 | tooltip label { 252 | color: @text; 253 | } 254 | 255 | #custom-icon { 256 | background-color: @base; 257 | } 258 | -------------------------------------------------------------------------------- /scripts/updpkg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if running on Arch Linux 4 | if [ ! -f "/etc/arch-release" ]; then 5 | echo "Error: This script can only be run on Arch Linux" 6 | exit 1 7 | fi 8 | 9 | # Check if running as root 10 | if [ "$EUID" -eq 0 ]; then 11 | echo "Error: This script should not be run as root" 12 | exit 1 13 | fi 14 | 15 | # Check if help is needed 16 | if [ "$1" == "--help" ] || [ "$1" == "-h" ]; then 17 | echo "Usage: updpkg [version]" 18 | echo 19 | echo "Arguments:" 20 | echo " pkg_name Package name (required)" 21 | echo " version Version number (optional)" 22 | echo 23 | echo "Environment variables:" 24 | echo " NOAUR If 'true', skip AUR package update" 25 | echo " NOBREW If 'true' Skip Homebrew formula update" 26 | echo 27 | echo "Available packages: roxide, otree, kubewrap, csync" 28 | exit 0 29 | fi 30 | 31 | # Check required argument 32 | if [ -z "$1" ]; then 33 | echo "Error: Missing required package name argument" 34 | echo "Use 'updpkg --help' to see usage" 35 | exit 1 36 | fi 37 | 38 | # Set variables 39 | pkg_name="$1" 40 | version="$2" 41 | 42 | NOAUR="$NOAUR" 43 | NOBREW="$NOBREW" 44 | 45 | if [ -n "$NOAUR" ] && [ -n "$NOBREW" ]; then 46 | echo "Error: No package to update" 47 | echo "Use 'updpkg --help' to see usage" 48 | exit 1 49 | fi 50 | 51 | set -eu 52 | 53 | if [ -z "$version" ]; then 54 | # Get latest version from GitHub API 55 | echo "Get the latest version from GitHub API" 56 | version=$(gh release view -R "fioncat/${pkg_name}" --json tagName -q '.tagName' | sed -E 's/^v?//') 57 | if [ -z "$version" ]; then 58 | echo "Error: Failed to get latest version from GitHub" 59 | exit 1 60 | fi 61 | fi 62 | 63 | update_aur() { 64 | # Set AUR package name 65 | aur_name="$pkg_name-release" 66 | 67 | echo "Begin to update AUR package $pkg_name to $version" 68 | 69 | aur_path="/tmp/aur_${aur_name}" 70 | if [[ ! -e "$aur_path" ]]; then 71 | echo "Cloning package from AUR..." 72 | git clone -c init.defaultBranch=master ssh://aur@aur.archlinux.org/${aur_name}.git "$aur_path" 73 | fi 74 | cd "$aur_path" 75 | 76 | # Read current version from PKGBUILD 77 | current_version=$(grep -E '^pkgver=' PKGBUILD | cut -d'=' -f2) 78 | if [ -z "$current_version" ]; then 79 | echo "Error: Failed to get current version from PKGBUILD" 80 | exit 1 81 | fi 82 | 83 | echo "Current AUR version is: $current_version" 84 | if [ "$current_version" != "$version" ]; then 85 | # Update version in PKGBUILD 86 | echo "Updating version in PKGBUILD..." 87 | sed -i "s/^pkgver=.*/pkgver=${version}/" PKGBUILD 88 | 89 | # Update package checksums 90 | echo "Updating package checksums..." 91 | updpkgsums 92 | 93 | # Update .SRCINFO 94 | echo "Updating .SRCINFO..." 95 | makepkg --printsrcinfo >.SRCINFO 96 | 97 | # Commit and push changes 98 | echo "Config git user and email..." 99 | git config user.name "fioncat" 100 | git config user.email "lazycat7706@gmail.com" 101 | 102 | echo "Commit and push changes..." 103 | git add PKGBUILD .SRCINFO 104 | git commit -m "update to ${version}" 105 | git push 106 | 107 | echo "Done, updated AUR $pkg_name to version: $version" 108 | else 109 | echo "AUR already up-to-date" 110 | fi 111 | 112 | echo "Cleaning up..." 113 | cd /tmp 114 | rm -rf "$aur_path" 115 | } 116 | 117 | update_homebrew() { 118 | echo "Begin to update homebrew formula $pkg_name to $version" 119 | tap_path="/tmp/homebrew-apps" 120 | if [[ ! -e "$tap_path" ]]; then 121 | echo "Cloning homebrew-apps..." 122 | echo "$tap_path" 123 | git clone git@github.com:fioncat/homebrew-apps.git "$tap_path" 124 | fi 125 | cd "$tap_path" 126 | 127 | # Read current version from formula url 128 | formula_path="Formula/${pkg_name}.rb" 129 | current_version=$(grep -E '^\s*url\s*"' "$formula_path" | grep -o 'v[0-9.]*' | sed 's/v\(.*\)/\1/') 130 | if [ -z "$current_version" ]; then 131 | echo "Error: Failed to get current version from formula url" 132 | exit 1 133 | fi 134 | 135 | echo "Current homebrew version is: $current_version" 136 | if [ "$current_version" != "$version" ]; then 137 | # Get formula URL and download file 138 | url=$(grep -E '^\s*url\s*"' "$formula_path" | sed 's/.*url\s*"\(.*\)".*/\1/') 139 | new_url=$(echo "$url" | sed "s/v${current_version}/v${version}/") 140 | 141 | echo "Downloading $new_url to calculate sha256..." 142 | tmp_file="/tmp/${pkg_name}-${version}.tar.gz" 143 | curl -L -o "$tmp_file" "$new_url" 144 | 145 | # Calculate sha256 146 | new_sha256=$(sha256sum "$tmp_file" | cut -d' ' -f1) 147 | rm -f "$tmp_file" 148 | 149 | # Update formula file 150 | echo "Updating formula URL and sha256..." 151 | sed -i "s|url \".*\"|url \"${new_url}\"|" "$formula_path" 152 | sed -i "s|sha256 \".*\"|sha256 \"${new_sha256}\"|" "$formula_path" 153 | 154 | echo "Config git user and email..." 155 | git config user.name "fioncat" 156 | git config user.email "lazycat7706@gmail.com" 157 | 158 | # Commit and push changes 159 | echo "Commit and push changes..." 160 | git add "$formula_path" 161 | git commit -m "Update ${pkg_name} to ${version}" 162 | git push 163 | else 164 | echo "Homebrew already up-to-date" 165 | fi 166 | 167 | echo "Cleaning up..." 168 | cd /tmp 169 | rm -rf "$tap_path" 170 | } 171 | 172 | if [ -z "$NOAUR" ]; then 173 | update_aur 174 | fi 175 | 176 | if [ -z "$NOBREW" ]; then 177 | update_homebrew 178 | fi 179 | 180 | echo 181 | echo "Done, references:" 182 | if [ -z "$NOAUR" ]; then 183 | echo " * AUR: https://aur.archlinux.org/packages/${aur_name}" 184 | fi 185 | if [ -z "$NOBREW" ]; then 186 | echo " * Homebrew: https://github.com/fioncat/homebrew-apps/blob/main/Formula/${pkg_name}.rb" 187 | fi 188 | -------------------------------------------------------------------------------- /scripts/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if running as root 4 | if [[ $EUID -eq 0 ]]; then 5 | echo "Error: This script should not be run as root" 6 | exit 1 7 | fi 8 | 9 | # Show help message 10 | if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then 11 | echo "Development Environment Setup Script" 12 | echo 13 | echo "Usage: setup.sh [options]" 14 | echo 15 | echo "Options:" 16 | echo " -h, --help Display this help message again" 17 | echo 18 | echo "This script will:" 19 | echo " - Check system requirements (Arch Linux and macOS only)" 20 | echo " - Verify required package managers (pacman/yay or brew)" 21 | echo " - Install and configure Python environment" 22 | echo " - Install required packages" 23 | echo " - Install Rust toolchain" 24 | echo " - Initialize development environment" 25 | exit 0 26 | fi 27 | 28 | set -eu 29 | 30 | # Check system and package managers 31 | system=$(uname -s | tr '[:upper:]' '[:lower:]') 32 | 33 | if [[ "$system" == "linux" ]]; then 34 | # Check if it's Arch Linux 35 | if [[ ! -f "/etc/arch-release" ]]; then 36 | echo "Error: Only Arch Linux is supported on Linux" 37 | exit 1 38 | fi 39 | 40 | # Check if pacman exists 41 | if ! command -v pacman &>/dev/null; then 42 | echo "Error: pacman is not installed" 43 | exit 1 44 | fi 45 | 46 | # Check if yay exists 47 | if ! command -v yay &>/dev/null; then 48 | echo "Error: yay is not installed" 49 | exit 1 50 | fi 51 | elif [[ "$system" == "darwin" ]]; then 52 | # Check if brew exists 53 | if ! command -v brew &>/dev/null; then 54 | echo "Error: brew is not installed" 55 | exit 1 56 | fi 57 | else 58 | echo "Error: Unsupported system: $system" 59 | exit 1 60 | fi 61 | 62 | # Check if python3 exists 63 | if ! command -v python3 &>/dev/null; then 64 | if [[ "$system" == "linux" ]]; then 65 | echo "Installing python3..." 66 | sudo pacman -S --noconfirm python 67 | else 68 | echo "Error: python3 is not installed. On macOS, python3 should be pre-installed" 69 | exit 1 70 | fi 71 | fi 72 | 73 | echo "Sync packages..." 74 | python3 ~/dotfiles/scripts/syncpkg.py 75 | 76 | # Check if cargo exists 77 | if ! cargo &>/dev/null; then 78 | echo "Installing rust..." 79 | if command -v rustup-init &>/dev/null; then 80 | rustup-init -y 81 | elif command -v rustup &>/dev/null; then 82 | rustup toolchain install stable 83 | rustup component add clippy 84 | rustup component add rust-analyzer 85 | rustup component add rust-src 86 | else 87 | echo "Error: rustup or rustup-init is not installed" 88 | exit 1 89 | fi 90 | fi 91 | 92 | # Check if goimports exists 93 | if ! command -v goimports &>/dev/null; then 94 | echo "Installing go tools..." 95 | go install golang.org/x/tools/cmd/goimports@latest 96 | go install github.com/fatih/gomodifytags@latest 97 | go install github.com/koron/iferr@latest 98 | fi 99 | 100 | if [[ "$system" == "linux" ]] && [[ ! " $@ " =~ " --nodocker " ]]; then 101 | if ! systemctl is-enabled docker &>/dev/null; then 102 | echo "Enabling docker service..." 103 | sudo systemctl enable --now docker 104 | else 105 | echo "Docker service is already enabled" 106 | fi 107 | else 108 | echo "Skip docker service" 109 | fi 110 | 111 | # Set default shell to zsh if not already 112 | if [[ $(basename $SHELL) != "zsh" ]]; then 113 | echo "Setting default shell to zsh..." 114 | if command -v zsh &>/dev/null; then 115 | sudo chsh -s $(which zsh) $USER 116 | else 117 | echo "Error: zsh is not installed" 118 | exit 1 119 | fi 120 | fi 121 | 122 | create_link() { 123 | local target="$1" 124 | local link="$2" 125 | if [[ -e "$link" ]]; then 126 | if [[ -L "$link" ]]; then 127 | echo "Link $link already exists, skip" 128 | return 129 | else 130 | echo "Removing existing non-symlink $link" 131 | rm -rf "$link" 132 | fi 133 | fi 134 | echo "Creating symlink $link -> $target" 135 | ln -s "$target" "$link" 136 | } 137 | 138 | mkdir -p $HOME/.config 139 | 140 | create_link $HOME/dotfiles/term/zsh/zshrc $HOME/.zshrc 141 | create_link $HOME/dotfiles/term/zsh/zshenv $HOME/.zshenv 142 | create_link $HOME/dotfiles/term/wezterm $HOME/.config/wezterm 143 | create_link $HOME/dotfiles/term/kitty $HOME/.config/kitty 144 | create_link $HOME/dotfiles/term/alacritty $HOME/.config/alacritty 145 | 146 | create_link $HOME/dotfiles/apps/lazygit $HOME/.config/lazygit 147 | create_link $HOME/dotfiles/apps/roxide $HOME/.config/roxide 148 | create_link $HOME/dotfiles/apps/starship.toml $HOME/.config/starship.toml 149 | create_link $HOME/dotfiles/apps/kubewrap $HOME/.config/kubewrap 150 | create_link $HOME/dotfiles/apps/k9s $HOME/.config/k9s 151 | create_link $HOME/dotfiles/apps/csync $HOME/.config/csync 152 | create_link $HOME/dotfiles/apps/flameshot $HOME/.config/flameshot 153 | create_link $HOME/dotfiles/apps/otree.toml $HOME/.config/otree.toml 154 | 155 | if [[ ! -d $HOME/.config/nvim ]]; then 156 | echo "Begin to install neovim configs" 157 | git clone https://github.com/fioncat/nvimdots.git $HOME/.config/nvim 158 | nvim --headless "+Lazy! sync" +qa 159 | nvim --headless $HOME/.config/nvim/init.lua -c "TSUpdateSync" +qa 160 | nvim --headless $HOME/.config/nvim/init.lua -c "MasonInstall gopls" +qa 161 | nvim --headless $HOME/.config/nvim/init.lua -c "MasonInstall bash-language-server html-lsp json-lsp lua-language-server python-lsp-server" +qa 162 | else 163 | echo "neovim configs has already been installed, skip" 164 | fi 165 | 166 | echo 167 | echo 168 | echo 169 | echo "██╗ █████╗ ███████╗██╗ ██╗ ██████╗ █████╗ ████████╗" 170 | echo "██║ ██╔══██╗╚══███╔╝╚██╗ ██╔╝██╔════╝██╔══██╗╚══██╔══╝" 171 | echo "██║ ███████║ ███╔╝ ╚████╔╝ ██║ ███████║ ██║ " 172 | echo "██║ ██╔══██║ ███╔╝ ╚██╔╝ ██║ ██╔══██║ ██║ " 173 | echo "███████╗██║ ██║███████╗ ██║ ╚██████╗██║ ██║ ██║ " 174 | echo "╚══════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ " 175 | echo 176 | echo 177 | echo 178 | echo " Done. Please restart your terminal :) " 179 | -------------------------------------------------------------------------------- /hyprland/waybar/config.jsonc: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // 3 | // Waybar configuration 4 | // 5 | // Configuration reference: https://github.com/Alexays/Waybar/wiki/Configuration 6 | // 7 | // ============================================================================= 8 | 9 | { 10 | // ------------------------------------------------------------------------- 11 | // Global configuration 12 | // ------------------------------------------------------------------------- 13 | 14 | "layer": "top", 15 | 16 | "position": "top", 17 | 18 | // If height property would be not present, it'd be calculated dynamically 19 | "height": 40, 20 | 21 | "modules-left": [ 22 | // "custom/icon", 23 | "hyprland/submap", 24 | "hyprland/workspaces" 25 | ], 26 | "modules-center": [ 27 | "clock#date", 28 | "clock#time" 29 | ], 30 | "modules-right": [ 31 | "tray", 32 | "bluetooth", 33 | "pulseaudio", 34 | "cpu", 35 | "temperature", 36 | "memory", 37 | "disk", 38 | "network" 39 | ], 40 | 41 | 42 | // ------------------------------------------------------------------------- 43 | // Modules 44 | // ------------------------------------------------------------------------- 45 | 46 | "clock#date": { 47 | "interval": 10, 48 | "format": "{:%a %b %e %Y}", // Icon: calendar-alt 49 | "tooltip-format": "{calendar}", 50 | "calendar": { 51 | "mode": "month", 52 | "mode-mon-col" : 3, 53 | "weeks-pos" : "right", 54 | "on-scroll" : 1, 55 | "on-click-right": "mode", 56 | "format": { 57 | "months": "{}", 58 | "days": "{}", 59 | "weeks": "W{}", 60 | "weekdays": "{}", 61 | "today": "{}" 62 | } 63 | }, 64 | "actions": { 65 | "on-click-right": "mode", 66 | "on-click-forward": "tz_up", 67 | "on-click-backward": "tz_down", 68 | "on-scroll-up": "shift_down", 69 | "on-scroll-down": "shift_up" 70 | }, 71 | "on-click": "~/.config/rofi/bin/rofi-powermenu" 72 | }, 73 | 74 | "clock#time": { 75 | "interval": 1, 76 | "format": "{:%H:%M}", 77 | "tooltip": false 78 | }, 79 | 80 | "keyboard-state": { 81 | "numlock": false, 82 | "capslock": true, 83 | "format": "{icon}", 84 | "format-icons": { 85 | "unlocked": "", 86 | "locked": "󰘶 Caps" 87 | } 88 | }, 89 | 90 | 91 | "bluetooth": { 92 | "format": " {status}", 93 | "format-disabled": "󰂲 Disabled", // an empty format will hide the module 94 | "format-connected": "󰂱 {num_connections}", 95 | "tooltip-format": "{controller_alias}\t{controller_address}", 96 | "tooltip-format-connected": "{controller_alias}\t{controller_address}\n\n{device_enumerate}", 97 | "tooltip-format-enumerate-connected": "{device_alias}\t{device_address}" 98 | }, 99 | 100 | "pulseaudio": { 101 | "format": "{icon} {volume:3}%", 102 | "format-bluetooth": "{icon} {volume:3}%", 103 | "format-muted": " Muted", 104 | "format-icons": { 105 | "headphone": "", 106 | "hands-free": "󱝉", 107 | "headset": "󰋍", 108 | "phone": "", 109 | "portable": "", 110 | "car": "", 111 | "default": ["", ""] 112 | }, 113 | "scroll-step": 1, 114 | "on-click": "pavucontrol", 115 | "ignored-sinks": ["Easy Effects Sink"] 116 | }, 117 | 118 | "cpu": { 119 | "interval": 1, 120 | "format": "{icon} {usage:3}%", // Icon: microchip 121 | "states": { 122 | "warning": 20, 123 | "critical": 50 124 | }, 125 | "format-icons": [ 126 | "󰄛", 127 | "", 128 | "" 129 | ], 130 | "on-click": "wezterm start -e btm" 131 | }, 132 | 133 | "temperature": { 134 | "critical-threshold": 80, 135 | "interval": 1, 136 | "format": "{icon} {temperatureC:3}°C", 137 | "format-icons": [ 138 | "", // Icon: temperature-empty 139 | "", // Icon: temperature-quarter 140 | "", // Icon: temperature-half 141 | "", // Icon: temperature-three-quarters 142 | "" // Icon: temperature-full 143 | ], 144 | "tooltip": true, 145 | "on-click": "wezterm start -e btm" 146 | }, 147 | 148 | "memory": { 149 | "interval": 1, 150 | "format": "󰍛 {percentage:3}%", // Icon: memory 151 | "states": { 152 | "warning": 20, 153 | "critical": 50 154 | }, 155 | "tooltip-format": "{used:0.1f}GiB / {total:0.1f}GiB", 156 | "on-click": "wezterm start -e btm" 157 | }, 158 | 159 | "network": { 160 | "interval": 1, 161 | "format-wifi": " {bandwidthTotalBytes:>12}", // Icon: wifi 162 | "format-ethernet": "󰀂 {bandwidthTotalBytes:>12}", // Icon: ethernet 163 | "format-disconnected": "󰯡 Disconnected", 164 | "tooltip-format": "{ifname}: {ipaddr}", 165 | "on-click": "nm-connection-editor" 166 | }, 167 | 168 | "disk": { 169 | "interval": 30, 170 | "format": " {free}", 171 | "path": "/", 172 | "tooltip-format": "{used} / {total}" 173 | }, 174 | 175 | "tray": { 176 | "icon-size": 21, 177 | "spacing": 10 178 | }, 179 | 180 | "hyprland/workspaces": { 181 | "format": "{id}: {icon}", 182 | "format-icons": { 183 | "1": " Term", 184 | "2": " Nvim", 185 | "3": " Debug", 186 | "4": " Web", 187 | "5": "󰨞 Code", 188 | "6": "󰭹 Chat", 189 | "7": "󰇮 Mail", 190 | "8": " Sys", 191 | "9": " Fun", 192 | "default": " Work" 193 | }, 194 | }, 195 | 196 | "hyprland/submap": { 197 | "format": " {}", 198 | "tooltip": false 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /apps/sddm/theme.conf: -------------------------------------------------------------------------------- 1 | [General] 2 | 3 | Background="background.png" 4 | ## Path relative to the theme root directory. Most standard image file formats are allowed including support for transparency. (e.g. background.jpeg/illustration.GIF/Foto.png/undraw.svgz) 5 | 6 | DimBackgroundImage="0.0" 7 | ## Double between 0 and 1 used for the alpha channel of a darkening overlay. Use to darken your background image on the fly. 8 | 9 | ScaleImageCropped="true" 10 | ## Whether the image should be cropped when scaled proportionally. Setting this to false will fit the whole image instead, possibly leaving white space. This can be exploited beautifully with illustrations (try it with "undraw.svg" included in the theme). 11 | 12 | ScreenWidth="2560" 13 | ScreenHeight="1440" 14 | ## Adjust to your resolution to help SDDM speed up on calculations 15 | 16 | 17 | 18 | ## [Blur Settings] 19 | 20 | FullBlur="true" 21 | PartialBlur="true" 22 | ## Enable or disable the blur effect; if HaveFormBackground is set to true then PartialBlur will trigger the BackgroundColor of the form element to be partially transparent and blend with the blur. 23 | 24 | BlurRadius="80" 25 | ## Set the strength of the blur effect. Anything above 100 is pretty strong and might slow down the rendering time. 0 is like setting false for any blur. 26 | 27 | 28 | 29 | ## [Design Customizations] 30 | 31 | HaveFormBackground="false" 32 | ## Have a full opacity background color behind the form that takes slightly more than 1/3 of screen estate; if PartialBlur is set to true then HaveFormBackground will trigger the BackgroundColor of the form element to be partially transparent and blend with the blur. 33 | 34 | FormPosition="center" 35 | ## Position of the form which takes roughly 1/3 of screen estate. Can be left, center or right. 36 | 37 | BackgroundImageHAlignment="center" 38 | ## Horizontal position of the background picture relative to its visible area. Applies when ScaleImageCropped is set to false or when HaveFormBackground is set to true and FormPosition is either left or right. Can be left, center or right; defaults to center if none is passed. 39 | 40 | BackgroundImageVAlignment="center" 41 | ## As before but for the vertical position of the background picture relative to its visible area. 42 | 43 | MainColor="#F8F8F2" 44 | ## Used for all elements when not focused/hovered etc. Usually the best effect is achieved by having this be either white or a very dark grey like #444 (not black for smoother antialias) 45 | ## Colors can be HEX or Qt names (e.g. red/salmon/blanchedalmond). See https://doc.qt.io/qt-5/qml-color.html 46 | 47 | AccentColor="#343746" 48 | ## Used for elements in focus/hover/pressed. Should be contrasting to the background and the MainColor to achieve the best effect. 49 | 50 | BackgroundColor="#21222C" 51 | ## Used for the user and session selection background as well as for ScreenPadding and FormBackground when either is true. If PartialBlur and FormBackground are both enabled this color will blend with the blur effect. 52 | 53 | placeholderColor="#bbbbbb" 54 | ## Placeholder text color. Example: username, password. 55 | 56 | IconColor="#ffffff" 57 | ## System icon colors 58 | 59 | OverrideLoginButtonTextColor="" 60 | ## The text of the login button may become difficult to read depending on your color choices. Use this option to set it independently for legibility. 61 | 62 | InterfaceShadowSize="6" 63 | ## Integer used as multiplier. Size of the shadow behind the user and session selection background. Decrease or increase if it looks bad on your background. Initial render can be slow no values above 5-7. 64 | 65 | InterfaceShadowOpacity="0.6" 66 | ## Double between 0 and 1. Alpha channel of the shadow behind the user and session selection background. Decrease or increase if it looks bad on your background. 67 | 68 | RoundCorners="20" 69 | ## Integer in pixels. Radius of the input fields and the login button. Empty for square. Can cause bad antialiasing of the fields. 70 | 71 | ScreenPadding="0" 72 | ## Integer in pixels. Increase or delete this to have a padding of color BackgroundColor all around your screen. This makes your login greeter appear as if it was a canvas. Cool! 73 | 74 | Font="Open Sans" 75 | ## If you want to choose a custom font it will have to be available to the X root user. See https://wiki.archlinux.org/index.php/fonts#Manual_installation 76 | 77 | FontSize="" 78 | ## Only set a fixed value if fonts are way too small for your resolution. Preferably kept empty. 79 | 80 | HideLoginButton="false" 81 | ## Hides login button if set to true. 82 | 83 | 84 | ## [Interface Behavior] 85 | 86 | ForceRightToLeft="false" 87 | ## Revert the layout either because you would like the login to be on the right hand side or SDDM won't respect your language locale for some reason. This will reverse the current position of FormPosition if it is either left or right and in addition position some smaller elements on the right hand side of the form itself (also when FormPosition is set to center). 88 | 89 | ForceLastUser="true" 90 | ## Have the last successfully logged in user appear automatically in the username field. 91 | 92 | ForcePasswordFocus="true" 93 | ## Give automatic focus to the password field. Together with ForceLastUser this makes for the fastest login experience. 94 | 95 | ForceHideCompletePassword="true" 96 | ## If you don't like to see any character at all not even while being entered set this to true. 97 | 98 | ForceHideVirtualKeyboardButton="false" 99 | ## Do not show the button for the virtual keyboard at all. This will completely disable functionality for the virtual keyboard even if it is installed and activated in sddm.conf 100 | 101 | ForceHideSystemButtons="false" 102 | ## Completely disable and hide any power buttons on the greeter. 103 | 104 | AllowEmptyPassword="false" 105 | ## Enable login for users without a password. This is discouraged. Makes the login button always enabled. 106 | 107 | AllowBadUsernames="false" 108 | ## Do not change this! Uppercase letters are generally not allowed in usernames. This option is only for systems that differ from this standard! Also shows username as is instead of capitalized. 109 | 110 | 111 | 112 | ## [Locale Settings] 113 | 114 | Locale="" 115 | ## The time and date locale should usually be set in your system settings. Only hard set this if something is not working by default or you want a separate locale setting in your login screen. 116 | 117 | HourFormat="HH:mm" 118 | ## Defaults to Locale.ShortFormat - Accepts "long" or a custom string like "hh:mm A". See http://doc.qt.io/qt-5/qml-qtqml-date.html 119 | 120 | DateFormat="dddd d MMMM" 121 | ## Defaults to Locale.LongFormat - Accepts "short" or a custom string like "dddd, d 'of' MMMM". See http://doc.qt.io/qt-5/qml-qtqml-date.html 122 | 123 | 124 | 125 | ## [Translations] 126 | 127 | HeaderText="" 128 | ## Header can be empty to not display any greeting at all. Keep it short. 129 | 130 | ## SDDM may lack proper translation for every element. Sugar defaults to SDDM translations. Please help translate SDDM as much as possible for your language: https://github.com/sddm/sddm/wiki/Localization. These are in order as they appear on screen. 131 | 132 | TranslatePlaceholderUsername="" 133 | TranslatePlaceholderPassword="" 134 | TranslateLogin="" 135 | TranslateLoginFailedWarning="" 136 | TranslateCapslockWarning="" 137 | TranslateSuspend="" 138 | TranslateHibernate="" 139 | TranslateReboot="" 140 | TranslateShutdown="" 141 | TranslateVirtualKeyboardButton="" 142 | ## These don't necessarily need to translate anything. You can enter whatever you want here. 143 | -------------------------------------------------------------------------------- /term/wezterm/plugin/catppuccin.lua: -------------------------------------------------------------------------------- 1 | local wezterm = require("wezterm") 2 | 3 | local M = {} 4 | 5 | local colors = { 6 | latte = { 7 | rosewater = "#dc8a78", 8 | flamingo = "#dd7878", 9 | pink = "#ea76cb", 10 | mauve = "#8839ef", 11 | red = "#d20f39", 12 | maroon = "#e64553", 13 | peach = "#fe640b", 14 | yellow = "#df8e1d", 15 | green = "#40a02b", 16 | teal = "#179299", 17 | sky = "#04a5e5", 18 | sapphire = "#209fb5", 19 | blue = "#1e66f5", 20 | lavender = "#7287fd", 21 | text = "#4c4f69", 22 | subtext1 = "#5c5f77", 23 | subtext0 = "#6c6f85", 24 | overlay2 = "#7c7f93", 25 | overlay1 = "#8c8fa1", 26 | overlay0 = "#9ca0b0", 27 | surface2 = "#acb0be", 28 | surface1 = "#bcc0cc", 29 | surface0 = "#ccd0da", 30 | crust = "#dce0e8", 31 | mantle = "#e6e9ef", 32 | base = "#eff1f5", 33 | }, 34 | frappe = { 35 | rosewater = "#f2d5cf", 36 | flamingo = "#eebebe", 37 | pink = "#f4b8e4", 38 | mauve = "#ca9ee6", 39 | red = "#e78284", 40 | maroon = "#ea999c", 41 | peach = "#ef9f76", 42 | yellow = "#e5c890", 43 | green = "#a6d189", 44 | teal = "#81c8be", 45 | sky = "#99d1db", 46 | sapphire = "#85c1dc", 47 | blue = "#8caaee", 48 | lavender = "#babbf1", 49 | text = "#c6d0f5", 50 | subtext1 = "#b5bfe2", 51 | subtext0 = "#a5adce", 52 | overlay2 = "#949cbb", 53 | overlay1 = "#838ba7", 54 | overlay0 = "#737994", 55 | surface2 = "#626880", 56 | surface1 = "#51576d", 57 | surface0 = "#414559", 58 | base = "#303446", 59 | mantle = "#292c3c", 60 | crust = "#232634", 61 | }, 62 | macchiato = { 63 | rosewater = "#f4dbd6", 64 | flamingo = "#f0c6c6", 65 | pink = "#f5bde6", 66 | mauve = "#c6a0f6", 67 | red = "#ed8796", 68 | maroon = "#ee99a0", 69 | peach = "#f5a97f", 70 | yellow = "#eed49f", 71 | green = "#a6da95", 72 | teal = "#8bd5ca", 73 | sky = "#91d7e3", 74 | sapphire = "#7dc4e4", 75 | blue = "#8aadf4", 76 | lavender = "#b7bdf8", 77 | text = "#cad3f5", 78 | subtext1 = "#b8c0e0", 79 | subtext0 = "#a5adcb", 80 | overlay2 = "#939ab7", 81 | overlay1 = "#8087a2", 82 | overlay0 = "#6e738d", 83 | surface2 = "#5b6078", 84 | surface1 = "#494d64", 85 | surface0 = "#363a4f", 86 | base = "#24273a", 87 | mantle = "#1e2030", 88 | crust = "#181926", 89 | }, 90 | mocha = { 91 | rosewater = "#f5e0dc", 92 | flamingo = "#f2cdcd", 93 | pink = "#f5c2e7", 94 | mauve = "#cba6f7", 95 | red = "#f38ba8", 96 | maroon = "#eba0ac", 97 | peach = "#fab387", 98 | yellow = "#f9e2af", 99 | green = "#a6e3a1", 100 | teal = "#94e2d5", 101 | sky = "#89dceb", 102 | sapphire = "#74c7ec", 103 | blue = "#89b4fa", 104 | lavender = "#b4befe", 105 | text = "#cdd6f4", 106 | subtext1 = "#bac2de", 107 | subtext0 = "#a6adc8", 108 | overlay2 = "#9399b2", 109 | overlay1 = "#7f849c", 110 | overlay0 = "#6c7086", 111 | surface2 = "#585b70", 112 | surface1 = "#45475a", 113 | surface0 = "#313244", 114 | base = "#1e1e2e", 115 | mantle = "#181825", 116 | crust = "#11111b", 117 | }, 118 | } 119 | 120 | local mappings = { 121 | mocha = "Catppuccin Mocha", 122 | macchiato = "Catppuccin Macchiato", 123 | frappe = "Catppuccin Frappe", 124 | latte = "Catppuccin Latte", 125 | } 126 | 127 | function M.select(palette, flavor, accent) 128 | local c = palette[flavor] 129 | -- shorthand to check for the Latte flavor 130 | local isLatte = palette == "latte" 131 | 132 | return { 133 | foreground = c.text, 134 | background = c.base, 135 | 136 | cursor_fg = isLatte and c.base or c.crust, 137 | cursor_bg = c.rosewater, 138 | cursor_border = c.rosewater, 139 | 140 | selection_fg = c.text, 141 | selection_bg = c.surface2, 142 | 143 | scrollbar_thumb = c.surface2, 144 | 145 | split = c.overlay0, 146 | 147 | ansi = { 148 | isLatte and c.subtext1 or c.surface1, 149 | c.red, 150 | c.green, 151 | c.yellow, 152 | c.blue, 153 | c.pink, 154 | c.teal, 155 | isLatte and c.surface2 or c.subtext1, 156 | }, 157 | 158 | brights = { 159 | isLatte and c.subtext0 or c.surface2, 160 | c.red, 161 | c.green, 162 | c.yellow, 163 | c.blue, 164 | c.pink, 165 | c.teal, 166 | isLatte and c.surface1 or c.subtext0, 167 | }, 168 | 169 | indexed = { [16] = c.peach, [17] = c.rosewater }, 170 | 171 | -- nightbuild only 172 | compose_cursor = c.flamingo, 173 | 174 | tab_bar = { 175 | background = c.crust, 176 | active_tab = { 177 | bg_color = c[accent], 178 | fg_color = c.crust, 179 | }, 180 | inactive_tab = { 181 | bg_color = c.mantle, 182 | fg_color = c.text, 183 | }, 184 | inactive_tab_hover = { 185 | bg_color = c.base, 186 | fg_color = c.text, 187 | }, 188 | new_tab = { 189 | bg_color = c.surface0, 190 | fg_color = c.text, 191 | }, 192 | new_tab_hover = { 193 | bg_color = c.surface1, 194 | fg_color = c.text, 195 | }, 196 | -- fancy tab bar 197 | inactive_tab_edge = c.surface0, 198 | }, 199 | 200 | visual_bell = c.surface0, 201 | } 202 | end 203 | 204 | local function select_for_appearance(appearance, options) 205 | if appearance:find("Dark") then 206 | return options.dark 207 | else 208 | return options.light 209 | end 210 | end 211 | 212 | local function tableMerge(t1, t2) 213 | for k, v in pairs(t2) do 214 | if type(v) == "table" then 215 | if type(t1[k] or false) == "table" then 216 | tableMerge(t1[k] or {}, t2[k] or {}) 217 | else 218 | t1[k] = v 219 | end 220 | else 221 | t1[k] = v 222 | end 223 | end 224 | return t1 225 | end 226 | 227 | function M.apply_to_config(c, opts) 228 | if not opts then 229 | opts = {} 230 | end 231 | 232 | -- default options 233 | local defaults = { 234 | flavor = "mocha", 235 | accent = "mauve", 236 | sync = false, 237 | sync_flavors = { light = "latte", dark = "mocha" }, 238 | color_overrides = { mocha = {}, macchiato = {}, frappe = {}, latte = {} }, 239 | token_overrides = { mocha = {}, macchiato = {}, frappe = {}, latte = {} }, 240 | } 241 | 242 | local o = tableMerge(defaults, opts) 243 | 244 | -- insert all flavors 245 | local color_schemes = {} 246 | local palette = tableMerge(colors, o.color_overrides) 247 | for flavor, name in pairs(mappings) do 248 | local spec = M.select(palette, flavor, o.accent) 249 | local overrides = o.token_overrides[flavor] 250 | color_schemes[name] = tableMerge(spec, overrides) 251 | end 252 | if c.color_schemes == nil then 253 | c.color_schemes = {} 254 | end 255 | c.color_schemes = tableMerge(c.color_schemes, color_schemes) 256 | 257 | if opts.sync then 258 | c.color_scheme = select_for_appearance(wezterm.gui.get_appearance(), { 259 | dark = mappings[o.sync_flavors.dark], 260 | light = mappings[o.sync_flavors.light], 261 | }) 262 | c.command_palette_bg_color = select_for_appearance(wezterm.gui.get_appearance(), { 263 | dark = colors[o.sync_flavors.dark].crust, 264 | light = colors[o.sync_flavors.light].crust, 265 | }) 266 | c.command_palette_fg_color = select_for_appearance(wezterm.gui.get_appearance(), { 267 | dark = colors[o.sync_flavors.dark].text, 268 | light = colors[o.sync_flavors.light].text, 269 | }) 270 | else 271 | c.color_scheme = mappings[o.flavor] 272 | c.command_palette_bg_color = colors[o.flavor].crust 273 | c.command_palette_fg_color = colors[o.flavor].text 274 | end 275 | 276 | local window_frame = { 277 | active_titlebar_bg = colors[o.flavor].crust, 278 | active_titlebar_fg = colors[o.flavor].text, 279 | inactive_titlebar_bg = colors[o.flavor].crust, 280 | inactive_titlebar_fg = colors[o.flavor].text, 281 | button_fg = colors[o.flavor].text, 282 | button_bg = colors[o.flavor].base, 283 | } 284 | 285 | if c.window_frame == nil then 286 | c.window_frame = {} 287 | end 288 | c.window_frame = tableMerge(c.window_frame, window_frame) 289 | end 290 | 291 | return M 292 | -------------------------------------------------------------------------------- /term/wezterm/config/keys.lua: -------------------------------------------------------------------------------- 1 | ---@type wezterm 2 | local wezterm = require("wezterm") 3 | local act = wezterm.action 4 | 5 | local shortcuts = {} 6 | 7 | local map = function(key, mods, action) 8 | if type(mods) == "string" then 9 | table.insert(shortcuts, { key = key, mods = mods, action = action }) 10 | elseif type(mods) == "table" then 11 | for _, mod in pairs(mods) do 12 | table.insert(shortcuts, { key = key, mods = mod, action = action }) 13 | end 14 | end 15 | end 16 | 17 | local toggleTabBar = wezterm.action_callback(function(window) 18 | window:set_config_overrides({ 19 | enable_tab_bar = not window:effective_config().enable_tab_bar, 20 | }) 21 | end) 22 | 23 | local openUrl = act.QuickSelectArgs({ 24 | label = "open url", 25 | patterns = { "https?://\\S+" }, 26 | action = wezterm.action_callback(function(window, pane) 27 | local url = window:get_selection_text_for_pane(pane) 28 | wezterm.open_with(url) 29 | end), 30 | }) 31 | 32 | local changeCtpFlavor = act.InputSelector({ 33 | title = "Change Catppuccin flavor", 34 | choices = { 35 | { label = "Mocha" }, 36 | { label = "Macchiato" }, 37 | { label = "Frappe" }, 38 | { label = "Latte" }, 39 | }, 40 | action = wezterm.action_callback(function(window, _, _, label) 41 | if label then 42 | window:set_config_overrides({ color_scheme = "Catppuccin " .. label }) 43 | end 44 | end), 45 | }) 46 | 47 | -- use 'Backslash' to split horizontally 48 | map("/", "LEADER", act.SplitHorizontal({ domain = "CurrentPaneDomain" })) 49 | -- and 'Minus' to split vertically 50 | map("-", "LEADER", act.SplitVertical({ domain = "CurrentPaneDomain" })) 51 | -- map 1-9 to switch to tab 1-9, Tab for the last tab 52 | for i = 1, 9 do 53 | map(tostring(i), { "LEADER" }, act.ActivateTab(i - 1)) 54 | end 55 | map("Tab", { "LEADER" }, act.ActivateLastTab) 56 | -- 'hjkl' to move between panes 57 | map("h", { "LEADER" }, act.ActivatePaneDirection("Left")) 58 | map("j", { "LEADER" }, act.ActivatePaneDirection("Down")) 59 | map("k", { "LEADER" }, act.ActivatePaneDirection("Up")) 60 | map("l", { "LEADER" }, act.ActivatePaneDirection("Right")) 61 | -- resize 62 | map("h", "LEADER|SHIFT", act.AdjustPaneSize({ "Left", 5 })) 63 | map("j", "LEADER|SHIFT", act.AdjustPaneSize({ "Down", 5 })) 64 | map("k", "LEADER|SHIFT", act.AdjustPaneSize({ "Up", 5 })) 65 | map("l", "LEADER|SHIFT", act.AdjustPaneSize({ "Right", 5 })) 66 | -- spawn & close 67 | map("c", "LEADER", act.SpawnTab("CurrentPaneDomain")) 68 | map("x", "LEADER", act.CloseCurrentPane({ confirm = true })) 69 | map("t", "LEADER", changeCtpFlavor) 70 | map("t", { "SHIFT|CTRL" }, act.SpawnTab("CurrentPaneDomain")) 71 | map("w", { "SHIFT|CTRL" }, act.CloseCurrentTab({ confirm = true })) 72 | map("n", { "SHIFT|CTRL" }, act.SpawnWindow) 73 | -- zoom states 74 | map("z", { "LEADER" }, act.TogglePaneZoomState) 75 | map("Z", { "LEADER" }, toggleTabBar) 76 | -- copy & paste 77 | map("Enter", "LEADER", act.ActivateCopyMode) 78 | map("c", { "SHIFT|CTRL" }, act.CopyTo("Clipboard")) 79 | map("v", { "SHIFT|CTRL" }, act.PasteFrom("Clipboard")) 80 | map("f", { "SHIFT|CTRL" }, act.Search({ CaseInSensitiveString = "" })) 81 | -- rotation 82 | map("e", { "LEADER" }, act.RotatePanes("Clockwise")) 83 | -- pickers 84 | map(" ", "LEADER", act.QuickSelect) 85 | map("o", { "LEADER" }, openUrl) 86 | map("q", { "LEADER" }, act.PaneSelect({ alphabet = "123456789" })) 87 | map("R", { "LEADER" }, act.ReloadConfiguration) 88 | map("u", "SHIFT|CTRL", act.CharSelect) 89 | map("p", { "SHIFT|CTRL" }, act.ActivateCommandPalette) 90 | -- view 91 | map("Enter", "ALT", act.ToggleFullScreen) 92 | map("-", { "SUPER" }, act.DecreaseFontSize) 93 | map("=", { "SUPER" }, act.IncreaseFontSize) 94 | map("0", { "SUPER" }, act.ResetFontSize) 95 | -- switch fonts 96 | map("f", "LEADER", act.EmitEvent("switch-font")) 97 | -- debug 98 | map("l", "SHIFT|CTRL", act.ShowDebugOverlay) 99 | 100 | map( 101 | "r", 102 | { "LEADER" }, 103 | act.ActivateKeyTable({ 104 | name = "resize_mode", 105 | one_shot = false, 106 | }) 107 | ) 108 | 109 | -- Edit tab title manually 110 | map( 111 | ",", 112 | "LEADER", 113 | act.PromptInputLine({ 114 | description = "Enter new name for tab", 115 | action = wezterm.action_callback(function(window, pane, line) 116 | -- line will be `nil` if they hit escape without entering anything 117 | -- An empty string if they just hit enter 118 | -- Or the actual line of text they wrote 119 | if line then 120 | window:active_tab():set_title(line) 121 | end 122 | end), 123 | }) 124 | ) 125 | 126 | -- Pin tab title to current working dirname 127 | map( 128 | ".", 129 | "LEADER", 130 | wezterm.action_callback(function(win, pane) 131 | -- See: https://wezfurlong.org/wezterm/config/lua/pane/get_current_working_dir.html 132 | local url = pane:get_current_working_dir() 133 | local name = string.gsub(url.file_path, "(.*[/\\])(.*)", "%2") 134 | win:active_tab():set_title(name) 135 | end) 136 | ) 137 | 138 | -- Pin tab title to roxide which 139 | map( 140 | ";", 141 | "LEADER", 142 | wezterm.action_callback(function(win, pane) 143 | local url = pane:get_current_working_dir() 144 | 145 | local script = 'ROXIDE_WORK="' .. url.file_path .. '" roxide which' 146 | local cmd = "zsh -c 'source ~/.zshrc; " .. script .. "'" 147 | 148 | local file = io.popen(cmd) 149 | if file == nil then 150 | return 151 | end 152 | local output = file:read("*a") 153 | file:close() 154 | 155 | output = string.gsub(output, "\n", "") 156 | if #output > 0 then 157 | win:active_tab():set_title(output) 158 | end 159 | end) 160 | ) 161 | 162 | local key_tables = { 163 | resize_mode = { 164 | { key = "h", action = act.AdjustPaneSize({ "Left", 1 }) }, 165 | { key = "j", action = act.AdjustPaneSize({ "Down", 1 }) }, 166 | { key = "k", action = act.AdjustPaneSize({ "Up", 1 }) }, 167 | { key = "l", action = act.AdjustPaneSize({ "Right", 1 }) }, 168 | { key = "LeftArrow", action = act.AdjustPaneSize({ "Left", 1 }) }, 169 | { key = "DownArrow", action = act.AdjustPaneSize({ "Down", 1 }) }, 170 | { key = "UpArrow", action = act.AdjustPaneSize({ "Up", 1 }) }, 171 | { key = "RightArrow", action = act.AdjustPaneSize({ "Right", 1 }) }, 172 | }, 173 | } 174 | 175 | -- add a common escape sequence to all key tables 176 | for k, _ in pairs(key_tables) do 177 | table.insert(key_tables[k], { key = "Escape", action = "PopKeyTable" }) 178 | table.insert(key_tables[k], { key = "Enter", action = "PopKeyTable" }) 179 | table.insert(key_tables[k], { key = "c", mods = "CTRL", action = "PopKeyTable" }) 180 | end 181 | 182 | local M = {} 183 | M.apply = function(c) 184 | c.leader = { 185 | key = "s", 186 | mods = "CTRL", 187 | timeout_milliseconds = math.maxinteger, 188 | } 189 | c.keys = shortcuts 190 | c.disable_default_key_bindings = true 191 | c.key_tables = key_tables 192 | c.mouse_bindings = { 193 | -- Change the default click behavior so that it only selects 194 | -- text and doesn't open hyperlinks 195 | { 196 | event = { Up = { streak = 1, button = "Left" } }, 197 | mods = "NONE", 198 | action = act.CompleteSelection("ClipboardAndPrimarySelection"), 199 | }, 200 | 201 | -- and make CTRL-Click open hyperlinks 202 | { 203 | event = { Up = { streak = 1, button = "Left" } }, 204 | mods = "CTRL", 205 | action = act.OpenLinkAtMouseCursor, 206 | }, 207 | 208 | -- Disable the 'Down' event of CTRL-Click to avoid weird program behaviors 209 | { 210 | event = { Down = { streak = 1, button = "Left" } }, 211 | mods = "CTRL", 212 | action = act.Nop, 213 | }, 214 | 215 | { 216 | event = { Down = { streak = 1, button = { WheelUp = 1 } } }, 217 | mods = "NONE", 218 | action = wezterm.action.ScrollByLine(-5), 219 | }, 220 | { 221 | event = { Down = { streak = 1, button = { WheelDown = 1 } } }, 222 | mods = "NONE", 223 | action = wezterm.action.ScrollByLine(5), 224 | }, 225 | } 226 | end 227 | return M 228 | -------------------------------------------------------------------------------- /term/wezterm/plugin/bar.lua: -------------------------------------------------------------------------------- 1 | local wezterm = require("wezterm") 2 | 3 | local M = {} 4 | 5 | -- default configuration 6 | local config = { 7 | position = "bottom", 8 | max_width = 32, 9 | dividers = "slant_right", 10 | indicator = { 11 | leader = { 12 | enabled = true, 13 | off = " ", 14 | on = " ", 15 | }, 16 | mode = { 17 | enabled = true, 18 | names = { 19 | resize_mode = "RESIZE", 20 | copy_mode = "VISUAL", 21 | search_mode = "SEARCH", 22 | }, 23 | }, 24 | }, 25 | tabs = { 26 | numerals = "arabic", 27 | pane_count = "superscript", 28 | brackets = { 29 | active = { "", ":" }, 30 | inactive = { "", ":" }, 31 | }, 32 | }, 33 | clock = { 34 | enabled = true, 35 | format = "%H:%M", 36 | }, 37 | } 38 | 39 | -- parsed config 40 | local C = {} 41 | 42 | local function tableMerge(t1, t2) 43 | for k, v in pairs(t2) do 44 | if type(v) == "table" then 45 | if type(t1[k] or false) == "table" then 46 | tableMerge(t1[k] or {}, t2[k] or {}) 47 | else 48 | t1[k] = v 49 | end 50 | else 51 | t1[k] = v 52 | end 53 | end 54 | return t1 55 | end 56 | 57 | local dividers = { 58 | slant_right = { 59 | left = utf8.char(0xe0be), 60 | right = utf8.char(0xe0bc), 61 | }, 62 | slant_left = { 63 | left = utf8.char(0xe0ba), 64 | right = utf8.char(0xe0b8), 65 | }, 66 | arrows = { 67 | left = utf8.char(0xe0b2), 68 | right = utf8.char(0xe0b0), 69 | }, 70 | rounded = { 71 | left = utf8.char(0xe0b6), 72 | right = utf8.char(0xe0b4), 73 | }, 74 | } 75 | 76 | -- conforming to https://github.com/wez/wezterm/commit/e4ae8a844d8feaa43e1de34c5cc8b4f07ce525dd 77 | -- exporting an apply_to_config function, even though we don't change the users config 78 | M.apply_to_config = function(c, opts) 79 | -- make the opts arg optional 80 | if not opts then 81 | opts = {} 82 | end 83 | 84 | -- combine user config with defaults 85 | config = tableMerge(config, opts) 86 | C.div = { 87 | l = "", 88 | r = "", 89 | } 90 | 91 | if config.dividers then 92 | C.div.l = dividers[config.dividers].left 93 | C.div.r = dividers[config.dividers].right 94 | end 95 | 96 | C.leader = { 97 | enabled = config.indicator.leader.enabled and true, 98 | off = config.indicator.leader.off, 99 | on = config.indicator.leader.on, 100 | } 101 | 102 | C.mode = { 103 | enabled = config.indicator.mode.enabled, 104 | names = config.indicator.mode.names, 105 | } 106 | 107 | C.tabs = { 108 | numerals = config.tabs.numerals, 109 | pane_count_style = config.tabs.pane_count, 110 | brackets = { 111 | active = config.tabs.brackets.active, 112 | inactive = config.tabs.brackets.inactive, 113 | }, 114 | } 115 | 116 | C.clock = { 117 | enabled = config.clock.enabled, 118 | format = config.clock.format, 119 | } 120 | 121 | -- set the right-hand padding to 0 spaces, if the rounded style is active 122 | C.p = (config.dividers == "rounded") and "" or " " 123 | 124 | -- set wezterm config options according to the parsed config 125 | c.use_fancy_tab_bar = false 126 | c.tab_bar_at_bottom = config.position == "bottom" 127 | c.tab_max_width = config.max_width 128 | end 129 | 130 | -- superscript/subscript 131 | local function numberStyle(number, script) 132 | local scripts = { 133 | superscript = { 134 | "⁰", 135 | "¹", 136 | "²", 137 | "³", 138 | "⁴", 139 | "⁵", 140 | "⁶", 141 | "⁷", 142 | "⁸", 143 | "⁹", 144 | }, 145 | subscript = { 146 | "₀", 147 | "₁", 148 | "₂", 149 | "₃", 150 | "₄", 151 | "₅", 152 | "₆", 153 | "₇", 154 | "₈", 155 | "₉", 156 | }, 157 | } 158 | local numbers = scripts[script] 159 | local number_string = tostring(number) 160 | local result = "" 161 | for i = 1, #number_string do 162 | local char = number_string:sub(i, i) 163 | local num = tonumber(char) 164 | if num then 165 | result = result .. numbers[num + 1] 166 | else 167 | result = result .. char 168 | end 169 | end 170 | return result 171 | end 172 | 173 | local roman_numerals = { 174 | "Ⅰ", 175 | "Ⅱ", 176 | "Ⅲ", 177 | "Ⅳ", 178 | "Ⅴ", 179 | "Ⅵ", 180 | "Ⅶ", 181 | "Ⅷ", 182 | "Ⅸ", 183 | "Ⅹ", 184 | "Ⅺ", 185 | "Ⅻ", 186 | } 187 | 188 | -- custom tab bar 189 | wezterm.on("format-tab-title", function(tab, tabs, _panes, conf, _hover, _max_width) 190 | local colours = conf.resolved_palette.tab_bar 191 | 192 | local active_tab_index = 0 193 | for _, t in ipairs(tabs) do 194 | if t.is_active == true then 195 | active_tab_index = t.tab_index 196 | end 197 | end 198 | 199 | -- TODO: make colors configurable 200 | local rainbow = { 201 | conf.resolved_palette.ansi[2], 202 | conf.resolved_palette.indexed[16], 203 | conf.resolved_palette.ansi[4], 204 | conf.resolved_palette.ansi[3], 205 | conf.resolved_palette.ansi[5], 206 | conf.resolved_palette.ansi[6], 207 | } 208 | 209 | local i = tab.tab_index % 6 210 | local active_bg = rainbow[i + 1] 211 | local active_fg = colours.background 212 | local inactive_bg = colours.inactive_tab.bg_color 213 | local inactive_fg = colours.inactive_tab.fg_color 214 | local new_tab_bg = colours.new_tab.bg_color 215 | 216 | local s_bg, s_fg, e_bg, e_fg 217 | 218 | -- the last tab 219 | if tab.tab_index == #tabs - 1 then 220 | if tab.is_active then 221 | s_bg = active_bg 222 | s_fg = active_fg 223 | e_bg = new_tab_bg 224 | e_fg = active_bg 225 | else 226 | s_bg = inactive_bg 227 | s_fg = inactive_fg 228 | e_bg = new_tab_bg 229 | e_fg = inactive_bg 230 | end 231 | elseif tab.tab_index == active_tab_index - 1 then 232 | s_bg = inactive_bg 233 | s_fg = inactive_fg 234 | e_bg = rainbow[(i + 1) % 6 + 1] 235 | e_fg = inactive_bg 236 | elseif tab.is_active then 237 | s_bg = active_bg 238 | s_fg = active_fg 239 | e_bg = inactive_bg 240 | e_fg = active_bg 241 | else 242 | s_bg = inactive_bg 243 | s_fg = inactive_fg 244 | e_bg = inactive_bg 245 | e_fg = inactive_bg 246 | end 247 | 248 | local pane_count = "" 249 | local tabi = wezterm.mux.get_tab(tab.tab_id) 250 | if C.tabs.pane_count_style then 251 | local muxpanes = tabi:panes() 252 | local count = #muxpanes == 1 and "" or tostring(#muxpanes) 253 | pane_count = numberStyle(count, C.tabs.pane_count_style) 254 | end 255 | 256 | local index_i 257 | if C.tabs.numerals == "roman" then 258 | index_i = roman_numerals[tab.tab_index + 1] 259 | else 260 | index_i = tab.tab_index + 1 261 | end 262 | 263 | local index 264 | if tab.is_active then 265 | index = string.format("%s%s%s ", C.tabs.brackets.active[1], index_i, C.tabs.brackets.active[2]) 266 | else 267 | index = string.format("%s%s%s ", C.tabs.brackets.inactive[1], index_i, C.tabs.brackets.inactive[2]) 268 | end 269 | 270 | -- start and end hardcoded numbers are the Powerline + " " padding 271 | local fillerwidth = 2 + string.len(index) + string.len(pane_count) + 2 272 | 273 | local tabtitle = tab.active_pane.title 274 | 275 | -- user can input title from `window:active_tab():set_title()` 276 | local usertitle = tabi:get_title() 277 | if usertitle ~= nil and #usertitle > 0 then 278 | tabtitle = usertitle 279 | end 280 | 281 | local width = conf.tab_max_width - fillerwidth - 1 282 | if (#tabtitle + fillerwidth) > conf.tab_max_width then 283 | tabtitle = wezterm.truncate_right(tabtitle, width) .. "…" 284 | end 285 | 286 | local title = string.format(" %s%s%s%s", index, tabtitle, pane_count, C.p) 287 | 288 | return { 289 | { Background = { Color = s_bg } }, 290 | { Foreground = { Color = s_fg } }, 291 | { Text = title }, 292 | { Background = { Color = e_bg } }, 293 | { Foreground = { Color = e_fg } }, 294 | { Text = C.div.r }, 295 | } 296 | end) 297 | 298 | wezterm.on("update-status", function(window, _pane) 299 | local active_kt = window:active_key_table() ~= nil 300 | local show = C.leader.enabled or (active_kt and C.mode.enabled) 301 | if not show then 302 | window:set_left_status("") 303 | return 304 | end 305 | 306 | local present, conf = pcall(window.effective_config, window) 307 | if not present then 308 | return 309 | end 310 | local palette = conf.resolved_palette 311 | 312 | local background = palette.ansi[5] 313 | if window:leader_is_active() then 314 | background = palette.indexed[16] 315 | end 316 | 317 | local leader = "" 318 | if C.leader.enabled then 319 | local leader_text = C.leader.off 320 | if window:leader_is_active() then 321 | leader_text = C.leader.on 322 | end 323 | leader = wezterm.format({ 324 | { Foreground = { Color = palette.background } }, 325 | { Background = { Color = background } }, 326 | { Text = " " .. leader_text .. C.p }, 327 | }) 328 | end 329 | 330 | local mode = "" 331 | if C.mode.enabled then 332 | local mode_text = "" 333 | local active = window:active_key_table() 334 | if C.mode.names[active] ~= nil then 335 | mode_text = C.mode.names[active] .. "" 336 | end 337 | mode = wezterm.format({ 338 | { Foreground = { Color = palette.background } }, 339 | { Background = { Color = background } }, 340 | { Attribute = { Intensity = "Bold" } }, 341 | { Text = mode_text }, 342 | "ResetAttributes", 343 | }) 344 | end 345 | 346 | local first_tab_active = window:mux_window():tabs_with_info()[1].is_active 347 | local divider_bg = first_tab_active and palette.ansi[2] or palette.tab_bar.inactive_tab.bg_color 348 | 349 | local divider = wezterm.format({ 350 | { Background = { Color = divider_bg } }, 351 | { Foreground = { Color = background } }, 352 | { Text = C.div.r }, 353 | }) 354 | 355 | window:set_left_status(leader .. mode .. divider) 356 | 357 | if C.clock.enabled then 358 | local time = wezterm.time.now():format(C.clock.format) 359 | window:set_right_status(wezterm.format({ 360 | { Background = { Color = palette.tab_bar.background } }, 361 | { Foreground = { Color = palette.ansi[6] } }, 362 | { Text = time }, 363 | })) 364 | end 365 | end) 366 | 367 | return M 368 | --------------------------------------------------------------------------------