Full Code of codingjerk/dotfiles for AI

main d925aa6f594d cached
67 files
197.9 KB
55.9k tokens
1 requests
Download .txt
Showing preview only (215K chars total). Download the full file or copy to clipboard to get everything.
Repository: codingjerk/dotfiles
Branch: main
Commit: d925aa6f594d
Files: 67
Total size: 197.9 KB

Directory structure:
gitextract_yheofb5_/

├── README.md
├── config/
│   ├── aria2/
│   │   └── aria2.conf
│   ├── cargo/
│   │   └── config.toml
│   ├── chrome/
│   │   └── flags.conf
│   ├── cspell/
│   │   ├── cspell.yml
│   │   └── dict-cj.txt
│   ├── curl/
│   │   └── curlrc
│   ├── electron/
│   │   └── electron-flags.conf
│   ├── fd/
│   │   └── ignore
│   ├── fontconfig/
│   │   └── fonts.conf
│   ├── foot/
│   │   └── foot.ini
│   ├── fuzzel/
│   │   └── fuzzel.ini
│   ├── git/
│   │   ├── config
│   │   ├── ignore
│   │   └── template
│   ├── gnupg/
│   │   ├── gpg-agent.conf
│   │   └── gpg.conf
│   ├── helix/
│   │   ├── config.toml
│   │   ├── ignore
│   │   ├── languages.toml
│   │   └── theme.toml
│   ├── htop/
│   │   └── htoprc
│   ├── hypr/
│   │   ├── hypridle.conf
│   │   ├── hyprland.conf
│   │   └── hyprlock.conf
│   ├── ipython/
│   │   └── ipython_config.py
│   ├── ledger/
│   │   └── ledgerrc
│   ├── less/
│   │   └── lesskey
│   ├── mako/
│   │   └── config
│   ├── matplotlib/
│   │   └── matplotlibrc
│   ├── mpv/
│   │   ├── input.conf
│   │   └── mpv.conf
│   ├── niri/
│   │   └── config.kdl
│   ├── npm/
│   │   └── npmrc
│   ├── numbat/
│   │   └── config.toml
│   ├── nvim/
│   │   ├── init.lua
│   │   └── nuitbleue.vim
│   ├── paru/
│   │   └── paru.conf
│   ├── postgres/
│   │   └── psqlrc
│   ├── pypoetry/
│   │   └── config.toml
│   ├── ruff/
│   │   └── ruff.toml
│   ├── ssh/
│   │   ├── authorized_keys
│   │   └── config
│   ├── sway/
│   │   └── config
│   ├── swaylock/
│   │   └── config
│   ├── termux/
│   │   ├── colors.properties
│   │   └── termux.properties
│   ├── tmux/
│   │   └── tmux.conf
│   ├── waybar/
│   │   ├── config
│   │   └── style.css
│   ├── wofi/
│   │   ├── config
│   │   └── style.css
│   ├── x11/
│   │   └── xcompose
│   ├── xdg/
│   │   ├── mimeapps.list
│   │   └── user-dirs.dirs
│   ├── xdg-desktop-portal-wlr/
│   │   └── config
│   ├── xkb/
│   │   ├── rules/
│   │   │   └── evdev
│   │   └── symbols/
│   │       └── group
│   ├── zathura/
│   │   └── zathurarc
│   ├── zed/
│   │   ├── keymap.json
│   │   ├── settings.json
│   │   └── theme.json
│   └── zsh/
│       ├── zprofile
│       └── zshrc
├── settings.toml
└── tools/
    ├── deps
    └── render

================================================
FILE CONTENTS
================================================

================================================
FILE: README.md
================================================
# Dotfiles

> Configuration of software I personally use for software development

![Showcase](./showcase.png)
*Hyprland with foot terminal, tmux and neovim*

## Install

Add user:

```sh
useradd -m -G docker,systemd-journal,users,wheel -k /dev/null -s /usr/bin/zsh cj
```

Clone repository and install dotfiles as a new user:

```sh
sudo -iu cj
git clone https://github.com/codingjerk/dotfiles.git
python ~/dotfiles/tools/render install
```

**WARNING:** it's for me and myself only,
I don't recommend to run it on your own machines.

If you're not me (lol), just clone this repository and poke into configuration files (it's in `config` directory!).

### Optional extra steps (on new hosts)

1. Generate ssh keys:

```sh
ssh-keygen -t ed25519
```

2. Import gpg keys:

```sh
gpg --import <key>.gpg
gpg --edit-key <key-id>
# trust, 5, save
```

3. Initialize stores:

```sh
git clone cj:private-pass .password-store
git clone cj:when-private .when
git clone cj:ledger-private .ledger
git clone cj:notes-private notes
```

4. Install LSPs for `neovim`.
   Check `neovim`'s `init.lua` for actual sources
   and build instructions.

5. Install lazy

```sh
mkdir -p ~/.local/share/nvim/lazy
cd $$
git clone https://github.com/folke/lazy.nvim.git

in vim:
:Lazy Install
```

## Update (re-render configuration files)

Pull sources and re-render configs:

```sh
git pull
python ~/dotfiles/tools/render install
```

## How it works?

This repository contains:

- `config` -- a bunch of configuration files and templates. Main directory here
- `settings.toml` -- configurable settings (color palette, font, etc.), used by templates
- `wallpaper.png` -- a wallpaper
- `tools`
   - `render` -- tool to render templates into configuration files

Itself, repository should be placed somewhere in your home directory,
and after running `update` it will place rendered configuration files
into your home directory.


================================================
FILE: config/aria2/aria2.conf
================================================
# Default download dir
dir=${HOME}/downloads/aria

# I usually have very bad internet, so no seeding :(
seed-time=0

# Speed up some downloads
disable-ipv6=true
file-allocation=falloc
bt-enable-lpd=true


================================================
FILE: config/cargo/config.toml
================================================
[cargo-new]
vcs = "none" # do not automatically create git repository

# Let's make cargo quiet, more UNIX-like
[term]
quiet = true
verbose = false
progress.when = "never"

[build]
# WARN: be careful deploying stuff built locally
rustflags = ["-Ctarget-cpu=native"]


================================================
FILE: config/chrome/flags.conf
================================================
# === Wayland support ===

--ozone-platform=wayland

# === Hardware acceleration tweaks ===

# HW accelerated video encoding is not needed, but it does not hurt
--enable-features=AcceleratedVideoDecodeLinuxGL,AcceleratedVideoEncoder

# === Other ===

--force-device-scale-factor=1.5
--password-store=basic


================================================
FILE: config/cspell/cspell.yml
================================================
---
$schema: https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json
version: '0.2'
language: en
dictionaries:
  - python
  - python-common
  - cpp
  - node
  - typescript
  - html
  - bash
  - en-us
  - ru-ru
  - custom-cj
  - custom-radar
dictionaryDefinitions:
  - name: custom-cj
    path: .local/cspell-cj.txt
  - name: custom-radar
    path: .local/cspell-radar.txt


================================================
FILE: config/cspell/dict-cj.txt
================================================
# Kekich
Кекич
kekich

# Assembler
cmov
cmovne

# Helix
nonwhitespace
textobject
noyank

# Chess
bitboard
bitboards
bitscan
movegen
startpos
perft
stockfish
shakmaty
zobrist

# Uci
wtime
btime
winc
binc
bestmove
uciok
readyok
ucinewgame

# Russian
дешборд
ревьюшка
ревьюшке
ревьюшках
скилл
скиллы
дисклеймер
дебаг
дебага
фронтенд

# Names
gruzdev
codingjerk

# Words
blazingly

# Rirs
rir
rirdb
rirs
afrinic
apnic
arin
lacnic
ripe
ripencc

# My projects
niced

# BGP
asnames
UUNET

# Countries
Åland
Plurinational
Sint
Eustatius
Bouvet
Burkina
Faso
Cabo
Rica
Côte
d'Ivoire
Eswatini
Réunion
Barthélemy
Cunha
Kitts
Marino
Sint
Maarten
Mayen
Leste
Tokelau
Caicos
Bolivarian
Viet
Futuna

# Programs
nmap
librir
addopts
norecursedirs
dockerhub
pastebin

# Other
ducati
testpaths
lockfile
lockfiles
pyright
langserver
wasd
autoimport
userns
initdb
willfarrell
autoheal
crond
linestyle
pytest
mypy
healthcheck
fastapi
loguru
uvicorn
aiohttp
brotli
asgi
orjson
jsonify
pydantic
asyncpg
middleware
middlewares
redoc
starlette
fetchval
bitnami
blackbox
blkio
cacheprovider
cobertura
gunicorn
hadolint
healthchecks
httpx
isready
microbenchmarking
psqlrc
pyndantic
qnet
qnetd
qrator
bview
bviews
batchwait
promtail
varlogs
peeringdb
setenv
testsuites
uvloop
Eeuo
exitfirst
gsed

# Python
popleft
maxsplit

# Python libs
fernet
libnotify
pypackages
aiopg

# Bash & Linux
iptables
wg
htoprc
traceroute
iwctl
iwd
hypr
hypridle
hyprland
hyprlock
lesskey
curlrc
waybar
wofi
fontconfig
linenr
satty
paru
zoxide
hexview
powertop
termdown
vimium
colemak
pipewire
wireplumber
textfiles
cadvisor
rootfs
tmpfs
pipefs
securityfs
sysfs
tracefs
devpts
devtmpfs
fusectl
hugetlbfs
autofs
sshfs
configfs
debugfs
smartctl
grub
journalctl
swapon
localectl
pkgfile
timedatectl
hwclock
sysyohc
oomd
networkd
timesyncd
zram
bootctl
mkinitcpio
nvme
cfdisk
sfdisk
noatime
lazytime
writeback
packstrap
devel
netcat
ucode
dhcpcd
noto
pulseaudio
zathura
swaybg
swayidle
polkit
vfat
fmask
dmask
iocharset
consolefonts
vconsole
modconf
zstd
kver
pacman
mirrorlist
vconsole
setfont
consolefonts
powersave
centisecs
printk
autogroup
logind
poweroff
LLMNR
resolv
pcspkr
uvcvideo
iwlwifi
iwlmvm
uapsd
multilib
rootflags
zswap
udev
wlan
tmpfiles
aspm
powersupersave
scache
pacstrap
nowatchdog
cpufreq
nofail
coredump
nspawn
nconfig
pipefail

# Technologies
nextdns
dotenv

# Own language servers
pylsp
tsls
dmypy
yapf
scls

# Configuration files
cursorline
statusline

# Typst
typst
smallcaps
emph

# Rust
rustflags
Ctarget
chrono
Datelike
Timelike
DEBG
peekable
rsplitn
userauth
rustfmt
flate
mimalloc
lumbermill
sqlx
unseparated
humantime
reqwest
serde
rustls
shadowsocks
clippy
chacha
rngs
dalek
getrandom
wgapi
defguard
prvkey

# Tech
CQRS
phind
ublock
matplotlibrc
xcompose
zathurarc
pypoetry
ledgerrc
termux
otus
ipinfo
mmdb
keepalive
keepalives

# Chess
halfmove
fullmove
rnbqkbnr


================================================
FILE: config/curl/curlrc
================================================
# Follow redirects
location

# Do not output anything except on error
silent
show-error

# Fail fast on server errors and show body
fail-with-body

# Use remote name for output files (if used if -O)
# NOTE: conflicts with some URLs, do not enable
# remote-header-name

# When following a redirect, automatically set the previous URL as referer.
referer = ";auto"

# Wait 5 seconds before timing out.
connect-timeout = 5

# Retry automatically
retry = 3
retry-delay = 1


================================================
FILE: config/electron/electron-flags.conf
================================================
# Wayland support
--enable-features=UseOzonePlatform,WaylandWindowDecorations,WebRTCPipeWireCapturer
--ozone-platform=wayland


================================================
FILE: config/fd/ignore
================================================
.git/
node_modules/
target/
dist/
__pycache__/
.mypy_cache/
.venv/
.zig-cache/
zig-out/


================================================
FILE: config/fontconfig/fonts.conf
================================================
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
<fontconfig>
  <!-- Disable embedded bitmap fonts -->
  <match target="font">
    <edit name="embeddedbitmap" mode="assign">
      <bool>false</bool>
    </edit>
  </match>

  <!-- Use Noto Thai Serif for Thai -->
  <match>
    <test name="lang" compare="contains">
      <string>th</string>
    </test>
    <test name="family">
      <string>serif</string>
    </test>
    <edit name="family" mode="prepend">
      <string>Noto Serif Thai</string>
    </edit>
  </match>
  <match>
    <test name="lang" compare="contains">
      <string>th</string>
    </test>
    <test name="family">
      <string>sans-serif</string>
    </test>
    <edit name="family" mode="prepend">
      <string>Noto Serif Thai</string>
    </edit>
  </match>
</fontconfig>


================================================
FILE: config/foot/foot.ini
================================================
[main]
# Fonts
font=Noto Sans Mono Light:size=11,Arundina Sans Mono:size=17
font-bold=Noto Sans Mono Light:size=11
font-italic=Noto Sans Mono Light:size=11:slant=italic
font-bold-italic=Noto Sans Mono Light:size=11:slant=italic

# Fonts fine-tuning
vertical-letter-offset=-1
line-height=13
underline-thickness=0.6
underline-offset=2

# Styling
bold-text-in-bright=palette-based
pad=24x24 center
initial-window-size-chars=80x30
resize-by-cells=no

# Misc
term=xterm
locked-title=yes
selection-target=both
workers=0
utmp-helper=none

# Colors
gamma-correct-blending=false

[bell]
urgent=yes

[scrollback]
lines=1000

[cursor]
beam-thickness=1.0

[mouse]
hide-when-typing=yes

[key-bindings]
clipboard-paste=Control+v Control+Shift+v
scrollback-up-page=none
scrollback-down-page=none
scrollback-up-half-page=Shift+Page_Up
scrollback-down-half-page=Shift+Page_Down
scrollback-up-line=Shift+Up
scrollback-down-line=Shift+Down

[mouse-bindings]
primary-paste=none

[tweak]
scaling-filter=none
font-monospace-warn=no
grapheme-width-method=wcswidth  # necessary to make emoji not too wide

grapheme-shaping=no
sixel=no

[colors]
cursor=${bg} ${fg_half_dim}

background=${bg}
foreground=${fg}

selection-foreground=${fg}
selection-background=${bg_sel}

regular0=${bg}
regular1=${red}
regular2=${green}
regular3=${yellow}
regular4=${blue}
regular5=${purple}
regular6=${cyan}
regular7=${fg_half_dim}

bright0=${fg_dim}
bright1=${orange}
bright2=${green}
bright3=${yellow}
bright4=${blue}
bright5=${pink}
bright6=${cyan}
bright7=${fg}

dim0=${fg_dim}
dim1=${orange}
dim2=${green}
dim3=${yellow}
dim4=${blue}
dim5=${pink}
dim6=${cyan}
dim7=${fg}


================================================
FILE: config/fuzzel/fuzzel.ini
================================================
font = Noto Sans Mono Light:pixelsize=18
prompt = ""
icons-enabled = no
lines = 8
width = 50
horizontal-pad = 24
vertical-pad = 24
anchor = top
y-margin = 75
inner-pad = 16
line-height = 24

[colors]
background = ${bg_dim_more}ff
text = ${fg_half_dim}ff
prompt = ff0000ff
placeholder = ff0000ff
input = ${blue}ff
match = ${purple}ff
selection = ${bg_dim_more}ff
selection-text = ${blue}ff
selection-match = ${purple}ff
border = ${bg_dim_more}ff

[border]
width = 1
radius = 24


================================================
FILE: config/git/config
================================================
[user]
    name = Denis Gruzdev
    email = codingjerk@gmail.com
    signingkey = E3DFEC736900FDE2

[commit]
    gpgSign = true
    template = ~/.config/git/template
    verbose = true  # add more context to commit messages

[core]
    autocrlf = input  # keep newlines as in input
    compression = 9  # trade cpu for network
    fsync = none
    whitespace = error  # threat incorrect whitespace as errors
    preloadindex = true  # preload index for faster status

[advice]  # disable advices
    addEmptyPathspec = false
    pushNonFastForward = false
    statusHints = false

[blame]
    coloring = highlightRecent
    date = relative

[diff]
    context = 3  # less context in diffs
    renames = copies  # detect copies as renames in diffs
    interHunkContext = 10  # merge near hunks in diffs

[init]
    defaultBranch = dev

[log]
    abbrevCommit = true  # short commits
    graphColors  = blue,yellow,cyan,magenta,green,red

[status]
    branch = true
    short = true
    showStash = true
    showUntrackedFiles = all  # show individual untracked files

[pager]
    branch = false  # no need to use pager for git branch
    tag = false
    diff = diff-so-fancy | $PAGER  # diff-so-fancy as diff pager

[push]
    autoSetupRemote = true  # easier to push new branches
    default = current  # push only current branch by default
    followTags = true  # push also tags
    gpgSign = false  # my remotes doesn't support sign pushes

[pull]
    rebase = true
    default = current

[submodule]
    fetchJobs = 16

[rebase]
    autoStash = true
    missingCommitsCheck = warn  # warn if rebasing with missing commits

[pack]
    threads = 0  # use all available threads
    windowMemory = 1g  # use 1g of memory for pack window
    packSizeLimit = 1g  # max size of a packfile

# Integrity
[transfer]
    fsckObjects = true

[receive]
    fsckObjects = true

[fetch]
    fsckObjects = true

[branch]
    sort = -committerdate

[tag]
    sort = -taggerdate

# Colors
[color "blame"]
    highlightRecent = black bold,1 year ago,white,1 month ago,default,7 days ago,blue

[color "branch"]
    current  = magenta
    local    = default
    remote   = yellow
    upstream = green
    plain    = blue

[color "diff"]
    meta       = black bold
    frag       = magenta
    context    = white
    whitespace = yellow reverse
    old        = red

[color.decorate]
    HEAD = red
    branch = blue
    tag = yellow
    remoteBranch = magenta

[interactive]
    diffFilter = diff-so-fancy --patch
    singlekey = true

# Third-party: diff-so-fancy
[diff-so-fancy]
    markEmptyLines = false

# URL shortcuts
[url "git@github.com:"]
    insteadOf = "gh:"

[url "git@github.com:codingjerk/"]
    insteadOf = "cj:"

[url "ssh://git@git.qrator.net:2202/"]
    insteadOf = "qrator:"

[url "ssh://git@git.qrator.net:2202/radar/"]
    insteadOf = "radar:"


================================================
FILE: config/git/ignore
================================================
# Python specific
.venv/
.mypy_cache/
.pytest_cache/
__pycache__/
.hypothesis/
.ruff_cache/
.ropeproject/

# Rust specific
target/

# Zig specific
.zig-cache/
zig-out/


================================================
FILE: config/git/template
================================================
# feat: ✨ 
# feat: 🔍 
# feat: 🔗 
# feat: 🔒 

# fix: 🐛 
# fix: 🐞 
# fix: 🩹 
# fix: 🚑️ 

# style: 💅 
# style: 🎨 
# style: 💄 

# ci: 🦊 
# ci: 📦 

# deploy: 🚀 
# deploy: 📦 

# chore: 🧹 
# chore: 🔧 
# chore: ⚙️ 
# docs: 📜 

# refactor: 🔨 
# perf: 🚀 

# test: 🚦 
# debug: 🧪 

# BREAKING CHANGE: 🚨 
# BREAKING CHANGE: 💥 
# BREAKING CHANGE: 💣 


================================================
FILE: config/gnupg/gpg-agent.conf
================================================
default-cache-ttl 1800  # 30 minutes

# Ask for password in nicer menu
pinentry-program /usr/bin/pinentry-tty


================================================
FILE: config/gnupg/gpg.conf
================================================
no-greeting
charset utf-8

keyserver https://keys.openpgp.org
keyserver https://keyserver.ubuntu.com
keyserver https://pgp.mit.edu


================================================
FILE: config/helix/config.toml
================================================
theme = "cj"

[editor]
  auto-save = false  # pretty annoying
  auto-pairs = false  # too annoying sometimes
  mouse = false  # I don't have mouse
  cursorline = true
  idle-timeout = 250
  completion-timeout = 5  # instant autocompletion
  completion-trigger-len = 1  # minimal length for autocompletion
  true-color = true  # force true color support
  color-modes = true  # use color to show modes
  jump-label-alphabet = "asdfzxcqwervtgbyhnujmikolp"
  rulers = [ 80, 120 ]
  end-of-line-diagnostics = "hint"

[editor.cursor-shape]
  insert = "bar"

[editor.file-picker]
  hidden = false  # show files starting with dot

[editor.gutters.line-numbers]
  min-width = 2

# TODO: enable similar line for rulers
# WATCH: https://github.com/helix-editor/helix/issues/5190
[editor.indent-guides]
  render = true
  character = "¦"  # "🭲" is okay too
  skip-levels = 1

[editor.search]
  wrap-around = false  # easier to navigate through matches

# TODO: disable cmdline / maybe statusline
# WATCH: https://github.com/helix-editor/helix/issues/1662
[editor.statusline]
  left = [ "mode", "read-only-indicator" ]
  center = []
  right = [ "diagnostics" ]
  mode.normal = " "
  mode.insert = "I"
  mode.select = "S"

[editor.whitespace.render]
  tab = "all"
  nbsp = "all"

[editor.whitespace.characters]
  nbsp = "⍽"

[keys.normal]
  # WASD movements
  w = "move_line_up"
  a = "move_char_left"
  s = "move_line_down"
  d = "move_char_right"

  W = ["move_line_up", "move_line_up", "move_line_up", "move_line_up", "move_line_up"]
  A = "move_prev_word_end"
  S = ["move_line_down", "move_line_down", "move_line_down", "move_line_down", "move_line_down"]
  D = "move_next_word_start"

  q = "extend_to_line_start"
  e = "extend_to_line_end"
  Q = "insert_at_line_start"
  E = "insert_at_line_end"

  # Bash-like C-a / C-e
  C-a = "goto_line_start"
  C-e = "goto_line_end"

  # Multiple cursors
  C-s = "select_regex"
  C-d = ["search_selection", "extend_search_next"]
  l = "split_selection_on_newline"

  # Command palette
  "C-p" = "command_palette"

  # Search
  "?" = "global_search"

  # Rebind missing actions
  x = "delete_selection"
  v = "extend_line_below"
  V = "select_mode"

  # Jump back / forward
  "j" = "jump_backward"
  "J" = "jump_forward"

  # Help
  "h" = "hover"

[keys.insert]
  # Bash-like C-a / C-e
  C-a = "goto_line_start"
  C-e = "goto_line_end_newline"

  # Insert tab character
  C-t = "insert_tab"

  # Command palette
  "C-p" = "command_palette"

[keys.select]
  # WASD movements
  w = "extend_line_up"
  a = "extend_char_left"
  s = "extend_line_down"
  d = "extend_char_right"

  W = "extend_line_up"
  A = "extend_prev_word_end"
  S = "extend_line_down"
  D = "extend_next_word_start"

  q = "extend_to_line_start"
  e = "extend_to_line_end"
  Q = "extend_to_line_start"
  E = "extend_to_line_end"

  # Bash-like C-a / C-e
  C-a = "goto_line_start"
  C-e = "goto_line_end"

  # Multiple cursors
  C-s = "select_regex"
  C-d = ["search_selection", "extend_search_next"]
  l = "split_selection_on_newline"

  # Command palette
  "C-p" = "command_palette"

  # Search
  "?" = "global_search"

  # Rebind missing actions
  x = "delete_selection"


================================================
FILE: config/helix/ignore
================================================
# Home directories
.cache/
.password-store/
.cargo/registry/
.npm/

*.tdb

# Git specific
.git-crypt/

# Python specific
.pyenv/
.venv/

# Rust specific
Cargo.lock
target/

# Zig specific
.zig-cache/
zig-out/


================================================
FILE: config/helix/languages.toml
================================================
# Source: https://github.com/estin/simple-completion-language-server
# Build: `cargo build --release`
[language-server.buffer]
  command = "${home}/dev/simple-completion-language-server/target/release/simple-completion-language-server"

  [language-server.buffer.config]
    max_completion_items = 500
    feature_snippets = false
    feature_unicode_input = false

# Source: https://github.com/vlabo/cspell-lsp
# Build: `npm install; npm run build`
[language-server.cspell]
  command = "node"
  args = [ "${home}/dev/cspell-lsp/index.js", "--stdio" ]

# Install: ruff-lsp
[language-server.ruff]
  command = "ruff-lsp"

# Install: pyright
[language-server.pyright]
  command = "pyright-langserver"

  [language-server.pyright.config.python.analysis]
    typeCheckingMode = "strict"

  [language-server.pyright.config.python.analysis.diagnosticSeverityOverrides]
    reportMissingImports = false
    reportMissingTypeStubs = false
    reportUntypedFunctionDecorator = false
    reportUnknownVariableType = false

    # Covered by ruff
    reportUnusedImport = false

# Install: python-lsp-server, python-rope, python-pylsp-mypy
[language-server.pylsp]
  command = "pylsp"

  [language-server.pylsp.config.pylsp.plugins]
    # Disable unused plugins
    autopep8.enabled = false
    flake8.enabled = false
    mccabe.enabled = false
    preload.enabled = false
    pycodestyle.enabled = false
    pyflakes.enabled = false
    yapf.enabled = false

    # Settings
    [language-server.pylsp.config.pylsp.plugins.jedi_completion]
      include_params = false
      fuzzy = true
      resolve_at_most = 100

[language-server.zls]
  command = "zls"

  [language-server.zls.config]
    enable_autofix = true
    enable_inlay_hints = false
    enable_argument_placeholders = false
    warn_style = true

[language-server.rust-analyzer]
  command = "${home}/.cargo/bin/ra-multiplex"

  [language-server.rust-analyzer.config]
    cachePriming.enable = false
    completion.callable.snippets = "none"
    completion.fullFunctionSignatures.enable = false  # make list shorter
    completion.limit = 1024
    completion.postfix.enable = false  # disable postfix snippets
    completion.hideDeprecated = true

    imports.preferNoStd = true

    hover.actions.run.enable = false
    hover.show.fields = 10

    inlayHints.chainingHints.enable = false
    inlayHints.closingBraceHints.enable = false
    inlayHints.genericParameterHints.const.enable = false
    inlayHints.typeHints.enable = false
    inlayHints.parameterHints.enable = false
    inlayHints.renderColons = false

    lens.enable = false

    lru.capacity = 512

    diagnostics.experimental.enable = true
    diagnostics.styleLints.enable = true

    check.command = "clippy"

    # Use separate target directory for rust-analyzer to remove interferences with cargo
    cargo.targetDir = true

    cargo.allTargets = false

    rustfmt.extraArgs = [
      "--config=empty_item_single_line=false",
      "--config=wrap_comments=true",
      "--config=condense_wildcard_suffixes=true",
      "--config=enum_discrim_align_threshold=10",
      "--config=format_code_in_doc_comments=true",
      "--config=hex_literal_case=Upper",
      "--config=max_width=80",
      "--config=reorder_impl_items=true",
      "--config=group_imports=StdExternalCrate",
      "--config=use_field_init_shorthand=true",
    ]

[[language]]
  name = "python"
  auto-format = true
  language-servers = [
    # Completions, documentation, go to definition
    { name = "pylsp", except-features = [ "diagnostics", "format" ] },
    # Linting, fixes, formatting
    "ruff",
    # Type checking
    { name = "pyright", only-features = [ "diagnostics" ] },
    "buffer",
    "cspell",
  ]

[[language]]
  name = "bash"
  # Install: bash-language-server
  language-servers = [ "bash-language-server", "buffer", "cspell" ]

[[language]]
  name = "dockerfile"
  # Install: dockerfile-language-server (aur)
  language-servers = [ "docker-langserver", "buffer", "cspell" ]

