Moving final computer over to OpenBSD 7.6. - dotfiles - These are my dotfiles. There are many like it, but these are mine.
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
---
(DIR) commit 2274190a12736e2d3c2dce6e346e582a7092dd5e
(DIR) parent 38522989aa40a65ccd5ce9d8635ec097f20a61d8
(HTM) Author: Jay Scott <me@jay.scot>
Date: Tue, 7 Jan 2025 20:11:03 +0000
Moving final computer over to OpenBSD 7.6.
Diffstat:
M README | 14 +++++++-------
A Xdefaults | 54 +++++++++++++++++++++++++++++++
D ashrc | 67 -------------------------------
A bin/diceware | 1338 ++++++++++++++++++++++++++++++
A bin/mullvad | 31 +++++++++++++++++++++++++++++++
M bin/music | 2 +-
A bin/pass | 279 +++++++++++++++++++++++++++++++
D bin/sway-start | 22 ----------------------
M bootstrap.sh | 4 ++--
D foot/foot.ini | 27 ---------------------------
A kshrc | 63 +++++++++++++++++++++++++++++++
A mpd/mpd.conf | 20 ++++++++++++++++++++
A ncmpcpp/config | 31 +++++++++++++++++++++++++++++++
M profile | 2 +-
D qutebrowser/blank.html | 44 -------------------------------
D qutebrowser/config.py | 92 -------------------------------
D qutebrowser/scripts/fingerprint.py | 43 ------------------------------
D qutebrowser/scripts/gruvbox.py | 332 -------------------------------
D qutebrowser/scripts/redirects.py | 70 -------------------------------
D qutebrowser/scripts/user_agent.py | 31 -------------------------------
A suckless/dmenu/Makefile | 39 +++++++++++++++++++++++++++++++
A suckless/dmenu/config.h | 16 ++++++++++++++++
A suckless/dmenu/patches/01-dmenu-bo… | 36 +++++++++++++++++++++++++++++++
A suckless/dmenu/patches/02-dmenu-ce… | 120 +++++++++++++++++++++++++++++++
A suckless/dwm/Makefile | 41 +++++++++++++++++++++++++++++++
A suckless/dwm/config.h | 201 ++++++++++++++++++++++++++++++
A suckless/dwm/patches/01-dwm-systra… | 746 +++++++++++++++++++++++++++++++
A suckless/herbe/Makefile | 40 +++++++++++++++++++++++++++++++
A suckless/herbe/config.h | 19 +++++++++++++++++++
A suckless/slstatus/Makefile | 35 +++++++++++++++++++++++++++++++
A suckless/slstatus/config.h | 71 +++++++++++++++++++++++++++++++
D sway/config | 69 ------------------------------
D waybar/config | 67 -------------------------------
D waybar/style.css | 55 -------------------------------
D waybar/waybar_mail.sh | 12 ------------
D waybar/waybar_vpn.sh | 9 ---------
A xenodm/Xresources | 24 ++++++++++++++++++++++++
A xenodm/Xsetup_0 | 7 +++++++
38 files changed, 3222 insertions(+), 951 deletions(-)
---
(DIR) diff --git a/README b/README
@@ -8,16 +8,16 @@
These are my dotfiles. There are many like it, but these are mine.
They are managed via the bootstrap.sh shell script, this links the files and
-folders in the appropriate place. They are used on Alpine Linux which I use as
-my main desktop OS and are forever evolving.
+folders in the appropriate place. They are used on OpenBSD which I use as my
+main desktop OS and are forever evolving.
- operating sys : alpine linux
- window manager : sway
- terminal : foot
- launcher : bemenu
+ operating sys : openbsd 7.6
+ window manager : dwm
+ terminal : xterm
+ launcher : dmenu
email : neomutt
- browser : qutebrowser / librewolf
+ browser : firefox / lynx
media : mpv
password mgmt : pass
vpn : mullvad
(DIR) diff --git a/Xdefaults b/Xdefaults
@@ -0,0 +1,54 @@
+xterm*FaceName: Hack
+xterm*FaceSize: 14
+xterm*toolBar: false
+xterm*scrollBar: false
+xterm*selectToClipboard: false
+XTerm*loginShell: true
+XTerm*scrollBar: false
+XTerm*selectToClipboard:true
+
+/* XFT */
+Xft.dpi: 96
+Xft.hinting: true
+Xft.rgba: rgb
+Xft.antialias: true
+Xft.autohint: false
+Xft.hintstyle: hintslight
+Xft.lcdfilter: lcddefault
+
+! special
+*.foreground: #ebdbb2
+*.background: #282828
+*.cursorColor: #fbf0d2
+
+! black
+*.color0: #181512
+*.color8: #454545
+
+! red
+*.color1: #bb6055
+*.color9: #c94539
+
+! green
+*.color2: #80964d
+*.color10: #aabb46
+
+! yellow
+*.color3: #8b6268
+*.color11: #dab733
+
+! blue
+*.color4: #756583
+*.color12: #a3535e
+
+! magenta
+*.color5: #628185
+*.color13: #becc90
+
+! cyan
+*.color6: #a4b810
+*.color14: #69c884
+
+! white
+*.color7: #d3cab3
+*.color15: #c9b09a
(DIR) diff --git a/ashrc b/ashrc
@@ -1,67 +0,0 @@
-export XDG_CONFIG_HOME="$HOME/.config"
-export XDG_CACHE_HOME="$HOME/.cache"
-export XDG_DATA_HOME="$HOME/.local/share"
-export XDG_STATE_HOME="$HOME/.local/state"
-
-# cleanup ~/
-export PASSWORD_STORE_DIR="$XDG_CONFIG_HOME"/pass
-export CARGO_HOME="$XDG_DATA_HOME"/cargo
-
-# common exports
-GPG_TTY=$(tty)
-export GPG_TTY
-export EDITOR="nvim"
-export BROWSER="qutebrowser"
-export PATH=$PATH:$HOME/bin
-
-# tools
-export OPENER=~/bin/link-handler
-export BEMENU_OPTS="-l 10 -p '>>> ' --tb '#55a1ba' --tf '#ffffff' --hf '#444444' -c -W0.4 --fn 'Hack 10'"
-
-# lynx
-export LYNX_CFG=$HOME/.config/lynx/config
-export LYNX_LSS=$HOME/.config/lynx/theme.lss
-
-# safety first kids!
-alias cp='cp -i'
-alias mv='mv -i'
-alias rm='rm -i'
-
-# random alias
-alias weather='curl wttr.in/?1QF'
-alias wget='wget --hsts-file="$XDG_CACHE_HOME/wget-hsts"'
-
-# git alias
-alias ga='git add -A'
-alias gs='git status -s'
-alias gl="git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
-alias gd='git diff'
-alias gma='git commit -am'
-
-# neo
-alias vim='nvim'
-alias mutt='neomutt'
-alias mpv="mpv --autofit=30% --really-quiet --no-terminal"
-alias w="w3m -B"
-
-# vpn
-alias von='doas wg-quick up mullvad'
-alias voff='doas wg-quick down mullvad'
-alias vcheck='curl https://am.i.mullvad.net/connected'
-
-# ash
-export LANG=en_US.UTF-8
-export LC_CTYPE="en_US.UTF-8"
-export LC_ALL=en_US.UTF-8
-export PS1="\[\e[00;34m\]▶▶▶ \W \[\e[0m\]"
-
-mirror_repo() {
- if [ -d .git ] || git rev-parse --git-dir > /dev/null 2>&1; then
- remote_url="git@jay.scot:$(basename $(pwd))"
- git remote add mirror "$remote_url" 2>/dev/null || true
- git push --mirror mirror
- echo "Mirrored to $remote_url"
- else
- echo "Not a git repository"
- fi
-}
(DIR) diff --git a/bin/diceware b/bin/diceware
@@ -0,0 +1,1338 @@
+#!/bin/sh
+#
+# diceware generates random phrases with 10 bits of entropy per
+# word. For a passphrase use 8 words or more.
+#
+# https://www.romanzolotarev.com/bin/diceware
+# Copyright 2017 Roman Zolotarev <hi@romanzolotarev.com>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# The word list: CC BY 3.0 US 2016 Electronic Frontier Foundation
+# https://www.eff.org/deeplinks/2016/07/new-wordlists-random-passphrases
+#
+set -e
+
+wordlist=$(cat << EOF
+1111 aardvark
+1112 abandoned
+1113 abbreviate
+1114 abdomen
+1115 abhorrence
+1116 abiding
+1121 abnormal
+1122 abrasion
+1123 absorbing
+1124 abundant
+1125 abyss
+1126 academy
+1131 accountant
+1132 acetone
+1133 achiness
+1134 acid
+1135 acoustics
+1136 acquire
+1141 acrobat
+1142 actress
+1143 acuteness
+1144 aerosol
+1145 aesthetic
+1146 affidavit
+1151 afloat
+1152 afraid
+1153 aftershave
+1154 again
+1155 agency
+1156 aggressor
+1161 aghast
+1162 agitate
+1163 agnostic
+1164 agonizing
+1165 agreeing
+1166 aidless
+1211 aimlessly
+1212 ajar
+1213 alarmclock
+1214 albatross
+1215 alchemy
+1216 alfalfa
+1221 algae
+1222 aliens
+1223 alkaline
+1224 almanac
+1225 alongside
+1226 alphabet
+1231 already
+1232 also
+1233 altitude
+1234 aluminum
+1235 always
+1236 amazingly
+1241 ambulance
+1242 amendment
+1243 amiable
+1244 ammunition
+1245 amnesty
+1246 amoeba
+1251 amplifier
+1252 amuser
+1253 anagram
+1254 anchor
+1255 android
+1256 anesthesia
+1261 angelfish
+1262 animal
+1263 anklet
+1264 announcer
+1265 anonymous
+1266 answer
+1311 antelope
+1312 anxiety
+1313 anyplace
+1314 aorta
+1315 apartment
+1316 apnea
+1321 apostrophe
+1322 apple
+1323 apricot
+1324 aquamarine
+1325 arachnid
+1326 arbitrate
+1331 ardently
+1332 arena
+1333 argument
+1334 aristocrat
+1335 armchair
+1336 aromatic
+1341 arrowhead
+1342 arsonist
+1343 artichoke
+1344 asbestos
+1345 ascend
+1346 aseptic
+1351 ashamed
+1352 asinine
+1353 asleep
+1354 asocial
+1355 asparagus
+1356 astronaut
+1361 asymmetric
+1362 atlas
+1363 atmosphere
+1364 atom
+1365 atrocious
+1366 attic
+1411 atypical
+1412 auctioneer
+1413 auditorium
+1414 augmented
+1415 auspicious
+1416 automobile
+1421 auxiliary
+1422 avalanche
+1423 avenue
+1424 aviator
+1425 avocado
+1426 awareness
+1431 awhile
+1432 awkward
+1433 awning
+1434 awoke
+1435 axially
+1436 azalea
+1441 babbling
+1442 backpack
+1443 badass
+1444 bagpipe
+1445 bakery
+1446 balancing
+1451 bamboo
+1452 banana
+1453 barracuda
+1454 basket
+1455 bathrobe
+1456 bazooka
+1461 blade
+1462 blender
+1463 blimp
+1464 blouse
+1465 blurred
+1466 boatyard
+1511 bobcat
+1512 body
+1513 bogusness
+1514 bohemian
+1515 boiler
+1516 bonnet
+1521 boots
+1522 borough
+1523 bossiness
+1524 bottle
+1525 bouquet
+1526 boxlike
+1531 breath
+1532 briefcase
+1533 broom
+1534 brushes
+1535 bubblegum
+1536 buckle
+1541 buddhist
+1542 buffalo
+1543 bullfrog
+1544 bunny
+1545 busboy
+1546 buzzard
+1551 cabin
+1552 cactus
+1553 cadillac
+1554 cafeteria
+1555 cage
+1556 cahoots
+1561 cajoling
+1562 cakewalk
+1563 calculator
+1564 camera
+1565 canister
+1566 capsule
+1611 carrot
+1612 cashew
+1613 cathedral
+1614 caucasian
+1615 caviar
+1616 ceasefire
+1621 cedar
+1622 celery
+1623 cement
+1624 census
+1625 ceramics
+1626 cesspool
+1631 chalkboard
+1632 cheesecake
+1633 chimney
+1634 chlorine
+1635 chopsticks
+1636 chrome
+1641 chute
+1642 cilantro
+1643 cinnamon
+1644 circle
+1645 cityscape
+1646 civilian
+1651 clay
+1652 clergyman
+1653 clipboard
+1654 clock
+1655 clubhouse
+1656 coathanger
+1661 cobweb
+1662 coconut
+1663 codeword
+1664 coexistent
+1665 coffeecake
+1666 cognitive
+2111 cohabitate
+2112 collarbone
+2113 computer
+2114 confetti
+2115 copier
+2116 cornea
+2121 cosmetics
+2122 cotton
+2123 couch
+2124 coverless
+2125 coyote
+2126 coziness
+2131 crawfish
+2132 crewmember
+2133 crib
+2134 croissant
+2135 crumble
+2136 crystal
+2141 cubical
+2142 cucumber
+2143 cuddly
+2144 cufflink
+2145 cuisine
+2146 culprit
+2151 cup
+2152 curry
+2153 cushion
+2154 cuticle
+2155 cybernetic
+2156 cyclist
+2161 cylinder
+2162 cymbal
+2163 cynicism
+2164 cypress
+2165 cytoplasm
+2166 dachshund
+2211 daffodil
+2212 dagger
+2213 dairy
+2214 dalmatian
+2215 dandelion
+2216 dartboard
+2221 dastardly
+2222 datebook
+2223 daughter
+2224 dawn
+2225 daytime
+2226 dazzler
+2231 dealer
+2232 debris
+2233 decal
+2234 dedicate
+2235 deepness
+2236 defrost
+2241 degree
+2242 dehydrator
+2243 deliverer
+2244 democrat
+2245 dentist
+2246 deodorant
+2251 depot
+2252 deranged
+2253 desktop
+2254 detergent
+2255 device
+2256 dexterity
+2261 diamond
+2262 dibs
+2263 dictionary
+2264 diffuser
+2265 digit
+2266 dilated
+2311 dimple
+2312 dinnerware
+2313 dioxide
+2314 diploma
+2315 directory
+2316 dishcloth
+2321 ditto
+2322 dividers
+2323 dizziness
+2324 doctor
+2325 dodge
+2326 doll
+2331 dominoes
+2332 donut
+2333 doorstep
+2334 dorsal
+2335 double
+2336 downstairs
+2341 dozed
+2342 drainpipe
+2343 dresser
+2344 driftwood
+2345 droppings
+2346 drum
+2351 dryer
+2352 dubiously
+2353 duckling
+2354 duffel
+2355 dugout
+2356 dumpster
+2361 duplex
+2362 durable
+2363 dustpan
+2364 dutiful
+2365 duvet
+2366 dwarfism
+2411 dwelling
+2412 dwindling
+2413 dynamite
+2414 dyslexia
+2415 eagerness
+2416 earlobe
+2421 easel
+2422 eavesdrop
+2423 ebook
+2424 eccentric
+2425 echoless
+2426 eclipse
+2431 ecosystem
+2432 ecstasy
+2433 edged
+2434 editor
+2435 educator
+2436 eelworm
+2441 eerie
+2442 effects
+2443 eggnog
+2444 egomaniac
+2445 ejection
+2446 elastic
+2451 elbow
+2452 elderly
+2453 elephant
+2454 elfishly
+2455 eliminator
+2456 elk
+2461 elliptical
+2462 elongated
+2463 elsewhere
+2464 elusive
+2465 elves
+2466 emancipate
+2511 embroidery
+2512 emcee
+2513 emerald
+2514 emission
+2515 emoticon
+2516 emperor
+2521 emulate
+2522 enactment
+2523 enchilada
+2524 endorphin
+2525 energy
+2526 enforcer
+2531 engine
+2532 enhance
+2533 enigmatic
+2534 enjoyably
+2535 enlarged
+2536 enormous
+2541 enquirer
+2542 enrollment
+2543 ensemble
+2544 entryway
+2545 enunciate
+2546 envoy
+2551 enzyme
+2552 epidemic
+2553 equipment
+2554 erasable
+2555 ergonomic
+2556 erratic
+2561 eruption
+2562 escalator
+2563 eskimo
+2564 esophagus
+2565 espresso
+2566 essay
+2611 estrogen
+2612 etching
+2613 eternal
+2614 ethics
+2615 etiquette
+2616 eucalyptus
+2621 eulogy
+2622 euphemism
+2623 euthanize
+2624 evacuation
+2625 evergreen
+2626 evidence
+2631 evolution
+2632 exam
+2633 excerpt
+2634 exerciser
+2635 exfoliate
+2636 exhale
+2641 exist
+2642 exorcist
+2643 explode
+2644 exquisite
+2645 exterior
+2646 exuberant
+2651 fabric
+2652 factory
+2653 faded
+2654 failsafe
+2655 falcon
+2656 family
+2661 fanfare
+2662 fasten
+2663 faucet
+2664 favorite
+2665 feasibly
+2666 february
+3111 federal
+3112 feedback
+3113 feigned
+3114 feline
+3115 femur
+3116 fence
+3121 ferret
+3122 festival
+3123 fettuccine
+3124 feudalist
+3125 feverish
+3126 fiberglass
+3131 fictitious
+3132 fiddle
+3133 figurine
+3134 fillet
+3135 finalist
+3136 fiscally
+3141 fixture
+3142 flashlight
+3143 fleshiness
+3144 flight
+3145 florist
+3146 flypaper
+3151 foamless
+3152 focus
+3153 foggy
+3154 folksong
+3155 fondue
+3156 footpath
+3161 fossil
+3162 fountain
+3163 fox
+3164 fragment
+3165 freeway
+3166 fridge
+3211 frosting
+3212 fruit
+3213 fryingpan
+3214 gadget
+3215 gainfully
+3216 gallstone
+3221 gamekeeper
+3222 gangway
+3223 garlic
+3224 gaslight
+3225 gathering
+3226 gauntlet
+3231 gearbox
+3232 gecko
+3233 gem
+3234 generator
+3235 geographer
+3236 gerbil
+3241 gesture
+3242 getaway
+3243 geyser
+3244 ghoulishly
+3245 gibberish
+3246 giddiness
+3251 giftshop
+3252 gigabyte
+3253 gimmick
+3254 giraffe
+3255 giveaway
+3256 gizmo
+3261 glasses
+3262 gleeful
+3263 glisten
+3264 glove
+3265 glucose
+3266 glycerin
+3311 gnarly
+3312 gnomish
+3313 goatskin
+3314 goggles
+3315 goldfish
+3316 gong
+3321 gooey
+3322 gorgeous
+3323 gosling
+3324 gothic
+3325 gourmet
+3326 governor
+3331 grape
+3332 greyhound
+3333 grill
+3334 groundhog
+3335 grumbling
+3336 guacamole
+3341 guerrilla
+3342 guitar
+3343 gullible
+3344 gumdrop
+3345 gurgling
+3346 gusto
+3351 gutless
+3352 gymnast
+3353 gynecology
+3354 gyration
+3355 habitat
+3356 hacking
+3361 haggard
+3362 haiku
+3363 halogen
+3364 hamburger
+3365 handgun
+3366 happiness
+3411 hardhat
+3412 hastily
+3413 hatchling
+3414 haughty
+3415 hazelnut
+3416 headband
+3421 hedgehog
+3422 hefty
+3423 heinously
+3424 helmet
+3425 hemoglobin
+3426 henceforth
+3431 herbs
+3432 hesitation
+3433 hexagon
+3434 hubcap
+3435 huddling
+3436 huff
+3441 hugeness
+3442 hullabaloo
+3443 human
+3444 hunter
+3445 hurricane
+3446 hushing
+3451 hyacinth
+3452 hybrid
+3453 hydrant
+3454 hygienist
+3455 hypnotist
+3456 ibuprofen
+3461 icepack
+3462 icing
+3463 iconic
+3464 identical
+3465 idiocy
+3466 idly
+3511 igloo
+3512 ignition
+3513 iguana
+3514 illuminate
+3515 imaging
+3516 imbecile
+3521 imitator
+3522 immigrant
+3523 imprint
+3524 iodine
+3525 ionosphere
+3526 ipad
+3531 iphone
+3532 iridescent
+3533 irksome
+3534 iron
+3535 irrigation
+3536 island
+3541 isotope
+3542 issueless
+3543 italicize
+3544 itemizer
+3545 itinerary
+3546 itunes
+3551 ivory
+3552 jabbering
+3553 jackrabbit
+3554 jaguar
+3555 jailhouse
+3556 jalapeno
+3561 jamboree
+3562 janitor
+3563 jarring
+3564 jasmine
+3565 jaundice
+3566 jawbreaker
+3611 jaywalker
+3612 jazz
+3613 jealous
+3614 jeep
+3615 jelly
+3616 jeopardize
+3621 jersey
+3622 jetski
+3623 jezebel
+3624 jiffy
+3625 jigsaw
+3626 jingling
+3631 jobholder
+3632 jockstrap
+3633 jogging
+3634 john
+3635 joinable
+3636 jokingly
+3641 journal
+3642 jovial
+3643 joystick
+3644 jubilant
+3645 judiciary
+3646 juggle
+3651 juice
+3652 jujitsu
+3653 jukebox
+3654 jumpiness
+3655 junkyard
+3656 juror
+3661 justifying
+3662 juvenile
+3663 kabob
+3664 kamikaze
+3665 kangaroo
+3666 karate
+4111 kayak
+4112 keepsake
+4113 kennel
+4114 kerosene
+4115 ketchup
+4116 khaki
+4121 kickstand
+4122 kilogram
+4123 kimono
+4124 kingdom
+4125 kiosk
+4126 kissing
+4131 kite
+4132 kleenex
+4133 knapsack
+4134 kneecap
+4135 knickers
+4136 koala
+4141 krypton
+4142 laboratory
+4143 ladder
+4144 lakefront
+4145 lantern
+4146 laptop
+4151 laryngitis
+4152 lasagna
+4153 latch
+4154 laundry
+4155 lavender
+4156 laxative
+4161 lazybones
+4162 lecturer
+4163 leftover
+4164 leggings
+4165 leisure
+4166 lemon
+4211 length
+4212 leopard
+4213 leprechaun
+4214 lettuce
+4215 leukemia
+4216 levers
+4221 lewdness
+4222 liability
+4223 library
+4224 licorice
+4225 lifeboat
+4226 lightbulb
+4231 likewise
+4232 lilac
+4233 limousine
+4234 lint
+4235 lioness
+4236 lipstick
+4241 liquid
+4242 listless
+4243 litter
+4244 liverwurst
+4245 lizard
+4246 llama
+4251 luau
+4252 lubricant
+4253 lucidity
+4254 ludicrous
+4255 luggage
+4256 lukewarm
+4261 lullaby
+4262 lumberjack
+4263 lunchbox
+4264 luridness
+4265 luscious
+4266 luxurious
+4311 lyrics
+4312 macaroni
+4313 maestro
+4314 magazine
+4315 mahogany
+4316 maimed
+4321 majority
+4322 makeover
+4323 malformed
+4324 mammal
+4325 mango
+4326 mapmaker
+4331 marbles
+4332 massager
+4333 matchstick
+4334 maverick
+4335 maximum
+4336 mayonnaise
+4341 moaning
+4342 mobilize
+4343 moccasin
+4344 modify
+4345 moisture
+4346 molecule
+4351 momentum
+4352 monastery
+4353 moonshine
+4354 mortuary
+4355 mosquito
+4356 motorcycle
+4361 mousetrap
+4362 movie
+4363 mower
+4364 mozzarella
+4365 muckiness
+4366 mudflow
+4411 mugshot
+4412 mule
+4413 mummy
+4414 mundane
+4415 muppet
+4416 mural
+4421 mustard
+4422 mutation
+4423 myriad
+4424 myspace
+4425 myth
+4426 nail
+4431 namesake
+4432 nanosecond
+4433 napkin
+4434 narrator
+4435 nastiness
+4436 natives
+4441 nautically
+4442 navigate
+4443 nearest
+4444 nebula
+4445 nectar
+4446 nefarious
+4451 negotiator
+4452 neither
+4453 nemesis
+4454 neoliberal
+4455 nephew
+4456 nervously
+4461 nest
+4462 netting
+4463 neuron
+4464 nevermore
+4465 nextdoor
+4466 nicotine
+4511 niece
+4512 nimbleness
+4513 nintendo
+4514 nirvana
+4515 nuclear
+4516 nugget
+4521 nuisance
+4522 nullify
+4523 numbing
+4524 nuptials
+4525 nursery
+4526 nutcracker
+4531 nylon
+4532 oasis
+4533 oat
+4534 obediently
+4535 obituary
+4536 object
+4541 obliterate
+4542 obnoxious
+4543 observer
+4544 obtain
+4545 obvious
+4546 occupation
+4551 oceanic
+4552 octopus
+4553 ocular
+4554 office
+4555 oftentimes
+4556 oiliness
+4561 ointment
+4562 older
+4563 olympics
+4564 omissible
+4565 omnivorous
+4566 oncoming
+4611 onion
+4612 onlooker
+4613 onstage
+4614 onward
+4615 onyx
+4616 oomph
+4621 opaquely
+4622 opera
+4623 opium
+4624 opossum
+4625 opponent
+4626 optical
+4631 opulently
+4632 oscillator
+4633 osmosis
+4634 ostrich
+4635 otherwise
+4636 ought
+4641 outhouse
+4642 ovation
+4643 oven
+4644 owlish
+4645 oxford
+4646 oxidize
+4651 oxygen
+4652 oyster
+4653 ozone
+4654 pacemaker
+4655 padlock
+4656 pageant
+4661 pajamas
+4662 palm
+4663 pamphlet
+4664 pantyhose
+4665 paprika
+4666 parakeet
+5111 passport
+5112 patio
+5113 pauper
+5114 pavement
+5115 payphone
+5116 pebble
+5121 peculiarly
+5122 pedometer
+5123 pegboard
+5124 pelican
+5125 penguin
+5126 peony
+5131 pepperoni
+5132 peroxide
+5133 pesticide
+5134 petroleum
+5135 pewter
+5136 pharmacy
+5141 pheasant
+5142 phonebook
+5143 phrasing
+5144 physician
+5145 plank
+5146 pledge
+5151 plotted
+5152 plug
+5153 plywood
+5154 pneumonia
+5155 podiatrist
+5156 poetic
+5161 pogo
+5162 poison
+5163 poking
+5164 policeman
+5165 poncho
+5166 popcorn
+5211 porcupine
+5212 postcard
+5213 poultry
+5214 powerboat
+5215 prairie
+5216 pretzel
+5221 princess
+5222 propeller
+5223 prune
+5224 pry
+5225 pseudo
+5226 psychopath
+5231 publisher
+5232 pucker
+5233 pueblo
+5234 pulley
+5235 pumpkin
+5236 punchbowl
+5241 puppy
+5242 purse
+5243 pushup
+5244 putt
+5245 puzzle
+5246 pyramid
+5251 python
+5252 quarters
+5253 quesadilla
+5254 quilt
+5255 quote
+5256 racoon
+5261 radish
+5262 ragweed
+5263 railroad
+5264 rampantly
+5265 rancidity
+5266 rarity
+5311 raspberry
+5312 ravishing
+5313 rearrange
+5314 rebuilt
+5315 receipt
+5316 reentry
+5321 refinery
+5322 register
+5323 rehydrate
+5324 reimburse
+5325 rejoicing
+5326 rekindle
+5331 relic
+5332 remote
+5333 renovator
+5334 reopen
+5335 reporter
+5336 request
+5341 rerun
+5342 reservoir
+5343 retriever
+5344 reunion
+5345 revolver
+5346 rewrite
+5351 rhapsody
+5352 rhetoric
+5353 rhino
+5354 rhubarb
+5355 rhyme
+5356 ribbon
+5361 riches
+5362 ridden
+5363 rigidness
+5364 rimmed
+5365 riptide
+5366 riskily
+5411 ritzy
+5412 riverboat
+5413 roamer
+5414 robe
+5415 rocket
+5416 romancer
+5421 ropelike
+5422 rotisserie
+5423 roundtable
+5424 royal
+5425 rubber
+5426 rudderless
+5431 rugby
+5432 ruined
+5433 rulebook
+5434 rummage
+5435 running
+5436 rupture
+5441 rustproof
+5442 sabotage
+5443 sacrifice
+5444 saddlebag
+5445 saffron
+5446 sainthood
+5451 saltshaker
+5452 samurai
+5453 sandworm
+5454 sapphire
+5455 sardine
+5456 sassy
+5461 satchel
+5462 sauna
+5463 savage
+5464 saxophone
+5465 scarf
+5466 scenario
+5511 schoolbook
+5512 scientist
+5513 scooter
+5514 scrapbook
+5515 sculpture
+5516 scythe
+5521 secretary
+5522 sedative
+5523 segregator
+5524 seismology
+5525 selected
+5526 semicolon
+5531 senator
+5532 septum
+5533 sequence
+5534 serpent
+5535 sesame
+5536 settler
+5541 severely
+5542 shack
+5543 shelf
+5544 shirt
+5545 shovel
+5546 shrimp
+5551 shuttle
+5552 shyness
+5553 siamese
+5554 sibling
+5555 siesta
+5556 silicon
+5561 simmering
+5562 singles
+5563 sisterhood
+5564 sitcom
+5565 sixfold
+5566 sizable
+5611 skateboard
+5612 skeleton
+5613 skies
+5614 skulk
+5615 skylight
+5616 slapping
+5621 sled
+5622 slingshot
+5623 sloth
+5624 slumbering
+5625 smartphone
+5626 smelliness
+5631 smitten
+5632 smokestack
+5633 smudge
+5634 snapshot
+5635 sneezing
+5636 sniff
+5641 snowsuit
+5642 snugness
+5643 speakers
+5644 sphinx
+5645 spider
+5646 splashing
+5651 sponge
+5652 sprout
+5653 spur
+5654 spyglass
+5655 squirrel
+5656 statue
+5661 steamboat
+5662 stingray
+5663 stopwatch
+5664 strawberry
+5665 student
+5666 stylus
+6111 suave
+6112 subway
+6113 suction
+6114 suds
+6115 suffocate
+6116 sugar
+6121 suitcase
+6122 sulphur
+6123 superstore
+6124 surfer
+6125 sushi
+6126 swan
+6131 sweatshirt
+6132 swimwear
+6133 sword
+6134 sycamore
+6135 syllable
+6136 symphony
+6141 synagogue
+6142 syringes
+6143 systemize
+6144 tablespoon
+6145 taco
+6146 tadpole
+6151 taekwondo
+6152 tagalong
+6153 takeout
+6154 tallness
+6155 tamale
+6156 tanned
+6161 tapestry
+6162 tarantula
+6163 tastebud
+6164 tattoo
+6165 tavern
+6166 thaw
+6211 theater
+6212 thimble
+6213 thorn
+6214 throat
+6215 thumb
+6216 thwarting
+6221 tiara
+6222 tidbit
+6223 tiebreaker
+6224 tiger
+6225 timid
+6226 tinsel
+6231 tiptoeing
+6232 tirade
+6233 tissue
+6234 tractor
+6235 tree
+6236 tripod
+6241 trousers
+6242 trucks
+6243 tryout
+6244 tubeless
+6245 tuesday
+6246 tugboat
+6251 tulip
+6252 tumbleweed
+6253 tupperware
+6254 turtle
+6255 tusk
+6256 tutorial
+6261 tuxedo
+6262 tweezers
+6263 twins
+6264 tyrannical
+6265 ultrasound
+6266 umbrella
+6311 umpire
+6312 unarmored
+6313 unbuttoned
+6314 uncle
+6315 underwear
+6316 unevenness
+6321 unflavored
+6322 ungloved
+6323 unhinge
+6324 unicycle
+6325 unjustly
+6326 unknown
+6331 unlocking
+6332 unmarked
+6333 unnoticed
+6334 unopened
+6335 unpaved
+6336 unquenched
+6341 unroll
+6342 unscrewing
+6343 untied
+6344 unusual
+6345 unveiled
+6346 unwrinkled
+6351 unyielding
+6352 unzip
+6353 upbeat
+6354 upcountry
+6355 update
+6356 upfront
+6361 upgrade
+6362 upholstery
+6363 upkeep
+6364 upload
+6365 uppercut
+6366 upright
+6411 upstairs
+6412 uptown
+6413 upwind
+6414 uranium
+6415 urban
+6416 urchin
+6421 urethane
+6422 urgent
+6423 urologist
+6424 username
+6425 usher
+6426 utensil
+6431 utility
+6432 utmost
+6433 utopia
+6434 utterance
+6435 vacuum
+6436 vagrancy
+6441 valuables
+6442 vanquished
+6443 vaporizer
+6444 varied
+6445 vaseline
+6446 vegetable
+6451 vehicle
+6452 velcro
+6453 vendor
+6454 vertebrae
+6455 vestibule
+6456 veteran
+6461 vexingly
+6462 vicinity
+6463 videogame
+6464 viewfinder
+6465 vigilante
+6466 village
+6511 vinegar
+6512 violin
+6513 viperfish
+6514 virus
+6515 visor
+6516 vitamins
+6521 vivacious
+6522 vixen
+6523 vocalist
+6524 vogue
+6525 voicemail
+6526 volleyball
+6531 voucher
+6532 voyage
+6533 vulnerable
+6534 waffle
+6535 wagon
+6536 wakeup
+6541 walrus
+6542 wanderer
+6543 wasp
+6544 water
+6545 waving
+6546 wheat
+6551 whisper
+6552 wholesaler
+6553 wick
+6554 widow
+6555 wielder
+6556 wifeless
+6561 wikipedia
+6562 wildcat
+6563 windmill
+6564 wipeout
+6565 wired
+6566 wishbone
+6611 wizardry
+6612 wobbliness
+6613 wolverine
+6614 womb
+6615 woolworker
+6616 workbasket
+6621 wound
+6622 wrangle
+6623 wreckage
+6624 wristwatch
+6625 wrongdoing
+6626 xerox
+6631 xylophone
+6632 yacht
+6633 yahoo
+6634 yard
+6635 yearbook
+6636 yesterday
+6641 yiddish
+6642 yield
+6643 yo-yo
+6644 yodel
+6645 yogurt
+6646 yuppie
+6651 zealot
+6652 zebra
+6653 zeppelin
+6654 zestfully
+6655 zigzagged
+6656 zillion
+6661 zipping
+6662 zirconium
+6663 zodiac
+6664 zombie
+6665 zookeeper
+6666 zucchini
+EOF
+)
+
+dice() {
+ tr -cd '1-6'</dev/urandom|fold -w 4|head -n "$1"
+}
+
+for num in $(dice "${1:-8}")
+do
+ echo "$wordlist"|
+ grep "$num"|
+ cut -d' ' -f2|
+ tr '\n' ' '
+done
+
+echo
(DIR) diff --git a/bin/mullvad b/bin/mullvad
@@ -0,0 +1,31 @@
+#!/bin/sh
+gw="$(route -n show | awk '$1 == "default" { print $2 }')"
+awk -v gw="$gw" '
+$1 == "PrivateKey" { key = $3 }
+$1 == "Address" {
+ addr = $3
+ sub(/,.*/, "", addr)
+}
+$1 == "DNS" { dns = $3 }
+$1 == "PublicKey" { peer = $3 }
+$1 == "AllowedIPs" {
+ aip = $3
+ sub(/,.*/, "", aip)
+}
+$1 == "Endpoint" {
+ endpoint = $3
+ sub(/:/, " ", endpoint)
+}
+END {
+ epip = substr(endpoint, 1, index(endpoint, " ")-1)
+ ifip = substr(addr, 1, index(addr, "/")-1)
+ printf("ifconfig wg0 create wgkey %s wgpeer %s wgendpoint %s wgaip %s\n", key, peer, endpoint, aip)
+ printf("ifconfig wg0 %s\n", addr)
+ printf("route nameserver wg0 %s\n", dns)
+ printf("route add %s %s\n", epip, gw)
+ printf("route change default %s\n", ifip)
+ printf("curl https://am.i.mullvad.net/connected\n")
+ printf("trap '\''ifconfig wg0 destroy; route delete %s; route add default %s'\'' EXIT\n", epip, gw)
+ printf("while read -r ch; do [ \"$ch\" = q ] && break; done </dev/tty\n")
+}' "$@" | doas /bin/sh -ex
+
(DIR) diff --git a/bin/music b/bin/music
@@ -3,7 +3,7 @@
DIRECTORY="$HOME/media/music_videos"
directories=$(find "$DIRECTORY" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | sort)
-selected_directory=$(printf "%s\n" "$directories" | bemenu -l 10 -p 'music: ')
+selected_directory=$(printf "%s\n" "$directories" | dmenu -l 10 -p 'music: ')
if [ -n "$selected_directory" ]; then
mpv --autofit=30% --really-quiet --no-terminal "$DIRECTORY/$selected_directory"
fi
(DIR) diff --git a/bin/pass b/bin/pass
@@ -0,0 +1,279 @@
+#!/bin/sh -e
+#
+# https://romanzolotarev.com/bin/pass
+# copyright 2018 roman zolotarev <hi@romanzolotarev.com>
+# copyright 2019-2022 romanzolotarev.com ou <hi@romanzolotarev.com>
+#
+# permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# the software is provided "as is" and the author disclaims all warranties
+# with regard to this software including all implied warranties of
+# merchantability and fitness. in no event shall the author be liable for
+# any special, direct, indirect, or consequential damages or any damages
+# whatsoever resulting from loss of use, data or profits, whether in an
+# action of contract, negligence or other tortious action, arising out of
+# or in connection with the use or performance of this software.
+#
+
+fail() { echo "$1"; exit 1; }
+should_exist() { if [ ! -f "$1" ]; then fail "Can't find $1."; fi; }
+should_not_exist() { if [ -f "$1" ]; then fail "$1 already exists."; fi; }
+should_be_dir() { if [ ! -d "$1" ]; then fail "$1 is not a directory."; fi; }
+should_be_defined() { if [ ! "$1" ]; then fail "$2 should be defined."; fi; }
+
+
+keygen() {
+ private_key="$1"
+ public_key="$2"
+ should_be_defined "$private_key" "Private key path"
+ should_be_defined "$public_key" "Public key path"
+ should_not_exist "$private_key"
+ should_be_dir "$(dirname "$private_key")"
+ should_not_exist "$public_key"
+ should_be_dir "$(dirname "$public_key")"
+
+ echo 'Generating public/private key pair.'
+
+ printf 'New pass phrase: '; stty -echo; read -r pass; stty echo; printf '\n'
+ if [ ! "$pass" ]; then fail 'The pass phrase cannot be empty.'; fi
+ printf 'Confirm: '; stty -echo; read -r pass_confirm; stty echo; printf '\n'
+
+ if [ "$pass" = "$pass_confirm" ]; then
+ openssl genrsa 2048 |
+ openssl pkcs8 -topk8 -inform pem -outform pem -out "$private_key" -v2 aes256 -passout "pass:$pass"
+ chmod 0400 "$private_key"
+ openssl rsa -in "$private_key" -out "$public_key" -outform pem -pubout -passin "pass:$pass"
+ chmod 0600 "$public_key"
+ else
+ fail 'Pass phrase mismatch.'
+ fi
+}
+
+
+passphrase() {
+ private_key="$1"
+ should_be_defined "$private_key" "Private key path"
+ should_exist "$private_key"
+
+ echo "Changing $private_key pass phrase."
+
+ printf 'Current pass phrase: '; stty -echo; read -r pass; stty echo; printf '\n'
+ printf 'New pass phrase: '; stty -echo; read -r new_pass; stty echo; printf '\n'
+ if [ ! "$new_pass" ]; then fail 'The pass phrase cannot be empty.'; fi
+ printf 'Confirm: '; stty -echo; read -r new_pass_confirm; stty echo; printf '\n'
+
+ if [ "$new_pass" = "$new_pass_confirm" ]; then
+ chmod 0600 "$private_key" &&
+ openssl rsa -aes256 -in "$private_key" -out "$private_key" -passin "pass:$pass" -passout "pass:$new_pass" 2>/dev/null ||
+ fail 'Pass phrase change failed.' &&
+ { echo 'Pass phrase changed.'; chmod 0400 "$private_key"; }
+ else
+ fail 'Pass phrase mismatch.'
+ fi
+}
+
+
+encrypt() {
+ public_key="$1"
+ data_file="$2"
+ should_be_defined "$data_file" "Data file path"
+ enc_file="$data_file.enc"
+ key_file="$data_file.key"
+ base_dir="$(dirname "$data_file")"
+ should_be_dir "$base_dir"
+ should_exist "$public_key"
+ should_not_exist "$enc_file"
+ should_not_exist "$key_file"
+
+ key=$(openssl rand -base64 180)
+ cleartext="$(cat)"
+ dir=$(dirname "$data_file"); mkdir -p "$dir"; chmod 0700 "$dir"
+
+ echo "$key" |
+ openssl rsautl -encrypt -pubin -inkey "$public_key" |
+ openssl enc -md md5 -base64 -out "$key_file" >/dev/null 2>&1 ||
+ fail 'Encryption failed.'
+
+ echo "$cleartext" |
+ openssl enc -md md5 -aes-256-cbc -base64 -salt -k "$key" -out "$enc_file"
+
+ cleartext=''
+ key=''
+
+ tar cf "$data_file" -C "$base_dir" "$(basename "$key_file")" "$(basename "$enc_file")"
+ rm "$key_file" "$enc_file"
+ chmod 0600 "$data_file"
+}
+
+
+sign() {
+ private_key="$1"
+ data_file="$2"
+ pass="$3"
+ should_be_defined "$data_file" "Data file path"
+ signature="$data_file.sig"
+ base_dir="$(dirname "$data_file")"
+ should_be_dir "$base_dir"
+ should_exist "$private_key"
+ should_exist "$data_file"
+
+ if [ ! "$pass" ]; then
+ if ! openssl dgst -sha256 -sign "$private_key" -out "$signature" "$data_file" 2>/dev/null; then
+ rm "$signature"
+ fail 'Signing failed.'
+ fi
+ else
+ if ! openssl dgst -sha256 -passin "pass:$pass" -sign "$private_key" -out "$signature" "$data_file" 2>/dev/null; then
+ rm "$signature"
+ fail 'Signing failed.'
+ fi
+ fi
+
+ chmod 0600 "$signature"
+}
+
+
+decrypt() {
+ private_key="$1"
+ data_file="$2"
+ pass="$3"
+ should_be_defined "$private_key" "Private key path"
+ should_be_defined "$data_file" "Data file path"
+ enc_file="$data_file.enc"
+ key_file="$data_file.key"
+ should_exist "$private_key"
+ should_exist "$data_file"
+
+ base_dir="$(dirname "$data_file")"
+ tar xf "$data_file" -C "$base_dir"
+ if [ ! "$pass" ]; then
+ key=$(openssl enc -d -base64 -in "$key_file"|openssl rsautl -decrypt -inkey "$private_key" 2>/dev/null)
+ else
+ key=$(openssl enc -d -base64 -in "$key_file"|openssl rsautl -passin "pass:$pass" -decrypt -inkey "$private_key" 2>/dev/null)
+ fi
+ openssl enc -md md5 -aes-256-cbc -d -base64 -k "$key" -in "$enc_file" 2>/dev/null
+ rm "$key_file" "$enc_file"
+}
+
+verify () {
+ public_key="$1"
+ data_file="$2"
+ signature="$data_file.sig"
+ should_exist "$public_key"
+ should_exist "$data_file"
+ should_exist "$signature"
+
+ if ! openssl dgst -sha256 -verify "$public_key" -signature "$signature" "$data_file" >/dev/null 2>&1; then
+ fail 'Invalid signature.'
+ fi
+}
+
+if [ ! "$PASS_BASE_DIR" ]; then PASS_BASE_DIR="$HOME/.pass"; fi
+if [ ! "$PASS_PRIVATE_KEY" ]; then PASS_PRIVATE_KEY="$PASS_BASE_DIR/.key"; fi
+if [ ! "$PASS_PUBLIC_KEY" ]; then PASS_PUBLIC_KEY="$PASS_BASE_DIR/.key.pub"; fi
+if [ "$2" ]; then ID="$2"; fi
+if [ "$3" ]; then PASS="$3"; fi
+
+
+case "$1" in
+
+passphrase)
+ passphrase "$PASS_PRIVATE_KEY"
+ ;;
+
+
+init)
+ mkdir -p "$(dirname "$PASS_PRIVATE_KEY")"; chmod 0700 "$(dirname "$PASS_PRIVATE_KEY")"
+ mkdir -p "$(dirname "$PASS_PUBLIC_KEY")"; chmod 0700 "$(dirname "$PASS_PUBLIC_KEY")"
+ keygen "$PASS_PRIVATE_KEY" "$PASS_PUBLIC_KEY"
+ ;;
+
+add)
+ should_be_defined "$ID" "id"
+ should_not_exist "$PASS_BASE_DIR/$ID"
+ printf 'Pass phrase: '; stty -echo; read -r pass; stty echo; printf '\n'
+ if [ ! "$pass" ]; then fail 'The pass phrase cannot be empty.'; fi
+ openssl rand -base64 10 |
+ openssl dgst -sha256 -passin "pass:$pass" -sign "$PASS_PRIVATE_KEY" >/dev/null 2>&1 ||
+ fail 'Invalid pass phrase.'
+ echo 'Press Enter and CTRL-D to complete.'
+ encrypt "$PASS_PUBLIC_KEY" "$PASS_BASE_DIR/$ID"
+ sign "$PASS_PRIVATE_KEY" "$PASS_BASE_DIR/$ID" "$pass"
+ ;;
+
+import)
+ should_be_defined "$ID" "id"
+ should_not_exist "$PASS_BASE_DIR/$ID"
+ encrypt "$PASS_PUBLIC_KEY" "$PASS_BASE_DIR/$ID"
+ sign "$PASS_PRIVATE_KEY" "$PASS_BASE_DIR/$ID" "$PASS"
+ ;;
+
+show)
+ should_be_defined "$ID" "id"
+ verify "$PASS_PUBLIC_KEY" "$PASS_BASE_DIR/$ID"
+ cleartext="$(decrypt "$PASS_PRIVATE_KEY" "$PASS_BASE_DIR/$ID")"
+ echo "$cleartext"|head -n1
+ totp_seed="$(echo "$cleartext"|grep 'totp: '|head -n1|cut -d' ' -f2)"
+ if [ "$totp_seed" ]; then
+ if oathtool --version >/dev/null 2>&1; then
+ oathtool --totp -b "$totp_seed"
+ else
+ echo 'oathtool(1) should be installed'
+ fi
+ fi
+ ;;
+
+export)
+ should_be_defined "$ID" "id"
+ verify "$PASS_PUBLIC_KEY" "$PASS_BASE_DIR/$ID"
+ decrypt "$PASS_PRIVATE_KEY" "$PASS_BASE_DIR/$ID" "$PASS"
+ ;;
+
+ls)
+ cd "$PASS_BASE_DIR"
+ find . \( -type f \
+ -name "${ID}"\* \
+ \! -name \*.enc \
+ \! -name \*.key \
+ \! -name \*.sig \
+ \! -name \.key \
+ \! -name \.key.pub \
+ \! -path \*/.git/\* \) | cut -f2 -d'/' | sort
+ ;;
+
+edit)
+ should_be_defined "$ID" "id"
+ # verify "$PASS_PUBLIC_KEY" "$PASS_BASE_DIR/$ID"
+ cleartext_file="$PASS_BASE_DIR/$ID.cleartext"
+ cleartext=$(decrypt "$PASS_PRIVATE_KEY" "$PASS_BASE_DIR/$ID")
+ touch "$cleartext_file"; chmod 0600 "$cleartext_file"
+ echo "$cleartext" > "$cleartext_file"
+ ${EDITOR:-$(which vi)} "$cleartext_file"
+ after=$(cat "$cleartext_file")
+ rm "$cleartext_file"
+ if [ "$(echo "$cleartext"|openssl dgst -r -sha256)" = "$(echo "$after"|openssl dgst -r -sha256)" ]; then
+ echo "No changes in $ID"
+ else
+ echo "$after"|encrypt "$PASS_PUBLIC_KEY" "$PASS_BASE_DIR/$ID"
+ sign "$PASS_PRIVATE_KEY" "$PASS_BASE_DIR/$ID"
+ fi
+ ;;
+
+*)
+ echo 'usage: export PASS_BASE_DIR=~/.pass'
+ echo ' export PASS_PRIVATE_KEY=~/.pass/.key'
+ echo ' export PASS_PUBLIC_KEY=~/.pass/.key.pub'
+ echo
+ echo ' pass init'
+ echo ' | passphrase'
+ echo ' | add id'
+ echo ' | import id <pass>'
+ echo ' | show id'
+ echo ' | export id <pass>'
+ echo ' | ls <id>'
+ exit 1
+ ;;
+
+esac
(DIR) diff --git a/bin/sway-start b/bin/sway-start
@@ -1,22 +0,0 @@
-#!/bin/sh
-export TERM=foot
-export _JAVA_AWT_WM_NONREPARENTING=1
-export XKB_DEFAULT_OPTIONS=caps:escape
-export GDK_BACKEND=wayland
-export XDG_SESSION_TYPE=wayland
-#export XCURSOR_THEME=Adwaita
-export XDG_DESKTOP_DIR="$HOME"
-export XDG_DOWNLOAD_DIR="$HOME/tmp"
-export XDG_DOCUMENTS_DIR="$HOME/tmp"
-export XDG_MUSIC_DIR="$HOME/tmp"
-export XDG_PICTURES_DIR="$HOME/tmp"
-export XDG_VIDEOS_DIR="$HOME/tmp"
-export XDG_CURRENT_DESKTOP=sway
-
-if [ -z "$XDG_RUNTIME_DIR" ]; then
- mkdir -p /tmp/runtime/jay
- chmod 700 /tmp/runtime/jay
- export XDG_RUNTIME_DIR=/tmp/runtime/jay
-fi
-
-exec dbus-run-session sway
(DIR) diff --git a/bootstrap.sh b/bootstrap.sh
@@ -2,9 +2,9 @@
DOTFILES=$(pwd)
-FILES='ashrc profile'
+FILES='kshrc profile Xdefaults Xresources'
ROOT='bin'
-CONFIG='foot git lynx mutt newsraft nvim qutebrowser sway waybar'
+CONFIG='git lynx mpd mutt ncmpcpp newsraft nvim'
link() {
for f in $FILES; do ln -sfn "$DOTFILES/$f" "$HOME/.$f"; done
(DIR) diff --git a/foot/foot.ini b/foot/foot.ini
@@ -1,27 +0,0 @@
-font=Hack:size=14
-
-[url]
-launch=link-handler ${url}
-
-[key-bindings]
-show-urls-launch=Control+Shift+p
-
-[colors]
-background=282828
-foreground=ebdbb2
-regular0=282828
-regular1=cc241d
-regular2=98971a
-regular3=d79921
-regular4=458588
-regular5=b16286
-regular6=689d6a
-regular7=a89984
-bright0=928374
-bright1=fb4934
-bright2=b8bb26
-bright3=fabd2f
-bright4=83a598
-bright5=d3869b
-bright6=8ec07c
-bright7=ebdbb2
(DIR) diff --git a/kshrc b/kshrc
@@ -0,0 +1,63 @@
+export XDG_CONFIG_HOME="$HOME/.config"
+export XDG_CACHE_HOME="$HOME/.cache"
+export XDG_DATA_HOME="$HOME/.local/share"
+export XDG_STATE_HOME="$HOME/.local/state"
+
+# cleanup ~/
+export CARGO_HOME="$XDG_DATA_HOME"/cargo
+
+# common exports
+GPG_TTY=$(tty)
+export GPG_TTY
+export EDITOR="nvim"
+export BROWSER="firefox"
+export PATH=$PATH:$HOME/bin
+
+# tools
+export OPENER=~/bin/link-handler
+
+# pass
+export PASS_BASE_DIR=~/src/pass
+export PASS_PRIVATE_KEY=~/src/pass/.key
+export PASS_PUBLIC_KEY=~/src/pass/.key.pub
+
+# lynx
+export LYNX_CFG=$HOME/.config/lynx/config
+export LYNX_LSS=$HOME/.config/lynx/theme.lss
+
+# safety first kids!
+alias cp='cp -i'
+alias mv='mv -i'
+alias rm='rm -i'
+
+# random alias
+alias weather='curl wttr.in/?1QF'
+
+# git alias
+alias ga='git add -A'
+alias gs='git status -s'
+alias gl="git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
+alias gd='git diff'
+alias gma='git commit -am'
+
+# neo
+alias vim='nvim'
+alias mutt='neomutt'
+alias mpv="mpv --autofit=30% --really-quiet --no-terminal"
+alias w="w3m -B"
+
+# vpn
+alias von='mullvad ~/.config/mullvad/se-mma-wg-111.conf'
+alias vcheck='curl https://am.i.mullvad.net/connected'
+
+# ksh
+export LANG=en_US.UTF-8
+export LC_CTYPE="en_US.UTF-8"
+export LC_ALL=en_US.UTF-8
+export PS1="\[\e[00;34m\]▶▶▶ \W \[\e[0m\]"
+export HISTFILE=/home/jay/.cache/sh_history
+export HISTSIZE=1000
+
+alias ls='colorls -G'
+set -o emacs
+
(DIR) diff --git a/mpd/mpd.conf b/mpd/mpd.conf
@@ -0,0 +1,20 @@
+music_directory "/home/jay/media/music"
+playlist_directory "/home/jay/.config/mpd/playlists"
+db_file "/home/jay/.config/mpd/mpd.db"
+log_file "syslog"
+pid_file "/home/jay/.config/mpd/mpd.pid"
+state_file "/home/jay/.config/mpd/mpdstate"
+
+audio_output {
+ type "pulse"
+ name "pulse audio"
+}
+audio_output {
+ type "fifo"
+ name "my_fifo"
+ path "/tmp/mpd.fifo"
+ format "44100:16:2"
+}
+
+bind_to_address "127.0.0.1"
+port "6600"
(DIR) diff --git a/ncmpcpp/config b/ncmpcpp/config
@@ -0,0 +1,31 @@
+# visual stuff for 8
+visualizer_data_source = /tmp/mpd.fifo
+visualizer_output_name = my_fifo
+visualizer_in_stereo = no
+#visualizer_type = spectrum
+visualizer_look = ∙▋
+visualizer_color = 7,5,8,3
+song_columns_list_format = "(50)[green]{a} (50)[white]{t|f}"
+
+playlist_display_mode = columns
+browser_display_mode = columns
+
+ncmpcpp_directory = ~/.config/ncmpcpp
+lyrics_directory = /tmp
+store_lyrics_in_song_dir = yes
+autocenter_mode = "yes"
+centered_cursor = "yes"
+cyclic_scrolling = "no"
+
+titles_visibility = "no"
+header_visibility = "no"
+statusbar_visibility = "no"
+progressbar_look = "❙❙❙"
+progressbar_color = "white"
+
+user_interface = "classic"
+
+startup_screen = playlist
+#startup_slave_screen = visualizer
+'startup_slave_screen_focus = no
+locked_screen_width_part = 35
(DIR) diff --git a/profile b/profile
@@ -1,2 +1,2 @@
-export ENV=$HOME/.ashrc
+export ENV=$HOME/.kshrc
. $ENV
(DIR) diff --git a/qutebrowser/blank.html b/qutebrowser/blank.html
@@ -1,44 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-
- <head>
- <style>
- body {
- color: #cfba58;
- background-color: #191919;
- font-family: monospace;
- }
-
- .flex {
- flex-direction: column;
- display: flex;
- justify-content: center;
- align-items: center;
- margin-top: 450px;
- }
-
- input {
- border: none;
- border-bottom: 2px solid #959A1C;
- min-width: 500px;
- max-width: 750px;
- width: 75%;
- padding-bottom: 10px;
- background-color: transparent;
- color: #fff;
- outline: 0;
- margin-bottom: 20px;
- font-size: 22px;
- }
- </style>
- </head>
-
- <body>
- <div class="flex">
- <form action="https://html.duckduckgo.com/html" method="get" target="_self">
- <input type="text" name="q" autofocus="autofocus" onfocus="this.select()" />
- </form>
- </div>
- </body>
-
-</html>
(DIR) diff --git a/qutebrowser/config.py b/qutebrowser/config.py
@@ -1,92 +0,0 @@
-config.load_autoconfig(False)
-
-try:
- from qutebrowser.api import message
-
- # gruvbox colour theme
- config.source('scripts/gruvbox.py')
- #config.source('scripts/redirects.py')
-
-except ImportError:
- pass
-
-# default local page
-DEFAULT_PAGE = str(config.configdir / 'blank.html')
-
-# keybinds remapping
-config.bind("xx", "set tabs.show always;; later 5000 set tabs.show switching")
-config.bind("xc", "spawn --userscript password_fill")
-config.bind("zd", "download-open")
-config.bind("xz", "hint links spawn --detach ~/bin/link-handler {hint-url}")
-config.bind("j", "cmd-run-with-count 5 scroll down")
-config.bind("k", "cmd-run-with-count 5 scroll up")
-
-# tabbar
-c.tabs.position = "top"
-c.tabs.show = "multiple"
-c.tabs.title.format = ""
-c.tabs.width = 28
-c.tabs.favicons.show = "never"
-
-# hints
-c.colors.hints.bg = "rgb(207,186,88)" #cfba58
-c.colors.hints.fg = "rgb(34, 34, 34)" #222222
-c.colors.webpage.darkmode.enabled = False
-c.colors.webpage.darkmode.algorithm = "lightness-hsl"
-
-# misc
-c.fonts.hints = "10pt Hack"
-c.fonts.default_size = '12pt'
-c.fonts.default_family = 'Hack'
-c.hints.uppercase = True
-c.scrolling.smooth = True
-c.editor.command = ["alacritty", "vim '{}'"]
-c.auto_save.session = True
-
-# ad-block
-c.content.blocking.enabled = True
-c.content.blocking.method = "both"
-c.content.blocking.adblock.lists = [
- "https://easylist.to/easylist/easyprivacy.txt",
- "https://secure.fanboy.co.nz/fanboy-cookiemonster.txt",
- "https://easylist.to/easylist/easylist.txt"
- ]
-
-# general privacy
-c.completion.web_history.max_items = 0 # no history
-c.downloads.remove_finished = 800 # clear dl history
-c.downloads.location.directory = '~/tmp'
-c.url.default_page = DEFAULT_PAGE
-c.url.start_pages = DEFAULT_PAGE
-c.content.private_browsing = True # always use private browsing
-c.content.register_protocol_handler = False
-c.content.webgl = False
-
-# normally default, lets make sure
-c.content.media.audio_capture = False
-c.content.media.audio_video_capture = False
-c.content.media.video_capture = False
-c.content.desktop_capture = False
-c.content.mouse_lock = False
-c.content.autoplay = False # no autoplay on <video> tags
-
-# fingerprint
-c.content.headers.accept_language = "en-US,en;q=0.5"
-c.content.headers.user_agent = "Mozilla/5.0 (X11; Linux i686; rv:109.0) Gecko/20100101 Firefox/120.0"
-c.content.headers.custom = {"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}
-c.content.headers.referer = "same-domain"
-c.content.cookies.accept = "no-3rdparty"
-c.content.javascript.enabled = False # disable tracking etc
-c.content.canvas_reading = False # canvas blocking
-c.content.geolocation = False # location ident
-c.content.webrtc_ip_handling_policy = "disable-non-proxied-udp"
-c.content.hyperlink_auditing = False # disable pingbacks
-c.content.dns_prefetch = False # disable pre-fetching
-
-# search engine shortneners
-c.url.searchengines = {
- "DEFAULT": "https://html.duckduckgo.com/html?q={}",
- "ru": "https://rutracker.org/forum/tracker.php?f=1992&nm={}",
- "wiby": "https://wiby.me/?q={}",
- "book": "http://libgen.rs/search.php?req={}&lg_topic=libgen&open=0&view=simple&res=25&phrase=1&column=def",
-}
(DIR) diff --git a/qutebrowser/scripts/fingerprint.py b/qutebrowser/scripts/fingerprint.py
@@ -1,43 +0,0 @@
-import random
-import json
-import datetime
-
-from pathlib import Path
-from qutebrowser.api import message, interceptor
-
-home = str(config.configdir)
-agentfile = Path("{}/useragent_list.json".format(home))
-
-fp_timer = datetime.datetime.now() + datetime.timedelta(minutes=1)
-
-if agentfile.is_file():
- with open(agentfile, "r") as filehandle:
- agentList = json.load(filehandle)
-
-
-def fingerprint_getheader(agent):
-
- FP_HTTP_HEADER = {
- "Firefox": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
- "Chrome": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
- "Edge": "text/html, application/xhtml+xml, image/jxr, */*",
- "Opera": "text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1",
- "Safari": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
- }
-
- for a, h in FP_HTTP_HEADER.items():
- if "{a}" in agent:
- return h
-
-
-def fingerprint(info: interceptor.Request):
- global fp_timer
-
- if fp_timer < datetime.datetime.now():
- fp_timer = datetime.datetime.now() + datetime.timedelta(minutes=1)
- agent = random.choice(tuple(agentList))
- c.content.headers.user_agent = agent
- c.content.headers.custom = {"accept": fingerprint_getheader(agent)}
-
-
-interceptor.register(fingerprint)
(DIR) diff --git a/qutebrowser/scripts/gruvbox.py b/qutebrowser/scripts/gruvbox.py
@@ -1,332 +0,0 @@
-# gruvbox dark hard qutebrowser theme by Florian Bruhin <me@the-compiler.org>
-#
-# Originally based on:
-# base16-qutebrowser (https://github.com/theova/base16-qutebrowser)
-# Base16 qutebrowser template by theova and Daniel Mulford
-# Gruvbox dark, hard scheme by Dawid Kurek (dawikur@gmail.com), morhetz (https://github.com/morhetz/gruvbox)
-
-bg0_hard = "#1d2021"
-bg0_soft = '#32302f'
-bg0_normal = '#282828'
-
-bg0 = bg0_normal
-bg1 = "#3c3836"
-bg2 = "#504945"
-bg3 = "#665c54"
-bg4 = "#7c6f64"
-
-fg0 = "#fbf1c7"
-fg1 = "#ebdbb2"
-fg2 = "#d5c4a1"
-fg3 = "#bdae93"
-fg4 = "#a89984"
-
-bright_red = "#fb4934"
-bright_green = "#b8bb26"
-bright_yellow = "#fabd2f"
-bright_blue = "#83a598"
-bright_purple = "#d3869b"
-bright_aqua = "#8ec07c"
-bright_gray = "#928374"
-bright_orange = "#fe8019"
-
-dark_red = "#cc241d"
-dark_green = "#98971a"
-dark_yellow = "#d79921"
-dark_blue = "#458588"
-dark_purple = "#b16286"
-dark_aqua = "#689d6a"
-dark_gray = "#a89984"
-dark_orange = "#d65d0e"
-
-### Completion
-
-# Text color of the completion widget. May be a single color to use for
-# all columns or a list of three colors, one for each column.
-c.colors.completion.fg = [fg1, bright_aqua, bright_yellow]
-
-# Background color of the completion widget for odd rows.
-c.colors.completion.odd.bg = bg0
-
-# Background color of the completion widget for even rows.
-c.colors.completion.even.bg = c.colors.completion.odd.bg
-
-# Foreground color of completion widget category headers.
-c.colors.completion.category.fg = bright_blue
-
-# Background color of the completion widget category headers.
-c.colors.completion.category.bg = bg1
-
-# Top border color of the completion widget category headers.
-c.colors.completion.category.border.top = c.colors.completion.category.bg
-
-# Bottom border color of the completion widget category headers.
-c.colors.completion.category.border.bottom = c.colors.completion.category.bg
-
-# Foreground color of the selected completion item.
-c.colors.completion.item.selected.fg = fg0
-
-# Background color of the selected completion item.
-c.colors.completion.item.selected.bg = bg4
-
-# Top border color of the selected completion item.
-c.colors.completion.item.selected.border.top = bg2
-
-# Bottom border color of the selected completion item.
-c.colors.completion.item.selected.border.bottom = c.colors.completion.item.selected.border.top
-
-# Foreground color of the matched text in the selected completion item.
-c.colors.completion.item.selected.match.fg = bright_orange
-
-# Foreground color of the matched text in the completion.
-c.colors.completion.match.fg = c.colors.completion.item.selected.match.fg
-
-# Color of the scrollbar handle in the completion view.
-c.colors.completion.scrollbar.fg = c.colors.completion.item.selected.fg
-
-# Color of the scrollbar in the completion view.
-c.colors.completion.scrollbar.bg = c.colors.completion.category.bg
-
-### Context menu
-
-# Background color of disabled items in the context menu.
-c.colors.contextmenu.disabled.bg = bg3
-
-# Foreground color of disabled items in the context menu.
-c.colors.contextmenu.disabled.fg = fg3
-
-# Background color of the context menu. If set to null, the Qt default is used.
-c.colors.contextmenu.menu.bg = bg0
-
-# Foreground color of the context menu. If set to null, the Qt default is used.
-c.colors.contextmenu.menu.fg = fg2
-
-# Background color of the context menu’s selected item. If set to null, the Qt default is used.
-c.colors.contextmenu.selected.bg = bg2
-
-#Foreground color of the context menu’s selected item. If set to null, the Qt default is used.
-c.colors.contextmenu.selected.fg = c.colors.contextmenu.menu.fg
-
-### Downloads
-
-# Background color for the download bar.
-c.colors.downloads.bar.bg = bg0
-
-# Color gradient start for download text.
-c.colors.downloads.start.fg = bg0
-
-# Color gradient start for download backgrounds.
-c.colors.downloads.start.bg = bright_blue
-
-# Color gradient end for download text.
-c.colors.downloads.stop.fg = c.colors.downloads.start.fg
-
-# Color gradient stop for download backgrounds.
-c.colors.downloads.stop.bg = bright_aqua
-
-# Foreground color for downloads with errors.
-c.colors.downloads.error.fg = bright_red
-
-### Hints
-
-# Font color for hints.
-c.colors.hints.fg = bg0
-
-# Background color for hints.
-c.colors.hints.bg = 'rgba(250, 191, 47, 200)' # bright_yellow
-
-# Font color for the matched part of hints.
-c.colors.hints.match.fg = bg4
-
-### Keyhint widget
-
-# Text color for the keyhint widget.
-c.colors.keyhint.fg = fg4
-
-# Highlight color for keys to complete the current keychain.
-c.colors.keyhint.suffix.fg = fg0
-
-# Background color of the keyhint widget.
-c.colors.keyhint.bg = bg0
-
-### Messages
-
-# Foreground color of an error message.
-c.colors.messages.error.fg = bg0
-
-# Background color of an error message.
-c.colors.messages.error.bg = bright_red
-
-# Border color of an error message.
-c.colors.messages.error.border = c.colors.messages.error.bg
-
-# Foreground color of a warning message.
-c.colors.messages.warning.fg = bg0
-
-# Background color of a warning message.
-c.colors.messages.warning.bg = bright_purple
-
-# Border color of a warning message.
-c.colors.messages.warning.border = c.colors.messages.warning.bg
-
-# Foreground color of an info message.
-c.colors.messages.info.fg = fg2
-
-# Background color of an info message.
-c.colors.messages.info.bg = bg0
-
-# Border color of an info message.
-c.colors.messages.info.border = c.colors.messages.info.bg
-
-### Prompts
-
-# Foreground color for prompts.
-c.colors.prompts.fg = fg2
-
-# Border used around UI elements in prompts.
-c.colors.prompts.border = f'1px solid {bg1}'
-
-# Background color for prompts.
-c.colors.prompts.bg = bg3
-
-# Background color for the selected item in filename prompts.
-c.colors.prompts.selected.bg = bg2
-
-### Statusbar
-
-# Foreground color of the statusbar.
-c.colors.statusbar.normal.fg = fg2
-
-# Background color of the statusbar.
-c.colors.statusbar.normal.bg = bg0
-
-# Foreground color of the statusbar in insert mode.
-c.colors.statusbar.insert.fg = bg0
-
-# Background color of the statusbar in insert mode.
-c.colors.statusbar.insert.bg = dark_aqua
-
-# Foreground color of the statusbar in passthrough mode.
-c.colors.statusbar.passthrough.fg = bg0
-
-# Background color of the statusbar in passthrough mode.
-c.colors.statusbar.passthrough.bg = dark_blue
-
-# Foreground color of the statusbar in private browsing mode.
-c.colors.statusbar.private.fg = bright_purple
-
-# Background color of the statusbar in private browsing mode.
-c.colors.statusbar.private.bg = bg0
-
-# Foreground color of the statusbar in command mode.
-c.colors.statusbar.command.fg = fg3
-
-# Background color of the statusbar in command mode.
-c.colors.statusbar.command.bg = bg1
-
-# Foreground color of the statusbar in private browsing + command mode.
-c.colors.statusbar.command.private.fg = c.colors.statusbar.private.fg
-
-# Background color of the statusbar in private browsing + command mode.
-c.colors.statusbar.command.private.bg = c.colors.statusbar.command.bg
-
-# Foreground color of the statusbar in caret mode.
-c.colors.statusbar.caret.fg = bg0
-
-# Background color of the statusbar in caret mode.
-c.colors.statusbar.caret.bg = dark_purple
-
-# Foreground color of the statusbar in caret mode with a selection.
-c.colors.statusbar.caret.selection.fg = c.colors.statusbar.caret.fg
-
-# Background color of the statusbar in caret mode with a selection.
-c.colors.statusbar.caret.selection.bg = bright_purple
-
-# Background color of the progress bar.
-c.colors.statusbar.progress.bg = bright_blue
-
-# Default foreground color of the URL in the statusbar.
-c.colors.statusbar.url.fg = fg4
-
-# Foreground color of the URL in the statusbar on error.
-c.colors.statusbar.url.error.fg = dark_red
-
-# Foreground color of the URL in the statusbar for hovered links.
-c.colors.statusbar.url.hover.fg = bright_orange
-
-# Foreground color of the URL in the statusbar on successful load
-# (http).
-c.colors.statusbar.url.success.http.fg = bright_red
-
-# Foreground color of the URL in the statusbar on successful load
-# (https).
-c.colors.statusbar.url.success.https.fg = fg0
-
-# Foreground color of the URL in the statusbar when there's a warning.
-c.colors.statusbar.url.warn.fg = bright_purple
-
-### tabs
-
-# Background color of the tab bar.
-c.colors.tabs.bar.bg = bg0
-
-# Color gradient start for the tab indicator.
-c.colors.tabs.indicator.start = bright_blue
-
-# Color gradient end for the tab indicator.
-c.colors.tabs.indicator.stop = bright_aqua
-
-# Color for the tab indicator on errors.
-c.colors.tabs.indicator.error = bright_red
-
-# Foreground color of unselected odd tabs.
-c.colors.tabs.odd.fg = fg2
-
-# Background color of unselected odd tabs.
-c.colors.tabs.odd.bg = bg2
-
-# Foreground color of unselected even tabs.
-c.colors.tabs.even.fg = c.colors.tabs.odd.fg
-
-# Background color of unselected even tabs.
-c.colors.tabs.even.bg = bg3
-
-# Foreground color of selected odd tabs.
-c.colors.tabs.selected.odd.fg = fg2
-
-# Background color of selected odd tabs.
-c.colors.tabs.selected.odd.bg = bg0
-
-# Foreground color of selected even tabs.
-c.colors.tabs.selected.even.fg = c.colors.tabs.selected.odd.fg
-
-# Background color of selected even tabs.
-c.colors.tabs.selected.even.bg = bg0
-
-# Background color of pinned unselected even tabs.
-c.colors.tabs.pinned.even.bg = bright_green
-
-# Foreground color of pinned unselected even tabs.
-c.colors.tabs.pinned.even.fg = bg2
-
-# Background color of pinned unselected odd tabs.
-c.colors.tabs.pinned.odd.bg = bright_green
-
-# Foreground color of pinned unselected odd tabs.
-c.colors.tabs.pinned.odd.fg = c.colors.tabs.pinned.even.fg
-
-# Background color of pinned selected even tabs.
-c.colors.tabs.pinned.selected.even.bg = bg0
-
-# Foreground color of pinned selected even tabs.
-c.colors.tabs.pinned.selected.even.fg = c.colors.tabs.selected.odd.fg
-
-# Background color of pinned selected odd tabs.
-c.colors.tabs.pinned.selected.odd.bg = c.colors.tabs.pinned.selected.even.bg
-
-# Foreground color of pinned selected odd tabs.
-c.colors.tabs.pinned.selected.odd.fg = c.colors.tabs.selected.odd.fg
-
-# Background color for webpages if unset (or empty to use the theme's
-# color).
-# c.colors.webpage.bg = bg4
(DIR) diff --git a/qutebrowser/scripts/redirects.py b/qutebrowser/scripts/redirects.py
@@ -1,70 +0,0 @@
-from qutebrowser.api import interceptor
-from urllib.parse import urljoin
-from PyQt6.QtCore import QUrl
-import operator
-
-o = operator.methodcaller
-s = 'setHost'
-i = interceptor
-
-def farside(url: QUrl, i) -> bool:
- url.setHost('farside.link')
- p = url.path().strip('/')
- url.setPath(urljoin(i, p))
- return True
-
-def nitter(url: QUrl) -> bool:
- return farside(url, '/nitter/')
-def rimgo(url: QUrl) -> bool:
- return farside(url, '/rimgo/')
-def scribe(url: QUrl) -> bool:
- return farside(url, '/scribe/')
-def wikiless(url: QUrl) -> bool:
- return farside(url, '/wikiless/')
-def invid(url: QUrl) -> bool:
- return farside(url, '/invidious/')
-def reddit(url: QUrl) -> bool:
- return farside(url, '/libreddit/')
-def bibliogram(url: QUrl) -> bool:
- return farside(url, '/bibliogram/')
-def simplytranslate(url: QUrl) -> bool:
- return farside(url, '/simplytranslate/')
-def proxitok(url: QUrl) -> bool:
- return farside(url, '/proxitok/')
-def querte (url: QUrl) -> bool:
- return farside(url, '/querte/')
-
-map = {
- "reddit.com": reddit,
- "www.reddit.com": reddit,
- "old.reddit.com": reddit,
-
- "youtu.be": invid,
- "youtube.com": invid,
- "www.youtube.com": invid,
-
- "twitter.com": nitter,
- "mobile.twitter.com": nitter,
-
- "imgur.com" : rimgo,
- "medium.com" : scribe,
- "en.wikipedia.org" : wikiless,
- "www.instagram.com": bibliogram,
- "translate.google.com" : simplytranslate,
- "vm.tiktok.com" : proxitok,
- "www.tiktok.com" : proxitok,
- "www.quora.com": querte,
-
- "www.twitch.tv" : o(s, 'm.twitch.tv'),
- "tumblr.com" : o(s, 'splashblr.fly.dev'),
- "www.npr.org" : o(s, 'text.npr.org'),
- }
-def f(info: i.Request):
- if (info.resource_type != i.ResourceType.main_frame or
- info.request_url.scheme() in {"data", "blob"}):
- return
- url = info.request_url
- redir = map.get(url.host())
- if redir is not None and redir(url) is not False:
- info.redirect(url)
-i.register(f)
(DIR) diff --git a/qutebrowser/scripts/user_agent.py b/qutebrowser/scripts/user_agent.py
@@ -1,31 +0,0 @@
-# qutebrowser script to set a random user-agent on launch. Add the following to
-# your qutebrowser config.py file:
-#
-# config.source('scripts/user_agent.py')
-#
-# You can download the most common user-agents with a script like this, I run
-# mine on cron every 3 days. :
-#
-# #!/bin/bash
-#
-# url='https://raw.githubusercontent.com/Kikobeats/top-user-agents/master/index.json'
-# path="$HOME/.config/qutebrowser/useragent_list.json"
-#
-# curl "$url" -o "$path"
-# awk '!/Firefox/' "$path" > /tmp/1 && mv /tmp/1 "$path"
-
-import random
-import json
-
-from pathlib import Path
-from qutebrowser.api import message
-
-home = str(config.configdir)
-agentfile = Path("{}/useragent_list.json".format(home))
-
-if agentfile.is_file():
- with open(agentfile, "r") as filehandle:
- agentList = json.load(filehandle)
-
- agent = random.choice(tuple(agentList))
- c.content.headers.user_agent = agent
(DIR) diff --git a/suckless/dmenu/Makefile b/suckless/dmenu/Makefile
@@ -0,0 +1,39 @@
+REPOSITORY = http://git.suckless.org/dmenu
+SRC_DIR = src
+PINNED_REVISION = HEAD
+PATCH_DIR = patches
+
+all: $(SRC_DIR)
+
+clean: reset
+ @if test -d $(SRC_DIR); then \
+ $(MAKE) -C "${SRC_DIR}" -s clean; \
+ git -C "${SRC_DIR}" clean -f; \
+ fi
+
+$(SRC_DIR): clone reset patch
+ @cp config.h $@
+ $(MAKE) -C "${SRC_DIR}" -s
+
+patch: $(PATCH_DIR)/*
+ @for file in $^ ; do \
+ patch -d "${SRC_DIR}" < $${file}; \
+ done
+reset:
+ @if [ -n "$(strip $(PINNED_REVISION))" ]; then \
+ git -C "${SRC_DIR}" reset --hard $(PINNED_REVISION); \
+ fi
+
+clone:
+ @if ! test -d $(SRC_DIR); then \
+ git clone $(REPOSITORY) $(SRC_DIR); \
+ fi
+
+update: clean
+ @git -C "${SRC_DIR}" pull
+
+install:
+ $(MAKE) -C "${SRC_DIR}" -s install
+
+
+.PHONY: all clean update install reset clone
(DIR) diff --git a/suckless/dmenu/config.h b/suckless/dmenu/config.h
@@ -0,0 +1,16 @@
+static int topbar = 1;
+static const char *fonts[] = {
+ "Hack:pixelsize=14"
+};
+static int centered = 1;
+static const char *prompt = "run »";
+static const char *colors[SchemeLast][2] = {
+ [SchemeNorm] = { "#ebdbb2", "#282828" },
+ [SchemeSel] = { "#ebdbb2", "#98971a" },
+ [SchemeOut] = { "#ebdbb2", "#8ec07c" },
+};
+
+static unsigned int lines = 0;
+static const char worddelimiters[] = " ";
+static int min_width = 800;
+static unsigned int border_width = 3;
(DIR) diff --git a/suckless/dmenu/patches/01-dmenu-border-4.9.diff b/suckless/dmenu/patches/01-dmenu-border-4.9.diff
@@ -0,0 +1,36 @@
+diff --git a/config.def.h b/config.def.h
+index 1edb647..dd3eb31 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -21,3 +21,6 @@ static unsigned int lines = 0;
+ * for example: " /?\"&[]"
+ */
+ static const char worddelimiters[] = " ";
++
++/* Size of the window border */
++static unsigned int border_width = 0;
+diff --git a/dmenu.c b/dmenu.c
+index 27b7a30..7c130fc 100644
+--- a/dmenu.c
++++ b/dmenu.c
+@@ -684,9 +684,11 @@ setup(void)
+ swa.override_redirect = True;
+ swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
+ swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
+- win = XCreateWindow(dpy, root, x, y, mw, mh, 0,
++ win = XCreateWindow(dpy, root, x, y, mw, mh, border_width,
+ CopyFromParent, CopyFromParent, CopyFromParent,
+ CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
++ if (border_width)
++ XSetWindowBorder(dpy, win, scheme[SchemeSel][ColBg].pixel);
+ XSetClassHint(dpy, win, &ch);
+
+
+@@ -757,6 +759,8 @@ main(int argc, char *argv[])
+ colors[SchemeSel][ColFg] = argv[++i];
+ else if (!strcmp(argv[i], "-w")) /* embedding window id */
+ embed = argv[++i];
++ else if (!strcmp(argv[i], "-bw"))
++ border_width = atoi(argv[++i]); /* border width */
+ else
+ usage();
(DIR) diff --git a/suckless/dmenu/patches/02-dmenu-center-20200111-8cd37e1.diff b/suckless/dmenu/patches/02-dmenu-center-20200111-8cd37e1.diff
@@ -0,0 +1,120 @@
+From 8cd37e1ab9e7cb025224aeb3543f1a5be8bceb93 Mon Sep 17 00:00:00 2001
+From: Nihal Jere <nihal@nihaljere.xyz>
+Date: Sat, 11 Jan 2020 21:16:08 -0600
+Subject: [PATCH] center patch now has adjustable minimum width
+
+---
+ config.def.h | 2 ++
+ dmenu.1 | 3 +++
+ dmenu.c | 39 ++++++++++++++++++++++++++++++++-------
+ 3 files changed, 37 insertions(+), 7 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index 1edb647..88ef264 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -2,6 +2,8 @@
+ /* Default settings; can be overriden by command line. */
+
+ static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
++static int centered = 0; /* -c option; centers dmenu on screen */
++static int min_width = 500; /* minimum width when centered */
+ /* -fn option overrides fonts[0]; default X11 font or font set */
+ static const char *fonts[] = {
+ "monospace:size=10"
+diff --git a/dmenu.1 b/dmenu.1
+index 323f93c..c036baa 100644
+--- a/dmenu.1
++++ b/dmenu.1
+@@ -40,6 +40,9 @@ which lists programs in the user's $PATH and runs the result in their $SHELL.
+ .B \-b
+ dmenu appears at the bottom of the screen.
+ .TP
++.B \-c
++dmenu appears centered on the screen.
++.TP
+ .B \-f
+ dmenu grabs the keyboard before reading stdin if not reading from a tty. This
+ is faster, but will lock up X until stdin reaches end\-of\-file.
+diff --git a/dmenu.c b/dmenu.c
+index 65f25ce..041c7f8 100644
+--- a/dmenu.c
++++ b/dmenu.c
+@@ -89,6 +89,15 @@ calcoffsets(void)
+ break;
+ }
+
++static int
++max_textw(void)
++{
++ int len = 0;
++ for (struct item *item = items; item && item->text; item++)
++ len = MAX(TEXTW(item->text), len);
++ return len;
++}
++
+ static void
+ cleanup(void)
+ {
+@@ -611,6 +620,7 @@ setup(void)
+ bh = drw->fonts->h + 2;
+ lines = MAX(lines, 0);
+ mh = (lines + 1) * bh;
++ promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
+ #ifdef XINERAMA
+ i = 0;
+ if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
+@@ -637,9 +647,16 @@ setup(void)
+ if (INTERSECT(x, y, 1, 1, info[i]))
+ break;
+
+- x = info[i].x_org;
+- y = info[i].y_org + (topbar ? 0 : info[i].height - mh);
+- mw = info[i].width;
++ if (centered) {
++ mw = MIN(MAX(max_textw() + promptw, min_width), info[i].width);
++ x = info[i].x_org + ((info[i].width - mw) / 2);
++ y = info[i].y_org + ((info[i].height - mh) / 2);
++ } else {
++ x = info[i].x_org;
++ y = info[i].y_org + (topbar ? 0 : info[i].height - mh);
++ mw = info[i].width;
++ }
++
+ XFree(info);
+ } else
+ #endif
+@@ -647,11 +664,17 @@ setup(void)
+ if (!XGetWindowAttributes(dpy, parentwin, &wa))
+ die("could not get embedding window attributes: 0x%lx",
+ parentwin);
+- x = 0;
+- y = topbar ? 0 : wa.height - mh;
+- mw = wa.width;
++
++ if (centered) {
++ mw = MIN(MAX(max_textw() + promptw, min_width), wa.width);
++ x = (wa.width - mw) / 2;
++ y = (wa.height - mh) / 2;
++ } else {
++ x = 0;
++ y = topbar ? 0 : wa.height - mh;
++ mw = wa.width;
++ }
+ }
+- promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
+ inputw = MIN(inputw, mw/3);
+ match();
+
+@@ -709,6 +732,8 @@ main(int argc, char *argv[])
+ topbar = 0;
+ else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */
+ fast = 1;
++ else if (!strcmp(argv[i], "-c")) /* centers dmenu on screen */
++ centered = 1;
+ else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
+ fstrncmp = strncasecmp;
+ fstrstr = cistrstr;
+--
+2.24.1
+
(DIR) diff --git a/suckless/dwm/Makefile b/suckless/dwm/Makefile
@@ -0,0 +1,41 @@
+REPOSITORY = http://git.suckless.org/dwm
+SRC_DIR = src
+PINNED_REVISION = HEAD
+PATCH_DIR = patches
+
+all: $(SRC_DIR)
+
+clean: reset
+ @if test -d $(SRC_DIR); then \
+ cd $(SRC_DIR); \
+ $(MAKE) -s clean; \
+ git clean -f; \
+ fi
+
+$(SRC_DIR): clone reset patch
+ @cp config.h $@
+ @cd $@ && $(MAKE) -s
+
+reset:
+ @if [ -n "$(strip $(PINNED_REVISION))" ]; then \
+ cd $(SRC_DIR) && git reset --hard $(PINNED_REVISION); \
+ fi
+
+patch: $(PATCH_DIR)/*
+ @for file in $^ ; do \
+ patch -d "${SRC_DIR}" < $${file}; \
+ done
+
+clone:
+ @if ! test -d $(SRC_DIR); then \
+ git clone $(REPOSITORY) $(SRC_DIR); \
+ fi
+
+update: clean
+ @cd $(SRC_DIR) && git pull
+
+install:
+ $(MAKE) -C "${SRC_DIR}" -s install
+
+
+.PHONY: all clean update install reset clone
(DIR) diff --git a/suckless/dwm/config.h b/suckless/dwm/config.h
@@ -0,0 +1,201 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <X11/XF86keysym.h>
+
+/* appearance */
+static const unsigned int borderpx = 3;
+static const unsigned int snap = 32;
+static const int lockfullscreen = 1;
+static const int showbar = 1;
+static const int topbar = 1;
+static const unsigned int systraypinning = 0;
+static const unsigned int systrayonleft = 0;
+static const unsigned int systrayspacing = 2;
+static const int systraypinningfailfirst = 1;
+static const int showsystray = 1;
+
+static const char *fonts[] = { "Hack:size=10" };
+static const char dmenufont[] = "Hack:size=10";
+static const char col_gray1[] = "#222222";
+static const char col_gray2[] = "#98971A";
+static const char col_gray3[] = "#bbbbbb";
+static const char col_gray4[] = "#eeeeee";
+static const char col_cyan[] = "#222222";
+static const char *colors[][3] = {
+ /* fg bg border */
+ [SchemeNorm] = { col_gray3, col_gray1, col_cyan },
+ [SchemeSel] = { col_gray4, col_cyan, col_gray2 },
+};
+
+
+/* custom functions */
+static void togglefullscreen(const Arg *arg);
+static void bstack(Monitor *m);
+static void centeredfloatingmaster(Monitor *m);
+
+/* custom defines for mouse buttons */
+/* only 1-5 are defined in X11/X.h */
+#define Button8 8
+#define Button9 9
+
+/* tagging */
+static const char *tags[] = { "1", "2", "3", "4", "5" };
+
+static Rule rules[] = {
+ /* class instance title tags mask isfloating monitor */
+ { NULL, NULL, NULL, 0, False, -1 },
+};
+
+/* layout(s) */
+static const float mfact = 0.65;
+static const int nmaster = 1;
+static const int resizehints = 0;
+
+static const Layout layouts[] = {
+ { "TTT", bstack },
+ { "[]=", tile },
+ { ">M>", centeredfloatingmaster },
+ { "><>", NULL },
+};
+
+#define MODKEY Mod1Mask
+#define TAGKEYS(KEY,TAG) \
+{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
+{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
+{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
+{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
+
+#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
+
+/* commands */
+static char dmenumon[2] = "0";
+static const char *dmenucmd[] = { "dmenu_run", NULL };
+static const char *termcmd[] = { "xterm", NULL };
+static const char *webcmd[] = { "firefox", NULL };
+static const char *musiccmd[] = { "/home/jay/bin/music", NULL };
+static const char *volup[] = { "sndioctl", "output.level=+0.1", NULL };
+static const char *voldown[] = { "sndioctl", "output.level=-0.1", NULL };
+
+
+static Key keys[] = {
+ /* modifier key function argument */
+ { MODKEY, XK_p, spawn, {.v = dmenucmd } },
+ { MODKEY, XK_space, spawn, {.v = termcmd } },
+ { MODKEY, XK_f, spawn, {.v = webcmd } },
+ { MODKEY, XK_m, spawn, {.v = musiccmd } },
+ { MODKEY, XF86XK_AudioRaiseVolume, spawn, {.v = volup } },
+ { MODKEY, XF86XK_AudioLowerVolume, spawn, {.v = voldown } },
+ { MODKEY, XK_j, focusstack, {.i = +1 } },
+ { MODKEY, XK_k, focusstack, {.i = -1 } },
+ { MODKEY, XK_h, setmfact, {.f = -0.05} },
+ { MODKEY, XK_l, setmfact, {.f = +0.05} },
+ { MODKEY, XK_Return, zoom, {0} },
+ { MODKEY, XK_Tab, view, {0} },
+ { MODKEY, XK_c, killclient, {0} },
+ { MODKEY|ShiftMask, XK_m, togglefullscreen, {0} },
+ { MODKEY, XK_period, focusmon, {.i = +1 } },
+ { MODKEY, XK_comma, tagmon, {.i = +1 } },
+ { MODKEY, XK_b, togglebar, {0} },
+ { MODKEY, XK_x, setlayout, {.v = &layouts[0]} },
+ { MODKEY|ShiftMask, XK_x, setlayout, {.v = &layouts[1]} },
+ TAGKEYS( XK_1, 0)
+ TAGKEYS( XK_2, 1)
+ TAGKEYS( XK_3, 2)
+ TAGKEYS( XK_4, 3)
+ TAGKEYS( XK_5, 4)
+ { MODKEY|ShiftMask, XK_q, quit, {0} },
+};
+
+/* button definitions */
+static Button buttons[] = {
+ { ClkRootWin, 0, Button8, spawn, {.v = voldown } },
+ { ClkRootWin, 0, Button9, spawn, {.v = volup } },
+ };
+
+void
+togglefullscreen(const Arg *arg)
+{
+ if (!selmon->sel)
+ return;
+ setfullscreen(selmon->sel, !selmon->sel->isfullscreen);
+}
+
+static void
+bstack(Monitor *m) {
+ int w, h, mh, mx, tx, ty, tw;
+ unsigned int i, n;
+ Client *c;
+
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+ if (n == 0)
+ return;
+ if (n > m->nmaster) {
+ mh = m->nmaster ? m->mfact * m->wh : 0;
+ tw = m->ww / (n - m->nmaster);
+ ty = m->wy + mh;
+ } else {
+ mh = m->wh;
+ tw = m->ww;
+ ty = m->wy;
+ }
+ for (i = mx = 0, tx = m->wx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
+ if (i < m->nmaster) {
+ w = (m->ww - mx) / (MIN(n, m->nmaster) - i);
+ resize(c, m->wx + mx, m->wy, w - (2 * c->bw), mh - (2 * c->bw), 0);
+ mx += WIDTH(c);
+ } else {
+ h = m->wh - mh;
+ resize(c, tx, ty, tw - (2 * c->bw), h - (2 * c->bw), 0);
+ if (tw != m->ww)
+ tx += WIDTH(c);
+ }
+ }
+}
+
+void
+centeredfloatingmaster(Monitor *m)
+{
+ unsigned int i, n, w, mh, mw, mx, mxo, my, myo, tx;
+ Client *c;
+
+ /* count number of clients in the selected monitor */
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+ if (n == 0)
+ return;
+
+ /* initialize nmaster area */
+ if (n > m->nmaster) {
+ /* go mfact box in the center if more than nmaster clients */
+ if (m->ww > m->wh) {
+ mw = m->nmaster ? m->ww * m->mfact : 0;
+ mh = m->nmaster ? m->wh * 0.9 : 0;
+ } else {
+ mh = m->nmaster ? m->wh * m->mfact : 0;
+ mw = m->nmaster ? m->ww * 0.9 : 0;
+ }
+ mx = mxo = (m->ww - mw) / 2;
+ my = myo = (m->wh - mh) / 2;
+ } else {
+ /* go fullscreen if all clients are in the master area */
+ mh = m->wh;
+ mw = m->ww;
+ mx = mxo = 0;
+ my = myo = 0;
+ }
+
+ for(i = tx = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
+ if (i < m->nmaster) {
+ /* nmaster clients are stacked horizontally, in the center
+ * of the screen */
+ w = (mw + mxo - mx) / (MIN(n, m->nmaster) - i);
+ resize(c, m->wx + mx, m->wy + my, w - (2*c->bw),
+ mh - (2*c->bw), 0);
+ mx += WIDTH(c);
+ } else {
+ /* stack clients are stacked horizontally */
+ w = (m->ww - tx) / (n - i);
+ resize(c, m->wx + tx, m->wy, w - (2*c->bw),
+ m->wh - (2*c->bw), 0);
+ tx += WIDTH(c);
+ }
+}
(DIR) diff --git a/suckless/dwm/patches/01-dwm-systray-6.4.diff b/suckless/dwm/patches/01-dwm-systray-6.4.diff
@@ -0,0 +1,746 @@
+diff --git a/config.def.h b/config.def.h
+index 9efa774..750529d 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -3,6 +3,11 @@
+ /* appearance */
+ static const unsigned int borderpx = 1; /* border pixel of windows */
+ static const unsigned int snap = 32; /* snap pixel */
++static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
++static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */
++static const unsigned int systrayspacing = 2; /* systray spacing */
++static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
++static const int showsystray = 1; /* 0 means no systray */
+ static const int showbar = 1; /* 0 means no bar */
+ static const int topbar = 1; /* 0 means bottom bar */
+ static const char *fonts[] = { "monospace:size=10" };
+@@ -101,8 +106,8 @@ static const Key keys[] = {
+ /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
+ static const Button buttons[] = {
+ /* click event mask button function argument */
+- { ClkLtSymbol, 0, Button1, setlayout, {0} },
+- { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
++ { ClkTagBar, MODKEY, Button1, tag, {0} },
++ { ClkTagBar, MODKEY, Button3, toggletag, {0} },
+ { ClkWinTitle, 0, Button2, zoom, {0} },
+ { ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
+ { ClkClientWin, MODKEY, Button1, movemouse, {0} },
+diff --git a/dwm.c b/dwm.c
+index 03baf42..4611a03 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -57,12 +57,27 @@
+ #define TAGMASK ((1 << LENGTH(tags)) - 1)
+ #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
+
++#define SYSTEM_TRAY_REQUEST_DOCK 0
++/* XEMBED messages */
++#define XEMBED_EMBEDDED_NOTIFY 0
++#define XEMBED_WINDOW_ACTIVATE 1
++#define XEMBED_FOCUS_IN 4
++#define XEMBED_MODALITY_ON 10
++#define XEMBED_MAPPED (1 << 0)
++#define XEMBED_WINDOW_ACTIVATE 1
++#define XEMBED_WINDOW_DEACTIVATE 2
++#define VERSION_MAJOR 0
++#define VERSION_MINOR 0
++#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
++
+ /* enums */
+ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
+ enum { SchemeNorm, SchemeSel }; /* color schemes */
+ enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
++ NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz,
+ NetWMFullscreen, NetActiveWindow, NetWMWindowType,
+ NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
++enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
+ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
+ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
+ ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
+@@ -141,6 +156,12 @@ typedef struct {
+ int monitor;
+ } Rule;
+
++typedef struct Systray Systray;
++struct Systray {
++ Window win;
++ Client *icons;
++};
++
+ /* function declarations */
+ static void applyrules(Client *c);
+ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
+@@ -172,6 +193,7 @@ static void focusstack(const Arg *arg);
+ static Atom getatomprop(Client *c, Atom prop);
+ static int getrootptr(int *x, int *y);
+ static long getstate(Window w);
++static unsigned int getsystraywidth();
+ static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
+ static void grabbuttons(Client *c, int focused);
+ static void grabkeys(void);
+@@ -189,13 +211,16 @@ static void pop(Client *c);
+ static void propertynotify(XEvent *e);
+ static void quit(const Arg *arg);
+ static Monitor *recttomon(int x, int y, int w, int h);
++static void removesystrayicon(Client *i);
+ static void resize(Client *c, int x, int y, int w, int h, int interact);
++static void resizebarwin(Monitor *m);
+ static void resizeclient(Client *c, int x, int y, int w, int h);
+ static void resizemouse(const Arg *arg);
++static void resizerequest(XEvent *e);
+ static void restack(Monitor *m);
+ static void run(void);
+ static void scan(void);
+-static int sendevent(Client *c, Atom proto);
++static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
+ static void sendmon(Client *c, Monitor *m);
+ static void setclientstate(Client *c, long state);
+ static void setfocus(Client *c);
+@@ -207,6 +232,7 @@ static void seturgent(Client *c, int urg);
+ static void showhide(Client *c);
+ static void sigchld(int unused);
+ static void spawn(const Arg *arg);
++static Monitor *systraytomon(Monitor *m);
+ static void tag(const Arg *arg);
+ static void tagmon(const Arg *arg);
+ static void tile(Monitor *m);
+@@ -224,18 +250,23 @@ static int updategeom(void);
+ static void updatenumlockmask(void);
+ static void updatesizehints(Client *c);
+ static void updatestatus(void);
++static void updatesystray(void);
++static void updatesystrayicongeom(Client *i, int w, int h);
++static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
+ static void updatetitle(Client *c);
+ static void updatewindowtype(Client *c);
+ static void updatewmhints(Client *c);
+ static void view(const Arg *arg);
+ static Client *wintoclient(Window w);
+ static Monitor *wintomon(Window w);
++static Client *wintosystrayicon(Window w);
+ static int xerror(Display *dpy, XErrorEvent *ee);
+ static int xerrordummy(Display *dpy, XErrorEvent *ee);
+ static int xerrorstart(Display *dpy, XErrorEvent *ee);
+ static void zoom(const Arg *arg);
+
+ /* variables */
++static Systray *systray = NULL;
+ static const char broken[] = "broken";
+ static char stext[256];
+ static int screen;
+@@ -258,9 +289,10 @@ static void (*handler[LASTEvent]) (XEvent *) = {
+ [MapRequest] = maprequest,
+ [MotionNotify] = motionnotify,
+ [PropertyNotify] = propertynotify,
++ [ResizeRequest] = resizerequest,
+ [UnmapNotify] = unmapnotify
+ };
+-static Atom wmatom[WMLast], netatom[NetLast];
++static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
+ static int running = 1;
+ static Cur *cursor[CurLast];
+ static Clr **scheme;
+@@ -442,7 +474,7 @@ buttonpress(XEvent *e)
+ arg.ui = 1 << i;
+ } else if (ev->x < x + TEXTW(selmon->ltsymbol))
+ click = ClkLtSymbol;
+- else if (ev->x > selmon->ww - (int)TEXTW(stext))
++ else if (ev->x > selmon->ww - (int)TEXTW(stext) - getsystraywidth())
+ click = ClkStatusText;
+ else
+ click = ClkWinTitle;
+@@ -485,6 +517,13 @@ cleanup(void)
+ XUngrabKey(dpy, AnyKey, AnyModifier, root);
+ while (mons)
+ cleanupmon(mons);
++
++ if (showsystray) {
++ XUnmapWindow(dpy, systray->win);
++ XDestroyWindow(dpy, systray->win);
++ free(systray);
++ }
++
+ for (i = 0; i < CurLast; i++)
+ drw_cur_free(drw, cursor[i]);
+ for (i = 0; i < LENGTH(colors); i++)
+@@ -516,9 +555,58 @@ cleanupmon(Monitor *mon)
+ void
+ clientmessage(XEvent *e)
+ {
++ XWindowAttributes wa;
++ XSetWindowAttributes swa;
+ XClientMessageEvent *cme = &e->xclient;
+ Client *c = wintoclient(cme->window);
+
++ if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
++ /* add systray icons */
++ if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
++ if (!(c = (Client *)calloc(1, sizeof(Client))))
++ die("fatal: could not malloc() %u bytes\n", sizeof(Client));
++ if (!(c->win = cme->data.l[2])) {
++ free(c);
++ return;
++ }
++ c->mon = selmon;
++ c->next = systray->icons;
++ systray->icons = c;
++ if (!XGetWindowAttributes(dpy, c->win, &wa)) {
++ /* use sane defaults */
++ wa.width = bh;
++ wa.height = bh;
++ wa.border_width = 0;
++ }
++ c->x = c->oldx = c->y = c->oldy = 0;
++ c->w = c->oldw = wa.width;
++ c->h = c->oldh = wa.height;
++ c->oldbw = wa.border_width;
++ c->bw = 0;
++ c->isfloating = True;
++ /* reuse tags field as mapped status */
++ c->tags = 1;
++ updatesizehints(c);
++ updatesystrayicongeom(c, wa.width, wa.height);
++ XAddToSaveSet(dpy, c->win);
++ XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
++ XReparentWindow(dpy, c->win, systray->win, 0, 0);
++ /* use parents background color */
++ swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
++ XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa);
++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
++ /* FIXME not sure if I have to send these events, too */
++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
++ XSync(dpy, False);
++ resizebarwin(selmon);
++ updatesystray();
++ setclientstate(c, NormalState);
++ }
++ return;
++ }
++
+ if (!c)
+ return;
+ if (cme->message_type == netatom[NetWMState]) {
+@@ -571,7 +659,7 @@ configurenotify(XEvent *e)
+ for (c = m->clients; c; c = c->next)
+ if (c->isfullscreen)
+ resizeclient(c, m->mx, m->my, m->mw, m->mh);
+- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
++ resizebarwin(m);
+ }
+ focus(NULL);
+ arrange(NULL);
+@@ -656,6 +744,11 @@ destroynotify(XEvent *e)
+
+ if ((c = wintoclient(ev->window)))
+ unmanage(c, 1);
++ else if ((c = wintosystrayicon(ev->window))) {
++ removesystrayicon(c);
++ resizebarwin(selmon);
++ updatesystray();
++ }
+ }
+
+ void
+@@ -699,7 +792,7 @@ dirtomon(int dir)
+ void
+ drawbar(Monitor *m)
+ {
+- int x, w, tw = 0;
++ int x, w, tw = 0, stw = 0;
+ int boxs = drw->fonts->h / 9;
+ int boxw = drw->fonts->h / 6 + 2;
+ unsigned int i, occ = 0, urg = 0;
+@@ -708,13 +801,17 @@ drawbar(Monitor *m)
+ if (!m->showbar)
+ return;
+
++ if(showsystray && m == systraytomon(m) && !systrayonleft)
++ stw = getsystraywidth();
++
+ /* draw status first so it can be overdrawn by tags later */
+ if (m == selmon) { /* status is only drawn on selected monitor */
+ drw_setscheme(drw, scheme[SchemeNorm]);
+- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
+- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
++ tw = TEXTW(stext) - lrpad / 2 + 2; /* 2px extra right padding */
++ drw_text(drw, m->ww - tw - stw, 0, tw, bh, lrpad / 2 - 2, stext, 0);
+ }
+
++ resizebarwin(m);
+ for (c = m->clients; c; c = c->next) {
+ occ |= c->tags;
+ if (c->isurgent)
+@@ -735,7 +832,7 @@ drawbar(Monitor *m)
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
+
+- if ((w = m->ww - tw - x) > bh) {
++ if ((w = m->ww - tw - stw - x) > bh) {
+ if (m->sel) {
+ drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
+ drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
+@@ -746,7 +843,7 @@ drawbar(Monitor *m)
+ drw_rect(drw, x, 0, w, bh, 1, 1);
+ }
+ }
+- drw_map(drw, m->barwin, 0, 0, m->ww, bh);
++ drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh);
+ }
+
+ void
+@@ -783,8 +880,11 @@ expose(XEvent *e)
+ Monitor *m;
+ XExposeEvent *ev = &e->xexpose;
+
+- if (ev->count == 0 && (m = wintomon(ev->window)))
++ if (ev->count == 0 && (m = wintomon(ev->window))) {
+ drawbar(m);
++ if (m == selmon)
++ updatesystray();
++ }
+ }
+
+ void
+@@ -870,14 +970,32 @@ getatomprop(Client *c, Atom prop)
+ unsigned char *p = NULL;
+ Atom da, atom = None;
+
+- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
++ /* FIXME getatomprop should return the number of items and a pointer to
++ * the stored data instead of this workaround */
++ Atom req = XA_ATOM;
++ if (prop == xatom[XembedInfo])
++ req = xatom[XembedInfo];
++
++ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
+ &da, &di, &dl, &dl, &p) == Success && p) {
+ atom = *(Atom *)p;
++ if (da == xatom[XembedInfo] && dl == 2)
++ atom = ((Atom *)p)[1];
+ XFree(p);
+ }
+ return atom;
+ }
+
++unsigned int
++getsystraywidth()
++{
++ unsigned int w = 0;
++ Client *i;
++ if(showsystray)
++ for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ;
++ return w ? w + systrayspacing : 1;
++}
++
+ int
+ getrootptr(int *x, int *y)
+ {
+@@ -1018,7 +1136,8 @@ killclient(const Arg *arg)
+ {
+ if (!selmon->sel)
+ return;
+- if (!sendevent(selmon->sel, wmatom[WMDelete])) {
++
++ if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) {
+ XGrabServer(dpy);
+ XSetErrorHandler(xerrordummy);
+ XSetCloseDownMode(dpy, DestroyAll);
+@@ -1105,6 +1224,13 @@ maprequest(XEvent *e)
+ static XWindowAttributes wa;
+ XMapRequestEvent *ev = &e->xmaprequest;
+
++ Client *i;
++ if ((i = wintosystrayicon(ev->window))) {
++ sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
++ resizebarwin(selmon);
++ updatesystray();
++ }
++
+ if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect)
+ return;
+ if (!wintoclient(ev->window))
+@@ -1226,6 +1352,17 @@ propertynotify(XEvent *e)
+ Window trans;
+ XPropertyEvent *ev = &e->xproperty;
+
++ if ((c = wintosystrayicon(ev->window))) {
++ if (ev->atom == XA_WM_NORMAL_HINTS) {
++ updatesizehints(c);
++ updatesystrayicongeom(c, c->w, c->h);
++ }
++ else
++ updatesystrayiconstate(c, ev);
++ resizebarwin(selmon);
++ updatesystray();
++ }
++
+ if ((ev->window == root) && (ev->atom == XA_WM_NAME))
+ updatestatus();
+ else if (ev->state == PropertyDelete)
+@@ -1276,6 +1413,19 @@ recttomon(int x, int y, int w, int h)
+ return r;
+ }
+
++void
++removesystrayicon(Client *i)
++{
++ Client **ii;
++
++ if (!showsystray || !i)
++ return;
++ for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
++ if (ii)
++ *ii = i->next;
++ free(i);
++}
++
+ void
+ resize(Client *c, int x, int y, int w, int h, int interact)
+ {
+@@ -1283,6 +1433,14 @@ resize(Client *c, int x, int y, int w, int h, int interact)
+ resizeclient(c, x, y, w, h);
+ }
+
++void
++resizebarwin(Monitor *m) {
++ unsigned int w = m->ww;
++ if (showsystray && m == systraytomon(m) && !systrayonleft)
++ w -= getsystraywidth();
++ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
++}
++
+ void
+ resizeclient(Client *c, int x, int y, int w, int h)
+ {
+@@ -1298,6 +1456,19 @@ resizeclient(Client *c, int x, int y, int w, int h)
+ XSync(dpy, False);
+ }
+
++void
++resizerequest(XEvent *e)
++{
++ XResizeRequestEvent *ev = &e->xresizerequest;
++ Client *i;
++
++ if ((i = wintosystrayicon(ev->window))) {
++ updatesystrayicongeom(i, ev->width, ev->height);
++ resizebarwin(selmon);
++ updatesystray();
++ }
++}
++
+ void
+ resizemouse(const Arg *arg)
+ {
+@@ -1444,26 +1615,37 @@ setclientstate(Client *c, long state)
+ }
+
+ int
+-sendevent(Client *c, Atom proto)
++sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
+ {
+ int n;
+- Atom *protocols;
++ Atom *protocols, mt;
+ int exists = 0;
+ XEvent ev;
+
+- if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
+- while (!exists && n--)
+- exists = protocols[n] == proto;
+- XFree(protocols);
++ if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
++ mt = wmatom[WMProtocols];
++ if (XGetWMProtocols(dpy, w, &protocols, &n)) {
++ while (!exists && n--)
++ exists = protocols[n] == proto;
++ XFree(protocols);
++ }
++ }
++ else {
++ exists = True;
++ mt = proto;
+ }
++
+ if (exists) {
+ ev.type = ClientMessage;
+- ev.xclient.window = c->win;
+- ev.xclient.message_type = wmatom[WMProtocols];
++ ev.xclient.window = w;
++ ev.xclient.message_type = mt;
+ ev.xclient.format = 32;
+- ev.xclient.data.l[0] = proto;
+- ev.xclient.data.l[1] = CurrentTime;
+- XSendEvent(dpy, c->win, False, NoEventMask, &ev);
++ ev.xclient.data.l[0] = d0;
++ ev.xclient.data.l[1] = d1;
++ ev.xclient.data.l[2] = d2;
++ ev.xclient.data.l[3] = d3;
++ ev.xclient.data.l[4] = d4;
++ XSendEvent(dpy, w, False, mask, &ev);
+ }
+ return exists;
+ }
+@@ -1477,7 +1659,7 @@ setfocus(Client *c)
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *) &(c->win), 1);
+ }
+- sendevent(c, wmatom[WMTakeFocus]);
++ sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
+ }
+
+ void
+@@ -1566,6 +1748,10 @@ setup(void)
+ wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
+ netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
+ netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
++ netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
++ netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
++ netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
++ netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False);
+ netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
+ netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
+ netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
+@@ -1573,6 +1759,9 @@ setup(void)
+ netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
+ netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
+ netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
++ xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
++ xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
++ xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
+ /* init cursors */
+ cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
+ cursor[CurResize] = drw_cur_create(drw, XC_sizing);
+@@ -1581,6 +1770,8 @@ setup(void)
+ scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
+ for (i = 0; i < LENGTH(colors); i++)
+ scheme[i] = drw_scm_create(drw, colors[i], 3);
++ /* init system tray */
++ updatesystray();
+ /* init bars */
+ updatebars();
+ updatestatus();
+@@ -1711,7 +1902,18 @@ togglebar(const Arg *arg)
+ {
+ selmon->showbar = !selmon->showbar;
+ updatebarpos(selmon);
+- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
++ resizebarwin(selmon);
++ if (showsystray) {
++ XWindowChanges wc;
++ if (!selmon->showbar)
++ wc.y = -bh;
++ else if (selmon->showbar) {
++ wc.y = 0;
++ if (!selmon->topbar)
++ wc.y = selmon->mh - bh;
++ }
++ XConfigureWindow(dpy, systray->win, CWY, &wc);
++ }
+ arrange(selmon);
+ }
+
+@@ -1807,11 +2009,18 @@ unmapnotify(XEvent *e)
+ else
+ unmanage(c, 0);
+ }
++ else if ((c = wintosystrayicon(ev->window))) {
++ /* KLUDGE! sometimes icons occasionally unmap their windows, but do
++ * _not_ destroy them. We map those windows back */
++ XMapRaised(dpy, c->win);
++ updatesystray();
++ }
+ }
+
+ void
+ updatebars(void)
+ {
++ unsigned int w;
+ Monitor *m;
+ XSetWindowAttributes wa = {
+ .override_redirect = True,
+@@ -1822,10 +2031,15 @@ updatebars(void)
+ for (m = mons; m; m = m->next) {
+ if (m->barwin)
+ continue;
+- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
++ w = m->ww;
++ if (showsystray && m == systraytomon(m))
++ w -= getsystraywidth();
++ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen),
+ CopyFromParent, DefaultVisual(dpy, screen),
+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
+ XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
++ if (showsystray && m == systraytomon(m))
++ XMapRaised(dpy, systray->win);
+ XMapRaised(dpy, m->barwin);
+ XSetClassHint(dpy, m->barwin, &ch);
+ }
+@@ -2002,6 +2216,125 @@ updatestatus(void)
+ if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
+ strcpy(stext, "dwm-"VERSION);
+ drawbar(selmon);
++ updatesystray();
++}
++
++
++void
++updatesystrayicongeom(Client *i, int w, int h)
++{
++ if (i) {
++ i->h = bh;
++ if (w == h)
++ i->w = bh;
++ else if (h == bh)
++ i->w = w;
++ else
++ i->w = (int) ((float)bh * ((float)w / (float)h));
++ applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
++ /* force icons into the systray dimensions if they don't want to */
++ if (i->h > bh) {
++ if (i->w == i->h)
++ i->w = bh;
++ else
++ i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
++ i->h = bh;
++ }
++ }
++}
++
++void
++updatesystrayiconstate(Client *i, XPropertyEvent *ev)
++{
++ long flags;
++ int code = 0;
++
++ if (!showsystray || !i || ev->atom != xatom[XembedInfo] ||
++ !(flags = getatomprop(i, xatom[XembedInfo])))
++ return;
++
++ if (flags & XEMBED_MAPPED && !i->tags) {
++ i->tags = 1;
++ code = XEMBED_WINDOW_ACTIVATE;
++ XMapRaised(dpy, i->win);
++ setclientstate(i, NormalState);
++ }
++ else if (!(flags & XEMBED_MAPPED) && i->tags) {
++ i->tags = 0;
++ code = XEMBED_WINDOW_DEACTIVATE;
++ XUnmapWindow(dpy, i->win);
++ setclientstate(i, WithdrawnState);
++ }
++ else
++ return;
++ sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
++ systray->win, XEMBED_EMBEDDED_VERSION);
++}
++
++void
++updatesystray(void)
++{
++ XSetWindowAttributes wa;
++ XWindowChanges wc;
++ Client *i;
++ Monitor *m = systraytomon(NULL);
++ unsigned int x = m->mx + m->mw;
++ unsigned int sw = TEXTW(stext) - lrpad + systrayspacing;
++ unsigned int w = 1;
++
++ if (!showsystray)
++ return;
++ if (systrayonleft)
++ x -= sw + lrpad / 2;
++ if (!systray) {
++ /* init systray */
++ if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
++ die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
++ systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel);
++ wa.event_mask = ButtonPressMask | ExposureMask;
++ wa.override_redirect = True;
++ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
++ XSelectInput(dpy, systray->win, SubstructureNotifyMask);
++ XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
++ PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1);
++ XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa);
++ XMapRaised(dpy, systray->win);
++ XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
++ if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
++ sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
++ XSync(dpy, False);
++ }
++ else {
++ fprintf(stderr, "dwm: unable to obtain system tray.\n");
++ free(systray);
++ systray = NULL;
++ return;
++ }
++ }
++ for (w = 0, i = systray->icons; i; i = i->next) {
++ /* make sure the background color stays the same */
++ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
++ XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
++ XMapRaised(dpy, i->win);
++ w += systrayspacing;
++ i->x = w;
++ XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
++ w += i->w;
++ if (i->mon != m)
++ i->mon = m;
++ }
++ w = w ? w + systrayspacing : 1;
++ x -= w;
++ XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh);
++ wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh;
++ wc.stack_mode = Above; wc.sibling = m->barwin;
++ XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc);
++ XMapWindow(dpy, systray->win);
++ XMapSubwindows(dpy, systray->win);
++ /* redraw background */
++ XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel);
++ XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh);
++ XSync(dpy, False);
+ }
+
+ void
+@@ -2069,6 +2402,16 @@ wintoclient(Window w)
+ return NULL;
+ }
+
++Client *
++wintosystrayicon(Window w) {
++ Client *i = NULL;
++
++ if (!showsystray || !w)
++ return i;
++ for (i = systray->icons; i && i->win != w; i = i->next) ;
++ return i;
++}
++
+ Monitor *
+ wintomon(Window w)
+ {
+@@ -2122,6 +2465,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee)
+ return -1;
+ }
+
++Monitor *
++systraytomon(Monitor *m) {
++ Monitor *t;
++ int i, n;
++ if(!systraypinning) {
++ if(!m)
++ return selmon;
++ return m == selmon ? m : NULL;
++ }
++ for(n = 1, t = mons; t && t->next; n++, t = t->next) ;
++ for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ;
++ if(systraypinningfailfirst && n < systraypinning)
++ return mons;
++ return t;
++}
++
+ void
+ zoom(const Arg *arg)
+ {
(DIR) diff --git a/suckless/herbe/Makefile b/suckless/herbe/Makefile
@@ -0,0 +1,40 @@
+REPOSITORY = https://github.com/dudik/herbe.git
+SRC_DIR = src
+PINNED_REVISION = HEAD
+PATCH_DIR = patches
+
+all: $(SRC_DIR)
+
+clean: reset
+ @if test -d $(SRC_DIR); then \
+ $(MAKE) -C "${SRC_DIR}" -s clean; \
+ git -C "${SRC_DIR}" clean -f; \
+ fi
+
+$(SRC_DIR): clone reset
+ @cp config.h $@
+ $(MAKE) -C "${SRC_DIR}" -s
+
+reset:
+ @if [ -n "$(strip $(PINNED_REVISION))" ]; then \
+ git -C "${SRC_DIR}" reset --hard $(PINNED_REVISION); \
+ fi
+
+patch: $(PATCH_DIR)/*
+ @for file in $^ ; do \
+ patch -d "${SRC_DIR}" < $${file}; \
+ done
+
+clone:
+ @if ! test -d $(SRC_DIR); then \
+ git clone $(REPOSITORY) $(SRC_DIR); \
+ fi
+
+update: clean
+ @git -C "${SRC_DIR}" pull
+
+install:
+ $(MAKE) -C "${SRC_DIR}" -s install
+
+
+.PHONY: all clean update install reset clone
(DIR) diff --git a/suckless/herbe/config.h b/suckless/herbe/config.h
@@ -0,0 +1,19 @@
+static const char *background_color = "#222222";
+static const char *border_color = "#008000";
+static const char *font_color = "#ffd7af";
+static const char *font_pattern = "Hack:pixelsize=12";
+static unsigned line_spacing = 5;
+static unsigned int padding = 12;
+
+static unsigned int width = 300;
+static unsigned int border_size = 3;
+static unsigned int pos_x = 30;
+static unsigned int pos_y = 60;
+
+enum corners { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT };
+enum corners corner = TOP_RIGHT;
+
+static unsigned int duration = 5; /* in seconds */
+
+#define DISMISS_BUTTON Button1
+#define ACTION_BUTTON Button3
(DIR) diff --git a/suckless/slstatus/Makefile b/suckless/slstatus/Makefile
@@ -0,0 +1,35 @@
+REPOSITORY = git://git.suckless.org/slstatus
+SRC_DIR = src
+PINNED_REVISION = HEAD
+
+all: $(SRC_DIR)
+
+clean: reset
+ @if test -d $(SRC_DIR); then \
+ cd $(SRC_DIR); \
+ $(MAKE) -s clean; \
+ git clean -f; \
+ fi
+
+$(SRC_DIR): clone reset
+ @cp config.h $@
+ @cd $@ && $(MAKE) -s
+
+reset:
+ @if [ -n "$(strip $(PINNED_REVISION))" ]; then \
+ cd $(SRC_DIR) && git reset --hard $(PINNED_REVISION); \
+ fi
+
+clone:
+ @if ! test -d $(SRC_DIR); then \
+ git clone $(REPOSITORY) $(SRC_DIR); \
+ fi
+
+update: clean
+ @cd $(SRC_DIR) && git pull
+
+install:
+ $(MAKE) -C "${SRC_DIR}" -s install
+
+
+.PHONY: all clean update install reset clone
(DIR) diff --git a/suckless/slstatus/config.h b/suckless/slstatus/config.h
@@ -0,0 +1,71 @@
+/* See LICENSE file for copyright and license details. */
+
+/* interval between updates (in ms) */
+const unsigned int interval = 1000;
+
+/* text to show if no value can be retrieved */
+static const char unknown_str[] = "n/a";
+
+/* maximum output string length */
+#define MAXLEN 2048
+
+/*
+ * function description argument (example)
+ *
+ * battery_perc battery percentage battery name (BAT0)
+ * NULL on OpenBSD/FreeBSD
+ * battery_remaining battery remaining HH:MM battery name (BAT0)
+ * NULL on OpenBSD/FreeBSD
+ * battery_state battery charging state battery name (BAT0)
+ * NULL on OpenBSD/FreeBSD
+ * cat read arbitrary file path
+ * cpu_freq cpu frequency in MHz NULL
+ * cpu_perc cpu usage in percent NULL
+ * datetime date and time format string (%F %T)
+ * disk_free free disk space in GB mountpoint path (/)
+ * disk_perc disk usage in percent mountpoint path (/)
+ * disk_total total disk space in GB mountpoint path (/)
+ * disk_used used disk space in GB mountpoint path (/)
+ * entropy available entropy NULL
+ * gid GID of current user NULL
+ * hostname hostname NULL
+ * ipv4 IPv4 address interface name (eth0)
+ * ipv6 IPv6 address interface name (eth0)
+ * kernel_release `uname -r` NULL
+ * keyboard_indicators caps/num lock indicators format string (c?n?)
+ * see keyboard_indicators.c
+ * keymap layout (variant) of current NULL
+ * keymap
+ * load_avg load average NULL
+ * netspeed_rx receive network speed interface name (wlan0)
+ * netspeed_tx transfer network speed interface name (wlan0)
+ * num_files number of files in a directory path
+ * (/home/foo/Inbox/cur)
+ * ram_free free memory in GB NULL
+ * ram_perc memory usage in percent NULL
+ * ram_total total memory size in GB NULL
+ * ram_used used memory in GB NULL
+ * run_command custom shell command command (echo foo)
+ * swap_free free swap in GB NULL
+ * swap_perc swap usage in percent NULL
+ * swap_total total swap size in GB NULL
+ * swap_used used swap in GB NULL
+ * temp temperature in degree celsius sensor file
+ * (/sys/class/thermal/...)
+ * NULL on OpenBSD
+ * thermal zone on FreeBSD
+ * (tz0, tz1, etc.)
+ * uid UID of current user NULL
+ * uptime system uptime NULL
+ * username username of current user NULL
+ * vol_perc OSS/ALSA volume in percent mixer file (/dev/mixer)
+ * NULL on OpenBSD/FreeBSD
+ * wifi_essid WiFi ESSID interface name (wlan0)
+ * wifi_perc WiFi signal in percent interface name (wlan0)
+ */
+static const struct arg args[] = {
+ /* function format argument */
+ { run_command, "VPN:%4s | ", "if curl -s https://am.i.mullvad.net/connected | grep -q 'server'; then echo 'On'; else echo 'Off'; fi" },
+ // { run_command, "VOL:%4s | ", "pactl list sinks | tr ' ' '\n' | grep -m1 '%'" },
+ { datetime, "%s", "%T" },
+};
(DIR) diff --git a/sway/config b/sway/config
@@ -1,69 +0,0 @@
-set $mod Mod1
-
-# colour theme
-set $colour #1c3c46
-set $menu bemenu-run -p '>>> ' --tb '#55a1ba' --tf '#ffffff' --hf '#444444' -c -W0.4 --fn 'Hack 10'
-
-# autostart
-exec foot --server
-exec wl-paste -t text --watch clipman store --no-persist
-exec /usr/libexec/pipewire-launcher
-
-# appearance
-default_border pixel 3
-default_floating_border pixel 5
-workspace_layout default
-font pango: Hack:style=Regular 2
-
-for_window [app_id="mpv"] floating enable, sticky enable, move absolute position 1340 760, no_focus
-
-# misc
-xwayland enable
-bar swaybar_command waybar
-
-# keyboard layout
-input * {
- xkb_layout "gb"
- xkb_variant "extd"
-}
-
-# keybinds
-bindsym $mod+Space exec footclient
-bindsym $mod+p exec $menu
-bindsym $mod+f exec qutebrowser
-bindsym $mod+m exec /home/jay/bin/music
-
-bindsym XF86AudioRaiseVolume exec pamixer -i 5
-bindsym XF86AudioLowerVolume exec pamixer -d 5
-
-bindsym $mod+c kill
-bindsym $mod+x exec killall -SIGUSR1 waybar
-bindsym $mod+Shift+c reload
-bindsym $mod+Shift+q exec swaymsg exit
-
-bindsym $mod+h focus left
-bindsym $mod+j focus down
-bindsym $mod+k focus up
-bindsym $mod+l focus right
-
-bindsym $mod+Left focus left
-bindsym $mod+Down focus down
-bindsym $mod+Up focus up
-bindsym $mod+Right focus right
-
-bindsym $mod+1 workspace number 1
-bindsym $mod+2 workspace number 2
-bindsym $mod+3 workspace number 3
-bindsym $mod+4 workspace number 4
-
-bindsym $mod+Tab focus next
-bindsym $mod+Shift+1 move container to workspace number 1
-bindsym $mod+Shift+2 move container to workspace number 2
-bindsym $mod+Shift+3 move container to workspace number 3
-bindsym $mod+Shift+4 move container to workspace number 4
-
-bindsym $mod+Shift+e layout toggle split
-bindsym $mod+Shift+m fullscreen
-bindsym $mod+Shift+w layout tabbed
-
-client.focused $colour $colour $colour
(DIR) diff --git a/waybar/config b/waybar/config
@@ -1,67 +0,0 @@
-{
- "layer": "top",
- "position": "top",
-
- "modules-left": [
- "sway/workspaces",
- "custom/right-arrow-dark"
- ],
-
- "modules-center": [
- "custom/vpn"
- ],
-
- "modules-right": [
- "custom/left-arrow-dark",
- "pulseaudio",
- "tray",
- "clock"
- ],
-
- "custom/right-arrow-dark": {
- "format": "",
- "tooltip": false
- },
-
- "custom/left-arrow-dark": {
- "format": "",
- "tooltip": false
- },
-
- "sway/workspaces": {
- "disable-scroll": true,
- "format": "{name}"
- },
-
- "clock": {
- "format": "{:%H:%M}",
- "tooltip": false
- },
-
- "pulseaudio": {
- "format": "{icon} {volume:2}% ",
- "format-muted": "MUTE",
- "format-icons": {
- "default": [
- "",
- ""
- ]
- },
- "scroll-step": 5,
- "on-click": "pamixer -t"
- },
-
- "custom/vpn":{
- "format": "{icon} {}",
- "format-icons": {
- "default": [""]
- },
- "return-type": "json",
- "interval": 60,
- "exec": "$HOME/.config/waybar/waybar_vpn.sh"
- },
-
- "tray": {
- "icon-size": 12
- }
-}
(DIR) diff --git a/waybar/style.css b/waybar/style.css
@@ -1,55 +0,0 @@
-* {
- font-size: 12px;
- font-family: Hack;
-}
-
-
-#custom-vpn,
-window#waybar {
- background: #292b2e;
- color: #fdf6e3;
-}
-
-#workspaces,
-#clock,
-#custom-mail,
-#pulseaudio,
-#tray {
- background: #1a1a1a;
-}
-
-#custom-right-arrow-dark,
-#custom-left-arrow-dark {
- color: #1a1a1a;
-}
-
-#workspaces button {
- padding: 0 0px;
- color: #fdf6e3;
-}
-#workspaces button.focused {
- color: #268bd2;
-}
-#workspaces button:hover {
- box-shadow: inherit;
- text-shadow: inherit;
-}
-#workspaces button:hover {
- background: #1a1a1a;
- border: #1a1a1a;
- padding: 0 1px;
-}
-
-#custom-vpn.connected {
- color: #007300;
-}
-
-#custom-vpn.disconnected {
- color: #d22635;
-}
-
-#clock,
-#custom-vpn,
-#pulseaudio {
- padding: 0 3px;
-}
(DIR) diff --git a/waybar/waybar_mail.sh b/waybar/waybar_mail.sh
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-maildirnew="$HOME/.mail/jay/Inbox/new/"
-new="$(find $maildirnew -type f | wc -l)"
-
-if [ $new -gt 0 ]
-then
- echo "{\"text\":\"$new\",\"tooltip\":\"$new Mail\",\"class\":\"new\"}"
-else
- echo '{"text":"No new mail","tooltip":"","class":""}'
-fi
-
(DIR) diff --git a/waybar/waybar_vpn.sh b/waybar/waybar_vpn.sh
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-country=$(curl -s https://am.i.mullvad.net/country)
-
-if curl -s https://am.i.mullvad.net/connected | grep -q "server"; then
- echo "{\"text\":\"$country\",\"class\":\"connected\"}"
-else
- echo "{\"text\":\"$country\",\"class\":\"disconnected\"}"
-fi
(DIR) diff --git a/xenodm/Xresources b/xenodm/Xresources
@@ -0,0 +1,24 @@
+! $OpenBSD: Xresources.in,v 1.4 2022/11/07 17:12:06 matthieu Exp $
+!
+
+xlogin.Login.echoPasswd: true
+xlogin.Login.fail: fail
+xlogin.Login.greeting:
+xlogin.Login.namePrompt: \040login\040
+xlogin.Login.passwdPrompt: passwd\040
+
+xlogin.Login.height: 180
+xlogin.Login.width: 500
+xlogin.Login.y: 320
+xlogin.Login.frameWidth: 0
+xlogin.Login.innerFramesWidth: 0
+
+xlogin.Login.background: black
+xlogin.Login.foreground: #eeeeee
+xlogin.Login.failColor: white
+xlogin.Login.inpColor: black
+xlogin.Login.promptColor: #eeeeec
+
+xlogin.Login.face: Hack-14
+xlogin.Login.failFace: Hack-14
+xlogin.Login.promptFace: Hack-14
(DIR) diff --git a/xenodm/Xsetup_0 b/xenodm/Xsetup_0
@@ -0,0 +1,7 @@
+#!/bin/sh
+# $OpenBSD: Xsetup_0.in,v 1.1 2021/08/30 15:38:27 matthieu Exp $
+
+xrandr --output default --dpi 96
+
+# set background
+/usr/X11R6/bin/xsetroot -solid black