Initial commit: sway + uwsm desktop dotfiles
Nord-themed Wayland setup on sway (via uwsm), including: - sway/swayidle/swaylock/swaddle — WM, idle/lock/inhibit - waybar, rofi — bar and launcher - dunst — notifications - foot — terminal - zsh (+fzf, syntax highlighting, autosuggestions) — shell - mpd/rmpc/mpc, mpv — music and video - nvim — editor (lazy.nvim) - ly — login manager - rbw + pinentry-rofi wrapper — Bitwarden/Vaultwarden CLI - per-window-layout, clipvault — helper systemd services
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
HISTFILE="$HOME/.zsh_history"
|
||||
HISTSIZE=10000
|
||||
SAVEHIST=10000
|
||||
|
||||
bindkey -v
|
||||
KEYTIMEOUT=1
|
||||
|
||||
setopt APPEND_HISTORY
|
||||
setopt SHARE_HISTORY
|
||||
setopt PROMPT_SUBST
|
||||
|
||||
autoload -U compinit
|
||||
compinit
|
||||
source <(fzf --zsh)
|
||||
|
||||
if [[ -f /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh ]]; then
|
||||
source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
|
||||
fi
|
||||
|
||||
if [[ -f /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh ]]; then
|
||||
source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
|
||||
fi
|
||||
|
||||
if [[ -f ~/.zsh/plugins/fzf-tab/fzf-tab.plugin.zsh ]]; then
|
||||
source ~/.zsh/plugins/fzf-tab/fzf-tab.plugin.zsh
|
||||
fi
|
||||
|
||||
if [[ -f ~/.zsh/plugins/fzf-tab-completion/zsh/fzf-tab-completion.plugin.zsh ]]; then
|
||||
source ~/.zsh/plugins/fzf-tab-completion/zsh/fzf-tab-completion.plugin.zsh
|
||||
fi
|
||||
|
||||
typeset -A ZSH_HIGHLIGHT_STYLES
|
||||
ZSH_HIGHLIGHT_STYLES[default]='fg=#eceff4'
|
||||
ZSH_HIGHLIGHT_STYLES[unknown-token]='fg=#bf616a'
|
||||
ZSH_HIGHLIGHT_STYLES[command]='fg=#88c0d0'
|
||||
ZSH_HIGHLIGHT_STYLES[builtin]='fg=#88c0d0'
|
||||
ZSH_HIGHLIGHT_STYLES[alias]='fg=#8fbcbb'
|
||||
ZSH_HIGHLIGHT_STYLES[function]='fg=#88c0d0'
|
||||
ZSH_HIGHLIGHT_STYLES[precommand]='fg=#81a1c1,bold'
|
||||
ZSH_HIGHLIGHT_STYLES[reserved-word]='fg=#81a1c1'
|
||||
ZSH_HIGHLIGHT_STYLES[commandseparator]='fg=#d08770'
|
||||
ZSH_HIGHLIGHT_STYLES[path]='fg=#eceff4,underline'
|
||||
ZSH_HIGHLIGHT_STYLES[path_prefix]='fg=#eceff4,underline'
|
||||
ZSH_HIGHLIGHT_STYLES[optstring]='fg=#ebcb8b'
|
||||
ZSH_HIGHLIGHT_STYLES[argument-base]='fg=#eceff4'
|
||||
ZSH_HIGHLIGHT_STYLES[dollar-parameter]='fg=#b48ead'
|
||||
ZSH_HIGHLIGHT_STYLES[dollar-parameter_extension]='fg=#b48ead'
|
||||
ZSH_HIGHLIGHT_STYLES[single-quoted-argument]='fg=#a3be8c'
|
||||
ZSH_HIGHLIGHT_STYLES[double-quoted-argument]='fg=#a3be8c'
|
||||
ZSH_HIGHLIGHT_STYLES[dollar-quoted-argument]='fg=#a3be8c'
|
||||
ZSH_HIGHLIGHT_STYLES[comment]='fg=#4c566a,italic'
|
||||
ZSH_HIGHLIGHT_STYLES[globbing]='fg=#ebcb8b'
|
||||
ZSH_HIGHLIGHT_STYLES[history-expansion]='fg=#d08770'
|
||||
|
||||
zstyle ':fzf-tab:*' fzf-flags \
|
||||
--color=fg:#eceff4,bg:#2e3440,fg+:#eceff4,bg+:#3b4252 \
|
||||
--color=hl:#88c0d0,hl+:#88c0d0,info:#b48ead,prompt:#81a1c1 \
|
||||
--color=pointer:#88c0d0,marker:#a3be8c,spinner:#88c0d0,header:#5e81ac \
|
||||
--color=border:#4c566a,label:#8fbcbb,query:#eceff4 \
|
||||
--color=preview-fg:#eceff4,preview-bg:#2e3440,preview-border:#4c566a,preview-label:#8fbcbb \
|
||||
--color=gutter:#3b4252,separator:#434c5e,scrollbar:#5e81ac,preview-scrollbar:#5e81ac \
|
||||
--color=disabled:#4c566a \
|
||||
--prompt='❯ '
|
||||
|
||||
export FZF_DEFAULT_OPTS="
|
||||
--color=fg:#eceff4,bg:#2e3440,fg+:#eceff4,bg+:#3b4252
|
||||
--color=hl:#88c0d0,hl+:#88c0d0,info:#b48ead,prompt:#81a1c1
|
||||
--color=pointer:#88c0d0,marker:#a3be8c,spinner:#88c0d0,header:#5e81ac
|
||||
--color=border:#4c566a,label:#8fbcbb,query:#eceff4
|
||||
--color=preview-fg:#eceff4,preview-bg:#2e3440,preview-border:#4c566a,preview-label:#8fbcbb
|
||||
--color=gutter:#3b4252,separator:#434c5e,scrollbar:#5e81ac,preview-scrollbar:#5e81ac
|
||||
--color=disabled:#4c566a
|
||||
--prompt='❯ '
|
||||
"
|
||||
|
||||
prompt_symbol() {
|
||||
if [[ "$KEYMAP" == "vicmd" ]]; then
|
||||
print -r -- "%F{#ebcb8b}❮%f"
|
||||
else
|
||||
print -r -- "%F{#88c0d0}❯%f"
|
||||
fi
|
||||
}
|
||||
|
||||
update_vim_prompt() {
|
||||
zle reset-prompt
|
||||
}
|
||||
|
||||
zle-keymap-select() {
|
||||
update_vim_prompt
|
||||
}
|
||||
|
||||
zle-line-init() {
|
||||
zle -K viins
|
||||
update_vim_prompt
|
||||
}
|
||||
|
||||
git_prompt_info() {
|
||||
local branch
|
||||
local staged
|
||||
local modified
|
||||
local untracked
|
||||
local deleted
|
||||
local conflicts
|
||||
local git_state=""
|
||||
|
||||
branch=$(git branch --show-current 2>/dev/null)
|
||||
|
||||
# Не Git-репозиторий
|
||||
if [[ -z "$branch" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
staged=$(git diff --cached --name-only 2>/dev/null | wc -l | tr -d ' ')
|
||||
modified=$(git diff --name-only 2>/dev/null | wc -l | tr -d ' ')
|
||||
untracked=$(git ls-files --others --exclude-standard 2>/dev/null | wc -l | tr -d ' ')
|
||||
deleted=$(git diff --name-only --diff-filter=D 2>/dev/null | wc -l | tr -d ' ')
|
||||
conflicts=$(git diff --name-only --diff-filter=U 2>/dev/null | wc -l | tr -d ' ')
|
||||
|
||||
if (( staged > 0 )); then
|
||||
git_state+=" %F{#b48ead} ${staged}%f"
|
||||
fi
|
||||
if (( modified > 0 )); then
|
||||
git_state+=" %F{#ebcb8b} ${modified}%f"
|
||||
fi
|
||||
if (( untracked > 0 )); then
|
||||
git_state+=" %F{#a3be8c} ${untracked}%f"
|
||||
fi
|
||||
if (( deleted > 0 )); then
|
||||
git_state+=" %F{#d08770} ${deleted}%f"
|
||||
fi
|
||||
if (( conflicts > 0 )); then
|
||||
git_state+=" %F{#bf616a} ${conflicts}%f"
|
||||
fi
|
||||
if [[ -n "$git_state" ]]; then
|
||||
git_state=" %F{#88c0d0}❯%f${git_state}"
|
||||
fi
|
||||
|
||||
print -r -- " %F{#88c0d0}❯%f %F{#8fbcbb} ${branch}%f${git_state}"
|
||||
}
|
||||
|
||||
precmd() {
|
||||
local exit_code=$?
|
||||
|
||||
if (( exit_code != 0 )); then
|
||||
PROMPT_EXIT="%F{#941703}✗${exit_code}%f "
|
||||
else
|
||||
PROMPT_EXIT=""
|
||||
fi
|
||||
}
|
||||
|
||||
nvim() {
|
||||
printf '\033]0;nvim\007'
|
||||
command nvim "$@"
|
||||
printf '\033]0;foot\007'
|
||||
}
|
||||
|
||||
zle -N zle-keymap-select
|
||||
zle -N zle-line-init
|
||||
|
||||
PROMPT='%F{#eceff4}%~%f$(git_prompt_info) $(prompt_symbol) '
|
||||
|
||||
vi() { nvim "$@"; }
|
||||
vim() { nvim "$@"; }
|
||||
alias rmpc='printf "\033]0;rmpc\007"; command rmpc; printf "\033]0;foot\007"'
|
||||
@@ -0,0 +1,153 @@
|
||||
# dotfiles-sway
|
||||
|
||||
Конфиги для Sway.
|
||||
|
||||
## Стек
|
||||
|
||||
|Компонент|Технология|Описание|
|
||||
|---|---|---|
|
||||
|Тайлинговый менеджер|sway|i3-совместимый Wayland-компоузер. Раскладка окон, workspaces, бинды, запуск через uwsm|
|
||||
||swayidle|Демон бездействия: блокирует экран, гасит мониторы (dpms off) и уходит в suspend по таймаутам; блокирует перед сном и включает мониторы после пробуждения|
|
||||
||swaylock|Экран блокировки для Wayland/sway, с Nord-темой и индикатором ввода пароля|
|
||||
||swaddle|MPRIS-инхибитор автоблокировки/сна — не даёт экрану гаснуть во время прослушивания музыки или просмотра видео|
|
||||
||waybar|Панель статуса: workspaces, clock, tray, idle-inhibitor, CPU/RAM/temp/disk, аудио-виджеты (wireplumber), кастомный лаунчер rofi|
|
||||
||rofi|Лаунчер приложений/меню: drun, кастомные моды по категориям (internet/dev/games/system/media), буфер обмена, история уведомлений, Bitwarden (rofi-rbw)|
|
||||
|Музыка|mpd|Music Player Daemon — бэкенд воспроизведения музыки (вывод через pipewire, replaygain по альбому)|
|
||||
||mpc|Консольный клиент-обёртка для MPD (control через CLI/скрипты — быстрые команды типа play/pause/next без запуска TUI)|
|
||||
||rmpc|TUI-клиент для MPD: очередь, браузер библиотеки, поиск, кастомный статус-бар (артист/альбом/трек/битрейт), Nord-тема|
|
||||
|Видео|mpv|Плеер с рендером через Vulkan (gpu-context=waylandvk, gpu-api=vulkan) и аппаратным декодированием на nvidia (hwdec=nvdec)|
|
||||
|Редактор|nvim|Neovim на lazy.nvim: цветовая схема nord, colorizer, render-markdown, nvim-tree, treesitter, gitsigns, bufferline|
|
||||
|Терминал|foot|Лёгкий Wayland-нативный терминал; шрифт Noto Mono, тёмная тема|
|
||||
|Уведомления|dunst|Демон уведомлений: позиция top-right, прогресс-бары, история (sticky), Nord-цвета по уровню важности|
|
||||
|Шелл|zsh|Интерактивный shell: vi-режим (bindkey -v), общая история между сессиями (SHARE_HISTORY), автодополнение через compinit, fzf (включая fzf-tab и fzf-tab-completion), подсветка синтаксиса (zsh-syntax-highlighting) и автоподсказки (zsh-autosuggestions) — всё в Nord-палитре. Кастомный promt с vi-режимом (❯/❮ в зависимости от normal/insert), git-статус в промпте (staged/modified/untracked/deleted/conflicts с иконками) и код выхода последней команды. Обёртки nvim/vi/vim и алиас rmpc меняют заголовок окна терминала (\033]0;...\007) на время работы программы|
|
||||
|Сессия|uwsm|Universal Wayland Session Manager — запускает sway как systemd-managed сессию, пробрасывает переменные окружения (WAYLAND_DISPLAY, SWAYSOCK, Qt-тема, ssh-agent через rbw)|
|
||||
|Логин-менеджер|ly|TUI display manager: анимация matrix, большие часы (bigclock=en), пустой пароль запрещён (allow_empty_password=false). Хоткеи: F1 shutdown, F2 restart, F3 suspend (systemctl suspend), F7 показать пароль; brightness/hibernate скрыты (*_key = null)|
|
||||
|
||||
## Зависимости
|
||||
|
||||
```bash
|
||||
sudo pacman -S \
|
||||
zsh \
|
||||
zsh-syntax-highlighting \
|
||||
zsh-autosuggestions \
|
||||
pipewire \
|
||||
wireplumber \
|
||||
wl-clipboard \
|
||||
noto-fonts \
|
||||
noto-fonts-cjk \
|
||||
noto-fonts-emoji \
|
||||
ttf-nerd-fonts-symbols-mono \
|
||||
sway \
|
||||
swaylock \
|
||||
swayidle \
|
||||
swaybg \
|
||||
slurp \
|
||||
grim \
|
||||
rbw \
|
||||
rofi \
|
||||
rofi-rbw \
|
||||
python-systemd \
|
||||
python-i3ipc \
|
||||
rmpc \
|
||||
neovim \
|
||||
mpv \
|
||||
mpc \
|
||||
mpd \
|
||||
mpd-mpris \
|
||||
playerctl \
|
||||
xorg-xwayland \
|
||||
xdg-utils \
|
||||
xdg-desktop-portal-gtk \
|
||||
xdg-desktop-portal-wlr \
|
||||
xorg-xwayland \
|
||||
xorg-xrandr \
|
||||
polkit \
|
||||
ly \
|
||||
jq \
|
||||
git \
|
||||
qt6ct \
|
||||
fzf \
|
||||
foot \
|
||||
dunst \
|
||||
uwsm \
|
||||
mc \
|
||||
imv
|
||||
```
|
||||
|
||||
```bash
|
||||
yay -S \
|
||||
swaddle \
|
||||
clipvault \
|
||||
pinentry-rofi
|
||||
```
|
||||
|
||||
## Деплой
|
||||
|
||||
```bash
|
||||
ln -s ./.zsh ~/.config/.zsh
|
||||
ln -s ./.zshrc ~/.zshrc
|
||||
ln -s ./dunst ~/.config/dunst
|
||||
ln -s ./foot ~/.config/foot
|
||||
ln -s ./uwsm ~/.config/uwsm
|
||||
ln -s ./systemd/user/* ~/.config/systemd/user/
|
||||
ln -s ./sway ~/.config/sway
|
||||
ln -s ./swaylock ~/.config/swaylock
|
||||
ln -s ./swaddle ~/.config/swaddle
|
||||
ln -s ./rofi ~/.config/rofi
|
||||
ln -s ./rmpc ~/.config/rmpc
|
||||
ln -s ./nvim ~/.config/nvim
|
||||
ln -s ./mpv ~/.config/mpv
|
||||
ln -s ./mpd ~/.config/mpd
|
||||
```
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.zsh/plugins
|
||||
git clone https://github.com/Aloxaf/fzf-tab ~/.zsh/plugins/fzf-tab
|
||||
git clone https://github.com/lincheney/fzf-tab-completion ~/.zsh/plugins/fzf-tab-completion
|
||||
```
|
||||
|
||||
```bash
|
||||
chsh -s /usr/bin/zsh
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo cp ./other/sway-uwsm.desktop /usr/share/wayland-sessions/
|
||||
sudo cp ./other/ly.ini /etc/ly/config.ini
|
||||
```
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.local/bin/
|
||||
ln -s ./other/pinentry-rofi-wrapper ~/.local/bin/pinentry-rofi-wrapper
|
||||
```
|
||||
|
||||
```bash
|
||||
rbw config set email $email
|
||||
rbw config set base_url $url
|
||||
rbw config set pinentry $pinentry_rofi_wrapper
|
||||
```
|
||||
|
||||
## Скриншоты
|
||||
|
||||
<p align="center">
|
||||
<img src="./assets/photo_2026-08-11_08-01-47.jpg" alt="waybar/rofi/dunst" width="800">
|
||||
<br>
|
||||
<sub>waybar / rofi / dunst</sub>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="./assets/photo_2026-08-11_08-01-57.jpg" alt="rmpc" width="800">
|
||||
<br>
|
||||
<sub>rmpc</sub>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="./assets/photo_2026-08-11_08-02-00.jpg" alt="nvim" width="800">
|
||||
<br>
|
||||
<sub>nvim</sub>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="./assets/photo_2026-08-11_08-02-03.jpg" alt="zsh/fzf" width="800">
|
||||
<br>
|
||||
<sub>zsh / fzf</sub>
|
||||
</p>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 73 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 87 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
@@ -0,0 +1,82 @@
|
||||
[global]
|
||||
monitor = 0
|
||||
follow = mouse
|
||||
origin = top-right
|
||||
offset = 5x5
|
||||
scale = 0
|
||||
|
||||
width = 340
|
||||
height = 300
|
||||
notification_limit = 5
|
||||
|
||||
progress_bar = true
|
||||
progress_bar_height = 10
|
||||
progress_bar_frame_width = 0
|
||||
progress_bar_min_width = 150
|
||||
progress_bar_max_width = 300
|
||||
progress_bar_corner_radius = 0
|
||||
|
||||
indicate_hidden = yes
|
||||
separator_height = 0
|
||||
padding = 10
|
||||
horizontal_padding = 10
|
||||
text_icon_padding = 10
|
||||
frame_width = 0
|
||||
separator_color = frame
|
||||
sort = yes
|
||||
idle_threshold = 120
|
||||
gap_size = 5
|
||||
|
||||
font = Noto Mono 10
|
||||
line_height = 0
|
||||
markup = full
|
||||
format = "<b>%s</b>\n%b"
|
||||
alignment = left
|
||||
vertical_alignment = center
|
||||
show_age_threshold = 60
|
||||
ellipsize = middle
|
||||
ignore_newline = no
|
||||
stack_duplicates = true
|
||||
hide_duplicate_count = false
|
||||
show_indicators = yes
|
||||
|
||||
icon_position = left
|
||||
min_icon_size = 32
|
||||
max_icon_size = 48
|
||||
|
||||
sticky_history = yes
|
||||
history_length = 20
|
||||
|
||||
dmenu = rofi -dmenu -p dunst
|
||||
browser = xdg-open
|
||||
|
||||
always_run_script = true
|
||||
title = Dunst
|
||||
class = Dunst
|
||||
corner_radius = 0
|
||||
ignore_dbusclose = false
|
||||
|
||||
force_xwayland = false
|
||||
force_xinerama = false
|
||||
|
||||
mouse_left_click = close_current
|
||||
mouse_middle_click = do_action, close_current
|
||||
mouse_right_click = close_all
|
||||
|
||||
[experimental]
|
||||
per_monitor_dpi = false
|
||||
|
||||
[urgency_low]
|
||||
background = "#2e3440"
|
||||
foreground = "#eceff4"
|
||||
timeout = 2
|
||||
|
||||
[urgency_normal]
|
||||
background = "#2e3440"
|
||||
foreground = "#eceff4"
|
||||
timeout = 8
|
||||
|
||||
[urgency_critical]
|
||||
background = "#2e3440"
|
||||
foreground = "#bf616a"
|
||||
timeout = 0
|
||||
@@ -0,0 +1,11 @@
|
||||
[main]
|
||||
font=Noto Mono:size=10
|
||||
dpi-aware=no
|
||||
pad=0x0
|
||||
|
||||
[colors-dark]
|
||||
background=2e3440
|
||||
|
||||
[key-bindings]
|
||||
clipboard-copy=Control+Shift+c
|
||||
clipboard-paste=Control+Shift+v
|
||||
@@ -0,0 +1,16 @@
|
||||
music_directory "/mnt/media1/music"
|
||||
playlist_directory "~/.config/mpd/playlists"
|
||||
db_file "~/.config/mpd/database"
|
||||
log_file "~/.config/mpd/log"
|
||||
pid_file "~/.config/mpd/pid"
|
||||
state_file "~/.config/mpd/state"
|
||||
sticker_file "~/.config/mpd/sticker.sql"
|
||||
bind_to_address "~/.config/mpd/socket"
|
||||
bind_to_address "127.0.0.1"
|
||||
port "6600"
|
||||
auto_update "yes"
|
||||
audio_output {
|
||||
type "pipewire"
|
||||
name "MPD PipeWire Output"
|
||||
}
|
||||
replaygain "album"
|
||||
@@ -0,0 +1,3 @@
|
||||
gpu-context=waylandvk
|
||||
gpu-api=vulkan
|
||||
hwdec=nvdec
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
require('core.configs')
|
||||
|
||||
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
|
||||
if not (vim.uv or vim.loop).fs_stat(lazypath) then
|
||||
vim.fn.system({
|
||||
"git",
|
||||
"clone",
|
||||
"--filter=blob:none",
|
||||
"https://github.com/folke/lazy.nvim.git",
|
||||
"--branch=stable",
|
||||
lazypath,
|
||||
})
|
||||
end
|
||||
vim.opt.rtp:prepend(lazypath)
|
||||
|
||||
require("lazy").setup({
|
||||
{
|
||||
"shaunsingh/nord.nvim",
|
||||
lazy = false,
|
||||
priority = 1000,
|
||||
config = function()
|
||||
vim.cmd("colorscheme nord")
|
||||
end,
|
||||
},
|
||||
{
|
||||
"NvChad/nvim-colorizer.lua",
|
||||
opts = {
|
||||
filetypes = { "*" },
|
||||
user_default_options = {
|
||||
RGB = true,
|
||||
RRGGBB = true,
|
||||
names = false,
|
||||
RRGGBBAA = true,
|
||||
css = true,
|
||||
mode = "background",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"MeanderingProgrammer/render-markdown.nvim",
|
||||
dependencies = { "nvim-treesitter/nvim-treesitter", "nvim-tree/nvim-web-devicons" },
|
||||
ft = { "markdown" },
|
||||
opts = {},
|
||||
},
|
||||
{
|
||||
"nvim-tree/nvim-tree.lua",
|
||||
version = "*",
|
||||
dependencies = { "nvim-tree/nvim-web-devicons" },
|
||||
config = function()
|
||||
require("nvim-tree").setup({
|
||||
view = { side = "left", width = 30 },
|
||||
})
|
||||
end,
|
||||
},
|
||||
{
|
||||
"nvim-treesitter/nvim-treesitter",
|
||||
build = ":TSUpdate",
|
||||
config = function()
|
||||
local status_ok, configs = pcall(require, "nvim-treesitter.configs")
|
||||
if not status_ok then
|
||||
return
|
||||
end
|
||||
|
||||
configs.setup({
|
||||
ensure_installed = { "python", "bash", "lua", "vim", "markdown" },
|
||||
highlight = { enable = true },
|
||||
})
|
||||
end,
|
||||
},
|
||||
{
|
||||
"lewis6991/gitsigns.nvim",
|
||||
opts = {},
|
||||
},
|
||||
{
|
||||
"akinsho/bufferline.nvim",
|
||||
version = "*",
|
||||
dependencies = "nvim-tree/nvim-web-devicons",
|
||||
config = function()
|
||||
require("bufferline").setup({
|
||||
options = {
|
||||
mode = "buffers",
|
||||
separator_style = "thick",
|
||||
diagnostics = "nvim_lsp",
|
||||
enforce_regular_tabs = true,
|
||||
tab_size = 14,
|
||||
},
|
||||
highlights = {
|
||||
fill = {
|
||||
bg = "#2e3440",
|
||||
},
|
||||
background = {
|
||||
bg = "#2e3440",
|
||||
fg = "#eceff4",
|
||||
},
|
||||
buffer_selected = {
|
||||
bg = "#3b4252",
|
||||
fg = "#eceff4",
|
||||
bold = false,
|
||||
italic = false,
|
||||
},
|
||||
close_button_selected = {
|
||||
bg = "#3b4252",
|
||||
fg = "#eceff4",
|
||||
},
|
||||
close_button = {
|
||||
bg = "#2e3440",
|
||||
fg = "#4c566a",
|
||||
},
|
||||
close_button_visible = {
|
||||
bg = "#2e3440",
|
||||
fg = "#4c566a",
|
||||
},
|
||||
separator = {
|
||||
bg = "#2e3440",
|
||||
fg = "#2e3440",
|
||||
},
|
||||
separator_selected = {
|
||||
bg = "#3b4252",
|
||||
fg = "#3b4252",
|
||||
},
|
||||
indicator_selected = {
|
||||
bg = "#3b4252",
|
||||
fg = "#88c0d0",
|
||||
},
|
||||
modified_selected = {
|
||||
bg = "#3b4252",
|
||||
fg = "#a3be8c",
|
||||
},
|
||||
modified = {
|
||||
bg = "#2e3440",
|
||||
fg = "#4c566a",
|
||||
},
|
||||
modified_visible = {
|
||||
bg = "#2e3440",
|
||||
fg = "#4c566a",
|
||||
},
|
||||
},
|
||||
})
|
||||
end,
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" },
|
||||
"gitsigns.nvim": { "branch": "main", "commit": "31d6fb2d618bca1482b9f274751ead5f03461408" },
|
||||
"lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" },
|
||||
"nord.nvim": { "branch": "master", "commit": "80c1e5321505aeb22b7a9f23eb82f1e193c12470" },
|
||||
"nvim-colorizer.lua": { "branch": "master", "commit": "72a05f62c52241bc7441c820eb53946f92b2e6a4" },
|
||||
"nvim-tree.lua": { "branch": "master", "commit": "531b807b8f0d6f75016a0ee1e0cd5ce2086e9d95" },
|
||||
"nvim-treesitter": { "branch": "main", "commit": "c9f9ed6c1892f629ea399f4ee7905f2686fa13f2" },
|
||||
"nvim-web-devicons": { "branch": "master", "commit": "2ae6958df7ced50baac5035cec0c15799eedfbf7" },
|
||||
"render-markdown.nvim": { "branch": "main", "commit": "f422cb5c6855f150e2ddcfaf44e7157b98b34f6a" }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
vim.opt.ignorecase = true
|
||||
vim.opt.smartcase = true
|
||||
vim.opt.number = true
|
||||
vim.opt.relativenumber = true
|
||||
vim.o.termguicolors = true
|
||||
vim.cmd("syntax enable")
|
||||
@@ -0,0 +1,4 @@
|
||||
vim.keymap.set('n', '<leader>e', ':NvimTreeToggle<CR>')
|
||||
vim.keymap.set('n', '<Tab>', ':BufferLineCycleNext<CR>')
|
||||
vim.keymap.set('n', '<S-Tab>', ':BufferLineCyclePrev<CR>')
|
||||
vim.keymap.set('n', '<leader>x', ':bdelete<CR>')
|
||||
+422
@@ -0,0 +1,422 @@
|
||||
# Ly supports 24-bit true color with styling, which means each color is a 32-bit value.
|
||||
# The format is 0xSSRRGGBB, where SS is the styling, RR is red, GG is green, and BB is blue.
|
||||
# Here are the possible styling options:
|
||||
# TB_BOLD 0x01000000
|
||||
# TB_UNDERLINE 0x02000000
|
||||
# TB_REVERSE 0x04000000
|
||||
# TB_ITALIC 0x08000000
|
||||
# TB_BLINK 0x10000000
|
||||
# TB_HI_BLACK 0x20000000
|
||||
# TB_BRIGHT 0x40000000
|
||||
# TB_DIM 0x80000000
|
||||
# Programmatically, you'd apply them using the bitwise OR operator (|), but because Ly's
|
||||
# configuration doesn't support using it, you have to manually compute the color value.
|
||||
# Note that, if you want to use the default color value of the terminal, you can use the
|
||||
# special value 0x00000000. This means that, if you want to use black, you *must* use
|
||||
# the styling option TB_HI_BLACK (the RGB values are ignored when using this option).
|
||||
|
||||
# Allow empty password or not when authenticating
|
||||
allow_empty_password = false
|
||||
|
||||
# The active animation
|
||||
# none -> Nothing
|
||||
# doom -> PSX DOOM fire
|
||||
# matrix -> CMatrix
|
||||
# colormix -> Color mixing shader
|
||||
# gameoflife -> John Conway's Game of Life
|
||||
# dur_file -> .dur file format (https://github.com/cmang/durdraw/tree/master)
|
||||
animation = matrix
|
||||
|
||||
# Delay between each animation frame in milliseconds
|
||||
animation_frame_delay = 5
|
||||
|
||||
# Stop the animation after some time
|
||||
# 0 -> Run forever
|
||||
# 1..2e12 -> Stop the animation after this many seconds
|
||||
animation_timeout_sec = 0
|
||||
|
||||
# The character used to mask the password
|
||||
# You can either type it directly as a UTF-8 character (like *), or use a UTF-32
|
||||
# codepoint (for example 0x2022 for a bullet point)
|
||||
# If null, the password will be hidden
|
||||
# Note: you can use a # by escaping it like so: \#
|
||||
asterisk = *
|
||||
|
||||
# The number of failed authentications before a special animation is played... ;)
|
||||
# If set to 0, the animation will never be played
|
||||
auth_fails = 10
|
||||
|
||||
# Identifier for battery whose charge to display at top left
|
||||
# Primary battery is usually BAT0 or BAT1
|
||||
# If set to null, battery status won't be shown
|
||||
battery_id = null
|
||||
|
||||
# Automatic login configuration
|
||||
# This feature allows Ly to automatically log in a user without password prompt.
|
||||
# IMPORTANT: Both auto_login_user and auto_login_session must be set for this to work.
|
||||
# Autologin only happens once at startup - it won't re-trigger after logout.
|
||||
|
||||
# PAM service name to use for automatic login
|
||||
# The default service (ly-autologin) uses pam_permit to allow login without password
|
||||
# The appropriate platform-specific PAM configuration (ly-autologin) will be used automatically
|
||||
auto_login_service = ly-autologin
|
||||
|
||||
# Session name to launch automatically
|
||||
# To find available session names, check the .desktop files in:
|
||||
# - /usr/share/xsessions/ (for X11 sessions)
|
||||
# - /usr/share/wayland-sessions/ (for Wayland sessions)
|
||||
# Use the filename without .desktop extension, the Name field inside the file or the value of the DesktopNames field
|
||||
# Examples: "i3", "sway", "gnome", "plasma", "xfce"
|
||||
# If null, automatic login is disabled
|
||||
auto_login_session = null
|
||||
|
||||
# Username to automatically log in
|
||||
# Must be a valid user on the system
|
||||
# If null, automatic login is disabled
|
||||
auto_login_user = null
|
||||
|
||||
# Background color id
|
||||
bg = 0x00000000
|
||||
|
||||
# Change the state and language of the big clock
|
||||
# none -> Disabled (default)
|
||||
# en -> English
|
||||
# fa -> Farsi
|
||||
bigclock = en
|
||||
|
||||
# Set bigclock to 12-hour notation.
|
||||
bigclock_12hr = false
|
||||
|
||||
# Set bigclock to show the seconds.
|
||||
bigclock_seconds = false
|
||||
|
||||
# Blank main box background
|
||||
# Setting to false will make it transparent
|
||||
blank_box = true
|
||||
|
||||
# Border foreground color id
|
||||
border_fg = 0x00FFFFFF
|
||||
|
||||
# Title to show at the top of the main box
|
||||
# If set to null, none will be shown
|
||||
box_title = null
|
||||
|
||||
# Brightness decrease command
|
||||
brightness_down_cmd = /usr/bin/brightnessctl -q -n s 10%-
|
||||
|
||||
# Brightness decrease key combination, or null to disable
|
||||
brightness_down_key = null
|
||||
|
||||
# Brightness increase command
|
||||
brightness_up_cmd = /usr/bin/brightnessctl -q -n s +10%
|
||||
|
||||
# Brightness increase key combination, or null to disable
|
||||
brightness_up_key = null
|
||||
|
||||
# Erase password input on failure
|
||||
clear_password = false
|
||||
|
||||
# Format string for clock in top right corner (see strftime specification). Example: %c
|
||||
# If null, the clock won't be shown
|
||||
clock = null
|
||||
|
||||
# CMatrix animation foreground color id
|
||||
cmatrix_fg = 0x0000FF00
|
||||
|
||||
# CMatrix animation character string head color id
|
||||
cmatrix_head_col = 0x01FFFFFF
|
||||
|
||||
# CMatrix animation minimum codepoint. It uses a 16-bit integer
|
||||
# For Japanese characters for example, you can use 0x3000 here
|
||||
cmatrix_min_codepoint = 0x21
|
||||
|
||||
# CMatrix animation maximum codepoint. It uses a 16-bit integer
|
||||
# For Japanese characters for example, you can use 0x30FF here
|
||||
cmatrix_max_codepoint = 0x7B
|
||||
|
||||
# Color mixing animation first color id
|
||||
colormix_col1 = 0x00FF0000
|
||||
|
||||
# Color mixing animation second color id
|
||||
colormix_col2 = 0x000000FF
|
||||
|
||||
# Color mixing animation third color id
|
||||
colormix_col3 = 0x20000000
|
||||
|
||||
# For custom binds: the horizontal limit in characters for each
|
||||
# line of custom binds before moving on to the next.
|
||||
# If null, defaults to the width of the terminal instead.
|
||||
custom_bind_width = null
|
||||
|
||||
# Custom sessions directory
|
||||
# You can specify multiple directories,
|
||||
# e.g. /etc/ly/custom-sessions:/usr/share/custom-sessions
|
||||
custom_sessions = /etc/ly/custom-sessions
|
||||
|
||||
# Input box active by default on startup
|
||||
# Available inputs: info_line, session, login, password
|
||||
default_input = login
|
||||
|
||||
# DOOM animation fire height (1 thru 9)
|
||||
doom_fire_height = 6
|
||||
|
||||
# DOOM animation fire spread (0 thru 4)
|
||||
doom_fire_spread = 2
|
||||
|
||||
# DOOM animation custom top color (low intensity flames)
|
||||
doom_top_color = 0x009F2707
|
||||
|
||||
# DOOM animation custom middle color (medium intensity flames)
|
||||
doom_middle_color = 0x00C78F17
|
||||
|
||||
# DOOM animation custom bottom color (high intensity flames)
|
||||
doom_bottom_color = 0x00FFFFFF
|
||||
|
||||
# Dur file path
|
||||
dur_file_path = /etc/ly/example.dur
|
||||
|
||||
# Dur file alignment
|
||||
# The dur file can be aligned with a direction and centered easily with the flags below
|
||||
# Available inputs: topleft, topcenter, topright, centerleft, center, centerright, bottomleft, bottomcenter, bottomright
|
||||
dur_offset_alignment = center
|
||||
|
||||
# Dur offset x direction (value is added to the current position determined by alignment, negatives are supported)
|
||||
dur_x_offset = 0
|
||||
|
||||
# Dur offset y direction (value is added to the current position determined by alignment, negatives are supported)
|
||||
dur_y_offset = 0
|
||||
|
||||
# Set margin to the edges of the DM (useful for curved monitors)
|
||||
edge_margin = 0
|
||||
|
||||
# Error background color id
|
||||
error_bg = 0x00000000
|
||||
|
||||
# Error foreground color id
|
||||
# Default is red and bold
|
||||
error_fg = 0x01FF0000
|
||||
|
||||
# Foreground color id
|
||||
fg = 0x00FFFFFF
|
||||
|
||||
# Render true colors (if supported)
|
||||
# If false, output will be in eight-color mode
|
||||
# All eight-color mode color codes:
|
||||
# TB_DEFAULT 0x0000
|
||||
# TB_BLACK 0x0001
|
||||
# TB_RED 0x0002
|
||||
# TB_GREEN 0x0003
|
||||
# TB_YELLOW 0x0004
|
||||
# TB_BLUE 0x0005
|
||||
# TB_MAGENTA 0x0006
|
||||
# TB_CYAN 0x0007
|
||||
# TB_WHITE 0x0008
|
||||
# If full color is off, the styling options still work. The colors are
|
||||
# always 32-bit values with the styling in the most significant byte.
|
||||
# Note: If using the dur_file animation option and the dur file's color range
|
||||
# is saved as 256 with this option disabled, the file will not be drawn.
|
||||
full_color = true
|
||||
|
||||
# Game of Life entropy interval (0 = disabled, >0 = add entropy every N generations)
|
||||
# 0 -> Pure Conway's Game of Life (will eventually stabilize)
|
||||
# 10 -> Add entropy every 10 generations (recommended for continuous activity)
|
||||
# 50+ -> Less frequent entropy for more natural evolution
|
||||
gameoflife_entropy_interval = 10
|
||||
|
||||
# Game of Life animation foreground color id
|
||||
gameoflife_fg = 0x0000FF00
|
||||
|
||||
# Game of Life frame delay (lower = faster animation, higher = slower)
|
||||
# 1-3 -> Very fast animation
|
||||
# 6 -> Default smooth animation speed
|
||||
# 10+ -> Slower, more contemplative speed
|
||||
gameoflife_frame_delay = 6
|
||||
|
||||
# Game of Life initial cell density (0.0 to 1.0)
|
||||
# 0.1 -> Sparse, minimal activity
|
||||
# 0.4 -> Balanced activity (recommended)
|
||||
# 0.7+ -> Dense, chaotic patterns
|
||||
gameoflife_initial_density = 0.4
|
||||
|
||||
# Command executed when pressing hibernate key (can be null)
|
||||
hibernate_cmd = null
|
||||
|
||||
# Specifies the key combination used for hibernate
|
||||
hibernate_key = null
|
||||
|
||||
# Remove main box borders
|
||||
hide_borders = false
|
||||
|
||||
# Remove power management command hints
|
||||
hide_key_hints = false
|
||||
|
||||
# Remove keyboard lock states from the top right corner
|
||||
hide_keyboard_locks = false
|
||||
|
||||
# Remove version number from the top left corner
|
||||
hide_version_string = false
|
||||
|
||||
# Command executed when no input is detected for a certain time
|
||||
# If null, no command will be executed
|
||||
inactivity_cmd = null
|
||||
|
||||
# Executes a command after a certain amount of seconds
|
||||
inactivity_delay = 0
|
||||
|
||||
# Initial text to show on the info line
|
||||
# If set to null, the info line defaults to the hostname
|
||||
initial_info_text = null
|
||||
|
||||
# Input boxes length
|
||||
input_len = 34
|
||||
|
||||
# Active language
|
||||
# Available languages are found in /etc/ly/lang/
|
||||
lang = en
|
||||
|
||||
# Command executed when logging in
|
||||
# If null, no command will be executed
|
||||
# Important: the code itself must end with `exec "$@"` in order to launch the session!
|
||||
# You can also set environment variables in there, they'll persist until logout
|
||||
login_cmd = null
|
||||
|
||||
# Path for login.defs file (used for listing all local users on the system on
|
||||
# Linux)
|
||||
login_defs_path = /etc/login.defs
|
||||
|
||||
# Command executed when logging out
|
||||
# If null, no command will be executed
|
||||
# Important: the session will already be terminated when this command is executed, so
|
||||
# no need to add `exec "$@"` at the end
|
||||
logout_cmd = null
|
||||
|
||||
# General log file path
|
||||
ly_log = /var/log/ly.log
|
||||
|
||||
# Main box horizontal margin
|
||||
margin_box_h = 2
|
||||
|
||||
# Main box vertical margin
|
||||
margin_box_v = 1
|
||||
|
||||
# Set numlock on/off at startup
|
||||
numlock = false
|
||||
|
||||
# Default path
|
||||
# If null, ly doesn't set a path
|
||||
path = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
|
||||
# Command executed when pressing restart_key
|
||||
restart_cmd = /sbin/shutdown -r now
|
||||
|
||||
# Specifies the key combination used for restart
|
||||
restart_key = F2
|
||||
|
||||
# Save the current desktop and login as defaults, and load them on startup
|
||||
save = true
|
||||
|
||||
# Service name (set to ly to use the provided pam config file)
|
||||
service_name = ly
|
||||
|
||||
# Session log file path
|
||||
# This will contain stdout and stderr of Wayland sessions
|
||||
# By default it's saved in the user's home directory
|
||||
# Important: due to technical limitations, X11, shell sessions as well as
|
||||
# launching session via KMSCON aren't supported, which means you won't get any
|
||||
# logs from those sessions.
|
||||
# If null, no session log will be created
|
||||
session_log = .local/state/ly-session.log
|
||||
|
||||
# Setup command
|
||||
setup_cmd = /etc/ly/setup.sh
|
||||
|
||||
# Show the shell session in the session list
|
||||
# If false, the shell session will be hidden
|
||||
shell = true
|
||||
|
||||
# Specifies the key combination used for showing the password
|
||||
show_password_key = F7
|
||||
|
||||
# Display the active TTY number (e.g. tty3) to the right of the clock in the top right corner
|
||||
# If the clock is disabled, the TTY label occupies the top right corner on its own
|
||||
# If false, the TTY number will not be shown
|
||||
show_tty = false
|
||||
|
||||
# Command executed when pressing shutdown_key
|
||||
shutdown_cmd = /sbin/shutdown -a now
|
||||
|
||||
# Specifies the key combination used for shutdown
|
||||
shutdown_key = F1
|
||||
|
||||
# Command executed when pressing sleep key (can be null)
|
||||
sleep_cmd = systemctl suspend
|
||||
|
||||
# Specifies the key combination used for sleep
|
||||
sleep_key = F3
|
||||
|
||||
# Command executed when starting Ly (before the TTY is taken control of)
|
||||
# See file at path below for an example of changing the default TTY colors
|
||||
start_cmd = /etc/ly/startup.sh
|
||||
|
||||
# Center the session name.
|
||||
text_in_center = false
|
||||
|
||||
# Default vi mode
|
||||
# normal -> normal mode
|
||||
# insert -> insert mode
|
||||
vi_default_mode = normal
|
||||
|
||||
# Enable vi keybindings
|
||||
vi_mode = false
|
||||
|
||||
# Wayland desktop environments
|
||||
# You can specify multiple directories,
|
||||
# e.g. /usr/share/wayland-sessions:/usr/local/share/wayland-sessions
|
||||
# If null, Wayland sessions will not be shown
|
||||
waylandsessions = /usr/share/wayland-sessions
|
||||
|
||||
# Xorg server command
|
||||
# Add the -quiet argument to hide startup logs from the server
|
||||
x_cmd = /usr/bin/X
|
||||
|
||||
# Xorg virtual terminal number
|
||||
# Mostly useful for FreeBSD where choosing the current TTY causes issues
|
||||
# If null, the current TTY will be chosen
|
||||
x_vt = null
|
||||
|
||||
# Xorg xauthority edition tool
|
||||
xauth_cmd = /usr/bin/xauth
|
||||
|
||||
# xinitrc
|
||||
# If null, the xinitrc session will be hidden
|
||||
xinitrc = ~/.xinitrc
|
||||
|
||||
# Xorg desktop environments
|
||||
# You can specify multiple directories,
|
||||
# e.g. /usr/share/xsessions:/usr/local/share/xsessions
|
||||
# If null, X11 sessions will not be shown
|
||||
xsessions = /usr/share/xsessions
|
||||
|
||||
# Custom Commands and Labels:
|
||||
# The following examples below give an outline for setting up custom commands and labels.
|
||||
# Unless specified as optional, an option is mandatory.
|
||||
|
||||
# Comments preceding with '##' are for documentation.
|
||||
# Comments preceding with '#' comment out the example INI.
|
||||
|
||||
## Declare a command with the F8 binding.
|
||||
#[cmd:F8]
|
||||
## The name of the command to show up in Ly.
|
||||
## Note: "$" in "$brightness_up" fetches the appropriate string from the specified locale file
|
||||
## and is replaced with the value representing "brightness_up".
|
||||
## You can see the list of keys in any locale file in /etc/ly/lang.
|
||||
#cmd = touch /tmp/ly.gaming
|
||||
#name = custom command $brightness_up
|
||||
|
||||
## Declare a label with an ID. This ID should be unique across all labels.
|
||||
#[lbl:kernel]
|
||||
#cmd = uname -srn
|
||||
## Optional, defaulting to 0.
|
||||
## In frames, the time to re-run the command and update the label.
|
||||
## If 0, only run once and do not refresh afterwards
|
||||
#refresh = 0
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
exec pinentry-rofi -- \
|
||||
-theme "$HOME/.config/rofi/password.rasi" \
|
||||
"$@"
|
||||
@@ -0,0 +1,7 @@
|
||||
[Desktop Entry]
|
||||
Name=Sway (uwsm-managed)
|
||||
Comment=An i3-compatible Wayland compositor
|
||||
Exec=uwsm start -e -D sway sway.desktop
|
||||
TryExec=uwsm
|
||||
DesktopNames=sway
|
||||
Type=Application
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
#![enable(implicit_some)]
|
||||
#![enable(unwrap_newtypes)]
|
||||
#![enable(unwrap_variant_newtypes)]
|
||||
(
|
||||
address: "127.0.0.1:6600",
|
||||
password: None,
|
||||
theme: "def",
|
||||
cache_dir: None,
|
||||
on_song_change: None,
|
||||
volume_step: 5,
|
||||
max_fps: 30,
|
||||
scrolloff: 0,
|
||||
wrap_navigation: false,
|
||||
enable_mouse: true,
|
||||
scroll_amount: 1,
|
||||
enable_config_hot_reload: true,
|
||||
enable_lyrics_hot_reload: false,
|
||||
status_update_interval_ms: 1000,
|
||||
rewind_to_start_sec: None,
|
||||
keep_state_on_song_change: true,
|
||||
reflect_changes_to_playlist: false,
|
||||
select_current_song_on_change: false,
|
||||
ignore_leading_the: true,
|
||||
browser_song_sort: [Disc, Track, Artist, Title],
|
||||
directories_sort: SortFormat(group_by_type: true, reverse: false),
|
||||
auto_open_downloads: true,
|
||||
album_art: (
|
||||
method: Auto,
|
||||
max_size_px: (width: 1200, height: 1200),
|
||||
disabled_protocols: ["http://", "https://"],
|
||||
vertical_align: Center,
|
||||
horizontal_align: Center,
|
||||
),
|
||||
keybinds: (
|
||||
global: {
|
||||
"q": Quit,
|
||||
"?": ShowHelp,
|
||||
":": CommandMode,
|
||||
"oI": ShowCurrentSongInfo,
|
||||
"oo": ShowOutputs,
|
||||
"op": ShowDecoders,
|
||||
"od": ShowDownloads,
|
||||
"oP": Partition(),
|
||||
"z": ToggleRepeat,
|
||||
"x": ToggleRandom,
|
||||
"c": ToggleConsume,
|
||||
"v": ToggleSingle,
|
||||
"p": TogglePause,
|
||||
"s": Stop,
|
||||
">": NextTrack,
|
||||
"<": PreviousTrack,
|
||||
"f": SeekForward,
|
||||
"b": SeekBack,
|
||||
".": VolumeUp,
|
||||
",": VolumeDown,
|
||||
"<Tab>": NextTab,
|
||||
"gt": NextTab,
|
||||
"<S-Tab>": PreviousTab,
|
||||
"gT": PreviousTab,
|
||||
"1": SwitchToTab("Queue"),
|
||||
"2": SwitchToTab("Directories"),
|
||||
//"3": SwitchToTab("Artists"),
|
||||
"3": SwitchToTab("Album Artists"),
|
||||
//"5": SwitchToTab("Albums"),
|
||||
"4": SwitchToTab("Playlists"),
|
||||
"5": SwitchToTab("Search"),
|
||||
"<C-u>": Update,
|
||||
"<C-U>": Rescan,
|
||||
"R": AddRandom,
|
||||
},
|
||||
navigation: {
|
||||
"<C-c>": Close,
|
||||
"<Esc>": Close,
|
||||
"<CR>": Confirm,
|
||||
"k": Up,
|
||||
"<Up>": Up,
|
||||
"j": Down,
|
||||
"<Down>": Down,
|
||||
"h": Left,
|
||||
"<Left>": Left,
|
||||
"l": Right,
|
||||
"<Right>": Right,
|
||||
"<C-w>k": PaneUp,
|
||||
"<C-Up>": PaneUp,
|
||||
"<C-w>j": PaneDown,
|
||||
"<C-Down>": PaneDown,
|
||||
"<C-w>h": PaneLeft,
|
||||
"<C-Left>": PaneLeft,
|
||||
"<C-w>l": PaneRight,
|
||||
"<C-Right>": PaneRight,
|
||||
"K": MoveUp,
|
||||
"J": MoveDown,
|
||||
"<C-u>": UpHalf,
|
||||
"<C-d>": DownHalf,
|
||||
"<C-b>": PageUp,
|
||||
"<PageUp>": PageUp,
|
||||
"<C-f>": PageDown,
|
||||
"<PageDown>": PageDown,
|
||||
"gg": Top,
|
||||
"G": Bottom,
|
||||
"<Space>": Select,
|
||||
"<C-Space>": InvertSelection,
|
||||
"/": EnterSearch,
|
||||
"n": NextResult,
|
||||
"N": PreviousResult,
|
||||
"a": Add,
|
||||
"A": AddAll,
|
||||
"D": Delete,
|
||||
"<C-r>": Rename,
|
||||
"i": FocusInput,
|
||||
"oi": ShowInfo,
|
||||
"<C-z>": ContextMenu(),
|
||||
"<C-s>s": Save(kind: Modal(all: false, duplicates_strategy: Ask)),
|
||||
"<C-s>a": Save(kind: Modal(all: true, duplicates_strategy: Ask)),
|
||||
"r": Rate(),
|
||||
},
|
||||
queue: {
|
||||
"d": Delete,
|
||||
"D": DeleteAll,
|
||||
"<CR>": Play,
|
||||
"C": JumpToCurrent,
|
||||
"X": Shuffle,
|
||||
},
|
||||
),
|
||||
search: (
|
||||
case_sensitive: false,
|
||||
ignore_diacritics: false,
|
||||
search_button: true,
|
||||
mode: Contains,
|
||||
tags: [
|
||||
(value: "any", label: "any tag"),
|
||||
(value: "artist", label: "artist"),
|
||||
(value: "album", label: "album"),
|
||||
(value: "albumartist", label: "album artist"),
|
||||
(value: "title", label: "title"),
|
||||
(value: "filename", label: "filename"),
|
||||
(value: "genre", label: "genre"),
|
||||
],
|
||||
),
|
||||
artists: (
|
||||
album_display_mode: SplitByDate,
|
||||
album_sort_by: Date,
|
||||
album_date_tags: [Date],
|
||||
),
|
||||
tabs: [
|
||||
(
|
||||
name: "queue",
|
||||
pane: Split(
|
||||
direction: Vertical,
|
||||
panes: [
|
||||
(
|
||||
size: "100%",
|
||||
pane: Split(
|
||||
direction: Vertical,
|
||||
panes: [
|
||||
(
|
||||
size: "1",
|
||||
//borders: "ALL",
|
||||
//border_symbols: Inherited(parent: Rounded, bottom_left: "├", bottom_right: "┤",),
|
||||
pane: Split(
|
||||
direction: Horizontal,
|
||||
panes: [
|
||||
/*(
|
||||
size: "1",
|
||||
pane: Pane(Empty())
|
||||
),*/
|
||||
(
|
||||
size: "100%",
|
||||
pane: Pane(QueueHeader())
|
||||
),
|
||||
]
|
||||
)
|
||||
),
|
||||
(
|
||||
size: "100%",
|
||||
//borders: "LEFT | RIGHT | BOTTOM",
|
||||
//border_symbols: Rounded,
|
||||
pane: Split(
|
||||
direction: Horizontal,
|
||||
panes: [
|
||||
/*(
|
||||
size: "1",
|
||||
pane: Pane(Empty())
|
||||
),*/
|
||||
(
|
||||
size: "100%",
|
||||
pane: Pane(Queue)
|
||||
),
|
||||
]
|
||||
)
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
(
|
||||
size: "8",
|
||||
pane: Split(
|
||||
direction: Horizontal,
|
||||
panes: [
|
||||
(
|
||||
size: "19",
|
||||
//borders: "", //LEFT | RIGHT | TOP",
|
||||
//border_symbols: Rounded,
|
||||
pane: Pane(AlbumArt)
|
||||
),
|
||||
(
|
||||
size: "100%",
|
||||
//borders: "", //ALL",
|
||||
//border_symbols: Inherited(parent: Rounded, top_left: "├", top_right: "┤",),
|
||||
//border_title: [(kind: Text(" Lyrics "))],
|
||||
//border_title_alignment: Right,
|
||||
pane: Component("column1"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
(
|
||||
name: "directories",
|
||||
pane: Split(
|
||||
size: "100%",
|
||||
direction: Vertical,
|
||||
panes: [(pane: Pane(Directories), size: "100%")] //, borders: "ALL", border_symbols: Rounded)],
|
||||
)
|
||||
),
|
||||
(
|
||||
name: "album artists",
|
||||
pane: Split(
|
||||
size: "100%",
|
||||
direction: Vertical,
|
||||
panes: [(pane: Pane(AlbumArtists), size: "100%")] //, borders: "ALL", border_symbols: Rounded)],
|
||||
)
|
||||
),
|
||||
(
|
||||
name: "playlists",
|
||||
pane: Split(
|
||||
size: "100%",
|
||||
direction: Vertical,
|
||||
panes: [(pane: Pane(Playlists), size: "100%")] //, borders: "ALL", border_symbols: Rounded)],
|
||||
)
|
||||
),
|
||||
(
|
||||
name: "search",
|
||||
pane: Split(
|
||||
size: "100%",
|
||||
direction: Vertical,
|
||||
panes: [(pane: Pane(Search), size: "100%")] //, borders: "ALL", border_symbols: Rounded)],
|
||||
)
|
||||
),
|
||||
],
|
||||
)
|
||||
+311
@@ -0,0 +1,311 @@
|
||||
#![enable(implicit_some)]
|
||||
#![enable(unwrap_newtypes)]
|
||||
#![enable(unwrap_variant_newtypes)]
|
||||
(
|
||||
default_album_art_path: None,
|
||||
format_tag_separator: " | ",
|
||||
browser_column_widths: [0,30,70],
|
||||
background_color: None,
|
||||
text_color: None,
|
||||
header_background_color: None,
|
||||
modal_background_color: None,
|
||||
modal_backdrop: false,
|
||||
preview_label_style: (fg: "#88c0d0"),
|
||||
preview_metadata_group_style: (fg: "#88c0d0", modifiers: "Bold"),
|
||||
highlighted_item_style: (fg: "#88c0d0", modifiers: "Bold"),
|
||||
current_item_style: (fg: "#2e3440", bg: "#88c0d0", modifiers: "Bold"),
|
||||
borders_style: (fg: "#88c0d0"),
|
||||
highlight_border_style: (fg: "#88c0d0"),
|
||||
symbols: (
|
||||
song: "S",
|
||||
dir: "D",
|
||||
playlist: "P",
|
||||
marker: "M",
|
||||
ellipsis: "...",
|
||||
song_style: (fg: "#88c0d0"),
|
||||
dir_style: (fg: "#ebcb8b"),
|
||||
playlist_style: (fg: "#b48ead"),
|
||||
),
|
||||
level_styles: (
|
||||
info: (fg: "blue", bg: "black"),
|
||||
warn: (fg: "yellow", bg: "black"),
|
||||
error: (fg: "red", bg: "black"),
|
||||
debug: (fg: "light_green", bg: "black"),
|
||||
trace: (fg: "magenta", bg: "black"),
|
||||
),
|
||||
progress_bar: (
|
||||
symbols: ["█", "█", "█", "█", "█"],
|
||||
track_style: (fg: "#4c566a"),
|
||||
elapsed_style: (fg: "#88c0d0"),
|
||||
thumb_style: (fg: "#5e81ac"),
|
||||
use_track_when_empty: true,
|
||||
),
|
||||
scrollbar: (
|
||||
symbols: ["│", "█", "", ""],
|
||||
track_style: (),
|
||||
ends_style: (),
|
||||
thumb_style: (fg: "#88c0d0"),
|
||||
),
|
||||
tab_bar: (
|
||||
active_style: (fg: "#2e3440", bg: "#88c0d0"),
|
||||
inactive_style: (fg: "#eceff4", bg: "#2e3440"),),
|
||||
lyrics: (
|
||||
timestamp: false
|
||||
),
|
||||
browser_song_format: [
|
||||
(
|
||||
kind: Group([
|
||||
(kind: Property(Track)),
|
||||
(kind: Text(" ")),
|
||||
])
|
||||
),
|
||||
(
|
||||
kind: Group([
|
||||
(kind: Property(Artist)),
|
||||
(kind: Text(" - ")),
|
||||
(kind: Property(Title)),
|
||||
]),
|
||||
default: (kind: Property(Filename))
|
||||
),
|
||||
],
|
||||
song_table_format: [
|
||||
(
|
||||
prop: (kind: Property(Artist), style: (fg: "#eceff4"),
|
||||
default: (kind: Text("unknown"), style: (fg: "#eceff4"))
|
||||
),
|
||||
label_prop: (kind: Text("artist"), style: (fg: "#8fbcbb", modifiers: "Bold")),
|
||||
width: "20%",
|
||||
),
|
||||
(
|
||||
prop: (kind: Property(Title), style: (fg: "#eceff4"),
|
||||
default: (kind: Text("unknown"), style: (fg: "#eceff4"))
|
||||
),
|
||||
label_prop: (kind: Text("title"), style: (fg: "#a3be8c", modifiers: "Bold")),
|
||||
width: "35%",
|
||||
),
|
||||
(
|
||||
prop: (kind: Property(Album), style: (fg: "#eceff4"),
|
||||
default: (kind: Text("unknown"), style: (fg: "#eceff4"))
|
||||
),
|
||||
label_prop: (kind: Text("album"), style: (fg: "#b48ead", modifiers: "Bold")),
|
||||
width: "30%",
|
||||
),
|
||||
(
|
||||
prop: (kind: Property(Duration), style: (fg: "#eceff4"),
|
||||
default: (kind: Text("-"), style: (fg: "#eceff4"))
|
||||
),
|
||||
label_prop: (kind: Text("duration"), style: (fg: "#ebcb8b", modifiers: "Bold")),
|
||||
width: "15%",
|
||||
alignment: Right,
|
||||
),
|
||||
],
|
||||
layout: Split(
|
||||
direction: Vertical,
|
||||
panes: [
|
||||
(
|
||||
size: "1",
|
||||
pane: Split(
|
||||
direction: Horizontal,
|
||||
panes: [
|
||||
( pane: Pane(Tabs), size: "70" ),
|
||||
( pane: Pane(Empty()), size: "100%" ),
|
||||
],
|
||||
),
|
||||
),
|
||||
(
|
||||
pane: Pane(TabContent),
|
||||
size: "100%",
|
||||
),
|
||||
(
|
||||
size: "1",
|
||||
pane: Split(
|
||||
direction: Horizontal,
|
||||
panes: [
|
||||
(
|
||||
size: "8",
|
||||
pane: Component("input_mode")
|
||||
),
|
||||
(
|
||||
size: "100%",
|
||||
pane: Component("progress_bar"),
|
||||
),
|
||||
(
|
||||
size: "20",
|
||||
pane: Component("volume_and_state"),
|
||||
)
|
||||
]
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
components: {
|
||||
"volume_and_state": Split(
|
||||
direction: Horizontal,
|
||||
panes: [
|
||||
(size: "100%", pane: Component("volume")),
|
||||
(size: "7", pane: Component("states")),
|
||||
]
|
||||
),
|
||||
"column1": Split(
|
||||
direction: Vertical,
|
||||
panes: [
|
||||
(size: "1", pane: Component("state")),
|
||||
(size: "1", pane: Component("artist")),
|
||||
(size: "1", pane: Component("album")),
|
||||
(size: "1", pane: Component("track")),
|
||||
(size: "1", pane: Component("title")),
|
||||
(size: "1", pane: Component("date")),
|
||||
(size: "1", pane: Component("elapsed")),
|
||||
(size: "1", pane: Component("bitrate")),
|
||||
]
|
||||
),
|
||||
"state": Pane(Property(
|
||||
content: [
|
||||
(kind: Text("state: "), style: (fg: "#88c0d0", modifiers: "Bold")),
|
||||
(kind: Property(Status(StateV2( ))), style: (fg: "#eceff4")),
|
||||
], align: Left, scroll_speed: 1
|
||||
)),
|
||||
"artist": Pane(Property(
|
||||
content: [
|
||||
(kind: Text("artist: "), style: (fg: "#88c0d0", modifiers: "Bold")),
|
||||
(kind: Property(Song(Artist)), style: (fg: "#eceff4"),
|
||||
default: (kind: Text("unknown"), style: (fg: "#eceff4"))),
|
||||
], align: Left, scroll_speed: 1
|
||||
)),
|
||||
"album": Pane(Property(
|
||||
content: [
|
||||
(kind: Text("album: "), style: (fg: "#88c0d0", modifiers: "Bold")),
|
||||
(kind: Property(Song(Album)), style: (fg: "#eceff4"),
|
||||
default: (kind: Text("unknown"), style: (fg: "#eceff4"))),
|
||||
], align: Left, scroll_speed: 1
|
||||
)),
|
||||
"track": Pane(Property(
|
||||
content: [
|
||||
(kind: Text("track: "), style: (fg: "#88c0d0", modifiers: "Bold")),
|
||||
(kind: Property(Song(Track)), style: (fg: "#eceff4"),
|
||||
default: (kind: Text("unknown"), style: (fg: "#eceff4"))),
|
||||
], align: Left, scroll_speed: 1
|
||||
)),
|
||||
"title": Pane(Property(
|
||||
content: [
|
||||
(kind: Text("title: "), style: (fg: "#88c0d0", modifiers: "Bold")),
|
||||
(kind: Property(Song(Title)), style: (fg: "#eceff4"),
|
||||
default: (kind: Text("unknown"), style: (fg: "#eceff4"))),
|
||||
], align: Left, scroll_speed: 1
|
||||
)),
|
||||
"date": Pane(Property(
|
||||
content: [
|
||||
(kind: Text("date: "), style: (fg: "#88c0d0", modifiers: "Bold")),
|
||||
(kind: Property(Song(Other("date"))), style: (fg: "#eceff4"),
|
||||
default: (kind: Text("unknown"), style: (fg: "#eceff4"))),
|
||||
], align: Left, scroll_speed: 1
|
||||
)),
|
||||
"elapsed": Pane(Property(
|
||||
content: [
|
||||
(kind: Text("elapsed: "), style: (fg: "#88c0d0", modifiers: "Bold")),
|
||||
(kind: Property(Status(Elapsed)), style: (fg: "#eceff4")),
|
||||
(kind: Text(" / ")),
|
||||
(kind: Property(Status(Duration)), style: (fg: "#eceff4")),
|
||||
],
|
||||
align: Left, scroll_speed: 1
|
||||
)),
|
||||
"bitrate": Pane(Property(
|
||||
content: [
|
||||
(kind: Text("bitrate: "), style: (fg: "#88c0d0", modifiers: "Bold")),
|
||||
(kind: Property(Status(Bitrate)), style: (fg: "#eceff4")),
|
||||
(kind: Text(" kbps"), style: (fg: "#eceff4")),
|
||||
],
|
||||
align: Left, scroll_speed: 1
|
||||
)),
|
||||
"volume": Split(
|
||||
direction: Horizontal,
|
||||
panes: [
|
||||
(size: "100%", pane: Pane(Volume(kind: Slider(
|
||||
symbols: (filled: "█", thumb: "█", track: "█"),
|
||||
filled_style: (fg: "#d08770"),
|
||||
track_style: (fg: "#4c566a"),
|
||||
thumb_style: (fg: "#bf616a"),
|
||||
)))),
|
||||
], align: Right
|
||||
),
|
||||
"states": Split(
|
||||
direction: Horizontal,
|
||||
panes: [
|
||||
(
|
||||
size: "1",
|
||||
pane: Pane(Empty())
|
||||
),
|
||||
(
|
||||
size: "100%",
|
||||
pane: Pane(Property(content: [(kind: Property(Status(InputBuffer())), style: (fg: "blue"), align: Right)]))
|
||||
),
|
||||
(
|
||||
size: "1",
|
||||
pane: Pane(Empty())
|
||||
),
|
||||
(
|
||||
size: "6",
|
||||
pane: Pane(Property(content: [
|
||||
(kind: Text(" "), style: (bg: "#4c566a")),
|
||||
(kind: Property(Status(RepeatV2(
|
||||
on_label: "z",
|
||||
off_label: "z",
|
||||
on_style: (fg: "#ebcb8b", bg: "#4c566a", modifiers: "Bold"),
|
||||
off_style: (fg: "#eceff4", bg: "#4c566a"),
|
||||
)))),
|
||||
(kind: Property(Status(RandomV2(
|
||||
on_label: "x",
|
||||
off_label: "x",
|
||||
on_style: (fg: "#ebcb8b", bg: "#4c566a", modifiers: "Bold"),
|
||||
off_style: (fg: "#eceff4", bg: "#4c566a"),
|
||||
)))),
|
||||
(kind: Property(Status(ConsumeV2(
|
||||
on_label: "c",
|
||||
off_label: "c",
|
||||
oneshot_label: "c",
|
||||
on_style: (fg: "#ebcb8b", bg: "#4c566a", modifiers: "Bold"),
|
||||
off_style: (fg: "#eceff4", bg: "#4c566a"),
|
||||
oneshot_style: (fg: "#d08770", bg: "#4c566a", modifiers: "Bold"),
|
||||
)))),
|
||||
(kind: Property(Status(SingleV2(
|
||||
on_label: "v",
|
||||
off_label: "v",
|
||||
oneshot_label: "v",
|
||||
on_style: (fg: "#ebcb8b", bg: "#4c566a", modifiers: "Bold"),
|
||||
off_style: (fg: "#eceff4", bg: "#4c566a"),
|
||||
oneshot_style: (fg: "#d08770", bg: "#4c566a", modifiers: "Bold"),
|
||||
)))),
|
||||
(kind: Text(" "), style: (bg: "#4c566a")),
|
||||
],
|
||||
align: Right
|
||||
))
|
||||
),
|
||||
]
|
||||
),
|
||||
"input_mode": Pane(Property(
|
||||
content: [
|
||||
(kind: Transform(Replace(content: (kind: Property(Status(InputMode()))), replacements: [
|
||||
(match: "Normal", replace: (kind: Text(" normal "), style: (fg: "#eceff4", bg: "#4c566a"))),
|
||||
(match: "Insert", replace: (kind: Text(" insert "), style: (fg: "#2e3440", bg: "#a3be8c"))),
|
||||
])))
|
||||
], align: Left
|
||||
)),
|
||||
"progress_bar": Split(
|
||||
direction: Horizontal,
|
||||
panes: [
|
||||
(
|
||||
size: "1",
|
||||
pane: Pane(Empty())
|
||||
),
|
||||
(
|
||||
size: "100%",
|
||||
pane: Pane(ProgressBar)
|
||||
),
|
||||
(
|
||||
size: "1",
|
||||
pane: Pane(Empty())
|
||||
),
|
||||
]
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,29 @@
|
||||
@import "config.rasi"
|
||||
|
||||
window {
|
||||
children: [ mainbox ];
|
||||
}
|
||||
|
||||
mainbox {
|
||||
background-color: transparent;
|
||||
children: [ inputbar, listview, message ];
|
||||
}
|
||||
|
||||
element {
|
||||
children: [ element-icon, element-text ];
|
||||
}
|
||||
|
||||
element-icon {
|
||||
size: 0px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
message {
|
||||
background-color: @NORD1;
|
||||
padding: 6px 0 12px 12px;
|
||||
}
|
||||
|
||||
textbox {
|
||||
text-color: @NORD6;
|
||||
background-color: transparent;
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
configuration {
|
||||
me-select-entry: "MouseSecondary";
|
||||
me-accept-entry: "MousePrimary";
|
||||
scroll-method: 1;
|
||||
show-icons: true;
|
||||
sidebar-mode: true;
|
||||
modi: "drun,internet:~/.config/rofi/rofi-filter internet,dev:~/.config/rofi/rofi-filter dev,games:~/.config/rofi/rofi-filter games,system:~/.config/rofi/rofi-filter system,media:~/.config/rofi/rofi-filter media,notifications:~/.config/rofi/rofi-filter notifications,clipboard:~/.config/rofi/rofi-filter clipboard";
|
||||
display-drun: "ALL";
|
||||
display-internet: "NET";
|
||||
display-dev: "DEV";
|
||||
display-games: "GMS";
|
||||
display-system: "SYS";
|
||||
display-media: "MED";
|
||||
display-notifications: "NTF";
|
||||
display-clipboard: "CLP";
|
||||
kb-remove-to-eol: "";
|
||||
kb-mode-complete: "";
|
||||
kb-remove-char-back: "BackSpace,Shift+BackSpace";
|
||||
kb-row-down: "Down,Control+j";
|
||||
kb-row-up: "Up,Control+k";
|
||||
kb-accept-entry: "Control+m,Return,KP_Enter";
|
||||
}
|
||||
|
||||
* {
|
||||
NORD0: #2e3440;
|
||||
NORD1: #3b4252;
|
||||
NORD2: #434c5e;
|
||||
NORD3: #4c566a;
|
||||
NORD4: #d8dee9;
|
||||
NORD5: #e5e9f0;
|
||||
NORD6: #eceff4;
|
||||
NORD7: #8fbcbb;
|
||||
NORD8: #88c0d0;
|
||||
NORD9: #81a1c1;
|
||||
NORD10: #5e81ac;
|
||||
NORD11: #bf616a;
|
||||
NORD12: #d08770;
|
||||
NORD13: #ebcb8b;
|
||||
NORD14: #a3be8c;
|
||||
NORD15: #b48ead;
|
||||
font: "Noto Sans Mono 10";
|
||||
}
|
||||
|
||||
window {
|
||||
background-color: @NORD0;
|
||||
location: north west;
|
||||
anchor: north west;
|
||||
width: 540px;
|
||||
height: 550px;
|
||||
x-offset: 5px;
|
||||
y-offset: 5px;
|
||||
padding: 0px;
|
||||
border: 0px;
|
||||
border-radius: 0px;
|
||||
children: [ sb-mainbox ];
|
||||
}
|
||||
|
||||
sb-mainbox {
|
||||
orientation: horizontal;
|
||||
spacing: 0px;
|
||||
children: [ left-bar-container, vertibox ];
|
||||
}
|
||||
|
||||
left-bar-container {
|
||||
background-color: @NORD0;
|
||||
orientation: vertical;
|
||||
width: 40px;
|
||||
expand: false;
|
||||
children: [ mode-switcher ];
|
||||
}
|
||||
|
||||
mode-switcher {
|
||||
orientation: vertical;
|
||||
spacing: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
button {
|
||||
text-color: @NORD4;
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
horizontal-align: 0.5;
|
||||
vertical-align: 0.5;
|
||||
padding: 6px 0px;
|
||||
border: 0px 0px 0px 2px;
|
||||
font: "Noto Sans Mono Bold 8";
|
||||
}
|
||||
|
||||
button selected {
|
||||
text-color: @NORD6;
|
||||
background-color: @NORD1;
|
||||
border-color: @NORD8;
|
||||
}
|
||||
|
||||
vertibox {
|
||||
background-color: @NORD0;
|
||||
orientation: vertical;
|
||||
spacing: 0px;
|
||||
padding: 0px;
|
||||
children: [ inputbar, listview ];
|
||||
}
|
||||
|
||||
inputbar {
|
||||
background-color: transparent;
|
||||
children: [ entry ];
|
||||
}
|
||||
|
||||
entry {
|
||||
text-color: @NORD6;
|
||||
background-color: transparent;
|
||||
placeholder-color: @NORD4;
|
||||
padding: 6px;
|
||||
placeholder: " [search...]";
|
||||
}
|
||||
|
||||
listview {
|
||||
background-color: transparent;
|
||||
margin: 0px;
|
||||
spacing: 0px;
|
||||
columns: 1;
|
||||
lines: 10;
|
||||
border: 0px;
|
||||
cycle: false;
|
||||
dynamic: true;
|
||||
scrollbar: false;
|
||||
}
|
||||
|
||||
element {
|
||||
background-color: transparent;
|
||||
padding: 8px;
|
||||
children: [ element-icon, element-text ];
|
||||
}
|
||||
|
||||
element normal.normal,
|
||||
element normal.urgent,
|
||||
element normal.active {
|
||||
text-color: @NORD6;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
element alternate.normal,
|
||||
element alternate.urgent,
|
||||
element alternate.active {
|
||||
text-color: @NORD6;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
element selected.normal,
|
||||
element selected.urgent,
|
||||
element selected.active {
|
||||
text-color: @NORD4;
|
||||
background-color: @NORD1;
|
||||
border: 0px 0px 0px 2px;
|
||||
border-color: @NORD8;
|
||||
}
|
||||
|
||||
element-icon {
|
||||
background-color: transparent;
|
||||
size: 14px;
|
||||
margin: 0 8px 0 6px;
|
||||
}
|
||||
|
||||
element-text {
|
||||
text-color: inherit;
|
||||
background-color: transparent;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
@import "config.rasi"
|
||||
|
||||
window {
|
||||
width: 540px;
|
||||
height: 60px;
|
||||
children: [ vertibox ];
|
||||
}
|
||||
|
||||
vertibox {
|
||||
children: [ label-box, inputbar ];
|
||||
}
|
||||
|
||||
label-box {
|
||||
background-color: @NORD1;
|
||||
children: [ prompt ];
|
||||
}
|
||||
|
||||
prompt {
|
||||
text-color: @NORD4;
|
||||
background-color: @NORD1;
|
||||
border-color: @NORD8;
|
||||
padding: 6px;
|
||||
border: 0px 0px 0px 2px;
|
||||
}
|
||||
|
||||
entry {
|
||||
placeholder: " [password...]";
|
||||
}
|
||||
Executable
+75
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
set -uo pipefail
|
||||
tmp_dir="/tmp/cliphist"
|
||||
mkdir -p "$tmp_dir"
|
||||
mode="${1:-}"
|
||||
selection="${2:-}"
|
||||
|
||||
if [[ -n "$selection" ]]; then
|
||||
if [[ "$mode" == "clipboard" ]]; then
|
||||
id="${selection%% *}"
|
||||
printf '%s' "$id" | clipvault get | wl-copy
|
||||
elif [[ "$mode" == "notifications" ]]; then
|
||||
body="${selection#*— }"
|
||||
printf '%s' "$body" | wl-copy
|
||||
else
|
||||
target_app=$(grep -rl "^Name=${selection}\$" /usr/share/applications/*.desktop 2>/dev/null | head -n1)
|
||||
if [[ -n "$target_app" ]]; then
|
||||
exec_cmd=$(awk -F= '/^Exec=/{print $2; exit}' "$target_app" | sed 's/%[uUfFck]//g')
|
||||
setsid $exec_cmd >/dev/null 2>&1 &
|
||||
disown
|
||||
fi
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
case "$mode" in
|
||||
clipboard)
|
||||
find "$tmp_dir" -type f -mmin +30 -delete 2>/dev/null
|
||||
while IFS=$'\t' read -r id rest; do
|
||||
[[ "$id" =~ ^[0-9]+$ ]] || continue
|
||||
[[ "$rest" == *"meta http-equiv"* ]] && continue
|
||||
if [[ "$rest" == *"binary data"* ]]; then
|
||||
ext=""
|
||||
case "$rest" in
|
||||
*jpeg*|*jpg*) ext="jpg" ;;
|
||||
*png*) ext="png" ;;
|
||||
*bmp*) ext="bmp" ;;
|
||||
*) continue ;;
|
||||
esac
|
||||
img="$tmp_dir/$id.$ext"
|
||||
[[ -s "$img" ]] || printf '%s\n' "$id" | clipvault get > "$img" 2>/dev/null
|
||||
[[ -s "$img" ]] && printf '%s [IMG]\0icon\x1f%s\n' "$id" "$img"
|
||||
else
|
||||
printf '%s %s\n' "$id" "$rest"
|
||||
fi
|
||||
done < <(clipvault list)
|
||||
;;
|
||||
notifications)
|
||||
dunstctl history | jq -r '
|
||||
.data[0][] |
|
||||
"\(.appname.data): \(.summary.data) — \(.body.data)"
|
||||
'
|
||||
;;
|
||||
internet|dev|media|games|system)
|
||||
case "$mode" in
|
||||
internet) category="Network" ;;
|
||||
dev) category="Development" ;;
|
||||
media) category="AudioVideo" ;;
|
||||
games) category="Game" ;;
|
||||
system) category="System" ;;
|
||||
esac
|
||||
awk -v cat="$category" '
|
||||
BEGINFILE { name=""; icon=""; match_cat=0 }
|
||||
/^Categories=/ { if (index($0, cat)) match_cat=1 }
|
||||
/^Name=/ && name=="" { sub(/^Name=/, ""); name=$0 }
|
||||
/^Icon=/ && icon=="" { sub(/^Icon=/, ""); icon=$0 }
|
||||
ENDFILE {
|
||||
if (match_cat && name != "") {
|
||||
if (icon != "") printf "%s\x00icon\x1f%s\n", name, icon
|
||||
else printf "%s\n", name
|
||||
}
|
||||
}
|
||||
' /usr/share/applications/*.desktop 2>/dev/null
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,5 @@
|
||||
debug = false
|
||||
|
||||
[server]
|
||||
inhibit_duration = 25
|
||||
sleep_duration = 5
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
client.focused #88c0d0 #88c0d0 #eceff4 #88c0d0 #88c0d0
|
||||
client.focused_inactive #00000000 #00000000 #81a1c1 #00000000 #00000000
|
||||
client.unfocused #00000000 #00000000 #81a1c1 #00000000 #00000000
|
||||
client.urgent #d08770 #d08770 #eceff4 #d08770 #d08770
|
||||
font pango:Noto Sans Mono 10
|
||||
smart_gaps off
|
||||
smart_borders off
|
||||
gaps inner 3
|
||||
gaps outer 1
|
||||
default_border pixel 1
|
||||
default_floating_border pixel 1
|
||||
titlebar_border_thickness 0
|
||||
default_orientation auto
|
||||
input type:keyboard {
|
||||
xkb_layout "us,ru"
|
||||
xkb_options "grp:win_space_toggle"
|
||||
}
|
||||
exec uwsm finalize WAYLAND_DISPLAY SWAYSOCK QT_QPA_PLATFORMTHEME QT_QPA_PLATFORMTHEME_QT6
|
||||
exec_always xrandr --output HDMI-A-2 --primary
|
||||
set $mod Mod4
|
||||
set $left h
|
||||
set $down j
|
||||
set $up k
|
||||
set $right l
|
||||
set $term foot
|
||||
set $menu rofi -show drun
|
||||
set $file foot mc
|
||||
workspace 1 output HDMI-A-2
|
||||
workspace 2 output HDMI-A-2
|
||||
workspace 3 output HDMI-A-2
|
||||
workspace 4 output HDMI-A-2
|
||||
workspace 5 output HDMI-A-2
|
||||
workspace 6 output HDMI-A-2
|
||||
workspace 7 output DP-1
|
||||
workspace 8 output DP-1
|
||||
workspace 9 output DP-2
|
||||
workspace 0 output DP-2
|
||||
workspace 1
|
||||
output DP-1 bg ~/Pictures/wallhaven-43qlkd.jpg fill
|
||||
output HDMI-A-2 bg ~/Pictures/wallhaven-478kjo.jpg fill
|
||||
output DP-2 bg ~/Pictures/wallhaven-4gx713.jpg fill
|
||||
output DP-1 resolution 1280x1024 position 0,220
|
||||
output HDMI-A-2 resolution 1920x1080 position 1280,0
|
||||
output DP-2 resolution 1280x102 position 3200,220
|
||||
floating_modifier $mod normal
|
||||
bindsym --to-code $mod+$left focus left
|
||||
bindsym --to-code $mod+$down focus down
|
||||
bindsym --to-code $mod+$up focus up
|
||||
bindsym --to-code $mod+$right focus right
|
||||
bindsym --to-code $mod+Shift+$left move left
|
||||
bindsym --to-code $mod+Shift+$down move down
|
||||
bindsym --to-code $mod+Shift+$up move up
|
||||
bindsym --to-code $mod+Shift+$right move right
|
||||
bindsym --to-code $mod+1 workspace number 1
|
||||
bindsym --to-code $mod+2 workspace number 2
|
||||
bindsym --to-code $mod+3 workspace number 3
|
||||
bindsym --to-code $mod+4 workspace number 4
|
||||
bindsym --to-code $mod+5 workspace number 5
|
||||
bindsym --to-code $mod+6 workspace number 6
|
||||
bindsym --to-code $mod+7 workspace number 7
|
||||
bindsym --to-code $mod+8 workspace number 8
|
||||
bindsym --to-code $mod+9 workspace number 9
|
||||
bindsym --to-code $mod+0 workspace number 10
|
||||
bindsym --to-code $mod+Shift+1 move container to workspace number 1
|
||||
bindsym --to-code $mod+Shift+2 move container to workspace number 2
|
||||
bindsym --to-code $mod+Shift+3 move container to workspace number 3
|
||||
bindsym --to-code $mod+Shift+4 move container to workspace number 4
|
||||
bindsym --to-code $mod+Shift+5 move container to workspace number 5
|
||||
bindsym --to-code $mod+Shift+6 move container to workspace number 6
|
||||
bindsym --to-code $mod+Shift+7 move container to workspace number 7
|
||||
bindsym --to-code $mod+Shift+8 move container to workspace number 8
|
||||
bindsym --to-code $mod+Shift+9 move container to workspace number 9
|
||||
bindsym --to-code $mod+Shift+0 move container to workspace number 10
|
||||
bindsym --to-code $mod+d exec $menu
|
||||
bindsym --to-code $mod+v exec rofi -show clipboard
|
||||
bindsym --to-code $mod+e exec $file
|
||||
bindsym --to-code $mod+Return exec $term
|
||||
bindsym --to-code $mod+c exec pkill -SIGRTMIN+13 waybar
|
||||
bindsym --to-code $mod+Shift+q kill
|
||||
bindsym --to-code $mod+f fullscreen
|
||||
bindsym --to-code $mod+m focus mode_toggle
|
||||
bindsym --to-code $mod+Shift+m floating toggle
|
||||
bindsym --to-code $mod+s scratchpad show
|
||||
bindsym --to-code $mod+Shift+s move scratchpad
|
||||
bindsym --to-code --locked XF86AudioRaiseVolume exec wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+
|
||||
bindsym --to-code --locked XF86AudioLowerVolume exec wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
|
||||
bindsym --to-code --locked XF86AudioMute exec wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
|
||||
bindsym --to-code --locked $mod+F12 exec wpctl set-volume -l 1 @DEFAULT_AUDIO_SOURCE@ 5%+
|
||||
bindsym --to-code --locked $mod+F11 exec wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 5%-
|
||||
bindsym --to-code --locked $mod+F10 exec wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
|
||||
bindsym --to-code --locked XF86AudioNext exec playerctl next
|
||||
bindsym --to-code --locked XF86AudioPause exec playerctl play-pause
|
||||
bindsym --to-code --locked XF86AudioPlay exec playerctl play-pause
|
||||
bindsym --to-code --locked XF86AudioPrev exec playerctl previous
|
||||
bindsym --to-code Print exec area=$(slurp) && grim -g "$area" - | wl-copy && notify-send -u low "Screenshot" "Captured: $area"
|
||||
bindsym --to-code $mod+Print exec active_class=$(swaymsg -t get_tree | jq -r '.. | select(.focused? == true) | .app_id // .window_properties.class // "unknown"') && geom=$(swaymsg -t get_tree | jq -r '.. | select(.focused? == true) | "\(.rect.x),\(.rect.y) \(.rect.width)x\(.rect.height)"') && grim -g "$geom" - | wl-copy && notify-send -u low "Screenshot" "Captured: $active_class"
|
||||
bindsym --to-code ctrl+Print exec monitor=$(swaymsg -t get_outputs | jq -r '.[] | select(.focused==true) | .name') && grim -o "$monitor" - | wl-copy && notify-send -u low "Screenshot" "Captured: $monitor"
|
||||
bindsym --to-code $mod+u exec sh -c 'rbw get ed-ssh | jq -r ".fields[]? | select(.name==\"privateKey\") | .text" | ssh-add -'
|
||||
bindsym --to-code $mod+b exec rofi-rbw --selector rofi --selector-args="-theme ~/.config/rofi/bitwarden.rasi -mesg 'alt+1: <span foreground=\\\"#d8dee9\\\">type username/password</span>\nalt+2: <span foreground=\\\"#d8dee9\\\">type username</span>\talt+3: <span foreground=\\\"#d8dee9\\\">type password</span>\talt+4: <span foreground=\\\"#d8dee9\\\">type totp</span>\talt+u: <span foreground=\\\"#d8dee9\\\">copy username</span>\talt+c: <span foreground=\\\"#d8dee9\\\">copy password</span>\talt+t: <span foreground=\\\"#d8dee9\\\">copy totp</span>\talt+m: <span foreground=\\\"#d8dee9\\\">menu</span>\t\talt+s: <span foreground=\\\"#d8dee9\\\">sync logins</span>'"
|
||||
mode "resize" {
|
||||
bindsym --to-code $left resize shrink width 10px
|
||||
bindsym --to-code $down resize grow height 10px
|
||||
bindsym --to-code $up resize shrink height 10px
|
||||
bindsym --to-code $right resize grow width 10px
|
||||
bindsym --to-code Return mode "default"
|
||||
bindsym --to-code Escape mode "default"
|
||||
}
|
||||
mode "reload sway? [y/n]" {
|
||||
bindsym --to-code y reload; mode "default"
|
||||
bindsym --to-code n mode "default"
|
||||
bindsym Escape mode "default"
|
||||
}
|
||||
mode "lock sway? [y/n]" {
|
||||
bindsym --to-code y exec swaylock; mode "default"
|
||||
bindsym --to-code n mode "default"
|
||||
bindsym Escape mode "default"
|
||||
}
|
||||
mode "exit sway? [y/n]" {
|
||||
bindsym --to-code y exec swaymsg exit; mode "default"
|
||||
bindsym --to-code n mode "default"
|
||||
bindsym Escape mode "default"
|
||||
}
|
||||
bindsym --to-code $mod+r mode "resize"
|
||||
bindsym --to-code $mod+Shift+r mode "reload sway? [y/n]"
|
||||
bindsym --to-code $mod+x mode "lock sway? [y/n]"
|
||||
bindsym --to-code $mod+Shift+x mode "exit sway? [y/n]"
|
||||
Executable
+282
@@ -0,0 +1,282 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
import signal
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Dict, Optional
|
||||
|
||||
try:
|
||||
from systemd import daemon
|
||||
except ImportError:
|
||||
daemon = None
|
||||
|
||||
import i3ipc
|
||||
from i3ipc.aio import Connection
|
||||
|
||||
DEFAULT_MODE = os.getenv("PWL_DEFAULT_MODE", "1") == "1"
|
||||
DEBUG = os.getenv("PWL_DEBUG", "0") == "1"
|
||||
INFO = os.getenv("PWL_INFO", "1") == "1"
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG if DEBUG else (logging.INFO if INFO else logging.WARNING),
|
||||
format="[pwl] %(asctime)s %(message)s",
|
||||
datefmt="%H:%M:%S",
|
||||
)
|
||||
log = logging.getLogger("pwl")
|
||||
|
||||
|
||||
def notify_systemd(msg: str) -> None:
|
||||
if daemon:
|
||||
try:
|
||||
daemon.notify(msg)
|
||||
except Exception as e:
|
||||
log.debug("Failed to notify systemd: %s", e)
|
||||
|
||||
|
||||
def notify_ready(status: str) -> None:
|
||||
notify_systemd(f"READY=1\nSTATUS={status}")
|
||||
|
||||
|
||||
def notify_status(status: str) -> None:
|
||||
notify_systemd(f"STATUS={status}")
|
||||
|
||||
|
||||
def notify_watchdog() -> None:
|
||||
notify_systemd("WATCHDOG=1")
|
||||
|
||||
|
||||
@dataclass
|
||||
class Keyboard:
|
||||
identifier: str
|
||||
default_index: int
|
||||
current_index: int
|
||||
layout_map: Dict[str, int] = field(default_factory=dict)
|
||||
|
||||
|
||||
class PerWindowLayout:
|
||||
def __init__(self) -> None:
|
||||
self.conn: Optional[Connection] = None
|
||||
self.keyboard: Optional[Keyboard] = None
|
||||
|
||||
self.window_layouts: Dict[int, int] = {}
|
||||
self.current_window: Optional[int] = None
|
||||
|
||||
self.stop_event = asyncio.Event()
|
||||
self._layout_map_built = False
|
||||
|
||||
async def connect(self) -> None:
|
||||
self.conn = await Connection(auto_reconnect=True).connect()
|
||||
|
||||
def _find_main_keyboard(self, inputs) -> Optional[object]:
|
||||
keyboards = [i for i in inputs if i.type == "keyboard"]
|
||||
if not keyboards:
|
||||
return None
|
||||
|
||||
real = [k for k in keyboards if "virtual" not in (k.identifier or "").lower()]
|
||||
return (real or keyboards)[0]
|
||||
|
||||
async def wait_until_ready(self) -> None:
|
||||
notify_status("Waiting for sway...")
|
||||
while not self.stop_event.is_set():
|
||||
try:
|
||||
inputs = await self.conn.get_inputs()
|
||||
except Exception:
|
||||
await asyncio.sleep(0.2)
|
||||
continue
|
||||
|
||||
main = self._find_main_keyboard(inputs)
|
||||
if main is None:
|
||||
await asyncio.sleep(0.2)
|
||||
continue
|
||||
|
||||
idx = main.xkb_active_layout_index or 0
|
||||
self.keyboard = Keyboard(
|
||||
identifier=main.identifier,
|
||||
default_index=idx,
|
||||
current_index=idx,
|
||||
)
|
||||
return
|
||||
|
||||
async def build_layout_map(self, force: bool = False) -> None:
|
||||
assert self.keyboard is not None
|
||||
inputs = await self.conn.get_inputs()
|
||||
current = self.keyboard.current_index
|
||||
|
||||
kbd = next((i for i in inputs if i.identifier == self.keyboard.identifier), None)
|
||||
if not kbd:
|
||||
return
|
||||
|
||||
layouts = kbd.xkb_layout_names or []
|
||||
count = len(layouts)
|
||||
|
||||
if self._layout_map_built and not force and len(self.keyboard.layout_map) == count:
|
||||
return
|
||||
|
||||
notify_status("Building layout map...")
|
||||
self.keyboard.layout_map.clear()
|
||||
|
||||
for i in range(count):
|
||||
await self.conn.command(f'input "{self.keyboard.identifier}" xkb_switch_layout {i}')
|
||||
inputs = await self.conn.get_inputs()
|
||||
kbd = next((k for k in inputs if k.identifier == self.keyboard.identifier), kbd)
|
||||
name = kbd.xkb_active_layout_name or str(i)
|
||||
self.keyboard.layout_map[name] = i
|
||||
|
||||
await self.conn.command(f'input "{self.keyboard.identifier}" xkb_switch_layout {current}')
|
||||
self.keyboard.current_index = current
|
||||
self._layout_map_built = True
|
||||
log.info("Layout map initialized (%d layouts)", len(self.keyboard.layout_map))
|
||||
|
||||
async def init_windows(self) -> None:
|
||||
assert self.keyboard is not None
|
||||
inputs = await self.conn.get_inputs()
|
||||
kbd = next((i for i in inputs if i.identifier == self.keyboard.identifier), None)
|
||||
idx = kbd.xkb_active_layout_index if kbd else self.keyboard.default_index
|
||||
|
||||
tree = await self.conn.get_tree()
|
||||
active_ids = set()
|
||||
|
||||
for con in tree.leaves():
|
||||
active_ids.add(con.id)
|
||||
if con.id not in self.window_layouts:
|
||||
self.window_layouts[con.id] = idx
|
||||
|
||||
stale = [wid for wid in self.window_layouts if wid not in active_ids]
|
||||
for wid in stale:
|
||||
self.window_layouts.pop(wid, None)
|
||||
|
||||
notify_status(f"Tracking {len(self.window_layouts)} windows")
|
||||
|
||||
async def switch_layout(self, idx: int) -> None:
|
||||
assert self.keyboard is not None
|
||||
if idx == self.keyboard.current_index:
|
||||
return
|
||||
await self.conn.command(f'input "{self.keyboard.identifier}" xkb_switch_layout {idx}')
|
||||
self.keyboard.current_index = idx
|
||||
|
||||
async def handle_active_window(self, con_id: int) -> None:
|
||||
assert self.keyboard is not None
|
||||
self.current_window = con_id
|
||||
|
||||
if con_id in self.window_layouts:
|
||||
idx = self.window_layouts[con_id]
|
||||
else:
|
||||
idx = self.keyboard.default_index if DEFAULT_MODE else self.keyboard.current_index
|
||||
self.window_layouts[con_id] = idx
|
||||
notify_status(f"Tracking {len(self.window_layouts)} windows")
|
||||
|
||||
await self.switch_layout(idx)
|
||||
|
||||
def handle_active_layout(self, identifier: str, layout_name: Optional[str]) -> None:
|
||||
assert self.keyboard is not None
|
||||
if identifier != self.keyboard.identifier or not layout_name:
|
||||
return
|
||||
|
||||
idx = self.keyboard.layout_map.get(layout_name)
|
||||
if idx is None:
|
||||
return
|
||||
|
||||
self.keyboard.current_index = idx
|
||||
if self.current_window is not None:
|
||||
self.window_layouts[self.current_window] = idx
|
||||
|
||||
def handle_close_window(self, con_id: int) -> None:
|
||||
if self.window_layouts.pop(con_id, None) is not None:
|
||||
notify_status(f"Tracking {len(self.window_layouts)} windows")
|
||||
|
||||
async def handle_device_change(self) -> None:
|
||||
inputs = await self.conn.get_inputs()
|
||||
main = self._find_main_keyboard(inputs)
|
||||
if main and self.keyboard and main.identifier != self.keyboard.identifier:
|
||||
log.info("Main keyboard changed: %s -> %s", self.keyboard.identifier, main.identifier)
|
||||
idx = main.xkb_active_layout_index or 0
|
||||
self.keyboard.identifier = main.identifier
|
||||
self.keyboard.default_index = idx
|
||||
self.keyboard.current_index = idx
|
||||
await self.build_layout_map(force=True)
|
||||
await self.init_windows()
|
||||
|
||||
def _register_handlers(self) -> None:
|
||||
assert self.conn is not None
|
||||
|
||||
async def on_window(_conn, event):
|
||||
change = event.change
|
||||
if change == "focus" and event.container is not None:
|
||||
await self.handle_active_window(event.container.id)
|
||||
elif change == "close" and event.container is not None:
|
||||
self.handle_close_window(event.container.id)
|
||||
|
||||
async def on_input(_conn, event):
|
||||
change = event.change
|
||||
if change == "xkb_layout" and event.input is not None:
|
||||
self.handle_active_layout(
|
||||
event.input.identifier, event.input.xkb_active_layout_name
|
||||
)
|
||||
elif change in ("added", "removed"):
|
||||
await self.handle_device_change()
|
||||
|
||||
self.conn.on(i3ipc.Event.WINDOW, on_window)
|
||||
self.conn.on(i3ipc.Event.INPUT, on_input)
|
||||
|
||||
async def watchdog_loop(self) -> None:
|
||||
interval = 10.0
|
||||
if daemon:
|
||||
try:
|
||||
wd = daemon.watchdog_enabled()
|
||||
if isinstance(wd, (int, float)) and wd > 0:
|
||||
interval = wd / 2.0
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
while not self.stop_event.is_set():
|
||||
notify_watchdog()
|
||||
await asyncio.sleep(interval)
|
||||
|
||||
async def run(self) -> None:
|
||||
await self.connect()
|
||||
await self.wait_until_ready()
|
||||
await self.build_layout_map()
|
||||
await self.init_windows()
|
||||
self._register_handlers()
|
||||
|
||||
notify_ready(f"Tracking {len(self.window_layouts)} windows")
|
||||
|
||||
async with asyncio.TaskGroup() as tg:
|
||||
tg.create_task(self.conn.main())
|
||||
tg.create_task(self.watchdog_loop())
|
||||
await self.stop_event.wait()
|
||||
await self.conn.main_quit()
|
||||
|
||||
|
||||
async def amain() -> None:
|
||||
pwl = PerWindowLayout()
|
||||
loop = asyncio.get_running_loop()
|
||||
|
||||
def shutdown_handler() -> None:
|
||||
pwl.stop_event.set()
|
||||
|
||||
for sig in (signal.SIGINT, signal.SIGTERM):
|
||||
loop.add_signal_handler(sig, shutdown_handler)
|
||||
|
||||
try:
|
||||
await pwl.run()
|
||||
except asyncio.CancelledError:
|
||||
raise
|
||||
except Exception:
|
||||
log.exception("Fatal error")
|
||||
raise
|
||||
|
||||
|
||||
def main() -> None:
|
||||
try:
|
||||
asyncio.run(amain())
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,39 @@
|
||||
ignore-empty-password
|
||||
show-failed-attempts
|
||||
daemonize
|
||||
color=2e3440
|
||||
indicator-idle-visible
|
||||
indicator-caps-lock
|
||||
disable-caps-lock-text
|
||||
hide-keyboard-layout
|
||||
indicator-radius=42
|
||||
indicator-thickness=2
|
||||
font=Noto Sans Mono
|
||||
font-size=10
|
||||
inside-color=00000000
|
||||
inside-clear-color=00000000
|
||||
inside-ver-color=00000000
|
||||
inside-wrong-color=00000000
|
||||
inside-caps-lock-color=00000000
|
||||
ring-color=4c566a
|
||||
ring-clear-color=ebcb8b
|
||||
ring-ver-color=a3be8c
|
||||
ring-wrong-color=bf616a
|
||||
ring-caps-lock-color=d08770
|
||||
line-color=00000000
|
||||
line-clear-color=00000000
|
||||
line-ver-color=00000000
|
||||
line-wrong-color=00000000
|
||||
line-caps-lock-color=00000000
|
||||
text-color=eceff4
|
||||
text-clear-color=ebcb8bff
|
||||
text-ver-color=a3be8cff
|
||||
text-wrong-color=bf616aff
|
||||
text-caps-lock-color=d08770ff
|
||||
separator-color=00000000
|
||||
key-hl-color=88c0d0ff
|
||||
caps-lock-key-hl-color=88c0d0ff
|
||||
bs-hl-color=ebcb8bff
|
||||
layout-bg-color=00000000
|
||||
layout-border-color=00000000
|
||||
layout-text-color=d8dee9ff
|
||||
@@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=clipvault
|
||||
PartOf=graphical-session.target
|
||||
After=graphical-session.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/wl-paste --watch clipvault store --max-entries 5000
|
||||
Restart=on-failure
|
||||
RestartSec=2
|
||||
|
||||
[Install]
|
||||
WantedBy=graphical-session.target
|
||||
@@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=GTK dark mode settings
|
||||
After=graphical-session.target
|
||||
PartOf=graphical-session.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/bin/gsettings set org.gnome.desktop.interface gtk-theme Adwaita-dark
|
||||
ExecStart=/usr/bin/gsettings set org.gnome.desktop.interface color-scheme prefer-dark
|
||||
|
||||
[Install]
|
||||
WantedBy=graphical-session.target
|
||||
@@ -0,0 +1,24 @@
|
||||
[Unit]
|
||||
Description=Per window keyboard layout (sway)
|
||||
Documentation=https://github.com/pyrschtjag
|
||||
PartOf=graphical-session.target
|
||||
After=graphical-session.target
|
||||
BindsTo=graphical-session.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
NotifyAccess=main
|
||||
ExecStart=%h/.config/sway/scripts/per-window-layout.py
|
||||
Environment=PWL_DEFAULT_MODE=1
|
||||
Environment=PWL_INFO=1
|
||||
Environment=PWL_DEBUG=0
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
NoNewPrivileges=yes
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
TimeoutStartSec=30
|
||||
TimeoutStopSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=graphical-session.target
|
||||
@@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=Swaddle
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/sbin/swaddle
|
||||
NoNewPrivileges=yes
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
|
||||
[Install]
|
||||
WantedBy=graphical-session.target
|
||||
@@ -0,0 +1,21 @@
|
||||
[Unit]
|
||||
Description=Sway idle daemon
|
||||
PartOf=graphical-session.target
|
||||
After=graphical-session.target
|
||||
BindsTo=graphical-session.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/swayidle -w \
|
||||
timeout 300 'pidof swaylock || swaylock -f' \
|
||||
timeout 360 'swaymsg "output * dpms off"' \
|
||||
timeout 420 'systemctl suspend' \
|
||||
before-sleep 'pidof swaylock || swaylock -f' \
|
||||
after-resume 'swaymsg "output * dpms on"'
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=graphical-session.target
|
||||
@@ -0,0 +1,3 @@
|
||||
export QT_QPA_PLATFORMTHEME=qt6ct
|
||||
export QT_QPA_PLATFORMTHEME_QT6=qt6ct
|
||||
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/rbw/ssh-agent-socket"
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
{
|
||||
"layer": "top",
|
||||
"position": "top",
|
||||
|
||||
"margin-top": 5,
|
||||
"margin-left": 5,
|
||||
"margin-right": 5,
|
||||
|
||||
"height": 34,
|
||||
|
||||
"modules-left": [
|
||||
"custom/rofi",
|
||||
"sway/workspaces",
|
||||
"sway/mode"
|
||||
],
|
||||
|
||||
"modules-center": [
|
||||
"clock#time"
|
||||
],
|
||||
|
||||
"modules-right": [
|
||||
"tray",
|
||||
"idle_inhibitor",
|
||||
"group/keyboard",
|
||||
"disk" ,
|
||||
"group/hardware",
|
||||
"group/temp",
|
||||
"group/audio"
|
||||
],
|
||||
|
||||
"group/keyboard": {
|
||||
"orientation": "horizontal",
|
||||
/*"modules": [
|
||||
"keyboard-state",
|
||||
"sway/language"
|
||||
]*/
|
||||
"modules": ["sway/language"]
|
||||
},
|
||||
|
||||
"group/hardware": {
|
||||
"orientation": "horizontal",
|
||||
"modules": [
|
||||
"cpu",
|
||||
"memory"
|
||||
]
|
||||
},
|
||||
|
||||
"group/temp": {
|
||||
"orientation": "horizontal",
|
||||
"modules": [
|
||||
"temperature#cpu",
|
||||
"custom/gpu_temperature"
|
||||
]
|
||||
},
|
||||
|
||||
"group/audio": {
|
||||
"orientation": "horizontal",
|
||||
"modules": [
|
||||
"wireplumber#source",
|
||||
"wireplumber#sink"
|
||||
]
|
||||
},
|
||||
|
||||
"custom/rofi": {
|
||||
"exec-if": "[ \"$USER\" != \"pyrschtjag\" ]",
|
||||
"exec": "echo '{\"text\": \"\", \"tooltip\": \"\"}'",
|
||||
"return-type": "json",
|
||||
"format": "<span color='#88c0d0'>{icon}</span><span rise='1000' font='Symbols Nerd Font Mono 8'>{text}</span>",
|
||||
"format-icons": [""],
|
||||
"interval": "once",
|
||||
"on-click": "rofi -show drun",
|
||||
"tooltip": false
|
||||
},
|
||||
|
||||
"sway/workspaces": {
|
||||
"format": "<span color='#88c0d0' weight='bold'>{icon}</span><span rise='1000' font='Symbols Nerd Font Mono 8'>{windows}</span>",
|
||||
"window-rewrite": {
|
||||
"class<firefox>": " ",
|
||||
"class<foot>": " ",
|
||||
"class<discord>": " ",
|
||||
"class<org.telegram.desktop>": " ",
|
||||
"class<steam>": " ",
|
||||
"class<org.gajim.Gajim>": " ",
|
||||
"class<Spotify>": " ",
|
||||
"title<nvim>": " ",
|
||||
"title<rmpc>": " ",
|
||||
"title<mc(.*)>": " ",
|
||||
"": " "
|
||||
},
|
||||
"tooltip": false
|
||||
},
|
||||
|
||||
"sway/mode": {
|
||||
"format": "<span color='#ebcb8b'>{}</span>",
|
||||
"max-length": 18,
|
||||
"tooltip": false
|
||||
},
|
||||
|
||||
"clock#time": {
|
||||
"format": "{:%H:%M}",
|
||||
"tooltip": false
|
||||
},
|
||||
|
||||
"tray": {
|
||||
"icon-size": 12,
|
||||
"spacing": 10,
|
||||
"tooltip": false
|
||||
},
|
||||
|
||||
"idle_inhibitor": {
|
||||
"format": "{icon}",
|
||||
"format-icons": {
|
||||
"activated": "<span color='#d08770' rise='1000' font='Symbols Nerd Font Mono 8'></span>",
|
||||
// "deactivated": ""
|
||||
"deactivated": "<span color='#ebcb8b' rise='1000' font='Symbols Nerd Font Mono 8'></span>"
|
||||
},
|
||||
"signal": 13,
|
||||
"tooltip": false,
|
||||
"cursor": ""
|
||||
},
|
||||
|
||||
"sway/language": {
|
||||
// "format": "{}",
|
||||
"format": "<span color='#8fbcbb' rise='1000' font='Symbols Nerd Font Mono 8'></span> {}",
|
||||
"format-en": "EN",
|
||||
"format-ru": "RU",
|
||||
"tooltip": false
|
||||
},
|
||||
|
||||
"keyboard-state": {
|
||||
"format": "{name}{icon}",
|
||||
"numlock": true,
|
||||
"capslock": true,
|
||||
"scrolllock": false,
|
||||
"format-icons": {
|
||||
"numlock": {
|
||||
"locked": "<span color='#a3be8c' rise='1000' font='Symbols Nerd Font Mono 8'></span> ",
|
||||
"unlocked": ""
|
||||
},
|
||||
"capslock": {
|
||||
"locked": "<span color='##8fbcbb' rise='1000' font='Symbols Nerd Font Mono 8'></span> <span color='#bf616a' rise='1000' font='Symbols Nerd Font Mono 8'></span> ",
|
||||
"unlocked": "<span color='##8fbcbb' rise='1000' font='Symbols Nerd Font Mono 8'></span> "
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"disk": {
|
||||
// enable when release waybar 0.16+
|
||||
// "format": "<span color='#a3be8c' rise='1000' font='Symbols Nerd Font Mono 8'></span> {free:5G}G",
|
||||
"format": "<span color='#a3be8c' rise='1000' font='Symbols Nerd Font Mono 8'></span> {free:7}",
|
||||
"paths": ["/"],
|
||||
"interval": 120,
|
||||
"tooltip": false
|
||||
},
|
||||
|
||||
"cpu": {
|
||||
"format": "<span color='#5e81ac' rise='1000' font='Symbols Nerd Font Mono 8'></span> {usage:03}%",
|
||||
"interval": 5,
|
||||
"tooltip": false
|
||||
},
|
||||
|
||||
"memory": {
|
||||
"format": "<span color='#81a1c1' rise='1000' font='Symbols Nerd Font Mono 8'></span> {percentage:03}%",
|
||||
"interval": 5,
|
||||
"tooltip": false
|
||||
},
|
||||
|
||||
"temperature#cpu": {
|
||||
"format": "<span color='#ebcb8b' rise='1000' font='Symbols Nerd Font Mono 8'></span> {temperatureC:03}°C",
|
||||
"hwmon-path": "/sys/class/hwmon/hwmon2/temp1_input",
|
||||
"interval": 5,
|
||||
"tooltip": false
|
||||
},
|
||||
|
||||
"custom/gpu_temperature": {
|
||||
"format": "<span color='#d08770' rise='1000' font='Symbols Nerd Font Mono 8'></span> {text}°C",
|
||||
"exec": "nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits | xargs printf '%03d'",
|
||||
"interval": 5,
|
||||
"tooltip": false
|
||||
},
|
||||
|
||||
"wireplumber#source": {
|
||||
"format": "<span color='#b48ead' rise='1000' font='Symbols Nerd Font Mono 8'></span> {volume:03}%",
|
||||
"format-muted": "<span color='#4c566a' rise='1000' font='Symbols Nerd Font Mono 8'></span> 000%",
|
||||
"node-type": "Audio/Source",
|
||||
"scroll-step": 5,
|
||||
"tooltip": false
|
||||
},
|
||||
|
||||
"wireplumber#sink": {
|
||||
"format": "<span color='#b48ead' rise='1000' font='Symbols Nerd Font Mono 8'>{icon}</span> {volume:03}%",
|
||||
"format-muted": "<span color='#4c566a' rise='1000' font='Symbols Nerd Font Mono 8'></span> 000%",
|
||||
"format-icons": ["", "", ""],
|
||||
"scroll-step": 5,
|
||||
"tooltip": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
@define-color nord0 #2e3440;
|
||||
@define-color nord1 #3b4252;
|
||||
@define-color nord2 #434c5e;
|
||||
@define-color nord3 #4c566a;
|
||||
@define-color nord4 #d8dee9;
|
||||
@define-color nord5 #e5e9f0;
|
||||
@define-color nord6 #eceff4;
|
||||
@define-color nord7 #8fbcbb;
|
||||
@define-color nord8 #88c0d0;
|
||||
@define-color nord9 #81a1c1;
|
||||
@define-color nord10 #5e81ac;
|
||||
@define-color nord11 #bf616a;
|
||||
@define-color nord12 #d08770;
|
||||
@define-color nord13 #ebcb8b;
|
||||
@define-color nord14 #a3be8c;
|
||||
@define-color nord15 #b48ead;
|
||||
|
||||
* {
|
||||
font-family: "Noto Sans Mono";
|
||||
font-size: 13px;
|
||||
border: 0px;
|
||||
border-radius: 0px;
|
||||
box-shadow: none;
|
||||
text-shadow: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
window#waybar {
|
||||
color: @nord6;
|
||||
background-color: @nord0;
|
||||
}
|
||||
|
||||
#custom-rofi {
|
||||
margin: 0 10px 0 10px;
|
||||
}
|
||||
|
||||
#workspaces button {
|
||||
color: @nord4;
|
||||
padding: 0px 10px;
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
#workspaces button.visible {
|
||||
color: @nord5;
|
||||
background-color: transparent;
|
||||
border-bottom: 2px solid @nord9;
|
||||
}
|
||||
|
||||
#workspaces button.focused {
|
||||
color: @nord6;
|
||||
background-color: @nord1;
|
||||
border-bottom: 2px solid @nord8;
|
||||
}
|
||||
|
||||
#workspaces button.urgent {
|
||||
color: @nord8;
|
||||
}
|
||||
|
||||
#workspaces button:hover {
|
||||
background: transparent;
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
#workspaces button:hover.active,
|
||||
#workspaces button:hover.visible {
|
||||
background-color: @nord1;
|
||||
border-bottom: 2px solid @nord8;
|
||||
}
|
||||
|
||||
#workspaces button.urgent {
|
||||
border-bottom: 2px solid @nord12;
|
||||
}
|
||||
|
||||
#mode {
|
||||
margin: 0 0 0 10px;
|
||||
}
|
||||
|
||||
#tray menu {
|
||||
background-color: @nord0;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
#tray menu menuitem {
|
||||
color: @nord4;
|
||||
padding: 4px 0px;
|
||||
border-left: 2px solid transparent;
|
||||
}
|
||||
|
||||
#tray menu menuitem:hover {
|
||||
background-color: @nord1;
|
||||
color: @nord6;
|
||||
border-left: 2px solid @nord8;
|
||||
}
|
||||
|
||||
#tray menu separator {
|
||||
background-color: @nord3;
|
||||
margin: 4px 0;
|
||||
min-height: 1px;
|
||||
}
|
||||
|
||||
#tray > .passive { opacity: 0.6; }
|
||||
#tray > .needs-attention { color: @nord8; }
|
||||
|
||||
/* delete when release waybar 0.16+ */
|
||||
#idle_inhibitor {
|
||||
margin: 0 10px 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* enable when release waybar 0.16+
|
||||
#idle_inhibitor {
|
||||
margin: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
#idle_inhibitor.activated {
|
||||
margin: 0 10px 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
*/
|
||||
|
||||
#tray,
|
||||
#keyboard,
|
||||
#disk,
|
||||
#hardware,
|
||||
#temp,
|
||||
#audio {
|
||||
margin: 0 10px 0 0;
|
||||
}
|
||||
|
||||
#wireplumber.source-muted,
|
||||
#wireplumber.sink-muted {
|
||||
color: @nord3;
|
||||
color: @nord3;
|
||||
}
|
||||
|
||||
#cpu,
|
||||
#temperature.cpu,
|
||||
#wireplumber.source {
|
||||
padding: 0 5px 0 0;
|
||||
}
|
||||
|
||||
#memory,
|
||||
#custom-gpu_temperature,
|
||||
#wireplumber.sink {
|
||||
padding: 0 0 0 5px;
|
||||
}
|
||||
|
||||
tooltip {
|
||||
background-color: @nord0;
|
||||
}
|
||||
|
||||
tooltip label {
|
||||
background-color: @nord0;
|
||||
color: @nord6;
|
||||
}
|
||||
Reference in New Issue
Block a user