[[language]]
  name = "markdown"
  # Install: marksman
  language-servers = [ "marksman", "buffer", "cspell" ]
  roots = ["README.md"]

[[language]]
  name = "yaml"
  language-servers = [ "buffer", "cspell" ]

[[language]]
  name = "html"
  language-servers = [ "buffer", "cspell" ]

[[language]]
  name = "toml"
  language-servers = [ "buffer", "cspell" ]

[[language]]
  name = "git-commit"
  rulers = []
  language-servers = [ "buffer", "cspell" ]

[[language]]
  name = "zig"
  # Install: zls
  language-servers = [ "zls", "buffer", "cspell" ]

[[language]]
  name = "rust"
  # Install: rust-analyzer, ra-multiplex
  language-servers = [ "rust-analyzer", "buffer", "cspell" ]


================================================
FILE: config/helix/theme.toml
================================================
# Syntax
"comment" = "fg-dim"

"type" = "fg-half-dim"
"constructor" = "yellow"

"constant.numeric" = "yellow"
"constant.builtin" = "orange"

"string" = "green"
"constant.character.escape" = "pink"
"string.special" = "green"

"variable.builtin" = "orange"
"variable.parameter" = "cyan"

"function" = "purple"
"function.method" = "fg"
"function.builtin" = "orange"

"punctuation" = "fg-half-dim"
"punctuation.bracket" = "fg-dim"
"punctuation.special" = "pink"
"operator" = "fg-dim"
"label" = "fg-dim"

"keyword" = "blue"
"namespace" = "fg"

"markup.heading" = "orange"
"markup.list" = "fg-dim"
"markup.list.unchecked" = "red"
"markup.bold" = "red"
"markup.italic" = { modifiers = ["italic"] }
"markup.strikethrough" = { modifiers = ["crossed_out"] }
"markup.link.url" = { underline.style = "line" }
"markup.quote" = "fg-half-dim"
"markup.raw.inline" = "yellow"

"special" = "blue"  # also, highlight in file picker

# HTML
"attribute" = "yellow"
"string.regexp" = "pink"
"tag" = "purple"

# Diff
"diff.plus" = "green"
"diff.minus" = "red"
"diff.delta" = "purple"

# Background
"ui.background" = { bg = "bg", fg = "fg" }

# Cursor
"ui.cursor" = { bg = "fg-dim", fg = "bg" }
"ui.selection" = { bg = "bg-sel" }
"ui.cursor.match" = { fg = "purple", underline.style = "line" }
"ui.cursorline.primary" = { bg = "bg-dim" }

# Gutter
"ui.linenr" = "fg-dim"
"ui.linenr.selected" = "fg"

"error" = "red"
"warning" = "orange"
"info" = "yellow"  # for TODO highlighting
"hint" = "gray"

# Diagnostics
"diagnostic.error" = { fg = "red", underline.style = "line" }
"diagnostic.warning" = { fg = "orange", underline.style = "line" }
"diagnostic.info" = { underline.style = "line" }
"diagnostic.hint" = { underline.style = "line" }

# Statusline
"ui.statusline" = { fg = "fg" }
"ui.statusline.insert" = { bg = "yellow", fg = "bg" }
"ui.statusline.select" = { bg = "purple", fg = "bg" }

# Whitespace
"ui.virtual.whitespace" = "red"
"ui.virtual.indent-guide" = "bg-sel"
"ui.virtual.ruler" = { bg = "bg-sel" }

# Windows & Popups
"ui.popup" = { bg = "bg-dim", fg = "fg-half-dim" }
"ui.popup.info" = { bg = "bg", fg = "fg-half-dim" }
"ui.window" = { fg = "fg-dim" }
"ui.help" = { fg = "fg-half-dim", bg = "bg-dim" }

"ui.text" = "fg"
"ui.text.focus" = { fg = "fg", bg = "bg-sel" }
"ui.text.inactive" = "fg-dim"

"ui.menu" = { fg = "fg-half-dim", bg = "bg-dim" }
"ui.menu.selected" = { fg = "fg", bg = "bg-sel" }
"ui.menu.scroll" = { bg = "bg-sel", fg = "bg-sel" }

"ui.highlight" = { bg = "bg-dim" }  # highlight in file picker

# Jump labels
"ui.virtual.jump-label" = { fg = "yellow", modifiers = [ "reversed" ] }

[palette]
  bg          = "#${bg}"
  bg-dim      = "#${bg_dim}"  # panels, line highlighting
  bg-sel      = "#${bg_sel}"  # selection

  fg          = "#${fg}"
  fg-half-dim = "#${fg_half_dim}"  # some menus
  fg-dim      = "#${fg_dim}"       # comments

  red         = "#${red}"     # errors, important stuff
  orange      = "#${orange}"  # warnings, less important stuff
  yellow      = "#${yellow}"  # highlighting
  green       = "#${green}"   # strings, good stuff
  cyan        = "#${cyan}"    # arguments
  blue        = "#${blue}"    # keywords
  purple      = "#${purple}"  # functions and tags
  pink        = "#${pink}"    # string interpolation, regexps


================================================
FILE: config/htop/htoprc
================================================
# Beware! This file is rewritten by htop when settings are changed in the interface.
# The parser is also very primitive, and not human-friendly.
htop_version=3.3.0
config_reader_min_version=3
fields=48 39 46 1
hide_kernel_threads=1
hide_userland_threads=1
hide_running_in_container=0
shadow_other_users=0
show_thread_names=0
show_program_path=0
highlight_base_name=1
highlight_deleted_exe=1
shadow_distribution_path_prefix=0
highlight_megabytes=1
highlight_threads=0
highlight_changes=1
highlight_changes_delay_secs=5
find_comm_in_cmdline=0
strip_exe_from_cmdline=0
show_merged_command=0
header_margin=0
screen_tabs=1
detailed_cpu_time=0
cpu_count_from_one=1
show_cpu_usage=1
show_cpu_frequency=0
show_cpu_temperature=0
degree_fahrenheit=0
update_process_names=0
account_guest_in_cpu_meter=0
color_scheme=0
enable_mouse=1
delay=50
hide_function_bar=2
header_layout=two_67_33
column_meters_0=AllCPUs4
column_meter_modes_0=1
column_meters_1=Memory Swap Tasks DiskIO NetworkIO
column_meter_modes_1=1 1 2 2 2
tree_view=0
sort_key=46
tree_sort_key=0
sort_direction=-1
tree_sort_direction=1
tree_view_always_by_pid=0
all_branches_collapsed=0
screen:Main=USER M_RESIDENT PERCENT_CPU Command
.sort_key=PERCENT_CPU
.tree_sort_key=PID
.tree_view_always_by_pid=0
.tree_view=0
.sort_direction=-1
.tree_sort_direction=1
.all_branches_collapsed=0
screen:More=PID USER STATE ELAPSED UTIME STIME NICE IO_PRIORITY M_RESIDENT M_SHARE IO_RATE IO_READ_RATE IO_WRITE_RATE Command
.sort_key=IO_RATE
.tree_sort_key=PID
.tree_view_always_by_pid=0
.tree_view=0
.sort_direction=-1
.tree_sort_direction=1
.all_branches_collapsed=0


================================================
FILE: config/hypr/hypridle.conf
================================================
general {
  lock_cmd = pidof hyprlock || hyprlock
}

# Lock the screen after inactivity
listener {
  timeout = 600  # 10 minutes
  on-timeout = pidof hyprlock || loginctl lock-session
}

# Turn off monitor faster when it's locked
listener {
  timeout = 15
  on-timeout = pidof hyprlock && niri msg action power-off-monitors
}



================================================
FILE: config/hypr/hyprland.conf
================================================
monitor=eDP-1,preferred,auto,auto

ecosystem {
  no_update_news = true
  no_donation_nag = true
}

misc {
  vrr = 1
  vfr = true

  enable_swallow = true
  swallow_regex = ^(footclient)$

  disable_hyprland_logo = true
  disable_splash_rendering = true
  force_default_wallpaper = 0
  disable_autoreload = true
  background_color = rgb(000000)

  mouse_move_enables_dpms = false
  key_press_enables_dpms = true
  focus_on_activate = false

  # Discard fullscreen on new window
  new_window_takes_over_fullscreen = 2

  # Keep special workspace open after closing last window
  close_special_on_empty = false

  # I often missclick middle button on my touchpad
  middle_click_paste = false
}

xwayland {
  # Disable scaling for xwayland applications
  force_zero_scaling = true
}

debug {
  # Disable watchdog
  watchdog_timeout = 0
}

group {
  groupbar {
    enabled = true

    gradients = false
    render_titles = false
    height = 2

    col.active = rgba(${bg}A0)
    col.inactive = rgba(${fg_dim}70)
  }
}

# Startup
exec-once = swaybg --image ${repo}/wallpaper.png --mode fill
exec-once = waybar
exec-once = hypridle
exec-once = foot --server --log-level=none
exec-once = hyprctl setcursor capitaine-cursors-light 32

# Environment variables

env = XCURSOR_THEME, capitaine-cursors-light
env = XCURSOR_SIZE, 32
env = GDK_SCALE, 2
env = QT_WAYLAND_DISABLE_WINDOWDECORATION, 1

# Hotkeys: windows
bind = SUPER, W, movefocus, u
bind = SUPER, A, movefocus, l
bind = SUPER, S, movefocus, d
bind = SUPER, D, movefocus, r

bind = SUPER SHIFT, W, movewindow, u
bind = SUPER SHIFT, A, movewindow, l
bind = SUPER SHIFT, S, movewindow, d
bind = SUPER SHIFT, D, movewindow, r

bind = SUPER, V, togglefloating,
bind = SUPER, P, pseudo,
bind = SUPER SHIFT, P, pin,
bind = SUPER, T, togglesplit,
bind = SUPER, U, focusurgentorlast,
bind = SUPER, Q, killactive,

# Hide waybar
bind = SUPER, M, exec, killall -SIGUSR1 waybar

# Hotkeys: groups
bind = SUPER, G, togglegroup,
bind = SUPER SHIFT, G, moveoutofgroup

bind = SUPER, X, changegroupactive, f
bind = SUPER SHIFT, X, changegroupactive, b

# Hotkeys: fullscreen
bind = SUPER, F, fullscreen,
bind = SUPER ALT, F, fullscreenstate, 1  # maximize with gaps
bind = SUPER SHIFT, F, fullscreenstate, 2  # maximize without gaps

# Hotkeys: workspaces
bind = SUPER, 1, workspace, 1
bind = SUPER, 2, workspace, 2
bind = SUPER, 3, workspace, 3
bind = SUPER, 4, workspace, 4
bind = SUPER, 5, workspace, 5
bind = SUPER, 6, workspace, 6
bind = SUPER, 7, workspace, 7
bind = SUPER, 8, workspace, 8
bind = SUPER, 9, workspace, 9
bind = SUPER, 0, workspace, 10

bind = SUPER SHIFT, 1, movetoworkspace, 1
bind = SUPER SHIFT, 2, movetoworkspace, 2
bind = SUPER SHIFT, 3, movetoworkspace, 3
bind = SUPER SHIFT, 4, movetoworkspace, 4
bind = SUPER SHIFT, 5, movetoworkspace, 5
bind = SUPER SHIFT, 6, movetoworkspace, 6
bind = SUPER SHIFT, 7, movetoworkspace, 7
bind = SUPER SHIFT, 8, movetoworkspace, 8
bind = SUPER SHIFT, 9, movetoworkspace, 9
bind = SUPER SHIFT, 0, movetoworkspace, 10

# Hotkeys: scratchpads
bind = SUPER, TAB, togglespecialworkspace, magicTab
bind = SUPER, E, togglespecialworkspace, magicE
bind = SUPER, C, togglespecialworkspace, magicC

bind = SUPER SHIFT, TAB, movetoworkspacesilent, special:magicTab
bind = SUPER SHIFT, E, movetoworkspacesilent, special:magicE
bind = SUPER SHIFT, C, movetoworkspacesilent, special:magicC

# Hotkeys: applications
bind = SUPER, R, exec, wofi
bind = SUPER, J, exec, footclient
bind = SUPER SHIFT, B, exec, google-chrome-unstable
bind = SUPER, B, exec, google-chrome-unstable --new-window 'https://www.google.com'

bind = SUPER ALT, E, exec, wofi-emoji
bind = SUPER ALT, C, exec, wl-color-picker

# Hotkeys: hyprland
bind = SUPER ALT, R, exec, hyprctl reload
bind = SUPER ALT, X, exec, pkill Hyprland
bind = SUPER, N, exec, makoctl dismiss --all

# Hotkeys: zoom
bind = SUPER, Z, exec, hyprctl keyword cursor:zoom_factor 4
bind = SUPER SHIFT, Z, exec, hyprctl keyword cursor:zoom_factor 1

# Hotkeys: media
bindl = , XF86AudioMute, exec, wpctl set-mute @DEFAULT_SINK@ toggle
bindle = , XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_SINK@ 5%-
bindle = , XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_SINK@ 5%+
bindl = , XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_SOURCE@ toggle

bindl = , XF86MonBrightnessDown, exec, brightnessctl -e set 5%-
bindl = , XF86MonBrightnessUp, exec, brightnessctl -e set 5%+

bindl = , Print, exec, slurp -b ${fg_dim}20 -c ${fg_dim}30 -w 1 | grim -g - - | wl-copy
bind = SHIFT, Print, exec, slurp -b ${fg_dim}20 -c ${fg_dim}30 -w 1 | grim -g - - | satty --filename=- --init-tool=rectangle
bind = ALT, Print, exec, grim - | satty --filename=- --init-tool=rectangle

# Mouse bindings
bindm = SUPER, mouse:272, movewindow  # Left button
bindm = SUPER, mouse:273, resizewindow  # Right button

# Locking / DPMS
bind = SUPER, L, exec, hyprlock
bindlr = SUPER SHIFT, L, exec, systemctl suspend
bindlr = SUPER, K, exec, sleep 0.5; hyprctl dispatch dpms off

# HACK: looks like my laptop sends wrong events on lid off / on
bindl = , switch:off:Lid Switch, dpms, on
bindl = , switch:on:Lid Switch, dpms, off

# OBS
bind = , F1, pass, class:^(com\.obsproject\.Studio)$
bind = , F2, pass, class:^(com\.obsproject\.Studio)$

input {
  kb_layout = us,ru
  kb_variant =
  kb_model =
  kb_options = grp:caps_toggle,grp_led:caps,compose:ralt
  kb_rules =

  repeat_rate = 15
  # 200 is too low for typing, cause in some cases
  # I just get repeated letters for no reason
  repeat_delay = 300

  follow_mouse = 1

  # Allow to use windows under special workspace
  special_fallthrough = true

  # Makes me use keyboard
  sensitivity = 0.25

  touchpad {
    natural_scroll = true
    scroll_factor = 0.15
  }
}

dwindle {
  pseudotile = true
  preserve_split = true  # allow to manually select split direction
  force_split = 2  # always split to right or bottom
}

animations {
  enabled = true
  first_launch_animation = false

  bezier=overshot,0.5,0.1,0.4,1.2

  animation = global, 1, 3, default
  animation = workspaces, 1, 4, default
  animation = windowsMove, 1, 2, default
  animation = fade, 1, 2, default
}

# Allow sliding animation for notifications
layerrule = animation slide, notifications

general {
    gaps_in = 12
    gaps_out = 24
    border_size = 0

    layout = dwindle
    allow_tearing = false

}

decoration {
  rounding = 24

  blur {
    enabled = false
  }

  shadow {
    enabled = true
    range = 16
    render_power = 3
    offset = 2 2
    color = rgba(${bg_dim}A0)
    color_inactive = rgba(${bg_dim}70)
  }

  dim_special = 0.35
}

gestures {
  workspace_swipe = false
}


================================================
FILE: config/hypr/hyprlock.conf
================================================
general {
  disable_loading_bar = false
  hide_cursor = true
  ignore_empty_input = true
}

background {
  path = ${repo}/wallpaper.png
}

input-field {
  size = 500, 75
  position = 0, 0

  fade_on_empty = true
  dots_size = 0.2
  dots_spacing = 0.5
  outline_thickness = 3
  placeholder_text =
  fail_text =

  outer_color = rgb(${bg})
  inner_color = rgb(${bg})
  font_color = rgb(${fg})
  check_color = rgb(${blue})
  fail_color = rgb(${red})
  capslock_color = rgb(${orange})

  shadow_passes = 1
  shadow_size = 8
  shadow_boost = 0.6
}

label {
  text = cmd[update:60000] TZ=Asia/Bangkok date "+%H:%M"
  position = 150, 250

  color = rgba(${blue}90)

  font_size = 120
  font_family = Noto Sans Mono Thin

  shadow_passes = 1
  shadow_size = 6
  shadow_boost = 0.75
}

label {
  text = cmd[update:60000] TZ=Asia/Bangkok TZ=Asia/Bangkok date "+%e %B, %A"
  position = 150, 150

  color = rgba(${blue}70)

  font_size = 40
  font_family = Noto Sans Mono Light

  shadow_passes = 1
  shadow_size = 4
  shadow_boost = 0.9
}


================================================
FILE: config/ipython/ipython_config.py
================================================
# No banner
c.TerminalIPythonApp.display_banner = False

# No exception tracebacks
c.InteractiveShell.xmode = "minimal"

# Do not confirm on exit
c.TerminalInteractiveShell.confirm_exit = False

# Useful DS/ML libraries
c.InteractiveShellApp.exec_lines = [
    "import matplotlib.pyplot as plt",
    "import numpy as np",
    "import pandas as pd",
    "import scipy as scp",
    "from pylab import plot",
    "%matplotlib",
    "%load_ext autoreload",
    "%autoreload 2",
]


================================================
FILE: config/ledger/ledgerrc
================================================
--file ~/.ledger/journal.ldg
--no-pager


================================================
FILE: config/less/lesskey
================================================
#command
w back-line
W back-screen

s forw-line
S forw-screen

a left-scroll
d right-scroll


================================================
FILE: config/mako/config
================================================
font=Noto Sans Mono Light 11

max-history=0
ignore-timeout=1
max-visible=-1

width=450
height=200
anchor=top-right
outer-margin=0
margin=12
padding=24
format=%s\n%b

background-color=#${bg}
text-color=#${fg}

border-radius=16
border-size=0


================================================
FILE: config/matplotlib/matplotlibrc
================================================
#### MATPLOTLIBRC FORMAT

## NOTE FOR END USERS: DO NOT EDIT THIS FILE!
##
## This is a sample Matplotlib configuration file - you can find a copy
## of it on your system in site-packages/matplotlib/mpl-data/matplotlibrc
## (relative to your Python installation location).
##
## You should find a copy of it on your system at
## site-packages/matplotlib/mpl-data/matplotlibrc (relative to your Python
## installation location).  DO NOT EDIT IT!
##
## If you wish to change your default style, copy this file to one of the
## following locations:
##     Unix/Linux:
##         $HOME/.config/matplotlib/matplotlibrc OR
##         $XDG_CONFIG_HOME/matplotlib/matplotlibrc (if $XDG_CONFIG_HOME is set)
##     Other platforms:
##         $HOME/.matplotlib/matplotlibrc
## and edit that copy.
##
## See https://matplotlib.org/users/customizing.html#the-matplotlibrc-file
## for more details on the paths which are checked for the configuration file.
##
## Blank lines, or lines starting with a comment symbol, are ignored, as are
## trailing comments.  Other lines must have the format:
##     key: val  # optional comment
##
## Formatting: Use PEP8-like style (as enforced in the rest of the codebase).
## All lines start with an additional '#', so that removing all leading '#'s
## yields a valid style file.
##
## Colors: for the color values below, you can either use
##     - a Matplotlib color string, such as r, k, or b
##     - an RGB tuple, such as (1.0, 0.5, 0.0)
##     - a hex string, such as ff00ff
##     - a scalar grayscale intensity such as 0.75
##     - a legal html color name, e.g., red, blue, darkslategray
##
## Matplotlib configuration are currently divided into following parts:
##     - BACKENDS
##     - LINES
##     - PATCHES
##     - HATCHES
##     - BOXPLOT
##     - FONT
##     - TEXT
##     - LaTeX
##     - AXES
##     - DATES
##     - TICKS
##     - GRIDS
##     - LEGEND
##     - FIGURE
##     - IMAGES
##     - CONTOUR PLOTS
##     - ERRORBAR PLOTS
##     - HISTOGRAM PLOTS
##     - SCATTER PLOTS
##     - AGG RENDERING
##     - PATHS
##     - SAVING FIGURES
##     - INTERACTIVE KEYMAPS
##     - ANIMATION

##### CONFIGURATION BEGINS HERE


## ***************************************************************************
## * BACKENDS                                                                *
## ***************************************************************************
## The default backend.  If you omit this parameter, the first working
## backend from the following list is used:
##     MacOSX Qt5Agg Gtk3Agg TkAgg WxAgg Agg
## Other choices include:
##     Qt5Cairo GTK3Cairo TkCairo WxCairo Cairo
##     Qt4Agg Qt4Cairo Wx  # deprecated.
##     PS PDF SVG Template
## You can also deploy your own backend outside of Matplotlib by referring to
## the module name (which must be in the PYTHONPATH) as 'module://my_backend'.
#backend: Agg

## The port to use for the web server in the WebAgg backend.
#webagg.port: 8988

## The address on which the WebAgg web server should be reachable
#webagg.address: 127.0.0.1

## If webagg.port is unavailable, a number of other random ports will
## be tried until one that is available is found.
#webagg.port_retries: 50

## When True, open the web browser to the plot that is shown
#webagg.open_in_browser: True

## If you are running pyplot inside a GUI and your backend choice
## conflicts, we will automatically try to find a compatible one for
## you if backend_fallback is True
#backend_fallback: True

#interactive: False
#toolbar:     toolbar2  # {None, toolbar2, toolmanager}
#timezone:    UTC       # a pytz timezone string, e.g., US/Central or Europe/Paris


## ***************************************************************************
## * LINES                                                                   *
## ***************************************************************************
## See https://matplotlib.org/api/artist_api.html#module-matplotlib.lines
## for more information on line properties.
#lines.linewidth: 1.5               # line width in points
#lines.linestyle: -                 # solid line
#lines.color:     C0                # has no affect on plot(); see axes.prop_cycle
#lines.marker:          None        # the default marker
#lines.markerfacecolor: auto        # the default marker face color
#lines.markeredgecolor: auto        # the default marker edge color
#lines.markeredgewidth: 1.0         # the line width around the marker symbol
#lines.markersize:      6           # marker size, in points
#lines.dash_joinstyle:  round       # {miter, round, bevel}
#lines.dash_capstyle:   butt        # {butt, round, projecting}
#lines.solid_joinstyle: round       # {miter, round, bevel}
#lines.solid_capstyle:  projecting  # {butt, round, projecting}
#lines.antialiased: True            # render lines in antialiased (no jaggies)

## The three standard dash patterns.  These are scaled by the linewidth.
#lines.dashed_pattern: 3.7, 1.6
#lines.dashdot_pattern: 6.4, 1.6, 1, 1.6
#lines.dotted_pattern: 1, 1.65
#lines.scale_dashes: True

#markers.fillstyle: full  # {full, left, right, bottom, top, none}

#pcolor.shading : flat
#pcolormesh.snap : True  # Whether to snap the mesh to pixel boundaries. This
                         # is provided solely to allow old test images to remain
                         # unchanged. Set to False to obtain the previous behavior.

## ***************************************************************************
## * PATCHES                                                                 *
## ***************************************************************************
## Patches are graphical objects that fill 2D space, like polygons or circles.
## See https://matplotlib.org/api/artist_api.html#module-matplotlib.patches
## for more information on patch properties.
#patch.linewidth:       1      # edge width in points.
#patch.facecolor:       C0
#patch.edgecolor:       black  # if forced, or patch is not filled
#patch.force_edgecolor: False  # True to always use edgecolor
#patch.antialiased:     True   # render patches in antialiased (no jaggies)


## ***************************************************************************
## * HATCHES                                                                 *
## ***************************************************************************
#hatch.color:     black
#hatch.linewidth: 1.0


## ***************************************************************************
## * BOXPLOT                                                                 *
## ***************************************************************************
#boxplot.notch:       False
#boxplot.vertical:    True
#boxplot.whiskers:    1.5
#boxplot.bootstrap:   None
#boxplot.patchartist: False
#boxplot.showmeans:   False
#boxplot.showcaps:    True
#boxplot.showbox:     True
#boxplot.showfliers:  True
#boxplot.meanline:    False

boxplot.flierprops.color:            white
#boxplot.flierprops.marker:          o
#boxplot.flierprops.markerfacecolor: none
boxplot.flierprops.markeredgecolor:  817c9c 
#boxplot.flierprops.markeredgewidth: 1.0
#boxplot.flierprops.markersize:      6
#boxplot.flierprops.linestyle:       none
#boxplot.flierprops.linewidth:       1.0

boxplot.boxprops.color:      817c9c
#boxplot.boxprops.linewidth: 1.0
#boxplot.boxprops.linestyle: -

boxplot.whiskerprops.color:     817c9c
#boxplot.whiskerprops.linewidth: 1.0
#boxplot.whiskerprops.linestyle: -

boxplot.capprops.color:      817c9c
#boxplot.capprops.linewidth: 1.0
#boxplot.capprops.linestyle: -

boxplot.medianprops.color:      393552
#boxplot.medianprops.linewidth: 1.0
#boxplot.medianprops.linestyle: -

#boxplot.meanprops.color:           C2
#boxplot.meanprops.marker:          ^
#boxplot.meanprops.markerfacecolor: C2
#boxplot.meanprops.markeredgecolor: C2
#boxplot.meanprops.markersize:       6
#boxplot.meanprops.linestyle:       --
#boxplot.meanprops.linewidth:       1.0


## ***************************************************************************
## * FONT                                                                    *
## ***************************************************************************
## The font properties used by `text.Text`.
## See https://matplotlib.org/api/font_manager_api.html for more information
## on font properties.  The 6 font properties used for font matching are
## given below with their default values.
##
## The font.family property can take either a concrete font name (not supported
## when rendering text with usetex), or one of the following five generic
## values:
##     - 'serif' (e.g., Times),
##     - 'sans-serif' (e.g., Helvetica),
##     - 'cursive' (e.g., Zapf-Chancery),
##     - 'fantasy' (e.g., Western), and
##     - 'monospace' (e.g., Courier).
## Each of these values has a corresponding default list of font names
## (font.serif, etc.); the first available font in the list is used.  Note that
## for font.serif, font.sans-serif, and font.monospace, the first element of
## the list (a DejaVu font) will always be used because DejaVu is shipped with
## Matplotlib and is thus guaranteed to be available; the other entries are
## left as examples of other possible values.
##
## The font.style property has three values: normal (or roman), italic
## or oblique.  The oblique style will be used for italic, if it is not
## present.
##
## The font.variant property has two values: normal or small-caps.  For
## TrueType fonts, which are scalable fonts, small-caps is equivalent
## to using a font size of 'smaller', or about 83%% of the current font
## size.
##
## The font.weight property has effectively 13 values: normal, bold,
## bolder, lighter, 100, 200, 300, ..., 900.  Normal is the same as
## 400, and bold is 700.  bolder and lighter are relative values with
## respect to the current weight.
##
## The font.stretch property has 11 values: ultra-condensed,
## extra-condensed, condensed, semi-condensed, normal, semi-expanded,
## expanded, extra-expanded, ultra-expanded, wider, and narrower.  This
## property is not currently implemented.
##
## The font.size property is the default font size for text, given in points.
## 10 pt is the standard value.
##
## Note that font.size controls default text sizes.  To configure
## special text sizes tick labels, axes, labels, title, etc., see the rc
## settings for axes and ticks.  Special text sizes can be defined
## relative to font.size, using the following values: xx-small, x-small,
## small, medium, large, x-large, xx-large, larger, or smaller

#font.family:  sans-serif
#font.style:   normal
#font.variant: normal
#font.weight:  normal
#font.stretch: normal
font.size:    18.0

font.serif:      Source Code Pro, DejaVu Serif, Bitstream Vera Serif, Computer Modern Roman, New Century Schoolbook, Century Schoolbook L, Utopia, ITC Bookman, Bookman, Nimbus Roman No9 L, Times New Roman, Times, Palatino, Charter, serif
font.sans-serif: Source Code Pro, DejaVu Sans, Bitstream Vera Sans, Computer Modern Sans Serif, Lucida Grande, Verdana, Geneva, Lucid, Arial, Helvetica, Avant Garde, sans-serif
font.cursive:    Source Code Pro, Apple Chancery, Textile, Zapf Chancery, Sand, Script MT, Felipa, Comic Neue, Comic Sans MS, cursive
font.fantasy:    Source Code Pro, Chicago, Charcoal, Impact, Western, Humor Sans, xkcd, fantasy
font.monospace:  Source Code Pro, DejaVu Sans Mono, Bitstream Vera Sans Mono, Computer Modern Typewriter, Andale Mono, Nimbus Mono L, Courier New, Courier, Fixed, Terminal, monospace


## ***************************************************************************
## * TEXT                                                                    *
## ***************************************************************************
## The text properties used by `text.Text`.
## See https://matplotlib.org/api/artist_api.html#module-matplotlib.text
## for more information on text properties
text.color: e0def4


## ***************************************************************************
## * LaTeX                                                                   *
## ***************************************************************************
## For more information on LaTeX properties, see
## https://matplotlib.org/tutorials/text/usetex.html
#text.usetex: False  # use latex for all text handling. The following fonts
                     # are supported through the usual rc parameter settings:
                     # new century schoolbook, bookman, times, palatino,
                     # zapf chancery, charter, serif, sans-serif, helvetica,
                     # avant garde, courier, monospace, computer modern roman,
                     # computer modern sans serif, computer modern typewriter
                     # If another font is desired which can loaded using the
                     # LaTeX \usepackage command, please inquire at the
                     # Matplotlib mailing list
#text.latex.preamble:   # IMPROPER USE OF THIS FEATURE WILL LEAD TO LATEX FAILURES
                        # AND IS THEREFORE UNSUPPORTED. PLEASE DO NOT ASK FOR HELP
                        # IF THIS FEATURE DOES NOT DO WHAT YOU EXPECT IT TO.
                        # text.latex.preamble is a single line of LaTeX code that
                        # will be passed on to the LaTeX system. It may contain
                        # any code that is valid for the LaTeX "preamble", i.e.
                        # between the "\documentclass" and "\begin{document}"
                        # statements.
                        # Note that it has to be put on a single line, which may
                        # become quite long.
                        # The following packages are always loaded with usetex, so
                        # beware of package collisions: color, geometry, graphicx,
                        # type1cm, textcomp.
                        # Adobe Postscript (PSSNFS) font packages may also be
                        # loaded, depending on your font settings.

## FreeType hinting flag ("foo" corresponds to FT_LOAD_FOO); may be one of the
## following (Proprietary Matplotlib-specific synonyms are given in parentheses,
## but their use is discouraged):
## - default: Use the font's native hinter if possible, else FreeType's auto-hinter.
##            ("either" is a synonym).
## - no_autohint: Use the font's native hinter if possible, else don't hint.
##                ("native" is a synonym.)
## - force_autohint: Use FreeType's auto-hinter.  ("auto" is a synonym.)
## - no_hinting: Disable hinting.  ("none" is a synonym.)
#text.hinting: force_autohint

#text.hinting_factor: 8  # Specifies the amount of softness for hinting in the
                         # horizontal direction.  A value of 1 will hint to full
                         # pixels.  A value of 2 will hint to half pixels etc.
#text.kerning_factor : 0  # Specifies the scaling factor for kerning values. This
                          # is provided solely to allow old test images to remain
                          # unchanged. Set to 6 to obtain previous behavior. Values
                          # other than 0 or 6 have no defined meaning.
#text.antialiased: True  # If True (default), the text will be antialiased.
                         # This only affects raster outputs.

## The following settings allow you to select the fonts in math mode.
#mathtext.fontset: dejavusans  # Should be 'dejavusans' (default),
                               # 'dejavuserif', 'cm' (Computer Modern), 'stix',
                               # 'stixsans' or 'custom' (unsupported, may go
                               # away in the future)
## "mathtext.fontset: custom" is defined by the mathtext.bf, .cal, .it, ...
## settings which map a TeX font name to a fontconfig font pattern.  (These
## settings are not used for other font sets.)
#mathtext.bf:  sans:bold
#mathtext.cal: cursive
#mathtext.it:  sans:italic
#mathtext.rm:  sans
#mathtext.sf:  sans
#mathtext.tt:  monospace
#mathtext.fallback: cm  # Select fallback font from ['cm' (Computer Modern), 'stix'
                        # 'stixsans'] when a symbol can not be found in one of the
                        # custom math fonts. Select 'None' to not perform fallback
                        # and replace the missing character by a dummy symbol.
#mathtext.default: it  # The default font to use for math.
                       # Can be any of the LaTeX font names, including
                       # the special name "regular" for the same font
                       # used in regular text.


## ***************************************************************************
## * AXES                                                                    *
## ***************************************************************************
## Following are default face and edge colors, default tick sizes,
## default font sizes for tick labels, and so on.  See
## https://matplotlib.org/api/axes_api.html#module-matplotlib.axes
axes.facecolor:      232136  # axes background color
axes.edgecolor:      59546d  # axes edge color
#axes.linewidth:     0.8     # edge line width
axes.grid:           True    # display grid or not
axes.grid.axis:      y       # which axis the grid should apply to
#axes.grid.which:    major   # grid lines at {major, minor, both} ticks
#axes.titlelocation: center  # alignment of the title: {left, right, center}
#axes.titlesize:     large   # font size of the axes title
#axes.titleweight:   normal  # font weight of title
#axes.titlecolor:    auto    # color of the axes title, auto falls back to
                             # text.color as default value
#axes.titley:        None    # position title (axes relative units).  None implies auto
#axes.titlepad:      6.0     # pad between axes and title in points
#axes.labelsize:     medium  # font size of the x and y labels
#axes.labelpad:      4.0     # space between label and axis
#axes.labelweight:   normal  # weight of the x and y labels
axes.labelcolor:     817c9c
axes.axisbelow:      True    # draw axis gridlines and ticks:
                             #     - below patches (True)
                             #     - above patches but below lines ('line')
                             #     - above all (False)

#axes.formatter.limits: -5, 6  # use scientific notation if log10
                               # of the axis range is smaller than the
                               # first or larger than the second
#axes.formatter.use_locale: False  # When True, format tick labels
                                   # according to the user's locale.
                                   # For example, use ',' as a decimal
                                   # separator in the fr_FR locale.
#axes.formatter.use_mathtext: False  # When True, use mathtext for scientific
                                     # notation.
#axes.formatter.min_exponent: 0  # minimum exponent to format in scientific notation
#axes.formatter.useoffset: True  # If True, the tick label formatter
                                 # will default to labeling ticks relative
                                 # to an offset when the data range is
                                 # small compared to the minimum absolute
                                 # value of the data.
#axes.formatter.offset_threshold: 4  # When useoffset is True, the offset
                                     # will be used when it can remove
                                     # at least this number of significant
                                     # digits from tick labels.

axes.spines.left:   True  # display axis spines
axes.spines.bottom: True
axes.spines.top:    False 
axes.spines.right:  False

#axes.unicode_minus: True  # use Unicode for the minus symbol rather than hyphen.  See
                           # https://en.wikipedia.org/wiki/Plus_and_minus_signs#Character_codes
axes.prop_cycle: cycler('color', ['eb6f92', 'f6c177', 'ea9a97', '3e8fb0', '9ccfd8', 'c4a7e7'])
                  # color cycle for plot lines as list of string color specs:
                  # single letter, long name, or web-style hex
                  # As opposed to all other parameters in this file, the color
                  # values must be enclosed in quotes for this parameter,
                  # e.g. '1f77b4', instead of 1f77b4.
                  # See also https://matplotlib.org/tutorials/intermediate/color_cycle.html
                  # for more details on prop_cycle usage.
#axes.xmargin:   .05  # x margin.  See `axes.Axes.margins`
#axes.ymargin:   .05  # y margin.  See `axes.Axes.margins`
#axes.zmargin:   .05  # z margin.  See `axes.Axes.margins`
#axes.autolimit_mode: data  # If "data", use axes.xmargin and axes.ymargin as is.
                            # If "round_numbers", after application of margins, axis
                            # limits are further expanded to the nearest "round" number.
#polaraxes.grid: True  # display grid on polar axes
#axes3d.grid:    True  # display grid on 3D axes


## ***************************************************************************
## * AXIS                                                                    *
## ***************************************************************************
#xaxis.labellocation: center  # alignment of the xaxis label: {left, right, center}
#yaxis.labellocation: center  # alignment of the yaxis label: {bottom, top, center}


## ***************************************************************************
## * DATES                                                                   *
## ***************************************************************************
## These control the default format strings used in AutoDateFormatter.
## Any valid format datetime format string can be used (see the python
## `datetime` for details).  For example, by using:
##     - '%%x' will use the locale date representation
##     - '%%X' will use the locale time representation
##     - '%%c' will use the full locale datetime representation
## These values map to the scales:
##     {'year': 365, 'month': 30, 'day': 1, 'hour': 1/24, 'minute': 1 / (24 * 60)}

#date.autoformatter.year:        %Y
#date.autoformatter.month:       %Y-%m
#date.autoformatter.day:         %Y-%m-%d
#date.autoformatter.hour:        %m-%d %H
#date.autoformatter.minute:      %d %H:%M
#date.autoformatter.second:      %H:%M:%S
#date.autoformatter.microsecond: %M:%S.%f
## The reference date for Matplotlib's internal date representation
## See https://matplotlib.org/examples/ticks_and_spines/date_precision_and_epochs.py
#date.epoch: 1970-01-01T00:00:00
## 'auto', 'concise':
#date.converter:                  auto
## For auto converter whether to use interval_multiples:
#date.interval_multiples:         True

## ***************************************************************************
## * TICKS                                                                   *
## ***************************************************************************
## See https://matplotlib.org/api/axis_api.html#matplotlib.axis.Tick
#xtick.top:           False   # draw ticks on the top side
#xtick.bottom:        True    # draw ticks on the bottom side
#xtick.labeltop:      False   # draw label on the top
#xtick.labelbottom:   True    # draw label on the bottom
#xtick.major.size:    3.5     # major tick size in points
#xtick.minor.size:    2       # minor tick size in points
#xtick.major.width:   0.8     # major tick width in points
#xtick.minor.width:   0.6     # minor tick width in points
#xtick.major.pad:     3.5     # distance to major tick label in points
#xtick.minor.pad:     3.4     # distance to the minor tick label in points
xtick.color:          817c9c  # color of the ticks
#xtick.labelcolor:    inherit # color of the tick labels or inherit from xtick.color
#xtick.labelsize:     medium  # font size of the tick labels
#xtick.direction:     out     # direction: {in, out, inout}
#xtick.minor.visible: False   # visibility of minor ticks on x-axis
#xtick.major.top:     True    # draw x axis top major ticks
#xtick.major.bottom:  True    # draw x axis bottom major ticks
#xtick.minor.top:     True    # draw x axis top minor ticks
#xtick.minor.bottom:  True    # draw x axis bottom minor ticks
#xtick.alignment:     center  # alignment of xticks

#ytick.left:          True    # draw ticks on the left side
#ytick.right:         False   # draw ticks on the right side
#ytick.labelleft:     True    # draw tick labels on the left side
#ytick.labelright:    False   # draw tick labels on the right side
#ytick.major.size:    3.5     # major tick size in points
#ytick.minor.size:    2       # minor tick size in points
#ytick.major.width:   0.8     # major tick width in points
#ytick.minor.width:   0.6     # minor tick width in points
#ytick.major.pad:     3.5     # distance to major tick label in points
#ytick.minor.pad:     3.4     # distance to the minor tick label in points
ytick.color:          817c9c  # color of the ticks
#ytick.labelcolor:    inherit # color of the tick labels or inherit from ytick.color
#ytick.labelsize:     medium  # font size of the tick labels
#ytick.direction:     out     # direction: {in, out, inout}
#ytick.minor.visible: False   # visibility of minor ticks on y-axis
#ytick.major.left:    True    # draw y axis left major ticks
#ytick.major.right:   True    # draw y axis right major ticks
#ytick.minor.left:    True    # draw y axis left minor ticks
#ytick.minor.right:   True    # draw y axis right minor ticks
#ytick.alignment:     center_baseline  # alignment of yticks


## ***************************************************************************
## * GRIDS                                                                   *
## ***************************************************************************
grid.color:      393552  # grid color
#grid.linestyle: -       # solid
#grid.linewidth: 0.8     # in points
#grid.alpha:     1.0     # transparency, between 0.0 and 1.0


## ***************************************************************************
## * LEGEND                                                                  *
## ***************************************************************************
#legend.loc:           best
#legend.frameon:       True     # if True, draw the legend on a background patch
#legend.framealpha:    0.8      # legend patch transparency
#legend.facecolor:     inherit  # inherit from axes.facecolor; or color spec
#legend.edgecolor:     0.8      # background patch boundary color
#legend.fancybox:      True     # if True, use a rounded box for the
                                # legend background, else a rectangle
#legend.shadow:        False    # if True, give background a shadow effect
#legend.numpoints:     1        # the number of marker points in the legend line
#legend.scatterpoints: 1        # number of scatter points
#legend.markerscale:   1.0      # the relative size of legend markers vs. original
#legend.fontsize:      medium
#legend.title_fontsize: None    # None sets to the same as the default axes.

## Dimensions as fraction of font size:
#legend.borderpad:     0.4  # border whitespace
#legend.labelspacing:  0.5  # the vertical space between the legend entries
#legend.handlelength:  2.0  # the length of the legend lines
#legend.handleheight:  0.7  # the height of the legend handle
#legend.handletextpad: 0.8  # the space between the legend line and legend text
#legend.borderaxespad: 0.5  # the border between the axes and legend edge
#legend.columnspacing: 2.0  # column separation


## ***************************************************************************
## * FIGURE                                                                  *
## ***************************************************************************
## See https://matplotlib.org/api/figure_api.html#matplotlib.figure.Figure
#figure.titlesize:   large     # size of the figure title (``Figure.suptitle()``)
#figure.titleweight: normal    # weight of the figure title
#figure.figsize:     6.4, 4.8  # figure size in inches
#figure.dpi:         100       # figure dots per inch
figure.facecolor:    232136    # figure face color
figure.edgecolor:    59546d    # figure edge color
#figure.frameon:     True      # enable figure frame
#figure.max_open_warning: 20   # The maximum number of figures to open through
                               # the pyplot interface before emitting a warning.
                               # If less than one this feature is disabled.
#figure.raise_window : True    # Raise the GUI window to front when show() is called.

## The figure subplot parameters.  All dimensions are a fraction of the figure width and height.
#figure.subplot.left:   0.125  # the left side of the subplots of the figure
#figure.subplot.right:  0.9    # the right side of the subplots of the figure
#figure.subplot.bottom: 0.11   # the bottom of the subplots of the figure
#figure.subplot.top:    0.88   # the top of the subplots of the figure
#figure.subplot.wspace: 0.2    # the amount of width reserved for space between subplots,
                               # expressed as a fraction of the average axis width
#figure.subplot.hspace: 0.2    # the amount of height reserved for space between subplots,
                               # expressed as a fraction of the average axis height

## Figure layout
#figure.autolayout: False  # When True, automatically adjust subplot
                           # parameters to make the plot fit the figure
                           # using `tight_layout`
#figure.constrained_layout.use: False  # When True, automatically make plot
                                       # elements fit on the figure. (Not
                                       # compatible with `autolayout`, above).
#figure.constrained_layout.h_pad:  0.04167  # Padding around axes objects. Float representing
#figure.constrained_layout.w_pad:  0.04167  # inches. Default is 3/72 inches (3 points)
#figure.constrained_layout.hspace: 0.02     # Space between subplot groups. Float representing
#figure.constrained_layout.wspace: 0.02     # a fraction of the subplot widths being separated.


## ***************************************************************************
## * IMAGES                                                                  *
## ***************************************************************************
#image.aspect: equal                # {equal, auto} or a number
#image.interpolation:  antialiased  # see help(imshow) for options
#image.cmap:   viridis              # A colormap name, gray etc...
#image.lut:    256                  # the size of the colormap lookup table
#image.origin: upper                # {lower, upper}
#image.resample:  True
#image.composite_image: True  # When True, all the images on a set of axes are
                              # combined into a single composite image before
                              # saving a figure as a vector graphics file,
                              # such as a PDF.


## ***************************************************************************
## * CONTOUR PLOTS                                                           *
## ***************************************************************************
#contour.negative_linestyle: dashed  # string or on-off ink sequence
#contour.corner_mask:        True    # {True, False, legacy}
#contour.linewidth:          None    # {float, None} Size of the contour line
                                     # widths. If set to None, it falls back to
                                     # `line.linewidth`.


## ***************************************************************************
## * ERRORBAR PLOTS                                                          *
## ***************************************************************************
#errorbar.capsize: 0  # length of end cap on error bars in pixels


## ***************************************************************************
## * HISTOGRAM PLOTS                                                         *
## ***************************************************************************
#hist.bins: 10  # The default number of histogram bins or 'auto'.


## ***************************************************************************
## * SCATTER PLOTS                                                           *
## ***************************************************************************
#scatter.marker: o         # The default marker type for scatter plots.
#scatter.edgecolors: face  # The default edge colors for scatter plots.


## ***************************************************************************
## * AGG RENDERING                                                           *
## ***************************************************************************
## Warning: experimental, 2008/10/10
#agg.path.chunksize: 0  # 0 to disable; values in the range
                        # 10000 to 100000 can improve speed slightly
                        # and prevent an Agg rendering failure
                        # when plotting very large data sets,
                        # especially if they are very gappy.
                        # It may cause minor artifacts, though.
                        # A value of 20000 is probably a good
                        # starting point.


## ***************************************************************************
## * PATHS                                                                   *
## ***************************************************************************
#path.simplify: True  # When True, simplify paths by removing "invisible"
                      # points to reduce file size and increase rendering
                      # speed
#path.simplify_threshold: 0.111111111111  # The threshold of similarity below
                                          # which vertices will be removed in
                                          # the simplification process.
#path.snap: True  # When True, rectilinear axis-aligned paths will be snapped
                  # to the nearest pixel when certain criteria are met.
                  # When False, paths will never be snapped.
#path.sketch: None  # May be None, or a 3-tuple of the form:
                    # (scale, length, randomness).
                    #     - *scale* is the amplitude of the wiggle
                    #         perpendicular to the line (in pixels).
                    #     - *length* is the length of the wiggle along the
                    #         line (in pixels).
                    #     - *randomness* is the factor by which the length is
                    #         randomly scaled.
#path.effects:


## ***************************************************************************
## * SAVING FIGURES                                                          *
## ***************************************************************************
## The default savefig parameters can be different from the display parameters
## e.g., you may want a higher resolution, or to make the figure
## background white
#savefig.dpi:       figure      # figure dots per inch or 'figure'
savefig.facecolor:  232136      # figure face color when saving
#savefig.edgecolor: auto        # figure edge color when saving
#savefig.format:    png         # {png, ps, pdf, svg}
#savefig.bbox:      standard    # {tight, standard}
                                # 'tight' is incompatible with pipe-based animation
                                # backends (e.g. 'ffmpeg') but will work with those
                                # based on temporary files (e.g. 'ffmpeg_file')
#savefig.pad_inches:   0.1      # Padding to be used when bbox is set to 'tight'
#savefig.directory:    ~        # default directory in savefig dialog box,
                                # leave empty to always use current working directory
#savefig.transparent: False     # setting that controls whether figures are saved with a
                                # transparent background by default
#savefig.orientation: portrait  # Orientation of saved figure

### tk backend params
#tk.window_focus:   False  # Maintain shell focus for TkAgg

### ps backend params
#ps.papersize:      letter  # {auto, letter, legal, ledger, A0-A10, B0-B10}
#ps.useafm:         False   # use of AFM fonts, results in small files
#ps.usedistiller:   False   # {ghostscript, xpdf, None}
                            # Experimental: may produce smaller files.
                            # xpdf intended for production of publication quality files,
                            # but requires ghostscript, xpdf and ps2eps
#ps.distiller.res:  6000    # dpi
#ps.fonttype:       3       # Output Type 3 (Type3) or Type 42 (TrueType)

### PDF backend params
#pdf.compression:    6  # integer from 0 to 9
                        # 0 disables compression (good for debugging)
#pdf.fonttype:       3  # Output Type 3 (Type3) or Type 42 (TrueType)
#pdf.use14corefonts : False
#pdf.inheritcolor:   False

### SVG backend params
#svg.image_inline: True  # Write raster image data directly into the SVG file
#svg.fonttype: path      # How to handle SVG fonts:
                         #     path: Embed characters as paths -- supported
                         #           by most SVG renderers
                         #     None: Assume fonts are installed on the
                         #           machine where the SVG will be viewed.
#svg.hashsalt: None      # If not None, use this string as hash salt instead of uuid4

### pgf parameter
## See https://matplotlib.org/tutorials/text/pgf.html for more information.
#pgf.rcfonts: True
#pgf.preamble:  # See text.latex.preamble for documentation
#pgf.texsystem: xelatex

### docstring params
#docstring.hardcopy: False  # set this when you want to generate hardcopy docstring


## ***************************************************************************
## * INTERACTIVE KEYMAPS                                                     *
## ***************************************************************************
## Event keys to interact with figures/plots via keyboard.
## See https://matplotlib.org/users/navigation_toolbar.html for more details on
## interactive navigation.  Customize these settings according to your needs.
## Leave the field(s) empty if you don't need a key-map. (i.e., fullscreen : '')
#keymap.fullscreen: f, ctrl+f   # toggling
#keymap.home: h, r, home        # home or reset mnemonic
#keymap.back: left, c, backspace, MouseButton.BACK  # forward / backward keys
#keymap.forward: right, v, MouseButton.FORWARD      # for quick navigation
#keymap.pan: p                  # pan mnemonic
#keymap.zoom: o                 # zoom mnemonic
#keymap.save: s, ctrl+s         # saving current figure
#keymap.help: f1                # display help about active tools
#keymap.quit: ctrl+w, cmd+w, q  # close the current figure
#keymap.quit_all:               # close all figures
#keymap.grid: g                 # switching on/off major grids in current axes
#keymap.grid_minor: G           # switching on/off minor grids in current axes
#keymap.yscale: l               # toggle scaling of y-axes ('log'/'linear')
#keymap.xscale: k, L            # toggle scaling of x-axes ('log'/'linear')
#keymap.copy: ctrl+c, cmd+c     # Copy figure to clipboard


## ***************************************************************************
## * ANIMATION                                                               *
## ***************************************************************************
#animation.html: none  # How to display the animation as HTML in
                       # the IPython notebook:
                       #     - 'html5' uses HTML5 video tag
                       #     - 'jshtml' creates a JavaScript animation
#animation.writer:  ffmpeg        # MovieWriter 'backend' to use
#animation.codec:   h264          # Codec to use for writing movie
#animation.bitrate: -1            # Controls size/quality trade-off for movie.
                                  # -1 implies let utility auto-determine
#animation.frame_format: png      # Controls frame format used by temp files
#animation.ffmpeg_path:  ffmpeg   # Path to ffmpeg binary. Without full path
                                  # $PATH is searched
#animation.ffmpeg_args:           # Additional arguments to pass to ffmpeg
#animation.convert_path: convert  # Path to ImageMagick's convert binary.
                                  # On Windows use the full path since convert
                                  # is also the name of a system tool.
#animation.convert_args:          # Additional arguments to pass to convert
#animation.embed_limit:  20.0     # Limit, in MB, of size of base64 encoded
                                  # animation in HTML (i.e. IPython notebook)



================================================
FILE: config/mpv/input.conf
================================================
# === Normalization ===
N af toggle "lavfi=[dynaudnorm=framelen=100:gausssize=11:peak=0.95:maxgain=100:coupling=1]"

# === Seeking ===
a seek -5 exact
d seek +5 exact
k seek +80 exact
LEFT  seek -5 exact
RIGHT seek +5 exact

# === Per-frame seeking ===
Ctrl+a frame-back-step
Ctrl+d frame-step
Ctrl+LEFT  frame-back-step
Ctrl+RIGHT frame-step

# === Chapters ===
PGUP  add chapter -1
PGDWN add chapter +1

# === Playback ===
MBTN_RIGHT cycle pause
SPACE      cycle pause

l ab-loop

A playlist-prev
D playlist-next

# === Video ===
z add panscan +0.1
Z add panscan -0.1

f cycle fullscreen

# === Effects ===
1 add contrast -1 ; show-text "Contrast: ${contrast}"
! add contrast +1 ; show-text "Contrast: ${contrast}"

2 add brightness -1 ; show-text "Brightness: ${brightness}"
@ add brightness +1 ; show-text "Brightness: ${brightness}"

3 add gamma -1 ; show-text "Gamma: ${gamma}"
SHARP add gamma +1 ; show-text "Gamma: ${gamma}"

4 add saturation -1 ; show-text "Saturation: ${saturation}"
$ add saturation +1 ; show-text "Saturation: ${saturation}"

5 add speed -0.05 ; show-text "Speed: ${speed}"
% add speed +0.05 ; show-text "Speed: ${speed}"

# === Audio ===
UP            add volume +5
WHEEL_UP      add volume +5
Ctrl+WHEEL_UP add volume +1

DOWN            add volume -5
WHEEL_DOWN      add volume -5
Ctrl+WHEEL_DOWN add volume -1

w cycle aid
W cycle aid down

# === Subs ===
s cycle sid
S cycle sid down
Ctrl+s cycle secondary-sid
Ctrl+S cycle secondary-sid down
x add sub-delay -0.1
X add sub-delay +0.1
v add sub-scale -0.05
V add sub-scale +0.05

# === Info ===
i show-text "${osd-ass-cc/0}{\\an5}${media-title}\\N\\N(${path})\\NResolution: ${width} x ${height}\\NTime: ${time-pos} / ${duration}\\NCache: ${demuxer-cache-duration}s + ${cache-used} / ${cache-size}\\N\\NFrames dropped: ${frame-drop-count}${osd-ass-cc/1}"
p show-text "${osd-ass-cc/0}{\\an5}${osd-ass-cc/1}${playlist-pos-1} / ${playlist-count}\n${playlist}"
c show-text "${osd-ass-cc/0}{\\an5}${osd-ass-cc/1}${chapter} / ${chapters}\n${chapter-list}"
o show-progress
I script-binding stats/display-stats-toggle

# === Misc ===
q quit


================================================
FILE: config/mpv/mpv.conf
================================================
# === Interface ===
window-dragging=no

osd-font=Noto Sans
osd-font-size=30
osd-duration=2500
osd-bar-align-y=0.50
osd-bar-w=51
osd-bar-h=2

force-window=immediate

# === Video ===
profile=opengl-hq
hwdec=auto

panscan=1.0

# === Audio ===
ad-lavc-downmix=no
audio-normalize-downmix=yes
audio-channels=2
volume-max=300
alang=jp,fr,fre,en,eng,enm,ru,rus
audio-file-auto=fuzzy

# === Subs ===
secondary-sid=auto
sid=auto
slang=fr,fre,en,eng,enm,jp,ru,rus
sub-ass=no
sub-auto=fuzzy
sub-pos=95
subs-with-matching-audio=no

# === Network ===
ytdl-format=bestvideo+bestaudio/best
ytdl-raw-options=sub-lang="en,ru,th",write-sub=,write-auto-sub=

cache=yes

demuxer-max-bytes=104857600 # 100 MiB
demuxer-max-back-bytes=10485760 # 10 MiB

demuxer-cache-wait=no
demuxer-seekable-cache=yes

# === Misc ===
input-default-bindings=no
save-position-on-quit=yes
reset-on-next-file=pause
load-unsafe-playlists=yes


================================================
FILE: config/niri/config.kdl
================================================
// vim: set ts=2 sw=2:

// Startup
spawn-at-startup "waybar"
spawn-at-startup "mako"
spawn-at-startup "swaybg" "--image" "/home/cj/dotfiles/wallpaper.png" "--mode" "fill"
spawn-at-startup "foot" "--server" "--log-level=none"

environment {
  QT_QPA_PLATFORM "wayland"
  ELECTRON_OZONE_PLATFORM_HINT "wayland"

  QT_WAYLAND_DISABLE_WINDOWDECORATION "1"

  GDK_DPI_SCALE "1.5"
}

cursor {
  xcursor-theme "capitaine-cursors-light"
  xcursor-size 48

  hide-when-typing
  hide-after-inactive-ms 3000
}

overview {
  zoom 0.5
  backdrop-color "#171c29" // bg-dim-more
}

input {
  disable-power-key-handling
  focus-follows-mouse max-scroll-amount="25%"
  workspace-auto-back-and-forth // for tab workspace
  warp-mouse-to-focus mode="center-xy"

  mod-key "Super"

  keyboard {
    xkb {
      layout "us,ru,th"
      options "grp:caps_toggle12,grp_led:caps,compose:ralt"
    }

    repeat-delay 300
    repeat-rate 15
    track-layout "window"
  }

  touchpad {
    tap
    drag true
    natural-scroll
    scroll-factor 0.15
  }

  // TODO: trackpoint
}

output "HDMI-A-1" {
  mode "2560x1440@60"
  scale 1
  variable-refresh-rate
}

binds {
  // Spawn
  Super+J repeat=false { spawn "footclient"; }
  Super+B repeat=false { spawn "google-chrome-unstable"; }
  Super+R repeat=false { spawn "fuzzel"; }

  // Window control
  Super+X repeat=false { close-window; }
  Super+V repeat=false { toggle-window-floating; }
  Super+Space repeat=false { switch-focus-between-floating-and-tiling; }

  Super+Alt+C { center-column; }

  // Tabs
  Super+Alt+T { toggle-column-tabbed-display; }
  Super+G { toggle-column-tabbed-display; }

  // Window size control
  Super+T { switch-preset-column-width; }
  Super+Shift+T { switch-preset-window-height; }

  Super+F { fullscreen-window; }
  Super+Alt+F { maximize-column; }
  Super+Shift+F { toggle-windowed-fullscreen; }

  Super+Minus { set-column-width "-5%"; }
  Super+Equal { set-column-width "+5%"; }

  Super+Shift+Minus { set-window-height "-5%"; }
  Super+Shift+Equal { set-window-height "+5%"; }

  // Window focus
  Super+A { focus-column-left; }
  Super+D { focus-column-right; }
  Super+W { focus-window-or-workspace-up; }
  Super+S { focus-window-or-workspace-down; }

  Super+Q { focus-column-first; }
  Super+E { focus-column-last; }

  // Window movement
  Super+Shift+A { move-column-left; }
  Super+Shift+D { move-column-right; }
  Super+Shift+W { move-window-up-or-to-workspace-up; }
  Super+Shift+S { move-window-down-or-to-workspace-down; }

  Super+Alt+A { consume-or-expel-window-left; }
  Super+Alt+D { consume-or-expel-window-right; }

  Super+Shift+Q { move-column-to-first; }
  Super+Shift+E { move-column-to-last; }

  // Workspaces
  Super+1 { focus-workspace "1"; }
  Super+2 { focus-workspace "2"; }
  Super+3 { focus-workspace "3"; }
  Super+4 { focus-workspace "4"; }
  Super+5 { focus-workspace "5"; }
  Super+6 { focus-workspace "6"; }
  Super+7 { focus-workspace "7"; }
  Super+8 { focus-workspace "8"; }
  Super+9 { focus-workspace "9"; }

  Super+0 { focus-workspace "obs"; }
  Super+C { focus-workspace "msg"; }
  Super+Tab { focus-workspace "tab"; }

  Super+Shift+1 { move-window-to-workspace "1"; }
  Super+Shift+2 { move-window-to-workspace "2"; }
  Super+Shift+3 { move-window-to-workspace "3"; }
  Super+Shift+4 { move-window-to-workspace "4"; }
  Super+Shift+5 { move-window-to-workspace "5"; }
  Super+Shift+6 { move-window-to-workspace "6"; }
  Super+Shift+7 { move-window-to-workspace "7"; }
  Super+Shift+8 { move-window-to-workspace "8"; }
  Super+Shift+9 { move-window-to-workspace "9"; }

  Super+Shift+0 { move-window-to-workspace "obs"; }
  Super+Shift+C { move-window-to-workspace "msg"; }
  Super+Shift+Tab { move-window-to-workspace "tab"; }

  // Moving workspaces
  Super+Alt+W { move-workspace-up; }
  Super+Alt+S { move-workspace-down; }

  // Niri control
  Super+Alt+X repeat=false { quit skip-confirmation=true; }
  Super+O repeat=false { toggle-overview; }
  Super+Z repeat=false { toggle-overview; }
  Super+Alt+H repeat=false { show-hotkey-overlay; }

  // Waybar
  Super+Alt+B repeat=false { spawn "pkill" "-SIGUSR1" "waybar"; }

  // Monitor control
  Super+L repeat=false { spawn "hyprlock"; }
  Super+Alt+K repeat=false { power-off-monitors; }
  Super+Alt+Shift+K repeat=false { power-on-monitors; }

  // Notifications
  Super+N repeat=false { spawn "makoctl" "dismiss" "--all"; }
  Super+Alt+N repeat=false { spawn "systemctl" "--user" "restart" "mako"; }

  // Media
  XF86AudioMute allow-when-locked=true repeat=false { spawn "wpctl" "set-mute" "@DEFAULT_SINK@" "toggle"; }
  XF86AudioLowerVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_SINK@" "5%-"; }
  XF86AudioRaiseVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_SINK@" "5%+"; }

  XF86AudioMicMute allow-when-locked=true repeat=false { spawn "wpctl" "set-mute" "@DEFAULT_SOURCE@" "toggle"; }
  F7 allow-when-locked=true repeat=false { spawn "wpctl" "set-mute" "@DEFAULT_SOURCE@" "toggle"; }

  // Brightness
  XF86MonBrightnessUp allow-when-locked=true {   spawn "brightnessctl" "-e" "set" "5%+"; }
  XF86MonBrightnessDown allow-when-locked=true { spawn "brightnessctl" "-e" "set" "5%-"; }

  // Print screen
  Print repeat=false { spawn "flameshot" "gui"; }

  // Language
  Super+Backspace repeat=false { switch-layout "2"; }
}

switch-events {
  // TODO: lid-close / lid-open
}

gestures {
  hot-corners {
    top-left
  }
}

layout {
  gaps 16

  struts {
    left 16
    right 16
    top 16
    bottom 16
  }

  center-focused-column "never" // "on-overflow"
  always-center-single-column

  preset-column-widths {
    proportion 0.5
    proportion 1.0
  }

  default-column-width { proportion 0.5; }

  preset-window-heights {
    proportion 1.0
    proportion 0.5
  }

  border {
    off
  }

  focus-ring {
    width 3
    active-color "#92b7ea" // blue
    inactive-color "#54678c" // fg-half-dim
    urgent-color "#D0879D" // red
  }

  shadow {
    on

    spread 10
    softness 50
  }

  tab-indicator {
    on
    hide-when-single-tab
    place-within-column

    gap 12
    width 12
    length total-proportion=0.25
    position "left"
    gaps-between-tabs 16
    corner-radius 16
    active-color "#AD9BEA" // purple

    inactive-color "#54678c90" // fg-half-dim with alpha
    urgent-color "#E0778D" // reder (brighter red)
  }

  insert-hint {
    on
    color "#92b7ea90" // blue with alpha
  }
}

// Workspaces
workspace "1" {}
workspace "2" {}
workspace "3" {}
workspace "4" {}
workspace "5" {}
workspace "6" {}
workspace "7" {}
workspace "8" {}
workspace "9" {}

workspace "obs" {}
workspace "msg" {}
workspace "tab" {}

// Window rules
window-rule {
  default-column-width { proportion 1.0; }
  open-focused true
  tiled-state true

  geometry-corner-radius 24
  clip-to-geometry true
}

window-rule {
  match app-id="^google-chrome-unstable$"
  focus-ring {
    active-color "#d3e3fd" // color of chrome window theme
  }
}

window-rule {
  match app-id="^foot(client)?$"
  default-column-width { proportion 0.5; }
}

window-rule {
  match app-id="^org.telegram.desktop|Element|discord$"
  exclude title="^Media viewer$"
  open-on-workspace "msg"
  open-focused false
  default-column-width { proportion 0.5; }
}

window-rule {
  match app-id="^com.obsproject.Studio$"
  open-on-workspace "obs"
}

window-rule {
  match app-id="^steam$"
  open-on-workspace "tab"
}

layer-rule {
  match namespace="^notifications$"

  block-out-from "screencast"
  baba-is-float true
}

layer-rule {
  match namespace="^launcher$"

  baba-is-float true
  shadow {
    on
  }

  geometry-corner-radius 24
}

animations {
  window-open {
    off
  }
}

// Other options
prefer-no-csd

hotkey-overlay {
  skip-at-startup
  hide-not-bound
}

// Recent windows
recent-windows {
  debounce-ms 0
  open-delay-ms 0

  highlight {
    active-color "#92b7ea" // blue
    urgent-color "#D0879D" // red
    padding 64
    corner-radius 24
  }

  previews {
    max-height 9999
    max-scale 0.66
  }

  binds {
    Super+BracketLeft  { previous-window; }
    Super+BracketRight { next-window; }
  }
}


================================================
FILE: config/npm/npmrc
================================================
prefix=~/.npm


================================================
FILE: config/numbat/config.toml
================================================
intro-banner = "off"
prompt = "\u001B[0;32m 󰪚\u001B[0;37m ❯ \u001B[0m"
pretty-print = "auto"

[exchange-rates]
fetching-policy = "on-first-use"


================================================
FILE: config/nvim/init.lua
================================================
---@diagnostic disable: lowercase-global
---@diagnostic disable: need-check-nil

----------
-- TODO --
----------

-- - clipboard manager (prbly for wayland)
-- - markdown wrapping
-- - 2-space indent for html, css, md
-- - Autoformatting for html and css
-- - Better help in python (like in Helix)

----------------
-- File types --
----------------

-- 2-space indent for some file types
vim.api.nvim_create_autocmd("FileType", {
    pattern = "yaml,toml,markdown,html,css",
    callback = function()
        vim.opt_local.tabstop = 2
        vim.opt_local.softtabstop = 2
        vim.opt_local.shiftwidth = 2
    end
})

-- Enable soft wrapping for some file types
vim.api.nvim_create_autocmd("FileType", {
    pattern = "markdown",
    callback = function()
        vim.opt_local.wrap = true
    end
})

-- Disable comment continuation
vim.api.nvim_create_autocmd("BufEnter", {
    pattern = "*",
    callback = function()
        vim.opt.formatoptions = "jql"
    end,
})

-------------
-- Plugins --
-------------

local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
vim.opt.rtp:prepend(lazypath)

vim.cmd.colorscheme("nuitbleue")
vim.opt.termguicolors = true

require("lazy").setup({
    local_spec = false,
    install = { missing = false },

    spec = {
        -- Surround
        {
            "kylechui/nvim-surround",
            version = "*", -- Use for stability; omit to use `main` branch for the latest features
            event = "VeryLazy",
            config = function()
                require("nvim-surround").setup({
                    keymaps = {},
                })

                -- HACK: restore an "S" overwritten by plugin. Fuck nvim-surround
                vim.keymap.set({ "n", "v" }, "S", "5j", {})

                -- HACK: remove "ds" keymap since it's breaking WASD movements
                vim.keymap.del({ "n" }, "ds")
            end
        },

        -- File Manager
        {
            "stevearc/oil.nvim",
            event = "VeryLazy",
            opts = {
                columns = { "icon", "permissions", "size" },

                delete_to_trash = true,
                skip_confirm_for_simple_edits = true,
                watch_for_changes = true,
                view_options = {
                    show_hidden = true,
                    show_column_number = false,
                },
                float = {
                    padding = 3,
                    max_width = 80,
                    max_height = 30,
                    ---@diagnostic disable-next-line: unused-local
                    get_win_title = function(winid)
                        return ""
                    end,
                },
                keymaps = {
                    ["?"] = { "actions.show_help", mode = "n" },
                    ["<bs>"] = { "actions.parent", mode = "n" },
                    ["<c-cr>"] = { "actions.preview", mode = "n" },
                },
            },
        },

        -- Highlight word under cursor
        {
            "tzachar/local-highlight.nvim",
            event = "VeryLazy",
            config = function()
                require("local-highlight").setup({
                    min_match_len = 2,
                    max_match_len = 30,
                    cw_hlgroup = "LocalHighlight",
                    highlight_single_match = true,
                    debounce_timeout = 50,
                    animate = {
                        enabled = false,
                    },
                })

                vim.cmd("LocalHighlightOn")
            end,
        },

        -- Copilot
        {
            "zbirenbaum/copilot.lua",
            event = "VeryLazy",
            config = function()
                require("copilot").setup({
                    panel = {
                        enabled = false,
                    },
                    suggestion = {
                        auto_trigger = true,
                        debounce = 25,
                    },
                    filetypes = {
                        markdown = true,
                        yaml = true,
                        gitcommit = true,
                    },
                })
            end,
        },

        -- Better notifications
        {
            "rcarriga/nvim-notify",
            event = "VeryLazy",
            opts = {
                timeout = 2000,
                stages = "static",
                render = "minimal",
            },
        },

        -- Better UI
        {
            "folke/noice.nvim",
            event = "VeryLazy",
            config = function()
                require("noice").setup({
                    routes = {
                        -- Remove search counter
                        {
                            filter = { event = "msg_show", kind = "search_count" },
                            opts = { skip = true },
                        },
                        -- Remove save file message
                        {
                            filter = { find = " written" },
                            opts = { skip = true },
                        },
                        -- Remove undo/redo messages
                        {
                            filter = { find = " before #" },
                            opts = { skip = true },
                        },
                        {
                            filter = { find = " after #" },
                            opts = { skip = true },
                        },
                        -- Remove paste messages
                        {
                            filter = { find = " more lines" },
                            opts = { skip = true },
                        },
                        -- Remove deprecated messages
                        {
                            filter = { find = " deprecate" },
                            opts = { skip = true },
                        },
                        -- Remove deprecated messages about diagnostic signs
                        {
                            filter = { find = "Defining diagnostic signs " },
                            opts = { skip = true },
                        },
                        -- Remove some non-critical LSP messages (?)
                        {
                            filter = { find = "ServerNotInitialized" },
                            opts = { skip = true },
                        },
                        -- LSP hover messages
                        {
                            filter = { find = "No information available" },
                            opts = { skip = true },
                        },
                        -- LSP shit
                        {
                            filter = { find = "method textDocument/signatureHelp is not supported" },
                            opts = { skip = true },
                        },
                    },
                    window = {
                        border = "rounded",
                    },
                    messages = {
                        enabled = true,
                    },
                    lsp = {
                        progress = {
                            enabled = false,
                        },
                    },
                    presets = {
                        bottom_search = true,
                        command_palette = true,
                        long_message_to_split = true,
                        inc_rename = false,
                        lsp_doc_border = true,
                    },
                })
            end,
        },

        -- Color column as a characters
        {
            "lukas-reineke/virt-column.nvim",
            opts = {},
            config = function()
                require("virt-column").setup({
                    char = "¦",
                    virtcolumn = "80,120",
                })
            end,
        },

        -- Move diagnostics to top
        {
            "dgagn/diagflow.nvim",
            version = false,
            event = "VeryLazy",
            opts = {
                padding_right = 2,
                gap_size = 2,
                -- FIXME: wait until author fixes https://github.com/dgagn/diagflow.nvim/issues/54
                show_borders = true,
                border_chars = {
                    top_left = " ",
                    top_right = " ",
                    bottom_left = " ",
                    bottom_right = " ",
                    horizontal = " ",
                    vertical = " "
                },
                scope = "line",
                format = function(diagnostic)
                    -- No errors in insert mode
                    if vim.api.nvim_get_mode().mode == "i" then
                        return ""
                    end

                    local current_line = vim.fn.line(".")
                    local top_line = vim.fn.line("w0")
                    local relative_line = current_line - top_line

                    -- No diagnostics then current line is too high in visible area
                    if relative_line < 8 then
                        return ""
                    end

                    -- NOTE: NBSP from pyright breaking the border
                    -- NOTE: quotes from harper too
                    return diagnostic.message:gsub(" ", ".")
                        :gsub("“", "\"")
                        :gsub("”", "\"")
                end,
            }
        },

        -- Indentation guides
        {
            "lukas-reineke/indent-blankline.nvim",
            main = "ibl",
            opts = {},
            config = function()
                require("ibl").setup({
                    indent = { char = "¦" },
                    scope = {
                        enabled = true,
                        show_start = false,
                        show_end = false,
                    },
                })
            end,
        },

        -- Completion
        {
            "hrsh7th/nvim-cmp",
            event = "VeryLazy",
            dependencies = {
                "hrsh7th/cmp-nvim-lsp",
                "hrsh7th/cmp-buffer",
                "hrsh7th/cmp-path",
                "hrsh7th/cmp-cmdline",
            },
            config = function()
                local cmp = require("cmp")

                local cmp_kinds = {
                    Text = '󰊄 ',
                    Method = '󰊕 ',
                    Function = '󰊕 ',
                    Constructor = '󰊕 ',
                    Field = '󰬟 ',
                    Variable = '󰬟 ',
                    Class = ' ',
                    Interface = '󰬐 ',
                    Module = '󰰐 ',
                    Property = '󰬟  ',
                    Unit = ' ',
                    Value = ' ',
                    Enum = ' ',
                    Keyword = ' ',
                    Snippet = ' ',
                    Color = ' ',
                    File = ' ',
                    Reference = ' ',
                    Folder = ' ',
                    EnumMember = ' ',
                    Constant = ' ',
                    Struct = ' ',
                    Event = ' ',
                    Operator = ' ',
                    TypeParameter = ' ',
                }

                cmp.setup({
                    preselect = false,
                    window = {
                        completion = cmp.config.window.bordered {
                            border = 'single',
                            winhighlight = 'Normal:NormalFloat,FloatBorder:FloatBorder,CursorLine:Visual,Search:None',
                        },
                        documentation = cmp.config.window.bordered {
                            border = 'single',
                            winhighlight = 'Normal:NormalFloat,FloatBorder:FloatBorder,CursorLine:Visual,Search:None',
                        },
                    },
                    mapping = {
                        ["<down>"] = cmp.mapping.select_next_item(),
                        ["<up>"] = cmp.mapping.select_prev_item(),
                        ["<c-e>"] = cmp.mapping.close(),
                        ["<c-cr>"] = cmp.mapping.confirm(),
                        -- NOTE: handled by tab_complete function
                        -- ["<tab>"] = cmp.mapping.select_next_item(),
                        ["<s-tab>"] = cmp.mapping.select_prev_item(),
                    },
                    sources = {
                        { name = "nvim_lsp" },
                        { name = "buffer" },
                        { name = "path" },
                    },
                    formatting = {
                        fields = { 'kind', 'abbr' },
                        format = function(_, vim_item)
                            vim_item.kind = cmp_kinds[vim_item.kind] or ''
                            vim_item.menu = ''
                            return vim_item
                        end,
                    },
                })
            end,
        },

        -- Multiple cursors
        --   Alternatives:
        --   - terryma/vim-multiple-cursors -- kinda works with custom mappings, but deprecated and buggy
        --   - mg979/vim-visual-multi -- doesn't work with custom mappings
        --   - jake-stewart/multicursor.nvim -- works, but is not interactive
        --   - brenton-leighton/multiple-cursors.nvim -- doesn't work with custom mappings
        {
            "jake-stewart/multicursor.nvim",
            event = "VeryLazy",
            branch = "1.0",
            config = function()
                local mc = require("multicursor-nvim")

                mc.setup()

                vim.keymap.set({ "n", "v" }, "C", function() mc.lineAddCursor(1) end)
                vim.keymap.set({ "n" }, "<c-d>", function()
                    vim.cmd('normal! viw')
                end)
                vim.keymap.set({ "v" }, "<c-d>", function() mc.matchAddCursor(1) end)
                vim.keymap.set({ "v" }, "l", function() mc.splitCursors("\n") end)

                vim.keymap.set("n", "<esc>", function()
                    if not mc.cursorsEnabled() then
                        mc.enableCursors()
                    elseif mc.hasCursors() then
                        mc.clearCursors()
                    else
                        vim.cmd("nohlsearch")

                        -- Close all floating windows except zen-mode
                        -- vim.cmd("fclose")
                        for _, win in ipairs(vim.api.nvim_list_wins()) do
                            local conf = vim.api.nvim_win_get_config(win)
                            if conf.relative ~= "" and conf.zindex > 40 then
                                vim.api.nvim_win_close(win, true)
                            end
                        end
                    end
                end)
            end,
        },

        -- LSP
        {
            "neovim/nvim-lspconfig",
            config = function()
                local lsp = require("lspconfig")
                local border = {
                    { "┌", "FloatBorder" },
                    { "─", "FloatBorder" },
                    { "┐", "FloatBorder" },
                    { "│", "FloatBorder" },
                    { "┘", "FloatBorder" },
                    { "─", "FloatBorder" },
                    { "└", "FloatBorder" },
                    { "│", "FloatBorder" },
                }

                local orig_util_open_floating_preview = vim.lsp.util.open_floating_preview
                function vim.lsp.util.open_floating_preview(contents, syntax, opts, ...)
                    opts = opts or {}
                    opts.border = opts.border or border
                    return orig_util_open_floating_preview(contents, syntax, opts, ...)
                end

                -- General
                -- lsp.harper_ls.setup({
                --     settings = {
                --         ["harper-ls"] = {
                --             diagnosticSeverity = "warning",
                --             linters = {
                --                 AvoidCurses = false,
                --             },
                --         }
                --     },
                -- })

                -- LanguageTool
                -- lsp.ltex.setup({})
                -- lsp.ltex_plus.setup({
                --     settings = {
                --         ltex = {
                --             diagnosticSeverity = "hint",
                --             checkFrequency = "save",
                --             dictionary = {
                --                 ["en-US"] = {
                --                     "zig",
                --                     "Zig",
                --                     "inlining",
                --                 },
                --             },
                --         }
                --     }
                -- })

                -- LUA
                lsp.lua_ls.setup({
                    settings = {
                        Lua = {
                            diagnostics = {
                                -- For init.lua
                                globals = {
                                    'vim',
                                    'require'
                                },
                            },
                            telemetry = { enable = false },
                        },
                    },
                })

                -- Python
                -- Autocomplete, Imports, Type checking
                lsp.pyright.setup({
                    settings = {
                        python = {
                            analysis = {
                                typeCheckingMode = "strict",

                                diagnosticSeverityOverrides = {
                                    -- Fix diagnostics level
                                    reportUnknownParameterType = "warning",
                                    reportMissingParameterType = "warning",
                                    reportUnknownArgumentType = "warning",
                                    reportUnknownLambdaType = "warning",
                                    reportUnknownMemberType = "warning",
                                    reportUnusedFunction = "warning",
                                    reportUnusedVariable = "warning",
                                    reportUntypedFunctionDecorator = "warning",
                                    reportDeprecated = "warning",

                                    -- Enable extra diagnostics
                                    reportUnusedCallResult = "warning",
                                    reportUninitializedInstanceVariable = "warning",

                                    -- Gradual typing in new projects
                                    reportMissingImports = false,
                                    reportMissingTypeStubs = false,
                                    reportUnknownVariableType = false,

                                    -- Covered by ruff
                                    reportUnusedImport = false,
                                },
                            },
                        },
                    },
                })

                -- Linting / formatting
                lsp.ruff.setup({})

                -- YAML
                lsp.yamlls.setup({})

                -- TOML
                lsp.taplo.setup({})

                -- HTML
                lsp.emmet_language_server.setup({
                    filetypes = { "python", "html" },
                    preferences = {
                        caniuse = {
                            enabled = false,
                        },
                    },
                })
                -- lsp.html.setup({}) -- vscode shit, doesn't provide autocomplete anyway
                lsp.superhtml.setup({})

                -- Bash
                lsp.bashls.setup({})

                -- Typst
                lsp.tinymist.setup({
                    settings = {
                        formatterMode = "typstyle",
                        exportPdf = "onType",
                    },
                })

                -- Zig
                lsp.zls.setup({
                    settings = {
                        zls = {
                            enable_autofix = true,
                            enable_inlay_hints = false,
                            enable_argument_placeholders = false,
                            semantic_tokens = "partial",

                            enable_build_on_save = true,
                            build_on_save_args = { "check" },

                            -- Mostly annoying
                            -- warn_style = true,
                        },
                    },
                })

                -- Rust
                lsp.rust_analyzer.setup({
                    settings = {
                        ["rust-analyzer"] = {
                            cachePriming = {
                                enable = false,
                            },
                            cargo = {
                                -- Use separate target directory for rust-analyzer to remove interferences with cargo
                                targetDir = true,
                            },
                            check = {
                                command = "clippy",
                            },
                            procMacro = {
                                enable = true,
                            },
                            completion = {
                                limit = 1024,
                                callable = {
                                    snippets = "none",
                                },
                                postfix = {
                                    enable = false,
                                },
                                hideDeprecated = true,
                            },
                            imports = {
                                preferNoStd = true,
                            },
                            lens = {
                                enable = false,
                            },
                            diagnostics = {
                                experimental = {
                                    enabled = true,
                                },
                                styleLints = {
                                    enable = true,
                                },
                            },
                            rustfmt = {
                                extraArgs = {
                                    "--config=empty_item_single_line=false",
                                    "--config=wrap_comments=true",
                                    "--config=condense_wildcard_suffixes=true",
                                    "--config=enum_discrim_align_threshold=10",
                                    "--config=format_code_in_doc_comments=true",
                                    "--config=hex_literal_case=Upper",
                                    "--config=max_width=120",
                                    "--config=reorder_impl_items=true",
                                    "--config=group_imports=StdExternalCrate",
                                    "--config=use_field_init_shorthand=true",
                                },
                            },
                        },
                    },
                })

                -- JavaScript
                lsp.ts_ls.setup({})

                -- Go
                lsp.gopls.setup({})

                -- Codebook (spell checking)
                lsp.codebook.setup({})
                vim.lsp.enable("codebook")
            end,
        },

        -- Treesitter
        {
            "nvim-treesitter/nvim-treesitter",
            version = false, -- Last release is way too old
            event = "VeryLazy",
            build = ":TSUpdate",
            config = function()
                local configs = require("nvim-treesitter.configs")

                configs.setup({
                    ensure_installed = {
                        -- Programming
                        "python",
                        "rust",
                        "zig",
                        "javascript",
                        "typescript",

                        -- Scripting
                        "lua",
                        "bash",

                        -- Markup & Web
                        "markdown",
                        "html",
                        "css",

                        -- Configuration
                        "toml",
                        "yaml",
                        "json",
                        "ini",
                        "kdl",

                        -- Other
                        "git_config",
                    },
                    sync_install = false,
                    highlight = {
                        enable = true,
                        additional_vim_regex_highlighting = false,
                    },
                    indent = { enable = true },
                })
            end,
        },

        -- Treesitter text objects
        {
            "nvim-treesitter/nvim-treesitter-textobjects",
            event = "VeryLazy",
            keys = {
                {
                    "mf",
                    function()
                        vim.cmd("normal! v")
                        require("nvim-treesitter.textobjects.select").select_textobject("@function.inner")
                    end,
                    mode = "n",
                },
                {
                    "ma",
                    function()
                        vim.cmd("normal! v")
                        require("nvim-treesitter.textobjects.select").select_textobject("@parameter.inner")
                    end,
                    mode = "n",
                },
                {
                    "mm",
                    function()
                        vim.cmd("normal! v")
                        require("nvim-treesitter.textobjects.select").select_textobject("@call.inner")
                    end,
                    mode = "n",
                },
                {
                    "Mf",
                    function()
                        vim.cmd("normal! v")
                        require("nvim-treesitter.textobjects.select").select_textobject("@function.outer")
                    end,
                    mode = "n",
                },
            },
        },

        -- Git gutter
        {
            "lewis6991/gitsigns.nvim",
            event = "VeryLazy",
            config = function()
                local signs = {
                    add          = { text = '│' },
                    change       = { text = '│' },
                    delete       = { text = '▁' },
                    topdelete    = { text = '▔' },
                    changedelete = { text = '⋯' },
                    untracked    = { text = '┆' },
                }

                require("gitsigns").setup({
                    signs = signs,
                    signs_staged = signs,
                    numhl = false,
                })
            end,
        },

        -- Scrollbar
        {
            "petertriho/nvim-scrollbar",
            event = "VeryLazy",
            opts = {
                handle = {
                    -- highlight = "Visual",
                },
                handlers = {
                    cursor = false,
                    diagnostic = true,
                    gitsigns = true,
                    handle = true,
                },
            },
        },

        -- File picker / Live grep
        {
            "nvim-telescope/telescope.nvim",
            event = "VeryLazy",
            dependencies = { 'nvim-lua/plenary.nvim' },
            config = function()
                local actions = require("telescope.actions");
                local actions_layout = require("telescope.actions.layout")
                local themes = require("telescope.themes")

                require("telescope").setup({
                    extensions = {
                        ["ui-select"] = {
                            themes.get_dropdown({
                                prompt_title = "",
                                layout_config = {
                                    vertical = {
                                        width = 0.3,
                                        height = 0.5,
                                    },
                                },
                            }),
                        },
                    },
                    defaults = {
                        -- Close pickers on first Escape instead of going to normal mode
                        mappings = {
                            i = {
                                ["<esc>"] = actions.close,
                                ["<c-p>"] = actions_layout.toggle_preview,
                                ["<c-down>"] = actions.cycle_history_next,
                                ["<c-up>"] = actions.cycle_history_prev,
                            },
                        },
                        sorting_strategy = "ascending",

                        hidden = true,
                        use_fd = true,

                        results_title = "",
                        prompt_title = "",
                        preview_title = "",
                        prompt_prefix = " ",

                        layout_config = {
                            horizontal = {
                                width = 0.9,
                                height = 0.9,
                                prompt_position = "top",
                                preview_cutoff = 80,
                                preview_width = 0.5,
                            },
                            vertical = {
                                width = 0.9,
                                height = 0.9,
                                prompt_position = "top",
                                preview_cutoff = 20,
                                preview_width = 0.5,
                                preview_height = 0.5,
                            },
                        },
                    },
                    pickers = {
                        buffers = {
                            bufnr_width = 0,
                            sort_lastused = true,
                            prompt_title = "",
                            preview_title = "",
                        },
                        diagnostics = {
                            layout_strategy = "vertical",
                            path_display = "hidden",
                            prompt_title = "",
                            preview_title = "",
                        },
                        find_files = {
                            hidden = true,
                            find_command = { "fd", "--type", "f", "--hidden" },
                            prompt_title = "",
                            preview_title = "",
                        },
                        lsp_document_symbols = {
                            prompt_title = "",
                            preview_title = "",
                        },
                        live_grep = {
                            file_ignore_patterns = { 'node_modules', '.git', '.venv', 'CHANGELOG.md', 'poetry.lock' },
                            additional_args = function(_)
                                return { "--hidden" }
                            end,
                            prompt_title = "",
                            preview_title = "",
                        },
                        lsp_references = {
                            prompt_title = "",
                        },
                        -- FIXME: todo-comments picker doesn't respect these settings
                        ["todo-comments"] = {
                            preview_title = "",
                            prompt_title = "",
                        },
                    },
                })
            end,
        },

        -- Code actions with telescope
        {
            'nvim-telescope/telescope-ui-select.nvim',
            event = "VeryLazy",
            config = function()
                require("telescope").load_extension("ui-select")
            end,
        },

        -- Yaml Schemata
        {
            "someone-stole-my-name/yaml-companion.nvim",
            event = "VeryLazy",
            config = function()
                require("telescope").load_extension("yaml_schema")
            end,
        },

        -- Highlight TODO-style comments
        {
            "folke/todo-comments.nvim",
            event = "VeryLazy",
            dependencies = { "nvim-lua/plenary.nvim" },
            config = function()
                local todos = require("todo-comments")
                todos.setup({
                    keywords = {
                        FIX = { icon = " ", color = "error", alt = { "FIXME", "BUG", "FIXIT", "ISSUE" } },
                        TODO = { icon = " ", color = "info" },
                        HACK = { icon = "󰈸 ", color = "warning" },
                        WARN = { icon = " ", color = "warning", alt = { "WARNING", "XXX" } },
                        PERF = { icon = " ", color = "info", alt = { "OPTIM", "PERFORMANCE", "OPTIMIZE" } },
                        NOTE = { icon = " ", color = "info", alt = { "INFO" } },
                        TEST = { icon = "󰙨 ", color = "warning", alt = { "TESTING", "PASSED", "FAILED" } },
                    },
                    highlight = {
                        multiline = false,
                        pattern = [[.*<(KEYWORDS)\s*]],
                        keyword = "fg",
                        after = "",
                    },
                    colors = {
                        error = { "ErrorMsg" },
                        warning = { "WarningMsg" },
                        info = { "Todo", "Normal" },
                        hint = { "Comment" },
                    },
                })

                vim.keymap.set("n", "]t", todos.jump_next, {})
                vim.keymap.set("n", "[t", todos.jump_prev, {})
            end,
        },

        -- Restore last position in file
        -- NOTE: it's deprecated, but works just fine
        -- NOTE: we need it in addition to session restore
        {
            "ethanholz/nvim-lastplace",
            config = function()
                require("nvim-lastplace").setup({})
            end,
        },

        -- Restore all buffers and their positions
        {
            "rmagatti/auto-session",
            lazy = false, -- We need to restore session ASAP
            opts = {
                suppressed_dirs = { '~/', '/', '~/downloads' },
                session_lens = {
                    theme_conf = {
                        layout_strategy = "horizontal",
                        prompt_title = "",
                        layout_config = {
                            prompt_position = "top",
                            width = 60,
                            height = 30,
                        },
                    },
                },
            },
        },
    }
})

--------------
-- Settings --
--------------

-- Do not hide markdown elements in AI chat and documentation
vim.opt.conceallevel = 0

-- Disable swap files
vim.opt.swapfile = false

-- Increase gutter spacing
vim.opt.statuscolumn = "%s%=%l  "

-- Enable some mouse (for selections)
vim.opt.mouse = "nv"

-- Show line numbers
vim.opt.number = true

-- Disable fill character (in gutter)
vim.opt.fillchars = "eob: ,vert:¦"

-- Enable case-insensitive search
vim.opt.ignorecase = true
vim.opt.smartcase = true

-- Disable soft wrapping
vim.opt.wrap = false

-- Merge command line and status line
vim.opt.cmdheight = 0

-- Tab as 4 spaces
vim.opt.tabstop = 4
vim.opt.expandtab = true
vim.opt.softtabstop = 4
vim.opt.shiftwidth = 4

-- Always keep sign column on
vim.opt.signcolumn = "yes"

-- Copy to system's clipboard
vim.schedule(function()
    vim.opt.clipboard = 'unnamedplus'
end)

-- Save undo history
vim.opt.undofile = true

-- Configure how new splits should be opened
vim.opt.splitright = true
vim.opt.splitbelow = true

-- Decrease update time. Used for swapfile and by gitsigns and local-highlight
vim.opt.updatetime = 25

-- Decrease mapped sequence wait time
vim.opt.timeoutlen = 300

-- White space characters
vim.opt.list = true
vim.opt.listchars = { tab = '» ', trail = '•', nbsp = '␣' }

-- Show which line your cursor is on
vim.opt.cursorline = true

-- Minimal number of screen lines to keep above and below the cursor
vim.opt.scrolloff = 6

-- Minimal number of screen columns to keep to the left and right of the cursor
vim.opt.sidescrolloff = 20

-- Hide status line
vim.opt.laststatus = 0

-- Replace window splitter status line with a character
vim.opt.statusline = "%{repeat('⸺',winwidth('.'))}"

-- Remove welcome screen
vim.opt.shortmess:append("A")
vim.opt.shortmess:append("I") -- No intro
vim.opt.shortmess:append("s") -- Search wrap without message
vim.opt.shortmess:append("c") -- Unsuccessful search without prompt

-- Diagnostics
vim.fn.sign_define("DiagnosticSignError", { text = "", texthl = "Error" })
vim.fn.sign_define("DiagnosticSignWarn", { text = "󰈸", texthl = "Warn" })
vim.fn.sign_define("DiagnosticSignSpell", { text = "X", texthl = "Warn" })
vim.fn.sign_define("DiagnosticSignInfo", { text = "󰋽", texthl = "Info" })
vim.fn.sign_define("DiagnosticSignHint", { text = "", texthl = "Hint" })

vim.diagnostic.config({
    underline = {
        min = vim.diagnostic.severity.ERROR,
        max = vim.diagnostic.severity.ERROR,
    },
    severity_sort = true,
})

-----------------
-- Keybindings --
-----------------

-- Leader key
vim.g.mapleader = " "

vim.keymap.set({ "n", "v" }, "<leader>t", "<cmd> Telescope todo-comments <cr>", {})
vim.keymap.set({ "n", "v" }, "<leader>f", "<cmd> Telescope find_files <cr>", {})
vim.keymap.set({ "n", "v" }, "<leader>k", "<cmd> Telescope keymaps <cr>", {})
vim.keymap.set({ "n", "v" }, "<leader>b", "<cmd> Telescope buffers <cr>", {})
vim.keymap.set({ "n", "v" }, "<leader>/", "<cmd> Telescope live_grep <cr>", {})
vim.keymap.set({ "n", "v" }, "<leader>j", "<cmd> Telescope jumplist <cr>", {})
vim.keymap.set({ "n", "v" }, "<leader>h", "<cmd> Telescope help_tags <cr>", {})
vim.keymap.set({ "n", "v" }, "<leader>d", "<cmd> Telescope diagnostics <cr>", {})
vim.keymap.set({ "n", "v" }, "<leader>s", "<cmd> Telescope lsp_document_symbols <cr>", {})
vim.keymap.set({ "n", "v" }, "<leader>S", "<cmd> Telescope lsp_workspace_symbols <cr>", {})
vim.keymap.set({ "n", "v" }, "<leader><leader>", "<cmd> Telescope resume <cr>", {})

vim.keymap.set({ "n", "v" }, "<leader>p", "<cmd> SessionSearch <cr>", {})
vim.keymap.set({ "n", "v" }, "<leader>o", function() require("oil").toggle_float() end, {})

-- WASD
vim.keymap.set({ "n", "v" }, "w", "k", {})
vim.keymap.set({ "n", "v" }, "s", "j", {})
vim.keymap.set({ "n", "v" }, "a", "h", {})
vim.keymap.set({ "n", "v" }, "d", "l", {})

vim.keymap.set({ "n", "v", "o" }, "q", "^", {})
vim.keymap.set({ "n", "v", "o" }, "e", "$", {})

vim.keymap.set({ "n", "v" }, "W", "5k", {})
vim.keymap.set({ "n", "v" }, "S", "5j", {})
vim.keymap.set({ "n", "v", "o" }, "A", "b", {})
vim.keymap.set({ "n", "v", "o" }, "D", "w", {})

vim.keymap.set({ "n", "v" }, "Q", "I", {})
vim.keymap.set({ "n", "v" }, "E", "A", {})

-- Movements
vim.keymap.set({ "n", "v" }, "ge", "G", {})

-- Windows
vim.keymap.set({ "n", "v" }, "<c-left>", "<c-w>h", {})
vim.keymap.set({ "n", "v" }, "<c-right>", "<c-w>l", {})
vim.keymap.set({ "n", "v" }, "<c-down>", "<c-w>j", {})
vim.keymap.set({ "n", "v" }, "<c-up>", "<c-w>k", {})

vim.keymap.set({ "i" }, "<c-left>", "<c-o><c-w>h", {})
vim.keymap.set({ "i" }, "<c-right>", "<c-o><c-w>l", {})
vim.keymap.set({ "i" }, "<c-down>", "<c-o><c-w>j", {})
vim.keymap.set({ "i" }, "<c-up>", "<c-o><c-w>k", {})

-- Jumps
vim.keymap.set({ "n", "v" }, "j", "<c-o>", {})
vim.keymap.set({ "n", "v" }, "J", "<c-i>", {})

-- Modifications
vim.keymap.set("v", "<", "<gv", {})
vim.keymap.set("v", ">", ">gv", {})

-- Undo
vim.keymap.set({ "n", "v" }, "U", "<c-r>", {})

-- Git
vim.keymap.set({ "n", "v" }, "gs", "<cmd> Telescope git_status <cr>", {})
vim.keymap.set({ "n", "v" }, "gl", "<cmd> Telescope git_bcommits <cr>", {})

-- Save
vim.keymap.set({ "n", "v", "i" }, "<c-s>", "<cmd> w <cr>", {})

-- Surround: selections
vim.keymap.set({ "n", "v" }, "mw", "viw", {})
vim.keymap.set({ "n", "v" }, "mb", "vib", {})
vim.keymap.set({ "n", "v" }, "m(", "vib", {})
vim.keymap.set({ "n", "v" }, "mp", "vip", {})
vim.keymap.set({ "n", "v" }, "mq", "vi\"", {})
vim.keymap.set({ "n", "v" }, "m\"", "vi\"", {})

vim.keymap.set({ "n" }, "(", "vib", {})
vim.keymap.set({ "n" }, "\"", "vi\"", {})
vim.keymap.set({ "n" }, "{", "vi{", {})
vim.keymap.set({ "n" }, "[", "vi[", {})
vim.keymap.set({ "n" }, "<", "vi<", {})
vim.keymap.set({ "n" }, ">", "vit", {})
vim.keymap.set({ "n" }, "`", "vi`", {})

-- Surround: wrapping
vim.keymap.set({ "v" }, "(", "<Plug>(nvim-surround-visual))", { remap = true, silent = true })
vim.keymap.set({ "v" }, ")", "<Plug>(nvim-surround-visual))", { remap = true, silent = true })
vim.keymap.set({ "v" }, "[", "<Plug>(nvim-surround-visual)]", { remap = true, silent = true })
vim.keymap.set({ "v" }, "]", "<Plug>(nvim-surround-visual)]", { remap = true, silent = true })
vim.keymap.set({ "v" }, "{", "<Plug>(nvim-surround-visual)}", { remap = true, silent = true })
vim.keymap.set({ "v" }, "}", "<Plug>(nvim-surround-visual)}", { remap = true, silent = true })
vim.keymap.set({ "v" }, "\"", "<Plug>(nvim-surround-visual)\"", { remap = true, silent = true })
vim.keymap.set({ "v" }, "\'", "<Plug>(nvim-surround-visual)\'", { remap = true, silent = true })
vim.keymap.set({ "v" }, "`", "<Plug>(nvim-surround-visual)`", { remap = true, silent = true })
vim.keymap.set({ "n" }, "t", "<Plug>(nvim-surround-change)t", { remap = true, silent = true })
vim.keymap.set({ "v" }, "t", "<Plug>(nvim-surround-visual)t", { remap = true, silent = true })

-- Select all
vim.keymap.set({ "n", "v" }, "%", "ggVG", {})

-- LSP
vim.keymap.set({ "n", "v" }, "gd", vim.lsp.buf.definition, {})
vim.keymap.set({ "n", "v" }, "gr", "<cmd> Telescope lsp_references <cr>", {})
vim.keymap.set({ "n", "v" }, "h", vim.lsp.buf.hover, {})
vim.keymap.set({ "n", "v" }, "<leader>a", vim.lsp.buf.code_action, {})
vim.keymap.set({ "n", "v" }, "<leader>r", vim.lsp.buf.rename, {})
vim.keymap.set({ "n", "v" }, "<c-f>", vim.lsp.buf.format, {})

-- Commenting
vim.keymap.set({ "v", "x" }, "<c-c>", "gcgv", { remap = true })
vim.keymap.set({ "n" }, "<c-c>", "gcc", { remap = true })

-- Completion
-- Some advanced but very practical and easy to use logic:
--   Continue nvim-cmp completion, if it's already active
--   Accept copilot suggestion, if any
--   Use nvim-cmp, if any
--   If in insert mode, insert tab
function tab_complete()
    local copilot = require("copilot.suggestion")
    local cmp = require("cmp")

    if cmp.get_selected_index() ~= nil then
        return cmp.select_next_item()
    end

    if copilot.is_visible() then
        return copilot.accept()
    end

    if cmp.visible() then
        return cmp.select_next_item()
    end

    if vim.api.nvim_get_mode().mode == "i" then
        vim.fn.feedkeys("\t")
        return
    end
end

-- Enter completion
-- Again, some advanced logic to simplify completion usage
--   If there is SELECTED completion, accept it
--   Feed enter key otherwise
function enter_complete()
    local cmp = require("cmp")

    if cmp.get_selected_index() ~= nil then
        return cmp.confirm()
    end

    vim.fn.feedkeys("\n")
end

function esc_complete()
    local cmp = require("cmp")
    local copilot = require("copilot.suggestion")

    if cmp.visible() and copilot.is_visible() then
        return cmp.close()
    end

    vim.fn.feedkeys("\027")
end

vim.keymap.set({ "i" }, "<tab>", tab_complete, {})
vim.keymap.set({ "i" }, "<cr>", enter_complete, {})
vim.keymap.set({ "i" }, "<esc>", esc_complete, {})

-- Don't modify clipboard
vim.keymap.set({ "n", "v" }, "X", '"_x', {})
vim.keymap.set({ "n", "v" }, "c", '"_c', {})
vim.keymap.set({ "x", "v" }, "p", 'P', {})
vim.keymap.set({ "x", "v" }, "P", 'P', {})
vim.keymap.set({ "n" }, "V", '"_V', {})


================================================
FILE: config/nvim/nuitbleue.vim
================================================
set background=dark

source $VIMRUNTIME/colors/vim.lua
let g:colors_name = "nuitbleue"

let s:bg="#1d2433"
let s:bg_dim="#1a202e"
let s:bg_dim_more="#171c29"
let s:bg_sel="#333e59"
let s:bg_sel_hi="#293145"

let s:fg="#bfd3ff"
let s:fg_half_dim="#54678c"
let s:fg_dim="#3d4a66"

let s:red="#D0879D"
let s:orange="#D0B1A2"
let s:yellow="#CDD2AF"
let s:green="#9FD6B6"
let s:blue="#92b7ea"
let s:purple="#AD9BEA"
let s:pink="#CD9BCC"

let s:accent_dim="#7C7FB7"

function! s:hl(group, fg, bg)
  exec "highlight " . a:group . " guifg=" . a:fg . " guibg=" . a:bg
endfunction

" Backgrounds
call s:hl("Normal", s:fg, s:bg)
call s:hl("CursorLine", "NONE", s:bg_dim)
call s:hl("CursorLineNr", s:blue, s:bg_dim)
call s:hl("Visual", "NONE", s:bg_sel)
call s:hl("SignColumn", "NONE", s:bg)
call s:hl("FoldColumn", "NONE", s:bg)

call s:hl("TabLine", "NONE", s:bg_dim)
call s:hl("TabLineFill", "NONE", s:bg_dim)
highlight TabLineFill gui=none

call s:hl("StatusLine", s:purple, "NONE")
highlight StatusLine gui=none

call s:hl("StatusLineNC", s:fg_dim, "NONE")
highlight StatusLineNC gui=none

call s:hl("NormalFloat", "NONE", s:bg_dim)
call s:hl("FloatBorder", s:bg_dim, s:bg_dim)

" Color column
call s:hl("NonText", s:fg_dim, "NONE")
call s:hl("WinSeparator", s:fg_dim, "NONE")
call s:hl("CursorColumn", "NONE", s:fg_dim)

" Ident guide
call s:hl("IblScope", s:accent_dim, "NONE")

" Cursor
call s:hl("MatchParen", s:purple, s:bg_sel)
call s:hl("Cursor", s:bg, s:fg_half_dim)
call s:hl("MultiCursorSign", s:blue, "NONE")
" exec "hi MatchParen gui=underline guisp=" . s:purple

" Search
call s:hl("Search",    s:yellow, "NONE")
call s:hl("CurSearch", s:yellow, "NONE")
call s:hl("IncSearch", s:yellow, "NONE")
exec "hi Search gui=underline guisp=" . s:yellow
exec "hi CurSearch gui=underline guisp=" . s:yellow
exec "hi IncSearch gui=underline guisp=" . s:yellow

" Autocomplete menu
call s:hl("Pmenu", s:fg, s:bg)
call s:hl("PmenuSel", s:fg, s:bg_sel)
call s:hl("PmenuThumb", s:fg_dim, s:fg_dim)
call s:hl("PmenuSbar", s:red, s:bg_dim)

" Dimmed text
call s:hl("LineNr", s:fg_dim, s:bg)
call s:hl("Comment", s:fg_half_dim, "NONE")
call s:hl("Question", s:fg_half_dim, "NONE")

" Trailing white space
call s:hl("EoLSpace", s:red, "NONE")
match EoLSpace /\s\+$/

" White
call s:hl("Statement", s:fg, "NONE")
call s:hl("Identifier", s:fg, "NONE")

" Blue (functions)
call s:hl("Function", s:blue, "NONE")
call s:hl("Todo", s:blue, "NONE")
call s:hl("@tag.html", s:blue, "NONE")
call s:hl("@tag.xml", s:blue, "NONE")
call s:hl("@tag.vue", s:blue, "NONE")
call s:hl("@tag.delimiter.vue", s:blue, "NONE")
call s:hl("@tag.delimiter", s:blue, "NONE")
call s:hl("dosiniLabel", s:blue, "NONE")
call s:hl("tomlKey", s:blue, "NONE")

" Red (mutable variables)
call s:hl("@lsp.mod.mutable", s:red, "NONE")

" Purple (keywords, directories, html attributes)
call s:hl("Keyword", s:purple, "NONE")
call s:hl("@keyword", s:purple, "NONE")
call s:hl("@keyword.repeat", s:purple, "NONE")
call s:hl("@keyword.import", s:purple, "NONE")
call s:hl("@keyword.exception", s:purple, "NONE")
call s:hl("@keyword.conditional", s:purple, "NONE")
call s:hl("@keyword.type.python", s:purple, "NONE")
call s:hl("Directory", s:purple, "NONE")
call s:hl("@tag.attribute.html", s:purple, "NONE")
call s:hl("@tag.attribute.xml", s:purple, "NONE")
call s:hl("@tag.attribute.vue", s:purple, "NONE")
call s:hl("dosiniHeader", s:purple, "NONE")
call s:hl("zigVarDecl", s:purple, "NONE")
call s:hl("zigConditional", s:purple, "NONE")
call s:hl("zigExecution", s:purple, "NONE")

call s:hl("CfgSection", s:purple, "NONE")
call s:hl("tomlTable", s:purple, "NONE")
call s:hl("tomlTableArray", s:purple, "NONE")
call s:hl("Title", s:purple, "NONE")

" Green (strings)
call s:hl("String", s:green, "NONE")
call s:hl("CfgValues", s:green, "NONE")
call s:hl("CfgOnOff", s:green, "NONE")
call s:hl("@punctuation.special.vue", s:green, "NONE")

" Yellow (constants)
call s:hl("Constant", s:yellow, "NONE")
call s:hl("@constant.bash", s:blue, "NONE") " special case

" Orange (types, classes)
call s:hl("Type", s:orange, "NONE")
call s:hl("@constructor", s:orange, "NONE")
call s:hl("@type.builtin", s:orange, "NONE")
call s:hl("@character.rust", s:orange, "NONE") " special case to distinguish from strings
call s:hl("@character.zig", s:orange, "NONE")

" Pink (special, rare, important, builtins)
call s:hl("Special", s:pink, "NONE")
call s:hl("PreProc", s:pink, "NONE")
call s:hl("@boolean", s:pink, "NONE")
call s:hl("@constant.html", s:pink, "NONE")
call s:hl("@lsp.type.builtin.zig", s:pink, "NONE")
call s:hl("zigBuiltinFn", s:pink, "NONE")
call s:hl("zigNull", s:pink, "NONE")
call s:hl("@keyword.import.zig", s:pink, "NONE")

" Disabled
call s:hl("Delimiter", s:fg_half_dim, "NONE")
call s:hl("Operator", s:fg_half_dim, "NONE")
call s:hl("@constructor.lua", s:fg_half_dim, "NONE")
call s:hl("@tag.delimiter.html", s:fg_half_dim, "NONE")
call s:hl("dosiniSection", s:fg_half_dim, "NONE")
call s:hl("Conceal", s:red, s:green)

" Diagnostic
call s:hl("DiagnosticError", s:red, "NONE")
call s:hl("Error", s:red, "NONE")
call s:hl("ErrorMsg", s:red, "NONE")
call s:hl("DiagnosticOk", s:green, "NONE")

call s:hl("DiagnosticWarn", s:orange, "NONE")
call s:hl("WarningMsg", s:orange, "NONE")
exec "highlight SpellBad" . " guisp=" . s:orange

call s:hl("DiagnosticInfo", s:fg_half_dim, "NONE")
call s:hl("DiagnosticHint", s:fg_half_dim, "NONE")

exec "highlight DiagnosticUnderlineHint gui=NONE"
exec "highlight DiagnosticUnderlineInfo gui=NONE"
exec "highlight DiagnosticUnderlineWarn gui=NONE"
exec "highlight DiagnosticUnderlineError gui=NONE"

" Notifications
call s:hl("NotifyBackground", s:bg_dim, s:bg_dim)
call s:hl("NotifyERRORBody", s:red, s:bg_dim)
call s:hl("NotifyERRORBorder", s:bg_dim, s:bg_dim)
call s:hl("NotifyERRORIcon", s:red, "NONE")
call s:hl("NotifyERRORTitle", s:red, "NONE")

call s:hl("NotifyWARNBody", s:bg_dim, s:bg_dim)
call s:hl("NotifyWARNBorder", s:bg_dim, s:bg_dim)
call s:hl("NotifyWARNIcon", s:orange, "NONE")
call s:hl("NotifyWARNTitle", s:orange, "NONE")

call s:hl("NotifyINFOBody", s:bg_dim, s:bg_dim)
call s:hl("NotifyINFOBorder", s:bg_dim, s:bg_dim)
call s:hl("NotifyINFOIcon", s:blue, "NONE")
call s:hl("NotifyINFOTitle", s:blue, "NONE")

call s:hl("NotifyDEBUGBody", s:bg_dim, s:bg_dim)
call s:hl("NotifyDEBUGBorder", s:bg_dim, s:bg_dim)
call s:hl("NotifyDEBUGIcon", s:fg_dim, "NONE")
call s:hl("NotifyDEBUGTitle", s:fg_dim, "NONE")

call s:hl("NotifyTRACEBody", s:bg_dim, s:bg_dim)
call s:hl("NotifyTRACEBorder", s:bg_dim, s:bg_dim)
call s:hl("NotifyTRACEIcon", s:fg_dim, "NONE")
call s:hl("NotifyTRACETitle", s:fg_dim, "NONE")

" Diff
call s:hl("DiffAdd", s:green, "NONE")
call s:hl("GitSignsAdd", s:green, "NONE")
call s:hl("GitSignsStagedAdd", s:green, "NONE")
call s:hl("GitSignsStagedAddNr", s:green, "NONE")

call s:hl("DiffChange", s:purple, "NONE")
call s:hl("Changed", s:purple, "NONE")
call s:hl("GitSignsChange", s:purple, "NONE")
call s:hl("GitSignsStagedChange", s:purple, "NONE")
call s:hl("GitSignsStagedChangeNr", s:purple, "NONE")

call s:hl("DiffDelete", s:red, "NONE")
call s:hl("Removed", s:red, "NONE")
call s:hl("GitSignsDelete", s:red, "NONE")
call s:hl("GitSignsStagedDelete", s:red, "NONE")
call s:hl("GitSignsStagedDeleteNr", s:red, "NONE")

" Language:Markdown
call s:hl("@markup.list.markdown", s:fg_dim, "NONE")
call s:hl("@markup.list.checked.markdown", s:fg_dim, "NONE")
call s:hl("@markup.list.unchecked.markdown", s:red, "NONE")
call s:hl("@markup.raw.markdown_inline", s:green, "NONE")
call s:hl("@markup.raw.block.markdown", s:fg_half_dim, "NONE")
call s:hl("@label.markdown", s:orange, "NONE")
call s:hl("@markup.quote.markdown", s:fg, "NONE")
hi @markup.quote.markdown gui=italic
call s:hl("@punctuation.special.markdown", s:fg_half_dim, "NONE")
call s:hl("@markup.link.url.markdown_inline", s:fg_half_dim, "NONE")
call s:hl("@markup.link.label.markdown_inline", s:blue, "NONE")
hi @markup.link.url.markdown_inline gui=underline

" Language:calendar
call s:hl("calendarMonth", s:purple, "NONE")

" Plugin:Telescope
call s:hl("TelescopeNormal", s:fg, s:bg_dim)
call s:hl("TelescopeBorder", s:bg_dim, s:bg_dim)

call s:hl("TelescopePromptNormal", s:fg, s:bg_dim_more)
call s:hl("TelescopePromptTitle", s:fg, s:bg_dim_more)
call s:hl("TelescopePromptBorder", s:bg_dim_more, s:bg_dim_more)

call s:hl("TelescopePreviewBorder", s:bg_dim, s:bg_dim)
call s:hl("TelescopePreviewTitle", s:bg_dim, s:bg_dim)

call s:hl("TelescopeSelectionCaret", s:bg_sel, s:bg_sel)

" Plugin:Noice
call s:hl("NoiceCmdlinePopup", s:fg, s:bg_dim)
call s:hl("NoiceCmdlinePopupBorder", s:bg_dim, s:bg_dim)
call s:hl("NoicePopup", "NONE", s:bg_dim)

" Plugin:Diagflow
call s:hl("DiagnosticFloatingError", s:red, s:bg_dim)
call s:hl("DiagnosticFloatingWarn", s:orange, s:bg_dim)
call s:hl("DiagnosticFloatingOK", s:fg_half_dim, s:bg_dim)
call s:hl("DiagnosticFloatingInfo", s:fg_half_dim, s:bg_dim)
call s:hl("DiagnosticFloatingHint", s:fg_half_dim, s:bg_dim)

" Plugin:LocalHighlight
call s:hl("LocalHighlight", "NONE", s:bg_sel_hi)

" Plugin:Oil
call s:hl("OilFile", s:blue, "NONE")


================================================
FILE: config/paru/paru.conf
================================================
[options]
AurOnly
SortBy=votes
SkipReview

# Skip check step and dependencies
NoCheck

# Exit after first package build failed
FailFast

# Update "devel" packages
Devel
DevelSuffixes = -git -cvs -svn -bzr -darcs -always -hg -fossil


================================================
FILE: config/postgres/psqlrc
================================================
\set QUIET 1

-- Prompt (database ❯)
\set PROMPT1 ' %[%033[34m%]%/%[%033[37m%] ❯%[%033[0m%] '

-- Table style
-- border with outer lines
\pset border 2
-- ascii borders -- renders well in code blocks and looks okay
\pset linestyle ascii
\pset null '∅'

-- Other options
\set ON_ERROR_STOP on
\set VERBOSITY verbose

-- Change application name for debugging
set application_name to psql;

-- Enable command timing
\timing on

\unset QUIET


================================================
FILE: config/pypoetry/config.toml
================================================
[installer]
max-workers = 16

[keyring]
enabled = false

[virtualenvs]
in-project = true
prefer-active-python = true

  [virtualenvs.options]
  no-pip = true
  no-setuptools = true


================================================
FILE: config/ruff/ruff.toml
================================================
# NOTE: to use this configuration with local config file
#       you'll need to add `extend = "~/.config/ruff/ruff.toml"` there
#       see https://github.com/astral-sh/ruff/discussions/16516

line-length = 80
target-version = "py314"

[format]
  line-ending = "lf"
  docstring-code-format = true

[lint]
  select = [ "ALL" ]
  fixable = [ "ALL" ]
  ignore = [
    # Documentation
    "D",

    # Formatter rules
    "COM812", "ISC001",

    # TODO notes
    "FIX002",  # Ignore TODO, and HACK, but lint FIXME
    "FIX004",  # ^
    "TD001",   # ^
    "TD002",   # Do not ask for TODO's author and issue link
    "TD003",   # ^

    # __init__.py
    "INP001",

    # Controversial
    "SIM118",  # `key in dict.keys()` is better than `key in dict`
    "T201",    # Yeah it's bad in finished products, but in most scripts and
               # while debugging it's really annoying
    "RET504",  # Naming result before returning can improve readability
  ]

[lint.isort]
  force-sort-within-sections = false

[lint.flake8-bugbear]
  extend-immutable-calls = ["fastapi.Depends", "fastapi.Query", "fastapi.params.Query"]

[lint.flake8-builtins]
  builtins-ignorelist = ["id"]

[lint.flake8-quotes]
  avoid-escape = false

[lint.per-file-ignores]
  "tests/**/*.py" = [
    "S101",    # Asserts are necessary in tests
    "PLR2004", # Magic values are useful in tests
  ]
  "tests/**/test_bench_*.py" = [
    "ANN001",  # Allows usage of benchmark fixture
  ]


================================================
FILE: config/ssh/authorized_keys
================================================
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGucK2JUauI8z8ghO5AzutHt8G6G7mZe2n1Ri6wWhcSs zeta
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMcy3e1Fwb1VloEWSTQNFbZCVhBh1ky4eKEERHvCxFPx xi
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGrKycMDC9eFJd1Y8jMdXXux1PXCvzSpRB/3pbA8yKZm iota
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG3HwhJT74a+T63HO38F5Vz4BvUgKC2+tQmoa2DKc/fQ tau


================================================
FILE: config/ssh/config
================================================
# vim: set ft=sshconfig

Host lambda lambda.cj.dog
    User cj
    Port 1022

Host *.cj.dog
    User cj

Host voyager
    Port 2206

Host *
    # If user is unspecified, connect as root
    User root
    ExitOnForwardFailure yes

    # Security
    StrictHostKeyChecking accept-new
    HashKnownHosts yes

    # Avoid unnecessary output
    LogLevel QUIET

    # Network options
    ConnectTimeout 5
    ConnectionAttempts 3

    Compression yes
    IPQoS lowdelay
    AddressFamily inet

    # Multiplexing
    ControlMaster auto
    ControlPersist 15m
    ControlPath ~/.ssh/control/%h-%p-%r

    # Keepalive
    TCPKeepAlive yes
    ServerAliveInterval 3
    ServerAliveCountMax 20


================================================
FILE: config/sway/config
================================================
# Update user's systemd environment variables
include /etc/sway/config.d/*

# Startup
exec foot --server --log-level=none
exec waybar

# Disable X11 support
xwayland disable

# Configure outputs
output "*" {
  mode "2880x1620@60Hz"
  background "${repo}/wallpaper.png" fill
}

seat "*" {
  xcursor_theme capitaine-cursors-light 32
  hide_cursor when-typing enable
}

input type:keyboard {
  xkb_layout "us,ru"
  xkb_options "grp:caps_toggle,grp_led:caps,compose:ralt"

  repeat_delay 250
  repeat_rate 20
}

input "*" {
  tap enabled

  pointer_accel 0.25
  scroll_factor 0.15
  natural_scroll enabled
  drag_lock disabled
  dwt disabled  # do not disable while typing
}

# Options
floating_modifier Mod4

# Look and feel
default_border pixel 2
smart_borders on
popup_during_fullscreen ignore

client.focused #${blue} #${blue} #${bg} #${purple}
client.urgent #${red} #${red} #${bg}
client.focused_inactive #${bg} #${bg} #${fg_half_dim}
client.unfocused #${bg} #${bg} #${fg_half_dim}

# Hotkeys: windows
bindsym --to-code Mod4+w focus up
bindsym --to-code Mod4+a focus left
bindsym --to-code Mod4+s focus down
bindsym --to-code Mod4+d focus right

bindsym --to-code Mod4+Shift+w move up
bindsym --to-code Mod4+Shift+a move left
bindsym --to-code Mod4+Shift+s move down
bindsym --to-code Mod4+Shift+d move right

# Hotkeys: Scratchpads
bindsym --to-code Mod4+Shift+e mark "scratchpad-e", move scratchpad
bindsym --to-code Mod4+e [con_mark="scratchpad-e"] scratchpad show

bindsym --to-code Mod4+Shift+tab mark "scratchpad-tab", move scratchpad
bindsym --to-code Mod4+tab [con_mark="scratchpad-tab"] scratchpad show

bindsym --to-code Mod4+Shift+c mark "scratchpad-c", move scratchpad
bindsym --to-code Mod4+c [con_mark="scratchpad-c"] scratchpad show

# Hotkeys: control

bindsym --to-code Mod4+f fullscreen toggle
bindsym --to-code Mod4+g floating toggle
bindsym --to-code Mod4+q kill

# Hotkeys: split
bindsym --to-code Mod4+h split h
bindsym --to-code Mod4+v split v

# Hotkeys: sway
bindsym --to-code Mod4+Alt+r reload
bindsym --to-code Mod4+Alt+q exit
bindsym --to-code Mod4+Alt+x exit

# Hotkeys: workspaces
bindsym --to-code Mod4+1 workspace 1
bindsym --to-code Mod4+2 workspace 2
bindsym --to-code Mod4+3 workspace 3
bindsym --to-code Mod4+4 workspace 4
bindsym --to-code Mod4+5 workspace 5
bindsym --to-code Mod4+6 workspace 6
bindsym --to-code Mod4+7 workspace 7
bindsym --to-code Mod4+8 workspace 8
bindsym --to-code Mod4+9 workspace 9
bindsym --to-code Mod4+0 workspace 10
bindsym --to-code Mod4+minus workspace 11
bindsym --to-code Mod4+equal workspace 12

bindsym --to-code Mod4+Shift+1 move window to workspace 1
bindsym --to-code Mod4+Shift+2 move window to workspace 2
bindsym --to-code Mod4+Shift+3 move window to workspace 3
bindsym --to-code Mod4+Shift+4 move window to workspace 4
bindsym --to-code Mod4+Shift+5 move window to workspace 5
bindsym --to-code Mod4+Shift+6 move window to workspace 6
bindsym --to-code Mod4+Shift+7 move window to workspace 7
bindsym --to-code Mod4+Shift+8 move window to workspace 8
bindsym --to-code Mod4+Shift+9 move window to workspace 9
bindsym --to-code Mod4+Shift+0 move window to workspace 10
bindsym --to-code Mod4+Shift+minus move window to workspace 11
bindsym --to-code Mod4+Shift+equal move window to workspace 12

# Hotkeys: applications
bindsym --to-code Mod4+j exec footclient
bindsym --to-code Mod4+r exec fuzzel
bindsym --to-code Mod4+b exec firefox
bindsym --to-code Mod4+n exec makoctl dismiss --all

# Hotkeys: locking
bindsym --to-code Mod4+l exec swaylock
bindsym --no-repeat --release --locked --to-code Mod4+k output eDP-1 dpms toggle

# Hotkeys: audio
bindsym --locked XF86AudioMute exec wpctl set-mute \@DEFAULT_SINK@ toggle
bindsym --locked XF86AudioLowerVolume exec wpctl set-volume \@DEFAULT_SINK@ 5%-
bindsym --locked XF86AudioRaiseVolume exec wpctl set-volume \@DEFAULT_SINK@ 5%+

# Hotkeys: mic
bindsym --locked XF86AudioMicMute exec wpctl set-mute \@DEFAULT_SOURCE@ toggle
bindsym --locked F7 exec wpctl set-mute \@DEFAULT_SOURCE@ toggle

# Hotkeys: media
bindsym --locked XF86AudioPlay exec playerctl play-pause
bindsym --locked XF86AudioPause exec playerctl play-pause
bindsym --locked XF86AudioNext exec playerctl next
bindsym --locked XF86AudioPrev exec playerctl previous

# Hotkeys: brightness
bindsym --locked XF86MonBrightnessDown exec brightnessctl -e set 5%-
bindsym --locked XF86MonBrightnessUp exec brightnessctl -e set 5%+

# Hotkeys: screenshots
bindsym --locked Print exec slurp -b ${fg_dim}20 -c ${fg_dim}30 -w 1 | grim -g - - | wl-copy
bindsym --locked F12 exec slurp -b ${fg_dim}20 -c ${fg_dim}30 -w 1 | grim -g - - | wl-copy

# Switches. On is closed, off is open
bindswitch --locked --reload lid:off exec swaymsg "output * dpms on"
bindswitch --locked --reload lid:on exec swaymsg "output * dpms off"


================================================
FILE: config/swaylock/config
================================================
ignore-empty-password
show-failed-attempts
clock
image=${repo}/wallpaper.png
effect-blur=10x1
hide-keyboard-layout
font=Noto Sans Mono Light
font-size=100
timestr=%R
datestr=%d %b

indicator-x-position=300

indicator-idle-visible
indicator-radius=200
indicator-thickness=20

inside-color=00000000
inside-clear-color=00000000
inside-ver-color=00000000
inside-wrong-color=00000000
key-hl-color=${blue}50
bs-hl-color=${red}50
line-uses-inside

separator-color=00000000

ring-color=00000000
ring-ver-color=${blue}50
ring-wrong-color=${red}80
ring-clear-color=${green}50

text-color=${fg}
text-ver=
text-wrong=
text-clear=


================================================
FILE: config/termux/colors.properties
================================================
background : #${bg}
foreground : #${fg}
color0  : #${bg}
color1  : #${red}
color2  : #${green}
color3  : #${yellow}
color4  : #${blue}
color5  : #${purple}
color6  : #${cyan}
color7  : #${fg_half_dim}
color8  : #${fg_dim}
color9  : #${orange}
color10 : #${green}
color11 : #${yellow}
color12 : #${blue}
color13 : #${pink}
color14 : #${cyan}
color15 : #${fg}


================================================
FILE: config/termux/termux.properties
================================================
back-key=back
extra-keys=[['\`','ESC','TAB','CTRL','LEFT','DOWN','UP','RIGHT']]
terminal-margin-horizontal=0
terminal-margin-vertical=0


================================================
FILE: config/tmux/tmux.conf
================================================
# Options
set -sg terminal-overrides ",*:RGB"  # true color support
set -g escape-time 0  # disable delays on escape sequences
set -g mouse on
set -g renumber-windows on  # keep numbering sequential
set -g repeat-time 1000  # increase "prefix-free" window

# Options: start indexes from 1
set -g base-index 1
set -g pane-base-index 1

# Change prefix
unbind C-b
set -g prefix `
bind ` send-prefix

# Theme: borders
set -g pane-border-lines simple
set -g pane-border-style fg=black,bright
set -g pane-active-border-style fg=magenta

# Theme: status
set -g status-style bg=default,fg=black,bright
set -g status-left ""
set -g status-right "#[fg=black,bright]#S"

# Theme: status (windows)
set -g window-status-format "●"
set -g window-status-current-format "●"

set -g window-status-current-style "#{?window_zoomed_flag,fg=yellow,fg=magenta\#,nobold}"
set -g window-status-bell-style "fg=red,nobold"

# Keybindings: wasd
bind w select-pane -U
bind a select-pane -L
bind s select-pane -D
bind d select-pane -R

bind -r W resize-pane -U
bind -r A resize-pane -L
bind -r S resize-pane -D
bind -r D resize-pane -R

# Keybindings: disable repeat for arrows
bind Up select-pane -U
bind Left select-pane -L
bind Down select-pane -D
bind Right select-pane -R

# Keybindings: split
bind h split-window -h
bind | split-window -h
bind v split-window -v
bind - split-window -v

# Keybindings: windows
bind -n C-Tab next-window
bind -n C-S-Tab previous-window

bind -n M-1 select-window -t :1
bind -n M-2 select-window -t :2
bind -n M-3 select-window -t :3
bind -n M-4 select-window -t :4
bind -n M-5 select-window -t :5
bind -n M-6 select-window -t :6
bind -n M-7 select-window -t :7
bind -n M-8 select-window -t :8
bind -n M-9 select-window -t :9

# Keybindings: other
bind f resize-pane -Z
bind q detach-client
bind e choose-window -Z

bind -n M-w select-pane -U
bind -n M-a select-pane -L
bind -n M-s select-pane -D
bind -n M-d select-pane -R
bind -n M-f resize-pane -Z


================================================
FILE: config/waybar/config
================================================
{
  "layer": "top", // don't dim in special workspaces

  "modules-left": [],

  "modules-center": [
    "niri/workspaces",
  ],

  "modules-right": [
    "battery",
    "pulseaudio",
    "niri/language",
    "clock",
  ],

  "niri/workspaces": {
    "format": "{icon}",
    "format-icons": {
      "1": "1",
      "2": "2",
      "3": "3",
      "4": "4",
      "5": "5",
      "6": "6",
      "7": "7",
      "8": "8",
      "9": "",
      "13": "", // no icon for default empty workspace

      "obs": "󰕧",
      "msg": "",
      "tab": "",
    }
  },

  "battery": {
    "format": "{icon} {capacity}%",
    "format-charging": "󰂄 {capacity}%",

    "tooltip-format": "{timeTo} | {power}w",
    "format-icons": [ "󰂃", "󰂎", "󰁺", "󰁻", "󰁼", "󰁽", "󰁾", "󰁿", "󰂀", "󰂁", "󰂂", "󰁹" ],

    "states": {
      "critical": 10,
      "warning": 25,
      "low": 50,
      "full": 100,
    },
  },

  "pulseaudio": {
    "format": "{format_source}{icon} {volume}%",
    "format-muted": "{format_source}󰝟",

    "format-source": "<span color='#${red}'>󰍬 on</span>  ",  // red
    "format-source-muted": "",

    "format-icons": {
      "default": [ "󰕿", "󰖀", "󰕾", "󱄠" ],
    },

    "tooltip": false,
    "on-click": "pavucontrol",
    "on-click-right": "wpctl set-mute @DEFAULT_SINK@ toggle",
  },

  "niri/language": {
    "format": "󰌌 {}",
    "format-en": "us",
    "format-ru": "ru",
    "format-th": "th",

    "keyboard-name": "keyd-virtual-keyboard",
  },

  "clock": {
    "timezone": "Asia/Bangkok",
    "format": "󰅐 {:%H:%M}",

    "tooltip": true,
    "tooltip-format": "{:%e %B, %A}",  // 2 April, Saturday

    "on-click": "footclient --hold when ci"
  },
}


================================================
FILE: config/waybar/style.css
================================================
#waybar {
  background: #${bg};
  color: #${fg};
  font-family: "Noto Sans Mono Light";
  font-size: 14px;
  font-feature-settings: "calt";
}

/* padding */

#workspaces,
#backlight,
#battery,
#pulseaudio,
#language,
#clock {
  padding: 6px 10px;
}
#workspaces {
  padding-left: 16px;
}

#clock {
  padding-right: 20px;
}

/* clock */

#clock:hover {
  color: #AD9BEA;
}

/* pulseaudio */

#pulseaudio:hover {
  color: #AD9BEA;
}

/* workspaces */

#workspaces button.empty {
  opacity: 0.25;
  font-size: 0;
  margin-left: -10px;
  margin-right: -10px;
  padding: 0;
}

#workspaces button.empty.active {
  opacity: 1.0;
}

#workspaces button {
  color: #${fg_dim};

  border: none;
  border-radius: 0;

  font-size: 24px;
  padding: 0 16px;
  margin-left: 2px;
  margin-right: 2px;
}

#workspaces button.active, #workspaces button.focused {
  color: #${blue};
  border-bottom: 5px solid #${blue};
  margin-bottom: -5px;

  padding: 0 16px;
  font-size: 24px;
  margin-left: 2px;
  margin-right: 2px;
}

#workspaces button.urgent {
  color: #${red};
  border-bottom: 5px solid #${red};
  margin-bottom: -5px;

  padding: 0 16px;
  font-size: 24px;
  margin-left: 2px;
  margin-right: 2px;
}

#workspaces button:hover {
  background: none;
  color: #${purple};

  /* SEE https://github.com/Alexays/Waybar/issues/60 */
  box-shadow: inherit;
  text-shadow: inherit;
}

/* battery */

#battery.critical {
  color: #${red};
}

#battery.warning {
  color: #${orange};
}

#battery.low {
  color: #${yellow};
}

#battery.charging {
  color: #${green};
}


================================================
FILE: config/wofi/config
================================================
mode=drun
prompt=

width=100%
height=100%
xoffset=0
yoffset=0

hide_scroll=true
no_actions=true

insensitive=true
halign=start
content_halign=start
filter_rate=25


================================================
FILE: config/wofi/style.css
================================================
* {
  background: none;
  color: #${fg};
  border: none;
  outline: none;
  box-shadow: none;
  font: Noto Sans Mono Light;
  font-size: 24px;
}

#window {
  background: rgba(29, 36, 51, 0.75);  /* bg with opacity */
}

#input {
  padding: 24px;
}

#input * {
  color: transparent;
}

#outer-box {
  margin: 24px;
}

#inner-box {
  margin-left: 48px;
}

#entry {
  padding: 8px;
}

#entry:selected * {
  color: #${blue};
}


================================================
FILE: config/x11/xcompose
================================================
include "%L"

# === Math ===
<Multi_key> <plus> <minus> : "±"
<Multi_key> <minus> <plus> : "∓"

<Multi_key> <x> <x>     : "×"
<Multi_key> <m> <u> <l> : "⋅"

<Multi_key> <slash> <equal> : "≠"
<Multi_key> <equal> <slash> : "≠"

<Multi_key> <asciitilde> <asciitilde> : "≈"
<Multi_key> <asciitilde> <equal>      : "≈"

<Multi_key> <slash> <asciitilde> : "≉"
<Multi_key> <asciitilde> <slash> : "≉"

<Multi_key> <less> <equal> : "≤"
<Multi_key> <equal> <less> : "≤"

<Multi_key> <greater> <equal> : "≥"
<Multi_key> <equal> <greater> : "≥"

<Multi_key> <0> <0> : "∞"
<Multi_key> <o> <o> : "∞"

<Multi_key> <asciicircum> <0> : "°"
<Multi_key> <0> <asciicircum> : "°"

<Multi_key> <p> <r> <o> <d> : "∏"
<Multi_key> <s> <u> <m> : "∑"

# === Arrows ===
<Multi_key> <asciicircum> <bar> : "↑"
<Multi_key> <bar> <asciicircum> : "↑"

<Multi_key> <bar> <v> : "↓"
<Multi_key> <v> <bar> : "↓"

# === Esperanto ===
<Multi_key> <c> <asciicircum> : "ĉ"
<Multi_key> <c> <x>           : "ĉ"
<Multi_key> <g> <asciicircum> : "ĝ"
<Multi_key> <g> <x>           : "ĝ"
<Multi_key> <j> <asciicircum> : "ĵ"
<Multi_key> <j> <x>           : "ĵ"
<Multi_key> <s> <asciicircum> : "ŝ"
<Multi_key> <s> <x>           : "ŝ"
<Multi_key> <u> <asciicircum> : "û"
<Multi_key> <u> <x>           : "û"

<Multi_key> <C> <asciicircum> : "Ĉ"
<Multi_key> <C> <x>           : "Ĉ"
<Multi_key> <G> <asciicircum> : "Ĝ"
<Multi_key> <G> <x>           : "Ĝ"
<Multi_key> <J> <asciicircum> : "Ĵ"
<Multi_key> <J> <x>           : "Ĵ"
<Multi_key> <S> <asciicircum> : "Ŝ"
<Multi_key> <S> <x>           : "Ŝ"
<Multi_key> <U> <asciicircum> : "Û"
<Multi_key> <U> <x>           : "Û"

# === French ===
<Multi_key> <asciicircum> <o> : "ô"
<Multi_key> <o> <asciicircum> : "ô"
<Multi_key> <o> <x>           : "ô"

<Multi_key> <asciicircum> <O> : "Ô"
<Multi_key> <O> <asciicircum> : "Ô"
<Multi_key> <O> <x>           : "Ô"

# === Bullets ===
<Multi_key> <minus> <v> : "✓"
<Multi_key> <minus> <x> : "✗"
<Multi_key> <minus> <o> : "•"
<Multi_key> <minus> <bracketleft> : "□"

<Multi_key> <bracketleft>     <bracketright> : "☐"
<Multi_key> <bracketleft> <v> <bracketright> : "☑"
<Multi_key> <bracketleft> <x> <bracketright> : "☒"


================================================
FILE: config/xdg/mimeapps.list
================================================
[Default Applications]
x-scheme-handler/http=google-chrome-unstable.desktop
x-scheme-handler/https=google-chrome-unstable.desktop
x-scheme-handler/chrome=google-chrome-unstable.desktop
text/html=google-chrome-unstable.desktop
application/x-extension-htm=google-chrome-unstable.desktop
application/x-extension-html=google-chrome-unstable.desktop
application/x-extension-shtml=google-chrome-unstable.desktop
application/xhtml+xml=google-chrome-unstable.desktop
application/x-extension-xhtml=google-chrome-unstable.desktop
application/x-extension-xht=google-chrome-unstable.desktop

application/pdf=org.pwmt.zathura.desktop


================================================
FILE: config/xdg/user-dirs.dirs
================================================
XDG_DESKTOP_DIR="$HOME/"
XDG_DOWNLOAD_DIR="$HOME/downloads"
XDG_TEMPLATES_DIR="$HOME/"
XDG_PUBLICSHARE_DIR="$HOME/"
XDG_DOCUMENTS_DIR="$HOME/"
XDG_MUSIC_DIR="$HOME/"
XDG_PICTURES_DIR="$HOME/"
XDG_VIDEOS_DIR="$HOME/"


================================================
FILE: config/xdg-desktop-portal-wlr/config
================================================
[screencast]
output_name=eDP-1
chooser_type=none


================================================
FILE: config/xkb/rules/evdev
================================================
! include %S/evdev

! layout[1] option = symbols
* grp:caps_toggle12 = +group(caps_will_switch_to_second_layout):1

! layout[2] option = symbols
* grp:caps_toggle12 = +group(caps_will_switch_to_first_layout):2

! layout[3] option = symbols
* grp:caps_toggle12 = +group(caps_will_switch_to_first_layout):3


================================================
FILE: config/xkb/symbols/group
================================================
partial xkb_symbols "caps_will_switch_to_first_layout" {
  replace key <CAPS> { [ ISO_First_Group ] };
};

partial xkb_symbols "caps_will_switch_to_second_layout" {
  // NOTE: name is ISO_Last_Group but it maps to the second group
  replace key <CAPS> { [ ISO_Last_Group ] };
};


================================================
FILE: config/zathura/zathurarc
================================================
# === Keybindings ===
map w scroll up
map a scroll left
map s scroll down
map d scroll right

map W scroll half-up
map A scroll left
map S scroll half-down
map D scroll right

map <PageUp> scroll half-up
map <PageDown> scroll half-down

map r set recolor
map R reload
map f adjust_window width

map Z zoom in
map z zoom out

# === Options ===
set guioptions ""
set font "Noto Sans Mono Light 11"
set adjust-open width
set database plain
set dbus-service false
set page-cache-size 32
set show-recent false
set selection-clipboard secondary
set sandbox strict
set page-padding 16

# === Colors ===
set default-bg \#${bg_dim}
set completion-bg \#${bg}
set completion-fg \#${fg}
set inputbar-bg \#${bg}
set inputbar-fg \#${fg}
set completion-group-bg \#${bg}
set completion-group-fg \#${fg}
set tabbar-bg \#${bg}
set tabbar-fg \#${fg}
set statusbar-bg \#${bg}
set statusbar-fg \#${fg}
set index-bg \#${bg}
set index-fg \#${fg}

set completion-highlight-bg \#${blue}
set completion-highlight-fg \#${bg}
set tabbar-focus-bg \#${blue}
set tabbar-focus-fg \#${bg}
set index-active-bg \#${blue}
set index-active-fg \#${bg}

set notification-bg \#${fg}
set notification-fg \#${bg}

set notification-warning-bg \#${yellow}
set notification-warning-fg \#${bg}

set notification-error-bg \#${red}
set notification-error-fg \#${bg}

set recolor-darkcolor \#${fg}
set recolor-lightcolor \#${bg}


================================================
FILE: config/zed/keymap.json
================================================
[
  {
    "bindings": {
      "ctrl-shift-w": null,
      "ctrl-q": "pane::CloseActiveItem",
      "ctrl-b": "workspace::ToggleLeftDock",

      // Tabs
      "ctrl-tab": "pane::ActivateNextItem",
      "ctrl-shift-tab": "pane::ActivatePrevItem",

      // Projects
      "ctrl-o": "projects::OpenRecent",
      "ctrl-shift-o": "workspace::Open",

      // Search
      "ctrl-f": "vim::Search",
      "ctrl-shift-f": "pane::DeploySearch",

      // AI
      // Toggle right dock panel
      "ctrl-e": "workspace::ToggleRightDock",
      // Navigate to previous AI suggestion
      "ctrl-[": "copilot::PreviousSuggestion",
      // Navigate to next AI suggestion
      "ctrl-]": "copilot::NextSuggestion",
      // Manually trigger AI suggestions
      "ctrl-shift-space": "copilot::Suggest",

      // Global file finder
      "f": "file_finder::Toggle"
    }
  },

  {
    "context": "Editor",

    "bindings": {
      // Restore "f"
      "f": ["vim::PushOperator", { "FindForward": { "before": false } }],

      // Ctrl+W to delete word
      "ctrl-w": "editor::DeleteToPreviousWordStart",

      // Multi-cursor
      "ctrl-up": "editor::AddSelectionAbove",
      "ctrl-down": "editor::AddSelectionBelow",

      // Copy paste
      "ctrl-c": "editor::Copy",
      "ctrl-v": "editor::Paste",
      "ctrl-x": "editor::Cut"
    }
  },

  {
    // Reset global one-char hotkeys
    "context": "vim_mode == insert || mode == single_line || Terminal || mode == auto_height",
    "bindings": {
      "[": null,
      "]": null,
      "f": null
    }
  },

  {
    "context": "VimControl",

    "bindings": {
      // WASD movements
      "w": "vim::Up",
      "s": "vim::Down",
      "a": "vim::Left",
      "d": "vim::Right",

      // Move by word with capital A/D
      "A": "vim::PreviousWordStart",
      "D": "vim::NextWordEnd",

      // Move by 5 lines with W/S
      "W": ["workspace::SendKeystrokes", "5 w"],
      "S": ["workspace::SendKeystrokes", "5 s"],

      // Q/E to move to start/end of line
      "q": "vim::FirstNonWhitespace",
      "e": "vim::EndOfLine",

      "Q": "vim::InsertFirstNonWhitespace",
      "E": "vim::InsertEndOfLine",

      // Ctrl+W to delete word
      "ctrl-w": "editor::DeleteToPreviousWordStart",

      // Modifications
      "x": "vim::HelixDelete",
      "U": "vim::Redo",

      // Jumps
      "j": "pane::GoBack",
      "J": "pane::GoForward",
      "g e": "vim::StartOfDocument",
      "g r": "editor::GoToDefinitionSplit",
      "g f": "editor::OpenExcerpts",
      "g F": "editor::OpenExcerptsSplit",

      // Excerpts (TODO)
      "z w": "editor::ExpandExcerptsUp",
      "z s": "editor::ExpandExcerptsDown",

      // Multi-cursor
      "ctrl-up": "editor::AddSelectionAbove",
      "ctrl-down": "editor::AddSelectionBelow",
      "C": "editor::AddSelectionBelow",
      "v": "vim::ToggleVisualLine",
      "ctrl-d": ["editor::SelectNext", { "replace_newest": false }],
      "l": "editor::SplitSelectionIntoLines",

      // Visual mode
      "ctrl-shift-v": "vim::ToggleVisual"
    }
  },

  {
    "context": "vim_mode == normal || vim_mode == visual",

    "bindings": {
      // Pickers
      "space f": "file_finder::Toggle",
      "space d": "editor::GoToDiagnostic",
      "space D": "diagnostics::Deploy",
      "space a": "editor::ToggleCodeActions",
      "space s": "outline::Toggle",

      // Indentation
      ">": "vim::Indent",
      "<": "editor::TabPrev",

      // Panes
      "[": ["workspace::ActivatePaneInDirection", "Left"],
      "]": ["workspace::ActivatePaneInDirection", "Right"],

      // Help
      "h": "editor::Hover",

      // AI
      "shift-enter": "assistant::InlineAssist",

      // Selection
      "\"": ["workspace::SendKeystrokes", "ctrl-shift-v i \""]
    }
  },

  {
    "context": "vim_mode == normal",

    // TODO: clipboard make c and p not touch the clipboard (only x should do it)
    "bindings": {
      "y": "vim::YankLine",

      // Vim-like Modifications
      "c w": ["workspace::SendKeystrokes", "ctrl-d c"],
      "c c": ["workspace::SendKeystrokes", "v c"]
    }
  },

  {
    "context": "vim_mode == visual",

    "bindings": {
      "y": "vim::VisualYank",

      // AI
      "r": "assistant::InlineAssist"
    }
  },

  {
    "context": "vim_mode == insert",

    "bindings": {
      // Bash-like: Ctrl+A / Ctrl+E to move to start/end of file
      "ctrl-a": "vim::FirstNonWhitespace"
      // Conflicts with AI
      // "ctrl-e": "vim::EndOfLine"
    }
  }
]


================================================
FILE: config/zed/settings.json
================================================
{
  // Disable shit
  "telemetry": {
    "diagnostics": false,
    "metrics": false
  },
  "show_user_picture": false,
  "scrollbar": {
    "show": "auto",
    "axes": {
      "vertical": true,
      "horizontal": false
    }
  },
  "toolbar": {
    "breadcrumbs": true,
    "quick_actions": false
  },
  "tab_bar": { "show": false },
  "project_panel": { "button": false },
  "outline_panel": { "button": false },
  "collaboration_panel": { "button": false },
  "notification_panel": { "button": false },
  "terminal": {
    "button": false,
    "copy_on_select": true,
    "dock": "left",
    "toolbar": {
      "breadcrumbs": false
    }
  },
  "git": {
    "inline_blame": {
      "enabled": false
    }
  },

  // AI
  "assistant": {
    "default_model": {
      "provider": "copilot_chat",
      "model": "o3-mini"
    },
    "version": "2"
  },

  // Rullers and wrapping
  "wrap_guides": [80, 120],
  "preferred_line_length": 80,
  "soft_wrap": "none", // enable per-language

  // Smaller gutter
  "gutter": {
    "code_actions": false,
    "runnables": false,
    "folds": false
  },

  // Smaller statusbar
  "line_indicator_format": "short",

  // Maybe
  "active_pane_modifiers": {
    "magnification": 1.5,
    "inactive_opacity": 0.85
  },

  // Usability
  "vim_mode": true,
  "auto_signature_help": true,
  "hover_popover_delay": 50,
  "scroll_sensitivity": 5,
  "restore_on_startup": "none",

  // Extensions
  "auto_install_extensions": {
    "html": true,
    "dockerfile": true,
    "docker-compose": true,
    "ruff": true
  },

  // Looks
  "buffer_line_height": {
    "custom": 1.16 // Like I've used in terminal, but it's pretty dense
  },
  "ui_font_size": 15,
  "buffer_font_size": 15.0,
  "buffer_font_family": "Noto Sans Mono",
  "buffer_font_weight": 300,
  "ui_font_weight": 400,
  "ui_font_family": "Noto Sans",
  "theme": {
    "mode": "dark",
    "light": "One Light",
    "dark": "Casablanca"
  },

  // LSPs
  "lsp": {
    "rust-analyzer": {
      "initialization_options": {
        "cachePriming": { "enable": false },
        "completion": {
          "callable": { "snippets": "none" },
          "fullFunctionSignatures": { "enable": false },
          "limit": 1024,
          "postfix": { "enable": false },
          "hideDeprecated": true
        },

        "imports": { "preferNoStd": true },

        "hover": {
          "actions": { "run": { "enable": false } },
          "show": { "fields": 10 }
        },

        "inlayHints": {
          "chainingHints": { "enable": false },
          "closingBraceHints": { "enable": false },
          "genericParameterHints": { "const": { "enable": false } },
          "typeHints": { "enable": false },
          "parameterHints": { "enable": false },
          "renderColons": false
        },
        "lens": {
          "enable": false
        },
        "lru": {
          "capacity": 512
        },
        "diagnostics": {
          "experimental": {
            "enable": true
          },
          "styleLints": {
            "enable": true
          }
        },
        "check": {
          "command": "clippy"
        },
        "cargo": {
          "targetDir": true,
          "allTargets": false
        },
        "rustfmt": {
          "extraArgs": [
            "--config=empty_item_single_line=false",
            "--config=wrap_comments=true",
            "--config=condense_wildcard_suffixes=true",
            "--config=enum_discrim_align_threshold=10",
            "--config=format_code_in_doc_comments=true",
            "--config=hex_literal_case=Upper",
            "--config=max_width=80",
            "--config=reorder_impl_items=true",
            "--config=group_imports=StdExternalCrate",
            "--config=use_field_init_shorthand=true"
          ]
        }
      }
    }
  },

  // Languages
  "languages": {
    "Python": {
      "format_on_save": "on",
      "formatter": [{ "language_server": { "name": "ruff" } }]
    },
    "Markdown": { "soft_wrap": "preferred_line_length" }
  }
}


================================================
FILE: config/zed/theme.json
================================================
{
  "$schema": "https://zed.dev/schema/themes/v0.1.0.json",
  "name": "Casablanca",
  "author": "Denis Gruzdev",
  "themes": [
    {
      "name": "Casablanca",
      "appearance": "dark",
      "style": {
        "border": "#181E2C",
        "border.variant": "#181E2C",
        "border.focused": "#babbf1",
        "border.selected": "#BBAAF2",
        "border.transparent": "#ACDF96",
        "border.disabled": "#626880",
        "elevated_surface.background": "#181E2C",
        "surface.background": "#1D2433",
        "background": "#1D2433",
        "element.background": "#181E2C",
        "element.hover": "#7379944d",
        "element.active": "#ca9ee633",
        "element.selected": "#313847",
        "element.disabled": "#737994",
        "drop_target.background": "#ca9ee666",
        "ghost_element.background": null,
        "ghost_element.hover": "#606D88",
        "ghost_element.active": "#62688080",
        "ghost_element.selected": "#313847",
        "ghost_element.disabled": "#737994",
        "text": "#BDD9F2",
        "text.muted": "#b5bfe2",
        "text.placeholder": "#626880",
        "text.disabled": "#737994",
        "text.accent": "#BBAAF2",
        "icon": "#BDD9F2",
        "icon.muted": "#606D88",
        "icon.disabled": "#737994",
        "icon.placeholder": "#626880",
        "icon.accent": "#BBAAF2",
        "status_bar.background": "#181E2C",
        "title_bar.background": "#181E2C",
        "title_bar.inactive_background": "#1D2433",
        "toolbar.background": "#1D2433",
        "tab_bar.background": "#181E2C",
        "tab.inactive_background": "#181E2C",
        "tab.active_background": "#1D2433",
        "search.match_background": "#313847",
        "panel.background": "#181E2C",
        "panel.focused_border": "#181E2C",
        "pane.focused_border": "#181E2C",
        "scrollbar.thumb.background": "#9BB8F210",
        "scrollbar.thumb.hover_background": "#737994",
        "scrollbar.thumb.border": "#9BB8F200",
        "scrollbar.track.background": "#1D2433",
        "scrollbar.track.border": "#1D2433",
        "editor.foreground": "#BDD9F2",
        "editor.background": "#1D2433",
        "editor.gutter.background": "#1D2433",
        "editor.subheader.background": "#181E2C",
        "editor.active_line.background": "#181E2C",
        "editor.highlighted_line.background": "#606D88",
        "editor.line_number": "#606D88",
        "editor.active_line_number": "#BDD9F2",
        "editor.invisible": "#505D78",
        "editor.wrap_guide": "#313847",
        "editor.active_wrap_guide": "#626880",
        "editor.indent_guide": "#313847",
        "editor.indent_guide_active": "#505D78",
        "editor.document_highlight.read_background": "#303D58",
        "editor.document_highlight.write_background": "#303D58",
        "terminal.background": "#1D2433",
        "terminal.foreground": "#BDD9F2",
        "terminal.dim_foreground": "#606D88",
        "terminal.bright_foreground": "#BDD9F2",
        "terminal.ansi.black": "#51576d",
        "terminal.ansi.red": "#e78284",
        "terminal.ansi.green": "#ACDF96",
        "terminal.ansi.yellow": "#e5c890",
        "terminal.ansi.blue": "#9BB8F2",
        "terminal.ansi.magenta": "#f4b8e4",
        "terminal.ansi.cyan": "#81c8be",
        "terminal.ansi.white": "#BDD9F2",
        "terminal.ansi.bright_black": "#626880",
        "terminal.ansi.bright_red": "#e78284",
        "terminal.ansi.bright_green": "#ACDF96",
        "terminal.ansi.bright_yellow": "#e5c890",
        "terminal.ansi.bright_blue": "#9BB8F2",
        "terminal.ansi.bright_magenta": "#f4b8e4",
        "terminal.ansi.bright_cyan": "#81c8be",
        "terminal.ansi.bright_white": "#a5adce",
        "terminal.ansi.dim_black": "#51576d",
        "terminal.ansi.dim_red": "#e78284",
        "terminal.ansi.dim_green": "#ACDF96",
        "terminal.ansi.dim_yellow": "#e5c890",
        "terminal.ansi.dim_blue": "#9BB8F2",
        "terminal.ansi.dim_magenta": "#f4b8e4",
        "terminal.ansi.dim_cyan": "#81c8be",
        "terminal.ansi.dim_white": "#b5bfe2",
        "link_text.hover": "#99d1db",
        "conflict": "#BBAAF2",
        "conflict.border": "#BBAAF2",
        "conflict.background": "#181E2C",
        "created": "#ACDF96",
        "created.border": "#ACDF96",
        "created.background": "#181E2C",
        "deleted": "#e78284",
        "deleted.border": "#e78284",
        "deleted.background": "#181E2C",
        "error": "#e78284",
        "error.border": "#e78284",
        "error.background": "#181E2C",
        "hidden": "#737994",
        "hidden.border": "#737994",
        "hidden.background": "#181E2C",
        "hint": "#71989f",
        "hint.border": "#626880",
        "hint.background": "#181E2C",
        "ignored": "#737994",
        "ignored.border": "#737994",
        "ignored.background": "#181E2C",
        "info": "#81c8be",
        "info.border": "#81c8be",
        "info.background": "#ca9ee666",
        "modified": "#e5c890",
        "modified.border": "#e5c890",
        "modified.background": "#181E2C",
        "predictive": "#7d93c8",
        "predictive.border": "#babbf1",
        "predictive.background": "#181E2C",
        "renamed": "#85c1dc",
        "renamed.border": "#85c1dc",
        "renamed.background": "#181E2C",
        "success": "#ACDF96",
        "success.border": "#ACDF96",
        "success.background": "#181E2C",
        "unreachable": "#e78284",
        "unreachable.border": "#e78284",
        "unreachable.background": "#181E2C",
        "warning": "#ef9f76",
        "warning.border": "#ef9f76",
        "warning.background": "#181E2C",
        "players": [
          {
            "cursor": "#BDD9F280",
            "selection": "#313847",
            "background": "#f2d5cf"
          },
          {
            "cursor": "#accaeb",
            "selection": "#accaeb33",
            "background": "#accaeb"
          },
          {
            "cursor": "#d3b1c8",
            "selection": "#d3b1c833",
            "background": "#d3b1c8"
          },
          {
            "cursor": "#abcddf",
            "selection": "#abcddf33",
            "background": "#abcddf"
          },
          {
            "cursor": "#d7bdc2",
            "selection": "#d7bdc233",
            "background": "#d7bdc2"
          },
          {
            "cursor": "#d3cdcd",
            "selection": "#d3cdcd33",
            "background": "#d3cdcd"
          },
          {
            "cursor": "#afc1f2",
            "selection": "#afc1f233",
            "background": "#afc1f2"
          },
          {
            "cursor": "#b9d1ca",
            "selection": "#b9d1ca33",
            "background": "#b9d1ca"
          }
        ],
        "syntax": {
          "attribute": {
            "color": "#BBAAF2",
            "font_style": null,
            "font_weight": null
          },
          "boolean": {
            "color": "#ef9f76",
            "font_style": null,
            "font_weight": null
          },
          "comment": {
            "color": "#606D88",
            "font_style": "italic",
            "font_weight": null
          },
          "comment.doc": {
            "color": "#606D88",
            "font_style": "italic",
            "font_weight": null
          },
          "constant": {
            "color": "#BDD9F2",
            "font_style": null,
            "font_weight": null
          },
          "constructor": {
            "color": "#9BB8F2",
            "font_style": null,
            "font_weight": null
          },
          "embedded": {
            "color": "#ea999c",
            "font_style": null,
            "font_weight": null
          },
          "emphasis": {
            "color": "#e78284",
            "font_style": "italic",
            "font_weight": null
          },
          "emphasis.strong": {
            "color": "#e78284",
            "font_style": null,
            "font_weight": 700
          },
          "enum": {
            "color": "#81c8be",
            "font_style": null,
            "font_weight": 700
          },
          "function": {
            "color": "#9BB8F2",
            "font_style": "italic",
            "font_weight": null
          },
          "hint": {
            "color": "#71989f",
            "font_style": "italic",
            "font_weight": null
          },
          "keyword": {
            "color": "#BBAAF2",
            "font_style": null,
            "font_weight": null
          },
          "link_text": {
            "color": "#9BB8F2",
            "font_style": null,
            "font_weight": null
          },
          "link_uri": {
            "color": "#9BB8F2",
            "font_style": null,
            "font_weight": null
          },
          "number": {
            "color": "#DFD6c6", // NOTE: this is new yellow
            "font_style": null,
            "font_weight": null
          },
          "operator": {
            "color": "#606D88",
            "font_style": null,
            "font_weight": null
          },
          "predictive": {
            "color": "#7d93c8",
            "font_style": null,
            "font_weight": null
          },
          "predoc": {
            "color": "#e78284",
            "font_style": null,
            "font_weight": null
          },
          "primary": {
            "color": "#ea999c",
            "font_style": null,
            "font_weight": null
          },
          "property": {
            "color": "#9BB8F2",
            "font_style": null,
            "font_weight": null
          },
          "punctuation": {
            "color": "#81c8be",
            "font_style": null,
            "font_weight": null
          },
          "punctuation.bracket": {
            "color": "#606D88",
            "font_style": null,
            "font_weight": null
          },
          "punctuation.delimiter": {
            "color": "#606D88",
            "font_style": null,
            "font_weight": null
          },
          "punctuation.list_marker": {
            "color": "#81c8be",
            "font_style": null,
            "font_weight": null
          },
          "punctuation.special": {
            "color": "#606D88",
            "font_style": null,
            "font_weight": null
          },
          "punctuation.special.symbol": {
            "color": "#e78284",
            "font_style": null,
            "font_weight": null
          },
          "string": {
            "color": "#99dfbc", // NOTE: this is new green
            "font_style": null,
            "font_weight": null
          },
          "string.escape": {
            "color": "#f4b8e4",
            "font_style": null,
            "font_weight": null
          },
          "string.regex": {
            "color": "#f4b8e4",
            "font_style": null,
            "font_weight": null
          },
          "string.special": {
            "color": "#f4b8e4",
            "font_style": null,
            "font_weight": null
          },
          "string.special.symbol": {
            "color": "#eebebe",
            "font_style": null,
            "font_weight": null
          },
          "tag": {
            "color": "#9BB8F2",
            "font_style": null,
            "font_weight": null
          },
          "text.literal": {
            "color": "#ACDF96",
            "font_style": null,
            "font_weight": null
          },
          "title": {
            "color": "#BDD9F2",
            "font_style": null,
            "font_weight": 800
          },
          "type": {
            "color": "#818DA7",
            "font_style": null,
            "font_weight": null
          },
          "type.interface": {
            "color": "#e5c890",
            "font_style": null,
            "font_weight": null
          },
          "type.super": {
            "color": "#e5c890",
            "font_style": null,
            "font_weight": null
          },
          "variable": {
            "color": "#96bFe0",
            "font_style": null,
            "font_weight": null
          },
          "variable.member": {
            "color": "#BDD9F2",
            "font_style": null,
            "font_weight": null
          },
          "variable.parameter": {
            "color": "#96cFd0", // NOTE: this is new cyan
            "font_style": "italic",
            "font_weight": null
          },
          "variable.special": {
            "color": "#DF96C7",
            "font_style": "italic",
            "font_weight": null
          },
          "variant": {
            "color": "#e78284",
            "font_style": null,
            "font_weight": null
          }
        }
      }
    }
  ],
  "id": "9Mm3QFvdaQXFHg7WHrWax"
}


================================================
FILE: config/zsh/zprofile
================================================
# Programs
export EDITOR='nvim'
export TERMINAL='footclient'
export BROWSER='google-chrome-unstable'
export PAGER='less'

export VISUAL="${EDITOR}"

# Settings: fzf
FZF_DEFAULT_OPTS_ARR=(
  --scheme=history
  --ansi
  --exact
  --no-mouse

  # Reverse order
  --tac
  --layout=reverse

  # Styling
  --height=90%
  --min-height=7
  '--prompt="  "'
  --info=inline-right
  --border=none
  --no-scrollbar
  --no-separator
  --color='bw,fg:white,hl:regular:blue,fg+:regular,hl+:regular:blue,info:black:bold,prompt:black:bold,pointer:black:bold'
)
export FZF_DEFAULT_OPTS="$FZF_DEFAULT_OPTS_ARR"

# Settings: less
export LESS='-cigRS -j4 -x4 -#5 -z-10'
export LESSHISTFILE="-"

# Settings: pass
export PASSWORD_STORE_CLIP_TIME=8

# Settings: LS_COLORS
LS_COLORS='no=0:fi=0:di=34'

# Hidden files
LS_COLORS+=":.*=90"

# Programming (purple)
LS_COLORS+=":*.py=36:*.sh=36"
LS_COLORS+=":*Dockerfile=36:*Makefile=36"

# Text files (green)
LS_COLORS+=":*.md=32:*.txt=32:*.html=32"

# Config files (yellow)
LS_COLORS+=":*.json=33:*.toml=33:*.yml=33"
LS_COLORS+=":*.in=33:*.conf=33:*.example=33"
LS_COLORS+=":.zshrc=33:.zprofile=33"
export LS_COLORS

# Cleanup environment variables
unset MAIL
unset DEBUGINFOD_URLS

# Path: zvm, local binaries, cargo
export ZVM_INSTALL="$HOME/.zvm/self"
export PATH="$HOME/.zvm/bin:$ZVM_INSTALL:$HOME/.local/bin:$HOME/.cargo/bin:$HOME/.npm/bin:$PATH"


================================================
FILE: config/zsh/zshrc
================================================
# Aliases: editor
alias e="$EDITOR"
alias E="sudo -e"

# Aliases: ls
alias l='eza -1A --group-directories-first --color=always --git-ignore'
alias ls='l'
alias la='l -l --time-style="+%Y-%m-%d %H:%M" --no-permissions --octal-permissions'
alias tree='l --tree'

# Aliases: git
alias ga='git add'
alias gap='ga --patch'
alias gb='git branch'
alias gba='gb --all'
alias gc='git commit'
alias gca='gc --amend --no-edit'
alias gce='gc --amend'
alias gco='git checkout'
alias gcl='git clone --recursive'
alias gd='git diff --output-indicator-new=" " --output-indicator-old=" "'
alias gds='gd --staged'
alias gi='git init'
alias gl='git log --graph --all --pretty=format:"%C(magenta)%h %C(white) %an  %ar%C(auto)  %D%n%s%n"'
alias gm='git merge'
alias gn='git checkout -b'  # new branch
alias gp='git push'
alias gr='git reset'
alias gs='git status --short'
alias gu='git pull'
alias gw='git switch'

gcm() { git commit --message "$*" }

# Aliases: docker
alias dps='docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"'
alias dl='docker logs --tail=100'
alias dc='docker compose'

# Aliases: tmux
alias ta='tmux attach'
alias tl='tmux list-sessions'
alias tn='tmux new-session -s'

# Aliases: rg
alias rg="rg --hidden --smart-case --glob='!.git/' --no-search-zip --trim --colors=line:fg:black --colors=line:style:bold --colors=path:fg:magenta --colors=match:style:nobold"

# Aliases: pass
alias pa='pass'
alias pac='pass -c'
alias po='pass otp'
alias poc='pass otp -c'
alias pg='openssl rand -base64 33'

# Aliases: systemd
alias sd='sudo systemctl'
alias sdu='systemctl --user'
alias jd='journalctl --no-pager'

# Aliases: human-readable
alias cal='TZ=Asia/Bangkok cal --monday'
alias du='du --human-readable'
alias free='free --human'

# Aliases: safety
alias cp='cp --interactive'
alias mv='mv --interactive'

# Aliases: misc
mk() {
  mkdir --parents "$1" && cd "$1"
}
alias rf='rm -rf'
alias py='python3'
alias ipy='ipython'
alias ping='ping -A'

alias -g p='2>&1 | less'
alias sudo='sudo '  # allow aliases with sudo

# Aliases: package managers
if [[ -n "$TERMUX_VERSION" ]]; then
  alias pi='pkg install'
  alias pf='pkg search'
  alias pr='pkg uninstall'
else
  alias pi='sudo pacman -S --needed'
  alias pf='pacman -Ss'
  alias pr='sudo pacman -Rs'
fi

# Recommended kind of update with reduced keyring-related problems
alias pu='sudo pacman -Sy --needed archlinux-keyring && sudo pacman -Su'

# Aliases: ledger
alias lg='ledger'
alias lga='ledger accounts'
alias lgb='ledger balance'
alias lgr='ledger register'

# Aliases: when
alias wi='TZ=Asia/Bangkok when ci --future=30'

# Aliases: editors
alias ew='when eci'
alias en='cd ~/notes && e'
alias el='e ~/.ledger/journal.ldg'

# Aliases: git
alias git-notes='git -C ~/notes'
alias git-when='git -C ~/.when'
alias git-ledger='git -C ~/.ledger'

alias sync-commit-notes='git-notes add --all; git-notes commit --message sync; git-notes pull; git-notes push'

alias cj-pull='pass git pull; git-notes pull; git-when pull; git-ledger pull'
alias cj-status='pass git status; git-notes status; git-when status; git-ledger status'

# Man colors
man() {
  GROFF_NO_SGR=1 \
  LESS_TERMCAP_mb=$'\e[31m' \
  LESS_TERMCAP_md=$'\e[34m' \
  LESS_TERMCAP_me=$'\e[0m' \
  LESS_TERMCAP_se=$'\e[0m' \
  LESS_TERMCAP_so=$'\e[1;30m' \
  LESS_TERMCAP_ue=$'\e[0m' \
  LESS_TERMCAP_us=$'\e[35m' \
  command man "$@"
}

# Prompt
PROMPT=$'%{\033[34m%} %2~ %{\033[37m%}❯ %{\033[0m%}'
PROMPT2=$'%{\033[33m%} ... %{\033[0m%}'
RPROMPT=$'%(0?..%(130?..%{\033[31m%}%?%{\033[0m%}))'

# ZLE
KEYTIMEOUT=1  # 10ms for grouping escape sequences
WORDCHARS='-_:'

setopt interactive_comments

# Jobs
setopt auto_continue  # continue jobs on disown
setopt check_jobs  # do not exit shell with jobs
setopt check_running_jobs

# History
HISTFILE="$HOME/.zsh_history"
HISTSIZE=10000
SAVEHIST="$HISTSIZE"

setopt extended_history
setopt inc_append_history
setopt inc_append_history_time
setopt share_history
setopt hist_fcntl_lock

setopt hist_ignore_dups
setopt hist_ignore_all_dups
setopt hist_save_no_dups
setopt hist_ignore_space
setopt hist_reduce_blanks
setopt hist_no_store  # ignore fc command

HISTORY_IGNORE='(rm *|rf *)'

# History: interactive search
__history() {
  LBUFFER="$(fc -ln 0 | fzf --query="${LBUFFER}")"
  zle redisplay
}

zle -N __history

# Completion
LISTMAX=10000  # do not show warning if there is too much items in completion

setopt glob_dots  # include dotfiles into completion by default
setopt hash_cmds  # hash command locations
setopt list_packed

autoload -Uz compinit
compinit -C  # -C disables security checks on dump file

# _complete is base completer
# _extensions will complete glob patters with extensions
zstyle ':completion:*' completer _extensions _complete

zstyle ':completion:*' menu select  # menu with selection
zstyle ':completion:*' increment yes
zstyle ':completion:*' verbose yes
zstyle ':completion:*' squeeze-slashes yes  # replace // with /

zstyle ':completion:*' file-sort modification  # show recently used files first
zstyle ':completion:*' list-dirs-first yes
zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"  # colored files and directories, blue selection box
zstyle ':completion:*' ignored-patterns '.git'

zstyle ':completion:*' rehash false  # improves performance
zstyle ':completion:*' use-cache true


# Keyboard
unsetopt flow_control  # disable ^S / ^Q

bindkey -e  # Zsh default keybindings are vim, because EDITOR is set to vim, use emacs ones

bindkey '^I' complete-word  # Tab, complete instead of expand-and-complete
bindkey '^[[3~' delete-char  # Delete
bindkey '^[[Z' reverse-menu-complete  # Shift+Tab
bindkey '^[[1;5D' backward-word  # Control-Left
bindkey '^[[1;5C' forward-word  # Control-Right

bindkey '^R' __history

# Line editor
autoload -Uz edit-command-line
zle -N edit-command-line
bindkey '^S' edit-command-line

# Super Ctrl-Z
fg-ctrl-z () {
  fg 2> /dev/null
}
zle -N fg-ctrl-z
bindkey '^Z' fg-ctrl-z

# Fix for GPG pinentry
# SOURCE: https://github.com/keybase/keybase-issues/issues/2798
export GPG_TTY=$(tty)

# Plugin: zoxide
export _ZO_FZF_OPTS="$FZF_DEFAULT_OPTS --no-tac --select-1 --exit-0"
eval "$(zoxide init zsh --no-cmd)"
alias z='__zoxide_zi'
alias ~='cd ~'
ze() {
  DIR=$(zoxide query -i "$@")
  [ -n "$DIR" ] && cd "$DIR" && e .
}

# Plugin: autosuggestions
if [[ -n "$TERMUX_VERSION" ]]; then
  source ~/third-party/zsh-autosuggestions/zsh-autosuggestions.zsh
else
  source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
fi

ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=#606090'
ZSH_AUTOSUGGEST_STRATEGY=(history completion)
ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=40

# Plugin: syntax highlighting
if [[ -n "$TERMUX_VERSION" ]]; then
  source ~/third-party/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
else
  source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
fi

ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets)
ZSH_HIGHLIGHT_MAXLENGTH=120

# Rainbow brackets in special order, easier for eyes
ZSH_HIGHLIGHT_STYLES[bracket-level-1]='fg=magenta'
ZSH_HIGHLIGHT_STYLES[bracket-level-2]='fg=green'
ZSH_HIGHLIGHT_STYLES[bracket-level-3]='fg=blue'
ZSH_HIGHLIGHT_STYLES[bracket-level-4]='fg=yellow'
ZSH_HIGHLIGHT_STYLES[bracket-level-5]='fg=cyan'
ZSH_HIGHLIGHT_STYLES[bracket-level-6]='fg=red'

# Custom styles
# Errors
ZSH_HIGHLIGHT_STYLES[unknown-token]='fg=red,underline'

# Keywords
ZSH_HIGHLIGHT_STYLES[reserved-word]='fg=blue'

# Commands
ZSH_HIGHLIGHT_STYLES[precommand]='fg=cyan'
ZSH_HIGHLIGHT_STYLES[suffix-alias]='fg=magenta'
ZSH_HIGHLIGHT_STYLES[global-alias]='fg=magenta'
ZSH_HIGHLIGHT_STYLES[arg0]='fg=magenta'

# Strings
ZSH_HIGHLIGHT_STYLES[single-quoted-argument]='fg=green'
ZSH_HIGHLIGHT_STYLES[double-quoted-argument]='fg=green'
ZSH_HIGHLIGHT_STYLES[dollar-quoted-argument]='fg=yellow'

# Redirections
ZSH_HIGHLIGHT_STYLES[redirection]='fg=cyan'

# Paths
ZSH_HIGHLIGHT_STYLES[path]='none'


================================================
FILE: settings.toml
================================================
# Colors
bg          = "1d2433"
bg_dim      = "1a202e"
bg_dim_more = "171c29"
bg_sel      = "293145"

fg          = "bfd3ff"
fg_half_dim = "54678c"
fg_dim      = "3d4a66"

red         = "D0879D"
orange      = "D0B1A2"
yellow      = "CD
Download .txt
gitextract_yheofb5_/

├── README.md
├── config/
│   ├── aria2/
│   │   └── aria2.conf
│   ├── cargo/
│   │   └── config.toml
│   ├── chrome/
│   │   └── flags.conf
│   ├── cspell/
│   │   ├── cspell.yml
│   │   └── dict-cj.txt
│   ├── curl/
│   │   └── curlrc
│   ├── electron/
│   │   └── electron-flags.conf
│   ├── fd/
│   │   └── ignore
│   ├── fontconfig/
│   │   └── fonts.conf
│   ├── foot/
│   │   └── foot.ini
│   ├── fuzzel/
│   │   └── fuzzel.ini
│   ├── git/
│   │   ├── config
│   │   ├── ignore
│   │   └── template
│   ├── gnupg/
│   │   ├── gpg-agent.conf
│   │   └── gpg.conf
│   ├── helix/
│   │   ├── config.toml
│   │   ├── ignore
│   │   ├── languages.toml
│   │   └── theme.toml
│   ├── htop/
│   │   └── htoprc
│   ├── hypr/
│   │   ├── hypridle.conf
│   │   ├── hyprland.conf
│   │   └── hyprlock.conf
│   ├── ipython/
│   │   └── ipython_config.py
│   ├── ledger/
│   │   └── ledgerrc
│   ├── less/
│   │   └── lesskey
│   ├── mako/
│   │   └── config
│   ├── matplotlib/
│   │   └── matplotlibrc
│   ├── mpv/
│   │   ├── input.conf
│   │   └── mpv.conf
│   ├── niri/
│   │   └── config.kdl
│   ├── npm/
│   │   └── npmrc
│   ├── numbat/
│   │   └── config.toml
│   ├── nvim/
│   │   ├── init.lua
│   │   └── nuitbleue.vim
│   ├── paru/
│   │   └── paru.conf
│   ├── postgres/
│   │   └── psqlrc
│   ├── pypoetry/
│   │   └── config.toml
│   ├── ruff/
│   │   └── ruff.toml
│   ├── ssh/
│   │   ├── authorized_keys
│   │   └── config
│   ├── sway/
│   │   └── config
│   ├── swaylock/
│   │   └── config
│   ├── termux/
│   │   ├── colors.properties
│   │   └── termux.properties
│   ├── tmux/
│   │   └── tmux.conf
│   ├── waybar/
│   │   ├── config
│   │   └── style.css
│   ├── wofi/
│   │   ├── config
│   │   └── style.css
│   ├── x11/
│   │   └── xcompose
│   ├── xdg/
│   │   ├── mimeapps.list
│   │   └── user-dirs.dirs
│   ├── xdg-desktop-portal-wlr/
│   │   └── config
│   ├── xkb/
│   │   ├── rules/
│   │   │   └── evdev
│   │   └── symbols/
│   │       └── group
│   ├── zathura/
│   │   └── zathurarc
│   ├── zed/
│   │   ├── keymap.json
│   │   ├── settings.json
│   │   └── theme.json
│   └── zsh/
│       ├── zprofile
│       └── zshrc
├── settings.toml
└── tools/
    ├── deps
    └── render
Condensed preview — 67 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (220K chars).
[
  {
    "path": "README.md",
    "chars": 1902,
    "preview": "# Dotfiles\n\n> Configuration of software I personally use for software development\n\n![Showcase](./showcase.png)\n*Hyprland"
  },
  {
    "path": "config/aria2/aria2.conf",
    "chars": 203,
    "preview": "# Default download dir\ndir=${HOME}/downloads/aria\n\n# I usually have very bad internet, so no seeding :(\nseed-time=0\n\n# S"
  },
  {
    "path": "config/cargo/config.toml",
    "chars": 266,
    "preview": "[cargo-new]\nvcs = \"none\" # do not automatically create git repository\n\n# Let's make cargo quiet, more UNIX-like\n[term]\nq"
  },
  {
    "path": "config/chrome/flags.conf",
    "chars": 306,
    "preview": "# === Wayland support ===\n\n--ozone-platform=wayland\n\n# === Hardware acceleration tweaks ===\n\n# HW accelerated video enco"
  },
  {
    "path": "config/cspell/cspell.yml",
    "chars": 400,
    "preview": "---\n$schema: https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json\nversion: '0.2'\nlanguage"
  },
  {
    "path": "config/cspell/dict-cj.txt",
    "chars": 2842,
    "preview": "# Kekich\nКекич\nkekich\n\n# Assembler\ncmov\ncmovne\n\n# Helix\nnonwhitespace\ntextobject\nnoyank\n\n# Chess\nbitboard\nbitboards\nbits"
  },
  {
    "path": "config/curl/curlrc",
    "chars": 469,
    "preview": "# Follow redirects\nlocation\n\n# Do not output anything except on error\nsilent\nshow-error\n\n# Fail fast on server errors an"
  },
  {
    "path": "config/electron/electron-flags.conf",
    "chars": 126,
    "preview": "# Wayland support\n--enable-features=UseOzonePlatform,WaylandWindowDecorations,WebRTCPipeWireCapturer\n--ozone-platform=wa"
  },
  {
    "path": "config/fd/ignore",
    "chars": 88,
    "preview": ".git/\nnode_modules/\ntarget/\ndist/\n__pycache__/\n.mypy_cache/\n.venv/\n.zig-cache/\nzig-out/\n"
  },
  {
    "path": "config/fontconfig/fonts.conf",
    "chars": 827,
    "preview": "<?xml version=\"1.0\"?>\n<!DOCTYPE fontconfig SYSTEM \"urn:fontconfig:fonts.dtd\">\n<fontconfig>\n  <!-- Disable embedded bitma"
  },
  {
    "path": "config/foot/foot.ini",
    "chars": 1633,
    "preview": "[main]\n# Fonts\nfont=Noto Sans Mono Light:size=11,Arundina Sans Mono:size=17\nfont-bold=Noto Sans Mono Light:size=11\nfont-"
  },
  {
    "path": "config/fuzzel/fuzzel.ini",
    "chars": 477,
    "preview": "font = Noto Sans Mono Light:pixelsize=18\nprompt = \"\"\nicons-enabled = no\nlines = 8\nwidth = 50\nhorizontal-pad = 24\nvertica"
  },
  {
    "path": "config/git/config",
    "chars": 2850,
    "preview": "[user]\n    name = Denis Gruzdev\n    email = codingjerk@gmail.com\n    signingkey = E3DFEC736900FDE2\n\n[commit]\n    gpgSign"
  },
  {
    "path": "config/git/ignore",
    "chars": 168,
    "preview": "# Python specific\n.venv/\n.mypy_cache/\n.pytest_cache/\n__pycache__/\n.hypothesis/\n.ruff_cache/\n.ropeproject/\n\n# Rust specif"
  },
  {
    "path": "config/git/template",
    "chars": 336,
    "preview": "# feat: ✨ \n# feat: 🔍 \n# feat: 🔗 \n# feat: 🔒 \n\n# fix: 🐛 \n# fix: 🐞 \n# fix: 🩹 \n# fix: 🚑️ \n\n# style: 💅 \n# style: 🎨 \n# style: "
  },
  {
    "path": "config/gnupg/gpg-agent.conf",
    "chars": 110,
    "preview": "default-cache-ttl 1800  # 30 minutes\n\n# Ask for password in nicer menu\npinentry-program /usr/bin/pinentry-tty\n"
  },
  {
    "path": "config/gnupg/gpg.conf",
    "chars": 131,
    "preview": "no-greeting\ncharset utf-8\n\nkeyserver https://keys.openpgp.org\nkeyserver https://keyserver.ubuntu.com\nkeyserver https://p"
  },
  {
    "path": "config/helix/config.toml",
    "chars": 3169,
    "preview": "theme = \"cj\"\n\n[editor]\n  auto-save = false  # pretty annoying\n  auto-pairs = false  # too annoying sometimes\n  mouse = f"
  },
  {
    "path": "config/helix/ignore",
    "chars": 209,
    "preview": "# Home directories\n.cache/\n.password-store/\n.cargo/registry/\n.npm/\n\n*.tdb\n\n# Git specific\n.git-crypt/\n\n# Python specific"
  },
  {
    "path": "config/helix/languages.toml",
    "chars": 4670,
    "preview": "# Source: https://github.com/estin/simple-completion-language-server\n# Build: `cargo build --release`\n[language-server.b"
  },
  {
    "path": "config/helix/theme.toml",
    "chars": 3263,
    "preview": "# Syntax\n\"comment\" = \"fg-dim\"\n\n\"type\" = \"fg-half-dim\"\n\"constructor\" = \"yellow\"\n\n\"constant.numeric\" = \"yellow\"\n\"constant."
  },
  {
    "path": "config/htop/htoprc",
    "chars": 1605,
    "preview": "# Beware! This file is rewritten by htop when settings are changed in the interface.\n# The parser is also very primitive"
  },
  {
    "path": "config/hypr/hypridle.conf",
    "chars": 327,
    "preview": "general {\n  lock_cmd = pidof hyprlock || hyprlock\n}\n\n# Lock the screen after inactivity\nlistener {\n  timeout = 600  # 10"
  },
  {
    "path": "config/hypr/hyprland.conf",
    "chars": 6625,
    "preview": "monitor=eDP-1,preferred,auto,auto\n\necosystem {\n  no_update_news = true\n  no_donation_nag = true\n}\n\nmisc {\n  vrr = 1\n  vf"
  },
  {
    "path": "config/hypr/hyprlock.conf",
    "chars": 1028,
    "preview": "general {\n  disable_loading_bar = false\n  hide_cursor = true\n  ignore_empty_input = true\n}\n\nbackground {\n  path = ${repo"
  },
  {
    "path": "config/ipython/ipython_config.py",
    "chars": 476,
    "preview": "# No banner\nc.TerminalIPythonApp.display_banner = False\n\n# No exception tracebacks\nc.InteractiveShell.xmode = \"minimal\"\n"
  },
  {
    "path": "config/ledger/ledgerrc",
    "chars": 40,
    "preview": "--file ~/.ledger/journal.ldg\n--no-pager\n"
  },
  {
    "path": "config/less/lesskey",
    "chars": 92,
    "preview": "#command\nw back-line\nW back-screen\n\ns forw-line\nS forw-screen\n\na left-scroll\nd right-scroll\n"
  },
  {
    "path": "config/mako/config",
    "chars": 240,
    "preview": "font=Noto Sans Mono Light 11\n\nmax-history=0\nignore-timeout=1\nmax-visible=-1\n\nwidth=450\nheight=200\nanchor=top-right\nouter"
  },
  {
    "path": "config/matplotlib/matplotlibrc",
    "chars": 40905,
    "preview": "#### MATPLOTLIBRC FORMAT\n\n## NOTE FOR END USERS: DO NOT EDIT THIS FILE!\n##\n## This is a sample Matplotlib configuration "
  },
  {
    "path": "config/mpv/input.conf",
    "chars": 2116,
    "preview": "# === Normalization ===\nN af toggle \"lavfi=[dynaudnorm=framelen=100:gausssize=11:peak=0.95:maxgain=100:coupling=1]\"\n\n# ="
  },
  {
    "path": "config/mpv/mpv.conf",
    "chars": 898,
    "preview": "# === Interface ===\nwindow-dragging=no\n\nosd-font=Noto Sans\nosd-font-size=30\nosd-duration=2500\nosd-bar-align-y=0.50\nosd-b"
  },
  {
    "path": "config/niri/config.kdl",
    "chars": 8108,
    "preview": "// vim: set ts=2 sw=2:\n\n// Startup\nspawn-at-startup \"waybar\"\nspawn-at-startup \"mako\"\nspawn-at-startup \"swaybg\" \"--image\""
  },
  {
    "path": "config/npm/npmrc",
    "chars": 14,
    "preview": "prefix=~/.npm\n"
  },
  {
    "path": "config/numbat/config.toml",
    "chars": 144,
    "preview": "intro-banner = \"off\"\nprompt = \"\\u001B[0;32m 󰪚\\u001B[0;37m ❯ \\u001B[0m\"\npretty-print = \"auto\"\n\n[exchange-rates]\nfetching-"
  },
  {
    "path": "config/nvim/init.lua",
    "chars": 44725,
    "preview": "---@diagnostic disable: lowercase-global\n---@diagnostic disable: need-check-nil\n\n----------\n-- TODO --\n----------\n\n-- - "
  },
  {
    "path": "config/nvim/nuitbleue.vim",
    "chars": 9078,
    "preview": "set background=dark\n\nsource $VIMRUNTIME/colors/vim.lua\nlet g:colors_name = \"nuitbleue\"\n\nlet s:bg=\"#1d2433\"\nlet s:bg_dim="
  },
  {
    "path": "config/paru/paru.conf",
    "chars": 232,
    "preview": "[options]\nAurOnly\nSortBy=votes\nSkipReview\n\n# Skip check step and dependencies\nNoCheck\n\n# Exit after first package build "
  },
  {
    "path": "config/postgres/psqlrc",
    "chars": 438,
    "preview": "\\set QUIET 1\n\n-- Prompt (database ❯)\n\\set PROMPT1 ' %[%033[34m%]%/%[%033[37m%] ❯%[%033[0m%] '\n\n-- Table style\n-- border "
  },
  {
    "path": "config/pypoetry/config.toml",
    "chars": 181,
    "preview": "[installer]\nmax-workers = 16\n\n[keyring]\nenabled = false\n\n[virtualenvs]\nin-project = true\nprefer-active-python = true\n\n  "
  },
  {
    "path": "config/ruff/ruff.toml",
    "chars": 1455,
    "preview": "# NOTE: to use this configuration with local config file\n#       you'll need to add `extend = \"~/.config/ruff/ruff.toml\""
  },
  {
    "path": "config/ssh/authorized_keys",
    "chars": 341,
    "preview": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGucK2JUauI8z8ghO5AzutHt8G6G7mZe2n1Ri6wWhcSs zeta\nssh-ed25519 AAAAC3NzaC1lZDI1NTE5AA"
  },
  {
    "path": "config/ssh/config",
    "chars": 685,
    "preview": "# vim: set ft=sshconfig\n\nHost lambda lambda.cj.dog\n    User cj\n    Port 1022\n\nHost *.cj.dog\n    User cj\n\nHost voyager\n  "
  },
  {
    "path": "config/sway/config",
    "chars": 4803,
    "preview": "# Update user's systemd environment variables\ninclude /etc/sway/config.d/*\n\n# Startup\nexec foot --server --log-level=non"
  },
  {
    "path": "config/swaylock/config",
    "chars": 618,
    "preview": "ignore-empty-password\nshow-failed-attempts\nclock\nimage=${repo}/wallpaper.png\neffect-blur=10x1\nhide-keyboard-layout\nfont="
  },
  {
    "path": "config/termux/colors.properties",
    "chars": 358,
    "preview": "background : #${bg}\nforeground : #${fg}\ncolor0  : #${bg}\ncolor1  : #${red}\ncolor2  : #${green}\ncolor3  : #${yellow}\ncolo"
  },
  {
    "path": "config/termux/termux.properties",
    "chars": 136,
    "preview": "back-key=back\nextra-keys=[['\\`','ESC','TAB','CTRL','LEFT','DOWN','UP','RIGHT']]\nterminal-margin-horizontal=0\nterminal-ma"
  },
  {
    "path": "config/tmux/tmux.conf",
    "chars": 1959,
    "preview": "# Options\nset -sg terminal-overrides \",*:RGB\"  # true color support\nset -g escape-time 0  # disable delays on escape seq"
  },
  {
    "path": "config/waybar/config",
    "chars": 1661,
    "preview": "{\n  \"layer\": \"top\", // don't dim in special workspaces\n\n  \"modules-left\": [],\n\n  \"modules-center\": [\n    \"niri/workspace"
  },
  {
    "path": "config/waybar/style.css",
    "chars": 1547,
    "preview": "#waybar {\n  background: #${bg};\n  color: #${fg};\n  font-family: \"Noto Sans Mono Light\";\n  font-size: 14px;\n  font-featur"
  },
  {
    "path": "config/wofi/config",
    "chars": 163,
    "preview": "mode=drun\nprompt=\n\nwidth=100%\nheight=100%\nxoffset=0\nyoffset=0\n\nhide_scroll=true\nno_actions=true\n\ninsensitive=true\nhalign"
  },
  {
    "path": "config/wofi/style.css",
    "chars": 423,
    "preview": "* {\n  background: none;\n  color: #${fg};\n  border: none;\n  outline: none;\n  box-shadow: none;\n  font: Noto Sans Mono Lig"
  },
  {
    "path": "config/x11/xcompose",
    "chars": 2155,
    "preview": "include \"%L\"\n\n# === Math ===\n<Multi_key> <plus> <minus> : \"±\"\n<Multi_key> <minus> <plus> : \"∓\"\n\n<Multi_key> <x> <x>     "
  },
  {
    "path": "config/xdg/mimeapps.list",
    "chars": 621,
    "preview": "[Default Applications]\nx-scheme-handler/http=google-chrome-unstable.desktop\nx-scheme-handler/https=google-chrome-unstabl"
  },
  {
    "path": "config/xdg/user-dirs.dirs",
    "chars": 216,
    "preview": "XDG_DESKTOP_DIR=\"$HOME/\"\nXDG_DOWNLOAD_DIR=\"$HOME/downloads\"\nXDG_TEMPLATES_DIR=\"$HOME/\"\nXDG_PUBLICSHARE_DIR=\"$HOME/\"\nXDG_"
  },
  {
    "path": "config/xdg-desktop-portal-wlr/config",
    "chars": 49,
    "preview": "[screencast]\noutput_name=eDP-1\nchooser_type=none\n"
  },
  {
    "path": "config/xkb/rules/evdev",
    "chars": 305,
    "preview": "! include %S/evdev\n\n! layout[1] option = symbols\n* grp:caps_toggle12 = +group(caps_will_switch_to_second_layout):1\n\n! la"
  },
  {
    "path": "config/xkb/symbols/group",
    "chars": 279,
    "preview": "partial xkb_symbols \"caps_will_switch_to_first_layout\" {\n  replace key <CAPS> { [ ISO_First_Group ] };\n};\n\npartial xkb_s"
  },
  {
    "path": "config/zathura/zathurarc",
    "chars": 1380,
    "preview": "# === Keybindings ===\nmap w scroll up\nmap a scroll left\nmap s scroll down\nmap d scroll right\n\nmap W scroll half-up\nmap A"
  },
  {
    "path": "config/zed/keymap.json",
    "chars": 4479,
    "preview": "[\n  {\n    \"bindings\": {\n      \"ctrl-shift-w\": null,\n      \"ctrl-q\": \"pane::CloseActiveItem\",\n      \"ctrl-b\": \"workspace:"
  },
  {
    "path": "config/zed/settings.json",
    "chars": 4020,
    "preview": "{\n  // Disable shit\n  \"telemetry\": {\n    \"diagnostics\": false,\n    \"metrics\": false\n  },\n  \"show_user_picture\": false,\n "
  },
  {
    "path": "config/zed/theme.json",
    "chars": 12739,
    "preview": "{\n  \"$schema\": \"https://zed.dev/schema/themes/v0.1.0.json\",\n  \"name\": \"Casablanca\",\n  \"author\": \"Denis Gruzdev\",\n  \"them"
  },
  {
    "path": "config/zsh/zprofile",
    "chars": 1374,
    "preview": "# Programs\nexport EDITOR='nvim'\nexport TERMINAL='footclient'\nexport BROWSER='google-chrome-unstable'\nexport PAGER='less'"
  },
  {
    "path": "config/zsh/zshrc",
    "chars": 7875,
    "preview": "# Aliases: editor\nalias e=\"$EDITOR\"\nalias E=\"sudo -e\"\n\n# Aliases: ls\nalias l='eza -1A --group-directories-first --color="
  },
  {
    "path": "settings.toml",
    "chars": 356,
    "preview": "# Colors\nbg          = \"1d2433\"\nbg_dim      = \"1a202e\"\nbg_dim_more = \"171c29\"\nbg_sel      = \"293145\"\n\nfg          = \"bfd"
  },
  {
    "path": "tools/deps",
    "chars": 2014,
    "preview": "#!/usr/bin/env python\n\nimport shutil\nimport sys\nfrom dataclasses import dataclass\n\n\n@dataclass\nclass Binary:\n    name: s"
  },
  {
    "path": "tools/render",
    "chars": 8963,
    "preview": "#!/usr/bin/env python\n\nimport os\nimport shutil\nimport sys\nimport tomllib\nfrom dataclasses import dataclass\nfrom pathlib "
  }
]

About this extraction

This page contains the full source code of the codingjerk/dotfiles GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 67 files (197.9 KB), approximately 55.9k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!