Switch to wayland

Added a simple wayland configuration.
Currently set up simple wayland configuration based on river window
manager and waybar.
Rivercarro is the layout manager, being the same in principle as rivertile,
the default layout manager for river, only it comes with smart gaps
(gaps turn off if there is only one window open)
and monocle mode (give one window all space).

Runs `keyd` in the background to replace the old `xcape` capslock switching
(capslock is escape and if held control).
Uses `swaybg` to set a wallpaper.

Added powermenu and lockscreen scripts.
Improved lockscreen script to detect and work for wayland.
Moved old rofi mode 'powermenu' to more general powermenu script,
which works with any rofi-like selector (dmenu, bemenu, wofi, etc.)
Loses some of its design quality but since it was wonky anyway,
and I rarely see the menu,
we could repurpose its functionality for a more general powermenu
concept.
Currently hardcoded for `bemenu` but can be easily swapped and possibly
even extended back to rofi.
Fixed file upload link sharing to clipboard.

Updated rofi-pass to pass-pick.
Made rofi-pass universal and less integrated to rofi - that's also the
reason for the name change.
`pass-pick` works with rofi (default), bemenu or dmenu. In theory it
should also work with any other picker that contains a stdin listing
function similar to dmenu.
It has been definitely tested both on rofi and bemenu.
The best user experience still reigns on rofi, where available keys are
displayed on the picker and the keys themselves make the most sense.
But all functions can be reached from bemenu as well, though the key
mappings are more arbitrary and can not be changed as in rofi.
The autofilling tool works with both xdotool and ydotool, so should work
both on X11 and on Wayland. Ydotool ideally requires its daemon to be
running, otherwise some of the typing may get gut off. Otherwise no
change should be necessary.

Updated qutebrowser open_download for bemenu.
Updated download opening script to work with both rofi and bemenu.
Prefers original rofi implementation but works with both, and can be set
to use a custom dmenu-like file picker as well.

Add brightnessctl and removed custom audio / brightness scripts since they
became unnecessary.

Updated bootstrap script to include system files:
With `keyd` taking its configuration from the `/etc` directory and not
home, a second stow stage was necessary. These stow files are in a
module called `system-packages` inside the top-level `bootstrap` stow
package.
They will not be installed by the default dotfile stow invocation but
have been integrated as an extra step into the install script.
Installing this module requires sudo privileges!

Switched vifm überzug to sixel graphics rendering.
überzug relies on X11 functionality to work, while sixel does not.
Unfortunately, alacritty does not work with sixel graphics yet, only
foot does (somewhat).

Waybar currently runs the gruvbox dark soft color scheme.
Added the old polybar archupdates script to waybar and extended it to
output json format with additional metadata that waybar can read.
Can still output the old plaintext format that polybar expects.
Added a wireguard connection to waybar,shows if currently
connected to either a wireguard or tun VPN service.
If so, shows an icon in the waybar - that can be hovered over to show
the full assigned IP address.
Added an upcoming event display to waybar,
a simple event indicator to show upcoming events on the calendar, on
hovering over it the tooltip lists all upcoming events.

Added `screenshot` script to take simple screenshots and
rectangle region shots of the current output.
Can be invoked through the river shortcut PrintScr:
`PrintScr` - Fullscreen screenshot
`Mod+PrintScr` - Region screenshot
`Shift+PrintScr` - Fullscreen screenshot and file upload
`Mod+Shift+PrintScr` - Region screenshot and file upload

Extended `sharefile` to take paths through stdin and make
use of `fd` if it is found on the system.
This commit is contained in:
Marty Oehme 2021-11-26 07:59:35 +01:00
parent 89d1402b3e
commit 6ac552d3d5
Signed by: Marty
GPG key ID: B7538B8F50A1C800
61 changed files with 1811 additions and 2032 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

BIN
.assets/waybar/simple.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View file

@ -1,61 +0,0 @@
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
<!-- Replacements from http://bohoomil.com/doc/05-fonts/ (until ibfonts-meta-extended) -->
<alias>
<family>serif</family>
<prefer><family>Heuristica</family></prefer>
</alias>
<alias>
<family>sans-serif</family>
<prefer><family>Noto Sans</family></prefer>
</alias>
<alias>
<family>monospace</family>
<prefer><family>Iosevka</family></prefer>
</alias>
<alias>
<family>fantasy</family>
<prefer><family>Signika</family></prefer>
</alias>
<alias>
<family>cursive</family>
<prefer><family>Comic Neue</family></prefer>
</alias>
<!-- more advanced replacements (replacing many fonts with open alternatives) see spark/fonts/local.conf -->
<match target="font">
<edit name="antialias" mode="assign">
<bool>true</bool>
</edit>
</match>
<match target="font">
<edit name="rgba" mode="assign">
<const>rgb</const>
</edit>
</match>
<match target="font">
<edit name="lcdfilter" mode="assign">
<const>lcddefault</const>
</edit>
</match>
<match target="font">
<edit name="hinting" mode="assign">
<bool>true</bool>
</edit>
</match>
<match target="font">
<edit name="hintstyle" mode="assign">
<const>hintfull</const>
</edit>
</match>
<match target="font">
<edit name="autohint" mode="assign">
<bool>false</bool>
</edit>
</match>
<match target="pattern">
<edit name="dpi" mode="assign">
<double>92</double>
</edit>
</match>
</fontconfig>

View file

@ -1,12 +0,0 @@
! ~/.Xresources
! Setting up commonly changed vars
#define myfontsize 11
#define myfont Iosevka Mono
#define myOpacity 90
! Font settings
#include "Xresources.d/fonts"
! Colorscheme
#include "Xresources.d/colorscheme"

View file

@ -1,7 +0,0 @@
Xft.antialias: 1
Xft.autohint: 0
Xft.dpi: 92
Xft.hinting: true
Xft.hintstyle: hintslight
Xft.lcdfilter: lcddefault
Xft.rgba: rgb

View file

@ -1,77 +0,0 @@
#!/bin/sh
userresources=$XDG_CONFIG_HOME/xresources/Xresources
usermodmap=$XDG_CONFIG_HOME/xresources/Xmodmap
sysresources=/etc/X11/xinit/.Xresources
sysmodmap=/etc/X11/xinit/.Xmodmap
# merge in defaults and keymaps
if [ -f $sysresources ]; then
xrdb -merge $sysresources
fi
if [ -f $sysmodmap ]; then
xmodmap $sysmodmap
fi
if [ -f "$userresources" ]; then
xrdb -merge "$userresources"
fi
if [ -f "$usermodmap" ]; then
xmodmap "$usermodmap"
fi
if [ -d /etc/X11/xinit/xinitrc.d ]; then
for f in /etc/X11/xinit/xinitrc.d/?*.sh; do
# shellcheck disable=1090
[ -x "$f" ] && . "$f"
done
unset f
fi
# unclutter is a program to hide your mouse cursor when it is not moved
type unclutter >/dev/null 2>&1 && unclutter &
# picom is the maintained version of desktop compositor compton
type picom >/dev/null 2>&1 && picom &
# if sxhkd - the key-binding daemon is installed, start it up
# set it to start up a custom fifo-creating version
# and set the chain-mode exiting key to a non existing one (default would be escape)
type sxhkd >/dev/null 2>&1 && sxhkd-piped -a "copyright" &
# if nextcloud-client exists, start it up
type nextcloud >/dev/null 2>&1 && nextcloud --background &
# load nm-applet, to allow easy vpn setting/switching from x interface
# TODO this should over time be replaced with a custom polybar interface
type nm-applet >/dev/null 2>&1 && nm-applet &
# additional config options for Touchpad devices ONLY
if [ "$(journalctl --dmesg -o short-monotonic --no-hostname --no-pager | grep -c "Touchpad")" -gt 0 ]; then
# enable touch tapping for XPS13 touchpad - for different devices get the touchpad name with xinput list-prop <TAB>
xinput set-prop "DLL075B:01 06CB:76AF Touchpad" "libinput Tapping Enabled" 1
# sets default to EURkey layout, with possibility to switch to german
# sets german layout to be default for the only pc I have with a german keyboard
# allows switching layouts with alt+space
setxkbmap -layout eu,de
else
setxkbmap -layout de,eu
fi
# Remaps Capslock key to control.
# (only works for x environment - I haven't needed it for non-x yet)
setxkbmap -option ctrl:nocaps
setxkbmap -option grp:alt_shift_toggle
# Makes Capslock behave as escape - when ONLY capslock is pressed and released
# this only works when we already substitute a ctrl for caps with the lines above,
# otherwise control itself will act as escape.
# Needs xcape package installed. https://github.com/alols/xcape
# set a timeout of 500ms, if pressed longer it will ignore esc
type xcape >/dev/null 2>&1 && xcape -e 'Control_L=Escape' -t 500
type feh >/dev/null 2>&1 && exec feh --bg-scale ~/pictures/wall.jpg &
type xss-lock >/dev/null 2>&1 && exec xss-lock &
type i3 >/dev/null 2>&1 && exec i3

View file

@ -1,36 +0,0 @@
#!/usr/bin/env sh
# clip -- easy copying to x clipboard manager with xclip
#
# clips the first argument to the clipboard
# or stdin if stdin is passed
# will copy png/jpg as image files
#
# idea ~~stolen~~ creatively borrowed from
# https://github.com/kyazdani42/dotfiles/blob/master/bin/copy
if ! exist xclip normal; then exit 1; fi
# if we are in a pipe, read from stdin
if [ ! -t 0 ]; then
xclip -i -selection clipboard /dev/stdin
exit 0
fi
if [ $# != 1 ] || [ ! -f "$1" ]; then
printf "No file argument passed to xclip to clip: %s" "$1"
exit 1
fi
options=""
if grep -qE '.png$' "$1"; then
options="-target image/png"
elif grep -qE '.jpe\?g$' "$1"; then
options="-target image/jpeg"
fi
if [ -n "$options" ]; then
xclip -selection clipboard "$options" "$1"
else
xclip -selection clipboard "$1"
fi

View file

@ -8,10 +8,11 @@ scrolling:
multiplier: 3
font:
size: 12.5
size: 12
# Allow terminal applications to change Alacritty's window title.
window.dynamic_title: true
background_opacity: 1.0
import:
- .config/alacritty/colorscheme.yml

View file

@ -3,3 +3,4 @@
^/install_packages.sh
^/packages.*.txt
^/README.md
^/system-packages

View file

@ -160,9 +160,6 @@ reflector
restic
ripgrep-all
rng-tools
rofi-calc
rofi-dmenu
rofi-greenclip
rofimoji
rtv
sc-im
@ -210,13 +207,6 @@ vifm
vim-language-server
vimiv
visidata
xcape
xclip
xsel
xorg-xev
xorg-xinit
xorg-xinput
xss-lock
youtube-dl
zathura-pdf-mupdf
zsh-autosuggestions
@ -257,3 +247,16 @@ zathura-djvu
yt-dlp-git
yaml-language-server-bin
river
rivercarro
keyd
waybar-git
swaybg
waylock
wl-clipboard
clipman
libqalculate
ydotool
brightnessctl
grim
slurp

View file

@ -0,0 +1,33 @@
# Makes capslock to control/escape
# insert to paste
# right alt to enable German Umlaute (äÄöÖüÜ),
# sharp s (ß), and the Euro sign (€).
# Needs compose key to be set in xkb to work correctly:
# $ setxkbmap -option "compose:menu"
capslock = overload(C, esc)
insert = S-insert
rightalt = layer(dia)
shift = layer(shift)
rightshift = layer(shift)
[shift:S]
rightalt = layer(shiftedDia)
[dia]
shift = layer(shiftedDia)
rightshift = layer(shiftedDia)
a = macro(compose a ")
o = macro(compose o ")
u = macro(compose u ")
s = macro(compose s s)
e = macro(compose = e)
[shiftedDia]
a = macro(compose A ")
o = macro(compose O ")
u = macro(compose U ")

View file

@ -0,0 +1,9 @@
# leftshift = oneshot(S)
# leftalt = oneshot(A)
# rightalt = oneshot(G)
# rightshift = oneshot(A)
# leftmeta = oneshot(M)
# rightmeta = oneshot(M)
capslock = overload(C, esc)
insert = S-insert

View file

@ -1,205 +0,0 @@
# This file has been auto-generated by i3-config-wizard(1).
# It will not be overwritten, so edit it as you like.
#
# Should you change your keyboard layout some time, delete
# this file and re-run i3-config-wizard(1).
#
# i3 config file (v4)
#
# Please see https://i3wm.org/docs/userguide.html for a complete reference!
set $mod Mod4
set $modemod Mod1
set $font "pango:Iosevka 8"
# Font for window titles. Will also be used by the bar unless a different font
# is used in the bar {} block below.
#font pango:monospace 8
font $font
workspace_auto_back_and_forth yes
# This font is widely installed, provides lots of unicode glyphs, right-to-left
# text rendering and scalability on retina/hidpi displays (thanks to pango).
#font pango:DejaVu Sans Mono 8
# Before i3 v4.8, we used to recommend this one as the default:
# font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
# The font above is very space-efficient, that is, it looks good, sharp and
# clear in small sizes. However, its unicode glyph coverage is limited, the old
# X core fonts rendering does not support right-to-left and this being a bitmap
# font, it doesnt scale on retina/hidpi displays.
# Use Mouse+$mod to drag floating windows to their wanted position
floating_modifier $mod
# kill focused window
bindsym $mod+Shift+c kill
# change focus
bindsym $mod+h focus left
bindsym $mod+j focus down
bindsym $mod+k focus up
bindsym $mod+l focus right
# alternatively, you can use the cursor keys:
bindsym $mod+Left focus left
bindsym $mod+Down focus down
bindsym $mod+Up focus up
bindsym $mod+Right focus right
# move focused window
bindsym $mod+Shift+h move left
bindsym $mod+Shift+j move down
bindsym $mod+Shift+k move up
bindsym $mod+Shift+l move right
# alternatively, you can use the cursor keys:
bindsym $mod+Shift+Left move left
bindsym $mod+Shift+Down move down
bindsym $mod+Shift+Up move up
bindsym $mod+Shift+Right move right
# split in horizontal orientation
bindsym $mod+Shift+s split v
# split in vertical orientation
bindsym $mod+s split h
# enter fullscreen mode for the focused container
bindsym $mod+f fullscreen toggle
# change container layout (stacked, tabbed, toggle split)
bindsym $mod+Shift+w layout stacking
bindsym $mod+w layout tabbed
bindsym $mod+e layout toggle split
# toggle tiling / floating
bindsym $mod+Shift+v floating toggle
# change focus between tiling / floating windows
bindsym $mod+v focus mode_toggle
# focus the parent/child container
bindsym $mod+Shift+a focus parent
bindsym $mod+a focus child
# make a (floating) window stick to all workspaces
bindsym $mod+ctrl+v sticky toggle
# set up scratch pad for todo and 'drop-down' terminal
# call scratchpads to current workspace -- scratchpads started on i3 starting (see end of file)
bindsym $mod+t [class="scratchpad" title="dropdown-todo"] scratchpad show
bindsym $mod+Shift+Return [class="scratchpad" title="dropdown-terminal"] scratchpad show
# GAP MANAGEMENT
# disable titles and borders, necessary for i3gaps to work apparently
for_window [class="^.*"] border pixel 0
# by default set no gaps when multiple windows are on the workspace
gaps inner 0
gaps outer 0
# increase/decrease inner gapping
bindsym $mod+shift+g gaps inner current plus 10
bindsym $mod+g gaps inner current minus 10
# increase/decrease border sizes
bindsym $mod+b border toggle 2
# Define names for default workspaces for which we configure key bindings later on.
# We use variables to avoid repeating the names in multiple places.
set $ws1 "1"
set $ws2 "2"
set $ws3 "3"
set $ws4 "4"
set $ws5 "5"
set $ws6 "6"
set $ws7 "7"
set $ws8 "8"
set $ws9 "9"
set $ws10 "10"
# switch to workspace
bindsym $mod+1 workspace $ws1
bindsym $mod+2 workspace $ws2
bindsym $mod+3 workspace $ws3
bindsym $mod+4 workspace $ws4
bindsym $mod+5 workspace $ws5
bindsym $mod+6 workspace $ws6
bindsym $mod+7 workspace $ws7
bindsym $mod+8 workspace $ws8
bindsym $mod+9 workspace $ws9
bindsym $mod+0 workspace $ws10
# move focused container to workspace
bindsym $mod+Shift+1 move container to workspace $ws1
bindsym $mod+Shift+2 move container to workspace $ws2
bindsym $mod+Shift+3 move container to workspace $ws3
bindsym $mod+Shift+4 move container to workspace $ws4
bindsym $mod+Shift+5 move container to workspace $ws5
bindsym $mod+Shift+6 move container to workspace $ws6
bindsym $mod+Shift+7 move container to workspace $ws7
bindsym $mod+Shift+8 move container to workspace $ws8
bindsym $mod+Shift+9 move container to workspace $ws9
bindsym $mod+Shift+0 move container to workspace $ws10
# resize window (you can also use the mouse for that)
mode "resize" {
# These bindings trigger as soon as you enter the resize mode
# Pressing left will shrink the windows width.
# Pressing right will grow the windows width.
# Pressing up will shrink the windows height.
# Pressing down will grow the windows height.
bindsym h resize shrink width 10 px or 10 ppt
bindsym Shift+h resize shrink width 30 px or 30 ppt
bindsym j resize grow height 10 px or 10 ppt
bindsym Shift+j resize grow height 30 px or 30 ppt
bindsym k resize shrink height 10 px or 10 ppt
bindsym Shift+k resize shrink height 30 px or 30 ppt
bindsym l resize grow width 10 px or 10 ppt
bindsym Shift+l resize grow width 30 px or 30 ppt
# same bindings, but for the arrow keys
bindsym Left resize shrink width 10 px or 10 ppt
bindsym Down resize grow height 10 px or 10 ppt
bindsym Up resize shrink height 10 px or 10 ppt
bindsym Right resize grow width 10 px or 10 ppt
# back to normal: Enter or Escape or $mod+r
bindsym Return mode "default"
bindsym Escape mode "default"
bindsym $modemod+r mode "default"
}
bindsym $modemod+r mode "resize"
# reload the configuration file
bindsym $mod+F12 reload
# restart i3 inplace (preserves your layout/session, can be used to upgrade i3)
bindsym $mod+Shift+F12 restart
# default workspaces for most used apps
# assign [class="^qutebrowser$"] → number 1
# spotify needs for_window, see https://i3wm.org/docs/userguide.html#assign_workspace
assign [class="^spotify$"] → 10
assign [class="^Spotify$"] → 10
#fix for spotify not moving to workspace 10
for_window [class="^spotify$"] move to workspace 10
# windows with class floating will automatically float
# windows with class scratchpad will automatically float and be sent to the scratchpad
for_window [class="floating"] floating enable
for_window [class="scratchpad"] floating enable
for_window [class="scratchpad"] move scratchpad
# Vim-like mark system - set with mod+m, go there with mod+'
# read 1 character and mark the current window with this character
bindsym $mod+m exec i3-input -F 'mark %s' -l 1 -P 'Mark: '
# read 1 character and go to the window with the character
bindsym $mod+apostrophe exec i3-input -F '[con_mark="%s"] focus' -l 1 -P 'Goto: '
# launch polybar (script ensures only 1 instance existing at a time)
exec_always --no-startup-id polybar-launch top

View file

@ -17,7 +17,7 @@ main() {
case "$1" in
-v | --version)
printf "Personal system bootstrap script.\n\n©Marty Oehme\n\nVersion: 0.1.1\n"
printf "Personal system bootstrap script.\n\nby Marty Oehme\n\nv0.2\n"
;;
-h | --help)
printf "Usage: install [-f|--force][-v|--version][-h|--help]\n\n-f Do not ask for any confirmations but force update and installation.\n"
@ -36,44 +36,41 @@ main() {
exit $ret
}
# takes default value (y/n), question, abort message as arguments
# automatically answers yes if unattended install
check_consent() {
echo "This will take a while, install many packages and link dotfiles all over the place. Proceed [y/N]?"
read -r yes
if [[ "$yes" != y* ]]; then
echo "Exiting."
exit
if [ "$UNATTENDED" == "true" ]; then
true
else
[[ "$1" == "y" ]] && default_consent="[Y/n]" || default_consent="[y/N]"
printf "%s %s " "$2" "$default_consent"
read -r answer
if [[ "$1" == "n" ]] && [[ "$answer" != y* ]]; then
echo first
printf "%s\n" "$3"
false
elif [[ "$1" == "y" ]] && [[ "$answer" == n* ]]; then
echo second
printf "%s\n" "$3"
false
else
true
fi
fi
}
entry_question() {
check_consent n "This will take a while, install many packages and link dotfiles all over the place. Proceed?" "Aborting." || exit
}
enable_git_hooks() {
if [ "$1" == "false" ]; then
echo "Should we enable git hooks for this repository, so that installed packages are automatically compared when committing? [Y/n]"
read -r no
if [[ "$no" == n* ]]; then
echo "Not changing repository settings."
return
fi
fi
check_consent y "Should we enable git hooks for this repository, so that installed packages are automatically compared when committing?" "Not changing repository settings." || return
git config --local core.hooksPath .githooks/
echo "Changed repository settings."
}
install() {
unattended=$1
if ! "$unattended"; then
check_consent
fi
echo "====================== BEGINNING INSTALLATION ============================="
if ! "$unattended"; then
export BOOTSTRAP_PACKAGES="bootstrap/packages.txt"
"$bootstrap_dir"/install_packages.sh
else
export BOOTSTRAP_PACKAGES="bootstrap/packages.txt"
"$bootstrap_dir"/install_packages.sh -f
fi
unset BOOTSTRAP_PACKAGES
echo "=================== BEGINNING DOTFILE MANAGEMENT =========================="
stow_dotfiles() {
check_consent y "Link home directory dot files?" "Not linking dotfiles." || return
# get all top level directories, remove their slashes and dots
# finally get rid of .dot-directories, since they are for the repo not for my homedir
targets="$(find . -maxdepth 1 -type d | sed -e 's/^\.\/\(.*\)$/\1/' | sed -e '/^\./d')"
@ -81,9 +78,42 @@ install() {
# shellcheck disable=2086
# -- for some reason stow only works with unqoted var expansion
stow -R ${targets} 2> >(grep -v 'Absolute/relative mismatch between Stow dir' 1>&2)
echo "Linked dotfiles."
}
stow_system_packages() {
check_consent n "Link system settings as well? This will require sudo access." "Not touching system files." || return
sudo stow --dir="$bootstrap_dir" --target="/" -R system-packages/
echo "Linked system files."
}
install_packages() {
check_consent n "Install pre-designated packages? This will take a while." "Not installing packages." || return
export BOOTSTRAP_PACKAGES="bootstrap/packages.txt"
if ! "$UNATTENDED"; then
"$bootstrap_dir"/install_packages.sh
else
"$bootstrap_dir"/install_packages.sh -f
fi
unset BOOTSTRAP_PACKAGES
echo "Installed packages."
}
install() {
UNATTENDED=$1
if ! "$UNATTENDED"; then
entry_question
fi
echo "====================== BEGINNING INSTALLATION ============================="
install_packages
echo "=================== BEGINNING DOTFILE MANAGEMENT =========================="
stow_dotfiles
stow_system_packages
echo "================== ENABLING GIT REPOSITORY HOOKS =========================="
enable_git_hooks "$unattended"
enable_git_hooks
echo "====================== INSTALLATION FINISHED =============================="
exit 0

View file

@ -31,8 +31,6 @@ import os
import socket
import errno
import subprocess
import fcntl
import stat
import string
files = sys.argv[1:]
@ -43,18 +41,21 @@ def is_url(filename):
if len(parts) < 2:
return False
# protocol prefix has no special characters => it's an URL
allowed_symbols = string.ascii_letters + string.digits + '_'
allowed_symbols = string.ascii_letters + string.digits + "_"
prefix = parts[0]
return all(map(lambda c: c in allowed_symbols, prefix))
# make them absolute; also makes them safe against interpretation as options
def make_abs(filename):
if not is_url(filename):
return os.path.abspath(filename)
return filename
files = [make_abs(f) for f in files]
SOCK = os.path.join(os.getenv("HOME"), ".umpv_socket")
SOCK = os.path.join(str(os.getenv("HOME")), ".umpv_socket")
sock = None
try:
@ -74,14 +75,16 @@ if sock:
# Unhandled race condition: what if mpv is terminating right now?
for f in files:
# escape: \ \n "
f = f.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n")
f = "\"" + f + "\""
f = f.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\\n")
f = '"' + f + '"'
sock.send(("raw loadfile " + f + " append\n").encode("utf-8"))
else:
# Let mpv recreate socket if it doesn't already exist.
opts = (os.getenv("MPV") or "mpv").split()
opts.extend(["--no-terminal",
opts.extend(
[
"--no-terminal",
"--force-window",
"--input-ipc-server=" + SOCK,
# position on lower left screen corner
@ -90,7 +93,11 @@ else:
"--geometry=15%+-10-+5",
"--on-all-workspaces",
"--force-window=immediate",
"--"])
"--x11-name=float",
"--wayland-app-id=float",
"--",
]
)
opts.extend(files)
subprocess.check_call(opts)

361
pass/.local/bin/pass-pick Executable file
View file

@ -0,0 +1,361 @@
#!/usr/bin/env bash
#
# Pass picker
#
# Use a dmenu-like list selector to display and autofill your pass passwords.
# Can work with rofi, bemenu and dmenu, or a custom picker given as an option.
# Invoke it with `pass-pick`. You can set options through environment variables
# or through a configuration file.
#
# Keys:
# By default shows the available keys on rofi, but not on bemenu/dmenu.
# ROFI mapped keys (main password list):
# return autofill username/password combination
# alt+return enter entry submenu
# alt+u autofill username
# alt+p autofill password
# alt+ctrl+u send username to clipboard
# alt+ctrl+p send password to clipboard
# ROFI mapped keys (individual entry):
# return autofill selected field
# alt+return send selected field to clipboard
# alt+s reveal hidden password field
# alt+backspace back to main password menu
# Those options also work on bemenu, but have different (and fixed) mappings.
# BEMENU mapped keys (main password list):
# return autofill username/password combination
# alt+2 send username to clipboard
# alt+3 send password to clipboard
# alt+4 autofill username
# alt+5 autofill password
# alt+6 enter entry submenu
# BEMENU mapped keys (individual entry):
# return autofill selected field
# alt+2 send selected field to clipboard
# alt+3 back to main password menu
# alt+4 reveal hidden password field
# Selector wrapper
# Prefers rofi if found, otherwise bemenu or dmenu if found, complains if no selector available.
# Passes along any options given to main script.
rofi_opts=("$@")
_picker() {
if [ -n "$PICKER" ]; then
"${PICKER[@]}"
elif command -v rofi 1>/dev/null 2>/dev/null; then
rofi -dmenu -no-auto-select -i "${rofi_opts[@]}" "$@" -p "entry"
elif command -v bemenu 1>/dev/null 2>/dev/null; then
bemenu -l 20 -i -p "entry >"
elif command -v dmenu 1>/dev/null 2>/dev/null; then
dmenu -i -p "entry >"
else
printf "%s: 📦 %s must be installed for %s function.\n" "critical" "rofi/dmenu" "this" >&2
notify-send "📦 rofi/dmenu" --urgency="critical" "must be installed for this function."
exit 1
fi
}
# parse, see https://unix.stackexchange.com/a/331965/8541
_parse_config() {
(grep -e "^$2=" -m 1 "$1" 2>/dev/null || printf "var=__UNDEFINED__\n") | head -n1 | cut -d '=' -f 2-
}
# read config file
get_config() {
local locations=(
"$PP_CONFIGURATION_FILE"
"${xdg_config_home:-$HOME/.config}/pass-picker/pass-picker.conf"
"$HOME/.pass-picker.conf"
"/etc/pass-picker.conf"
)
# return the first config file with a valid path
for config in "${locations[@]}"; do
if [[ -n "$config" && -f "$config" ]]; then
# see if the config has been given a value
local val
val="$(_parse_config "$config" "$1")"
break
fi
done
# if there was a config file but no value
# or there was no config file at all
if [ "$val" = "__UNDEFINED__" ] || [ -z "$val" ]; then
val="$2"
fi
printf -- "%s" "$val"
}
set_defaults() {
# The location of the pass-picker config file
# PP_CONFIGURATION_FILE="~/.config/pass-picker/pass-picker.conf"
# set options, leaving already set environment variables intact
# try to read any settings from config files
PICKER="${PP_PICKER:-$(get_config PICKER)}"
KEY_AUTOFILL="${PP_KEY_AUTOFILL:-$(get_config KEY_AUTOFILL Return)}"
KEY_ENTRY_OPEN="${PP_KEY_ENTRY_OPEN:-$(get_config KEY_ENTRY_OPEN Alt+Return)}"
KEY_FILL_USER="${PP_KEY_FILL_USER:-$(get_config KEY_FILL_USER Alt+u)}"
KEY_CLIP_USER="${PP_KEY_CLIP_USER:-$(get_config KEY_CLIP_USER Ctrl+Alt+u)}"
KEY_FILL_PASS="${PP_KEY_FILL_PASS:-$(get_config KEY_FILL_PASS Alt+p)}"
KEY_CLIP_PASS="${PP_KEY_CLIP_PASS:-$(get_config KEY_CLIP_PASS Ctrl+Alt+p)}"
KEY_ENTRYMENU_FILL="${PP_KEY_ENTRYMENU_FILL:-$(get_config KEY_ENTRYMENU_FILL Return)}"
KEY_ENTRYMENU_CLIP="${PP_KEY_ENTRYMENU_CLIP:-$(get_config KEY_ENTRYMENU_CLIP Alt+Return)}"
KEY_ENTRYMENU_SHOWFIELD="${KEY_ENTRYMENU_SHOWFIELD:-$(get_config KEY_ENTRYMENU_SHOWFIELD Alt+s)}"
KEY_ENTRYMENU_QUIT="${PP_KEY_ENTRYMENU_QUIT:-$(get_config KEY_ENTRYMENU_QUIT Alt+BackSpace)}"
AUTOFILL_BACKEND="${PP_AUTOFILL_BACKEND:-$(get_config AUTOFILL_BACKEND ydotool)}"
AUTOFILL_CHAIN="${PP_AUTOENTRY_CHAIN:-$(get_config AUTOFILL_CHAIN 'username :tab password')}"
AUTOFILL_DELAY="${PP_AUTOENTRY_DELAY:-$(get_config AUTOFILL_DELAY 30)}"
PASS_USERNAME_FIELD="${PP_PASS_USERNAME_FIELD:-$(get_config PASS_USERNAME_FIELD 'username user login')}"
}
# exit on escape pressed
exit_check() {
[ "$1" -eq 1 ] && exit
}
# simply return a list of all passwords in pass store
# TODO only show website names (+ folder names), and account names for multiple accounts on one site
list_passwords() {
shopt -s nullglob globstar
prefix=${PASSWORD_STORE_DIR:-~/.password-store}
password_files=("$prefix"/**/*.gpg)
password_files=("${password_files[@]#"$prefix"/}")
password_files=("${password_files[@]%.gpg}")
printf '%s\n' "${password_files[@]}"
}
# return password for argument passed
show_password() {
pass show "$1" | head -n1
}
# send password to clipboard
clip_password() {
pass show -c "$1"
}
# attempt to return the field specified
# attempts all (space separated) fields until the
# first one successfully returned
_p_get_field() {
local gp_entry="$1"
local gp_field="$2"
local clip="$3"
# return on first successfully returned key
for key in $gp_field; do
local value
value=$(_p_get_key_value "$gp_entry" "$key")
# found entry
if [ -n "$value" ]; then
if [ -n "$clip" ]; then
# copies to clipboard, removes any trailing newlines,
# and only keeps it in for 1 paste (1 loop to read in script, 1 to output)
if command -v wl-copy; then
echo "$value" | wl-copy -o && break
elif command -v xclip; then
echo "$value" | xclip -i -selection 'clipboard' -loops 2 -rmlastnl && break
elif command -v xsel; then
echo "$value" | xsel -b && break
else
notify-send "No clipboard utility" "Install wl-copy, xclip or xsel."
fi
else
echo "$value" && break
fi
fi
done
}
# returns the corresponding value for the key passed in
# arguments:
# $1: pass (file) entry to search through
# $2: string name of the containting key
_p_get_key_value() {
local value
value=$(list_fields "$1" | grep "$2")
# get everything after first colon, remove whitespace
echo "$value" | cut -d':' -f2- | tr -d '[:blank:]'
}
# return username for argument passed
show_username() {
_p_get_field "$1" "${PASS_USERNAME_FIELD}"
}
clip_username() {
_p_get_field "$1" "${PASS_USERNAME_FIELD}" "-c"
}
show_field() {
_p_get_field "$1" "$2"
}
clip_field() {
_p_get_field "$1" "$2" "-c"
}
list_fields() {
pass show "$1" | tail -n+2
}
# invoke the dotool to type inputs
_type() {
local tool="${AUTOFILL_BACKEND}"
local toolmode="$1"
local key="$2"
if [ "$tool" = "xdotool" ]; then
"$tool" "$toolmode" --delay "${AUTOFILL_DELAY}" "$key"
elif [ "$tool" = "ydotool" ]; then
"$tool" "$toolmode" --key-delay "${AUTOFILL_DELAY}" "$key"
else
"$tool" "$toolmode" "$key"
fi
}
# automatically fill out fields
# transform special chain entries into valid dotool commands
autofill() {
local selected="${1}"
local autoentry_chain="${2}"
for part in $autoentry_chain; do
case "$part" in
":tab") _type key Tab ;;
":return") _type key Return ;;
":space") _type key space ;;
"username") _type type "$(show_username "$selected")" ;;
"password") _type type "$(show_password "$selected")" ;;
":direct") _type type "$selected" ;;
*) printf '%s' "$selected" ;;
esac
done
}
# opens a menu for the specified pass entry, containing its individual fields
entrymenu() {
local entry="$1"
local deobfuscate="$2"
local k_entrymenu_fill="${KEY_ENTRYMENU_FILL}"
local k_entrymenu_clip="${KEY_ENTRYMENU_CLIP}"
local k_entrymenu_showfield="${KEY_ENTRYMENU_SHOWFIELD}"
local k_entrymenu_quit="${KEY_ENTRYMENU_QUIT}"
local pass
if [ "$deobfuscate" = "true" ]; then
pass="$(show_password "$entry")"
else
pass="(hidden)"
fi
local field
field=$(
printf "password: %s\n%s" "$pass" "$(list_fields "$entry")" |
_picker \
-kb-accept-entry "" \
-kb-custom-1 "$k_entrymenu_fill" \
-kb-custom-2 "$k_entrymenu_clip" \
-kb-custom-3 "$k_entrymenu_quit" \
-kb-custom-4 "$k_entrymenu_showfield" \
-mesg " ᐊ $k_entrymenu_quit ᐊ | $k_entrymenu_fill: fill selection | $k_entrymenu_clip: clip selection | $k_entrymenu_showfield: reveal password"
)
exit_value=$?
exit_check "$exit_value"
# get field name
field=${field%%:*}
case "$exit_value" in
"0" | "10")
if [ "$field" = "password" ]; then
autofill "$entry" "password"
else
autofill "$(show_field "$entry" "$field")" ":direct"
fi
exit 0
;;
"11")
if [ "$field" = "password" ]; then
clip_password "$entry"
else
clip_field "$entry" "$field"
fi
exit 0
;;
"12")
main
;;
"13")
local toggle
if [ "$deobfuscate" = "true" ]; then
toggle=false
else
toggle=true
fi
entrymenu "$entry" "$toggle"
;;
esac
}
main() {
local autoentry_chain="${AUTOFILL_CHAIN}"
local k_autofill="${KEY_AUTOFILL}"
local k_fill_user="${KEY_FILL_USER}"
local k_clip_user="${KEY_CLIP_USER}"
local k_fill_pass="${KEY_FILL_PASS}"
local k_clip_pass="${KEY_CLIP_PASS}"
local k_submenu="${KEY_ENTRY_OPEN}"
entry="$(
list_passwords |
_picker -kb-accept-entry "" \
-kb-custom-1 "$k_autofill" \
-kb-custom-2 "$k_clip_user" \
-kb-custom-3 "$k_clip_pass" \
-kb-custom-4 "$k_fill_user" \
-kb-custom-5 "$k_fill_pass" \
-kb-custom-6 "$k_submenu" \
-mesg "| $k_autofill: fill credentials | $k_submenu: open entry | $k_fill_user: fill username | $k_fill_pass: fill password | $k_clip_user: clip username | $k_clip_pass: clip password |"
)"
exit_value=$?
echo "$entry"
exit_check "$exit_value"
case "$exit_value" in
"0" | "10")
autofill "$entry" "$autoentry_chain"
exit 0
;;
"11")
clip_username "$entry"
exit 0
;;
"12")
clip_password "$entry"
exit
;;
"13")
autofill "$entry" "username"
exit
;;
"14")
autofill "$entry" "password"
exit
;;
"15")
entrymenu "$entry"
exit
;;
esac
}
set_defaults
main

View file

@ -1,307 +0,0 @@
#!/usr/bin/env bash
#
# selector wrapper
# uses rofi if found, or dmenu if found, complains if no selector available
# passes along any options given to main script
rofi_opts=("$@")
_rofi() {
if type rofi 1>/dev/null 2>/dev/null; then
rofi -dmenu -no-auto-select -i "${rofi_opts[@]}" "$@" -p "Entry"
elif type dmenu 1>/dev/null 2>/dev/null; then
dmenu -i "${rofi_opts[@]}" "$@" -p "Entry"
else
printf "%s: 📦 %s must be installed for %s function.\n" "critical" "rofi/dmenu" "this" >&2
notify-send "📦 rofi/dmenu" --urgency="critical" "must be installed for this function."
exit 1
fi
}
# parse, see https://unix.stackexchange.com/a/331965/8541
_parse_config() {
(grep -E "^$2=" -m 1 "$1" 2>/dev/null || printf "VAR=__UNDEFINED__\n") | head -n1 | cut -d '=' -f 2-
}
# read config file
get_config() {
local locations=(
"$RP_CONFIGURATION_FILE"
"${XDG_CONFIG_HOME:-$HOME/.config}/rofi-pass/rofi-pass.conf"
"$HOME/.rofi-pass.conf"
"/etc/rofi-pass.conf"
)
# return the first config file with a valid path
for config in "${locations[@]}"; do
if [[ -n "$config" && -f "$config" ]]; then
# see if the config has been given a value
local val
val="$(_parse_config "$config" "$1")"
break
fi
done
# if there was a config file but no value
# or there was no config file at all
if [ "$val" = "__UNDEFINED__" ] || [ -z "$val" ]; then
val="$2"
fi
printf -- "%s" "$val"
}
set_defaults() {
# The location of the rofi-pass config file
# RP_CONFIGURATION_FILE="~/.config/rofi-pass/rofi-pass.conf"
# set options, leaving already set environment variables intact
# try to read any settings from config files
KEY_AUTOFILL="${RP_KEY_AUTOFILL:-$(get_config KEY_AUTOFILL Return)}"
KEY_ENTRY_OPEN="${RP_KEY_ENTRY_OPEN:-$(get_config KEY_ENTRY_OPEN Alt+Return)}"
KEY_FILL_USER="${RP_KEY_FILL_USER:-$(get_config KEY_FILL_USER Alt+u)}"
KEY_CLIP_USER="${RP_KEY_CLIP_USER:-$(get_config KEY_CLIP_USER Ctrl+Alt+u)}"
KEY_FILL_PASS="${RP_KEY_FILL_PASS:-$(get_config KEY_FILL_PASS Alt+p)}"
KEY_CLIP_PASS="${RP_KEY_CLIP_PASS:-$(get_config KEY_CLIP_PASS Ctrl+Alt+p)}"
KEY_ENTRYMENU_FILL="${RP_KEY_ENTRYMENU_FILL:-$(get_config KEY_ENTRYMENU_FILL Return)}"
KEY_ENTRYMENU_CLIP="${RP_KEY_ENTRYMENU_CLIP:-$(get_config KEY_ENTRYMENU_CLIP Alt+Return)}"
KEY_ENTRYMENU_SHOWFIELD="${KEY_ENTRYMENU_SHOWFIELD:-$(get_config KEY_ENTRYMENU_SHOWFIELD Alt+s)}"
KEY_ENTRYMENU_QUIT="${RP_KEY_ENTRYMENU_QUIT:-$(get_config KEY_ENTRYMENU_QUIT Alt+BackSpace)}"
AUTOFILL_BACKEND="${RP_AUTOFILL_BACKEND:-$(get_config AUTOFILL_BACKEND xdotool)}"
AUTOFILL_CHAIN="${RP_AUTOENTRY_CHAIN:-$(get_config AUTOFILL_CHAIN 'username :tab password')}"
AUTOFILL_DELAY="${RP_AUTOENTRY_DELAY:-$(get_config AUTOFILL_DELAY 30)}"
PASS_USERNAME_FIELD="${RP_PASS_USERNAME_FIELD:-$(get_config PASS_USERNAME_FIELD 'username user login')}"
}
# exit on escape pressed
# rofi returns exit code 1 on esc
exit_check() {
[ "$1" -eq 1 ] && exit
}
# simply return a list of all passwords in pass store
# TODO only show website names (+ folder names), and account names for multiple accounts on one site
list_passwords() {
shopt -s nullglob globstar
prefix=${PASSWORD_STORE_DIR:-~/.password-store}
password_files=("$prefix"/**/*.gpg)
password_files=("${password_files[@]#"$prefix"/}")
password_files=("${password_files[@]%.gpg}")
printf '%s\n' "${password_files[@]}"
}
# return password for argument passed
show_password() {
pass show "$1" | head -n1
}
# send password to clipboard
clip_password() {
pass show -c "$1"
}
# attempt to return the field specified
# attempts all (space separated) fields until the
# first one successfully returned
_p_get_field() {
local gp_entry="$1"
local gp_field="$2"
local clip="$3"
# return on first successfully returned key
for key in $gp_field; do
local value
value=$(_p_get_key_value "$gp_entry" "$key")
# found entry
if [ -n "$value" ]; then
if [ -n "$clip" ]; then
# copies to clipboard, removes any trailing newlines,
# and only keeps it in for 1 paste (1 loop to read in script, 1 to output)
echo "$value" | xclip -i -selection 'clipboard' -loops 2 -rmlastnl && break
else
echo "$value" && break
fi
fi
done
}
# returns the corresponding value for the key passed in
# arguments:
# $1: pass (file) entry to search through
# $2: string name of the containting key
_p_get_key_value() {
local value
value=$(list_fields "$1" | grep "$2")
# get everything after first colon, remove whitespace
echo "$value" | cut -d':' -f2- | tr -d '[:blank:]'
}
# return username for argument passed
show_username() {
_p_get_field "$1" "${PASS_USERNAME_FIELD}"
}
clip_username() {
_p_get_field "$1" "${PASS_USERNAME_FIELD}" "-c"
}
show_field() {
_p_get_field "$1" "$2"
}
clip_field() {
_p_get_field "$1" "$2" "-c"
}
list_fields() {
pass show "$1" | tail -n+2
}
# invoke the dotool to type inputs
_type() {
local tool="${AUTOFILL_BACKEND}"
local toolmode="$1"
local key="$2"
"$tool" "$toolmode" --delay "${AUTOFILL_DELAY}" "$key"
}
# automatically fill out fields
# transform special chain entries into valid dotool commands
autofill() {
local selected="${1}"
local autoentry_chain="${2}"
for part in $autoentry_chain; do
case "$part" in
":tab") _type key Tab ;;
":return") _type key Return ;;
":space") _type key space ;;
"username") _type type "$(show_username "$selected")" ;;
"password") _type type "$(show_password "$selected")" ;;
":direct") _type type "$selected" ;;
*) printf '%s' "$selected" ;;
esac
done
}
# opens a menu for the specified pass entry, containing its individual fields
entrymenu() {
local entry="$1"
local deobfuscate="$2"
local k_entrymenu_fill="${KEY_ENTRYMENU_FILL}"
local k_entrymenu_clip="${KEY_ENTRYMENU_CLIP}"
local k_entrymenu_showfield="${KEY_ENTRYMENU_SHOWFIELD}"
local k_entrymenu_quit="${KEY_ENTRYMENU_QUIT}"
local pass
if [ "$deobfuscate" = "true" ]; then
pass="$(show_password "$entry")"
else
pass="(hidden)"
fi
local field
field=$(
printf "password: %s\n%s" "$pass" "$(list_fields "$entry")" |
_rofi \
-kb-accept-entry "" \
-kb-custom-1 "$k_entrymenu_fill" \
-kb-custom-2 "$k_entrymenu_clip" \
-kb-custom-3 "$k_entrymenu_quit" \
-kb-custom-4 "$k_entrymenu_showfield" \
-mesg " ᐊ $k_entrymenu_quit ᐊ | $k_entrymenu_fill: fill selection | $k_entrymenu_clip: clip selection | $k_entrymenu_showfield: reveal password"
)
exit_value=$?
exit_check "$exit_value"
# get field name
field=${field%%:*}
case "$exit_value" in
"10")
if [ "$field" = "password" ]; then
autofill "$entry" "password"
else
autofill "$(show_field "$entry" "$field")" ":direct"
fi
exit 0
;;
"11")
if [ "$field" = "password" ]; then
clip_password "$entry"
else
clip_field "$entry" "$field"
fi
exit 0
;;
"12")
main
;;
"13")
local toggle
if [ "$deobfuscate" = "true" ]; then
toggle=false
else
toggle=true
fi
entrymenu "$entry" "$toggle"
;;
esac
}
main() {
local autoentry_chain="${AUTOFILL_CHAIN}"
local k_autofill="${KEY_AUTOFILL}"
local k_fill_user="${KEY_FILL_USER}"
local k_clip_user="${KEY_CLIP_USER}"
local k_fill_pass="${KEY_FILL_PASS}"
local k_clip_pass="${KEY_CLIP_PASS}"
local k_submenu="${KEY_ENTRY_OPEN}"
entry="$(
list_passwords |
_rofi -kb-accept-entry "" \
-kb-custom-1 "$k_autofill" \
-kb-custom-2 "$k_clip_user" \
-kb-custom-3 "$k_clip_pass" \
-kb-custom-4 "$k_fill_user" \
-kb-custom-5 "$k_fill_pass" \
-kb-custom-6 "$k_submenu" \
-mesg "| $k_autofill: fill credentials | $k_submenu: open entry | $k_fill_user: fill username | $k_fill_pass: fill password | $k_clip_user: clip username | $k_clip_pass: clip password |"
)"
exit_value=$?
exit_check "$exit_value"
case "$exit_value" in
"10")
autofill "$entry" "$autoentry_chain"
exit 0
;;
"11")
clip_username "$entry"
exit 0
;;
"12")
clip_password "$entry"
exit
;;
"13")
autofill "$entry" "username"
exit
;;
"14")
autofill "$entry" "password"
exit
;;
"15")
entrymenu "$entry"
exit
;;
esac
}
set_defaults
main

View file

@ -1,364 +0,0 @@
;==========================================================
;
;
; ██████╗ ██████╗ ██╗ ██╗ ██╗██████╗ █████╗ ██████╗
; ██╔══██╗██╔═══██╗██║ ╚██╗ ██╔╝██╔══██╗██╔══██╗██╔══██╗
; ██████╔╝██║ ██║██║ ╚████╔╝ ██████╔╝███████║██████╔╝
; ██╔═══╝ ██║ ██║██║ ╚██╔╝ ██╔══██╗██╔══██║██╔══██╗
; ██║ ╚██████╔╝███████╗██║ ██████╔╝██║ ██║██║ ██║
; ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
;
;
; To learn more about how to configure Polybar
; go to https://github.com/polybar/polybar
;
; The README contains a lot of information
;
;==========================================================
[colors]
background = ${xrdb:background}
background-alt = ${xrdb:color8}
foreground = ${xrdb:foreground}
foreground-alt = ${xrdb:color3}
primary = ${xrdb:color1}
secondary = ${xrdb:color4}
alert = ${xrdb:color2}
[settings]
; The throttle settings lets the eventloop swallow up til X events
; if they happen within Y millisecond after first event was received.
; This is done to prevent flood of update event.
;
; For example if 5 modules emit an update event at the same time, we really
; just care about the last one. But if we wait too long for events to swallow
; the bar would appear sluggish so we continue if timeout
; expires or limit is reached.
throttle-output = 5
throttle-output-for = 10
; Time in milliseconds that the input handler will wait between processing events
throttle-input-for = 30
[global/wm]
margin-top = 0
margin-bottom = 0
[bar/top]
; enable inter process communication, so that we can send messages
; to polybar via polybar-msg command
enable-ipc = true
; Put the bar at the bottom of the screen
bottom=false
width = 100%
height = 20
padding-left = 0
padding-right = 0
module-margin-left = 2
module-margin-right = 2
modules-left = sxhkdmode workspaces pomo papersdue
modules-center = music datecal
modules-right = dunstpaused networkspeed mail weather archupdates cpu temp volume battery
; do not use offsets for the bar, would only work with override-redirect
; and will mess up tray https://github.com/polybar/polybar/issues/1355
tray-position = right
; Basic Colors, defined further up
background = ${colors.background}
foreground = ${colors.foreground}
line-size = 1
line-color = ${colors.primary}
; Prefer fixed center position for the `modules-center` block.
; The center block will stay in the middle of the bar whenever
; possible. It can still be pushed around if other blocks need
; more space.
; When false, the center block is centered in the space between
; the left and right block.
fixed-center = true
; Fonts are defined using <font-name>;<vertical-offset>
; Font names are specified using a fontconfig pattern.
; font-0 = NotoSans-Regular:size=8;2
; font-1 = MaterialIcons:size=10
; font-2 = Termsynu:size=8;-1
; font-3 = FontAwesome:size=10
; See the Fonts wiki page for more details
font-0 = Comic Neue:size=10
font-1 = NotoSans:size=23
font-2 = Iosevka:size=14;1
cursor-click = pointer
[module/sxhkdmode]
type = custom/script
exec = sxhkd-chain-labels
exec-if = type sxhkd-chain-labels
tail = true
format = <label>
format-padding = 5
format-prefix = "狀 "
format-background = ${colors.primary}
format-foreground = ${colors.background}
[module/workspaces]
; module type
type = internal/i3
; default formatting
format = <label-mode><label-state>
; removes numbers for workspaces which have distinct names / icons
strip-wsnumbers = true
ws-icon-0 = 1;
ws-icon-1 = 2;
ws-icon-2 = 3;
ws-icon-3 = 4;4
ws-icon-4 = 5;5
ws-icon-5 = 6;6
ws-icon-6 = 7;7
ws-icon-7 = 8;8
ws-icon-8 = 9;
ws-icon-9 = 10;
ws-icon-default = ♟
; Available tokens:
; %name%
; %icon%
; %index%
; %output%
; Default: %icon% %name%
; unfocused = Inactive workspace on any monitor
label-unfocused = %icon%
label-unfocused-padding = 2
label-unfocused-underline = ${colors.background-alt}
; focused = Active workspace on focused monitor
label-focused = %icon%
label-focused-foreground = ${colors.foreground}
label-focused-background = ${colors.background-alt}
label-focused-underline = ${colors.primary}
label-focused-padding = ${self.label-unfocused-padding}
; visible = Active workspace on unfocused monitor
label-visible = %icon%
label-visible-background = ${self.label-focused-background}
label-visible-underline = ${self.label-focused-underline}
label-visible-padding = ${self.label-unfocused-padding}
; urgent = Workspace with urgency hint set
label-urgent = %icon%
label-urgent-background = ${colors.alert}
label-urgent-padding = ${self.label-unfocused-padding}
; formatting of the mode display
label-mode = %mode%
label-mode-padding = ${self.label-unfocused-padding}
label-mode-foreground = ${colors.background}
label-mode-background = ${colors.primary}
[module/cpu]
; module type
type = internal/cpu
; Seconds to sleep between updates
interval = 1.0
; Available tags:
; <label> (default)
; <bar-load>
; <ramp-load>
; <ramp-coreload>
format = <ramp-load>
; Available tokens:
; %percentage% (default) - total cpu load averaged over all cores
; %percentage-sum% - Cumulative load on all cores
; %percentage-cores% - load percentage for each core
; %percentage-core[1-9]% - load percentage for specific core
label = 
; enable large icon font
label-font = 2
; Spacing between individual per-core ramps
ramp-load-0 = ▁
ramp-load-1 = %{F#ffe5e5}▂%{F-}
ramp-load-2 = %{F#ffcccc}▃%{F-}
ramp-load-3 = %{F#ffb2b2}▄%{F-}
ramp-load-4 = %{F#ff9999}▅%{F-}
ramp-load-5 = %{F#ff6666}▆%{F-}
ramp-load-6 = %{F#ff3232}▇%{F-}
ramp-load-7 = %{F#ff0000}█%{F-}
format-underline = ${colors.primary}
[module/temp]
type = internal/temperature
; Seconds to sleep between updates
interval = 1.0
; Thermal zone to use
; To list all the zone types, run
; $ for i in /sys/class/thermal/thermal_zone*; do echo "$i: $(<$i/type)"; done
; Default: 0
thermal-zone = 2
; Use `sensors` to find preferred temperature source, then run
; $ for i in /sys/class/hwmon/hwmon*/temp*_input; do echo "$(<$(dirname $i)/name): $(cat ${i%_*}_label 2>/dev/null || echo $(basename ${i%_*})) $(readlink -f $i)"; done
; hwmon-path = /sys/devices/platform/coretemp.0/hwmon/hwmon0/temp1_input
; Base temperature for where to start the ramp (in degrees celsius)
base-temperature = 50
; Threshold temperature to display warning label (in degrees celsius)
warn-temperature = 70
units = true
format = <ramp>
format-warn = <ramp> <label-warn>
label-warn = %temperature-c%
label-warn-foreground = ${colors.alert}
ramp-0 =
ramp-1 = %{F#ff9999}ﲲﲲ%{F-}
ramp-2 = %{F#ff0000}ﲲﲲﲲ%{F-}
format-underline = ${colors.primary}
[module/date]
type = internal/date
; Seconds to sleep between updates
interval = 5.0
; See "http://en.cppreference.com/w/cpp/io/manip/put_time" for details on how to format the date string
; NOTE: if you want to use syntax tags here you need to use %%{...}
date = %d/%m
; Optional time format
time = %H:%M
; if `date-alt` or `time-alt` is defined, clicking
; the module will toggle between formats
date-alt = %A, %d %B %Y (W %V)
time-alt = %H:%M:%S
label = %date%%{T2}  %{T-}%time%
format-underline = ${colors.primary}
[module/datecal]
type = custom/script
exec = $XDG_CONFIG_HOME/polybar/scripts/poly-date
tail = true
click-left = gsimplecal
click-right = kill -USR1 %pid%
format-underline = ${colors.primary}
; display information on currently playing track, allows simple track manipulation
; TODO: add album art display (on click?) - retrieved by playerctl metadata mpris:artUrl
[module/music]
type = custom/script
exec = $XDG_CONFIG_HOME/polybar/scripts/poly-mprisdisplay
exec-if = type $XDG_CONFIG_HOME/polybar/scripts/poly-mprisdisplay
tail = true
click-left = kill -USR1 %pid%
click-right = kill -USR2 %pid%
format-underline = ${colors.primary}
; display information on remaining papers to read for the upcoming week
[module/papersdue]
type = custom/script
exec = $XDG_CONFIG_HOME/polybar/scripts/poly-papersdue
exec-if = type bib-due
tail = true
; show list with high prio
click-left = exist rofi-bib-due normal "opening due papers" && rofi-bib-due -p1 -u $(date --date='fri this week' +%Y-%m-%d)
; show list with all
click-right = exist rofi-bib-due normal "opening due papers" && rofi-bib-due -p3 -u $(date --date='fri this week' +%Y-%m-%d)
format-prefix = " "
interval = 120
format-underline = ${colors.primary}
[module/dunstpaused]
type = custom/script
exec = sed -e 's/true/⏾/' -e 's/false//' /tmp/dunstpaused
exec-if = [ -f /tmp/dunstpaused ]
tail = true
format-underline = ${colors.primary}
[module/mail]
type = custom/script
exec = echo "$( [ $(systemctl --user --property=ActiveState show mbsync.timer) = 'ActiveState=active' ] && echo "" || echo "" ) $(notmuch count tag:inbox and tag:unread)"
exec-if = check-internet && [ "$(notmuch count tag:inbox and tag:unread)" -gt 0 ]
click-right = systemctl --user start mbsync.timer
click-left = systemctl --user stop mbsync.timer
interval = 300.0
format-underline = ${colors.primary}
[module/weather]
type = custom/script
exec = $XDG_CONFIG_HOME/polybar/scripts/poly-weather 'Copenhagen?m&format=%t+%C+(%p)'
exec-if = type $XDG_CONFIG_HOME/polybar/scripts/poly-weather && check-internet
interval = 60.0
; format-background = ${colors.primary}
; format-foreground = ${colors.background}
format-underline = ${colors.primary}
; displays a small pomodoro timer
[module/pomo]
type = custom/script
exec = $XDG_CONFIG_HOME/polybar/scripts/poly-pomo
exec-if = exist pomo normal "pomodoro timer"
format-underline = ${colors.primary}
; pause timer
click-left = $XDG_CONFIG_HOME/polybar/scripts/poly-pomo toggle
; restart timer
click-right = $XDG_CONFIG_HOME/polybar/scripts/poly-pomo restart
tail = true
; display unified available packages for update on arch from repos/aur
; uses pacman-contrib/checkupdates if available to avoid partial arch upgrades
[module/archupdates]
type = custom/script
exec = $XDG_CONFIG_HOME/polybar/scripts/poly-archupdates
exec-if = type $XDG_CONFIG_HOME/polybar/scripts/poly-archupdates && check-internet
interval = 600
format = <label>
format-prefix = " "
; format-foreground = ${colors.primary}
format-underline = ${colors.primary}
[module/networkspeed]
type = custom/script
exec = $XDG_CONFIG_HOME/polybar/scripts/poly-networkspeed
exec-if = type $XDG_CONFIG_HOME/polybar/scripts/poly-networkspeed && check-internet
tail = true
format-underline = ${colors.primary}
[module/volume]
type = internal/pulseaudio
; Available tags:
; <label-volume> (default)
; <ramp-volume>
; <bar-volume>
format-volume = <ramp-volume>
format-underline = ${colors.primary}
; Use PA_VOLUME_UI_MAX (~153%) if true, or PA_VOLUME_NORM (100%) if false
use-ui-max = false
label-muted = ﱝ
label-muted-foreground = ${colors.foreground-alt}
; Only applies if <ramp-volume> is used
ramp-volume-0 = 
ramp-volume-1 = 
ramp-volume-2 = 
ramp-volume-3 = 墳
[module/backlight]
type = internal/xbacklight
format = <ramp><label>
ramp-0 = 
ramp-1 = 
ramp-2 = 
ramp-3 = 
ramp-4 = 
format-underline = ${colors.primary}
enable-scroll = true
[module/battery]
type = internal/battery
battery = BAT0
adapter = AC
label-charging =  %percentage%%
label-discharging = %percentage%%
format-discharging = <ramp-capacity> <label-discharging>
format-charging = <label-charging>
ramp-capacity-0 = 
ramp-capacity-1 = 
ramp-capacity-2 = 
ramp-capacity-3 = 
ramp-capacity-4 = 
format-underline = ${colors.primary}
; vim:ft=dosini

View file

@ -1,31 +0,0 @@
#!/usr/bin/env sh
update_time=5
mode=${1:-0}
separator='  '
short_date_string='%d/%m'"${separator}"'%H:%M'
long_date_string='%A, %d %B %Y (CW %V)'"${separator}"'%H:%M:%S'
modetoggle() {
mode=$(((mode + 1) % 2))
}
trap "modetoggle" USR1
display_date() {
if [ "$1" = "long" ]; then
date +"${long_date_string}"
else
date +"${short_date_string}"
fi
}
while true; do
if [ $mode -eq 0 ]; then
display_date short
elif [ $mode -eq 1 ]; then
display_date long
fi
sleep $update_time &
wait
done

View file

@ -1,47 +0,0 @@
#!/bin/sh
# script to echo the current playback situation
#
# call without args to return playing symbol or empty, depending on current playback status
# call with 1 to return 'artist - title' metadata (verbose mode)
# send SIGUSR2 signal to toggle pause/playing state of song (e.g. kill -USR2 %PID)
#
# depends on playerctl being installed
exist playerctl low "polybar music" || exit 1
mode=${1:-0}
update_time=1
symbol_playing=""
symbol_paused=""
modetoggle() {
mode=$(((mode + 1) % 2))
}
trap "modetoggle" USR1
playpause() {
playerctl play-pause
}
trap "playpause" USR2
decorate() {
if [ "$player_status" = "Playing" ]; then
echo "${symbol_playing}$1"
elif [ "$player_status" = "Paused" ]; then
echo "${symbol_paused}$1"
else
echo ""
fi
}
while true; do
player_status=$(playerctl status 2>/dev/null)
if [ $mode -eq 0 ]; then
decorate ""
elif [ $mode -eq 1 ]; then
decorate " $(playerctl metadata artist) - $(playerctl metadata title)"
fi
sleep $update_time &
wait
done

View file

@ -1,83 +0,0 @@
#!/bin/bash
INTERVAL=3
# interfaces for desktop and laptop
INTERFACES="enp6s0 wlp0s29u1u1 wlp56s0"
print_bytes() {
if [ "$1" -eq 0 ] || [ "$1" -lt 1000 ]; then
bytes="0"
elif [ "$1" -lt 1000000 ]; then
bytes="$(echo "scale=0;$1/1000" | bc -l)k"
else
bytes="$(echo "scale=1;$1/1000000" | bc -l)M"
fi
echo "$bytes"
}
print_bit() {
if [ "$1" -eq 0 ] || [ "$1" -lt 10 ]; then
bit="0 B"
elif [ "$1" -lt 100 ]; then
bit="$(echo "scale=0;$1*8" | bc -l) B"
elif [ "$1" -lt 100000 ]; then
bit="$(echo "scale=0;$1*8/1000" | bc -l) K"
else
bit="$(echo "scale=1;$1*8/1000000" | bc -l) M"
fi
echo "$bit"
}
declare -A bytes
get_initial_throughput() {
for interface in $INTERFACES; do
local dir="/sys/class/net/$interface"
if [ -d "$dir" ]; then
bytes[past_rx_$interface]="$(cat "$dir"/statistics/rx_bytes)"
bytes[past_tx_$interface]="$(cat "$dir"/statistics/tx_bytes)"
fi
done
}
get_throughput() {
while true; do
down=0
up=0
for interface in $INTERFACES; do
local dir="/sys/class/net/$interface"
if [ -d "$dir" ]; then
bytes[now_rx_$interface]="$(cat "$dir"/statistics/rx_bytes)"
bytes[now_tx_$interface]="$(cat "$dir"/statistics/tx_bytes)"
bytes_down=$((((${bytes[now_rx_$interface]} - ${bytes[past_rx_$interface]})) / INTERVAL))
bytes_up=$((((${bytes[now_tx_$interface]} - ${bytes[past_tx_$interface]})) / INTERVAL))
down=$(((("$down" + "$bytes_down"))))
up=$(((("$up" + "$bytes_up"))))
bytes[past_rx_$interface]=${bytes[now_rx_$interface]}
bytes[past_tx_$interface]=${bytes[now_tx_$interface]}
fi
done
if [ "$down" -gt 1000 ] || [ "$up" -gt 1000 ]; then
echo " $(print_bytes $down) 祝$(print_bytes $up)"
else
echo ""
fi
# echo "Download: $(print_bytes $down) / Upload: $(print_bytes $up)"
# echo "Download: $(print_bit $down) / Upload: $(print_bit $up)"
sleep $INTERVAL
done
}
get_initial_throughput
get_throughput

View file

@ -1,15 +0,0 @@
#!/usr/bin/env sh
while true; do
all="$(bib-due -u 'fri this week' -p3 | wc -l)"
required="$(bib-due -u 'fri this week' -p1 | wc -l)"
# add polybar formatting to color required readings red
# https://github.com/polybar/polybar/wiki/Formatting#format-tags
# TODO use xresources
colorreq=$(xrdb -query | grep -e '\*color1:' | cut -f2)
colorall=$(xrdb -query | grep -e '\*foreground:' | cut -f2)
printf "%s%s%s(%s)\n" "%{F${colorall:-#000}}" "$all" "%{F${colorreq:-#d00}}" "$required"
sleep 120
done

View file

@ -1,41 +0,0 @@
#!/usr/bin/env sh
run_notify() {
pomo notify &
PID_NOTIFY="$!"
echo "$PID_NOTIFY" >"${XDG_RUNTIME_DIR:-$HOME}"/.running-pomo.lock
}
# create background notify process; close it when this process is killed
close_notify() {
lockfile="${XDG_RUNTIME_DIR:-$HOME}"/.running-pomo.lock
[ -f "$lockfile" ] && kill "$(cat "$lockfile")"
kill "$PID_NOTIFY"
rm "${XDG_RUNTIME_DIR:-$HOME}"/.running-pomo.lock
}
trap close_notify EXIT
restart_notify() {
close_notify
run_notify
}
if [ -z "$1" ]; then
run_notify
while true; do
display=$(pomo clock)
# replace W (work)
# B (break)
# P (paused) with pomodoro symbols
# remove seconds *except for* when 00 minutes reached
display=$(echo "$display" | sed -e 's/--:--/ /;s/P.*$/  /;s/W/ /;s/B/ /;/00:/! { s/:[[:digit:]]\+$// }')
echo "$display"
sleep 1
done
elif [ "$1" = "toggle" ]; then
pomo pause
restart_notify
elif [ "$1" = "restart" ]; then
pomo stop
restart_notify
fi

View file

@ -1,23 +0,0 @@
#!/usr/bin/env sh
wttr() {
# change Paris to your default location
request="wttr.in/${1-~Leipzig}"
curl -s -H "Accept-Language: ${LANG%_*}" --compressed "${request}"
}
wttr "$@"
# while true; do
# all="$(bib-due -u 'fri this week' -p3 | wc -l)"
# required="$(bib-due -u 'fri this week' -p1 | wc -l)"
# # add polybar formatting to color required readings red
# # https://github.com/polybar/polybar/wiki/Formatting#format-tags
# # TODO use xresources
# colorreq=$(xrdb -query | grep -e '\*color1:' | cut -f2)
# colorall=$(xrdb -query | grep -e '\*foreground:' | cut -f2)
# printf "%s%s%s(%s)\n" "%{F${colorall:-#000}}" "$all" "%{F${colorreq:-#d00}}" "$required"
# sleep 120
# done

View file

@ -1,20 +0,0 @@
#!/usr/bin/env bash
# force start or restart (all) polybar instances
# if ipc is enabled, can be replaced with `polybar-msg cmd restart`, provided polybar is not stuck
# Terminate already running bar instances
killall -q polybar
# Wait until the processes have been shut down
while pgrep -u $UID -x polybar >/dev/null; do sleep 1; done
startbars() {
for bar in "$@"; do
local logfile="/tmp/polybar-$bar.log"
printf -- "---\npolybar: %s starting...\n---\n" "$bar" | tee -a "$logfile"
polybar "$bar" >>"$logfile" 2>&1 &
done
}
startbars "$@"
echo "Polybars launched..."

View file

@ -1 +0,0 @@
../share/pomo-app/pomo.sh

@ -1 +0,0 @@
Subproject commit 68a8e26a46f8516ee73b429c153a1fc7a4a2c300

View file

@ -1,92 +0,0 @@
# Polybar module
[polybar](https://polybar.github.io/) - a fast and easy-to-use statusbar
[[_TOC_]]
## Polybar look
minimal look:
![minimal](.assets/polybar/minimal.png)
Active i3 workspaces are displayed left with current workspace highlighted, and any active i3 modes. The center contains information on the currently playing song, displaying notes if something is playing, date and time, and upcoming bib readings from the library. The right contains system information and the task tray.
with network activity:
![network](.assets/polybar/network.png)
full-load and temperature warning:
![full](.assets/polybar/full.png)
In general, the bar's colors are derived from the colors defined in xresources. It follows the base16 color template, as does every module in these dotfiles. That means the bar can be quickly re-themed using base16 color themes and the process can be automated (e.g. with styler).
## i3 workspaces
![normal](.assets/polybar/i3-normal.png) -- focus on workspace 4
The i3 workspaces module is pretty simple and self-explanatory. It shows all existing workspaces, and highlights the one that is currently active. It also highlights any workspaces on which an event took place.
![highlight](.assets/polybar/i3-highlight.png) -- focus on workspace 2, workspace 1 highlighted
Additionally, if an i3 mode is active, it will be displayed next to the workspaces in a stark color to notice the mode being active. This is slowly being deprecated in favor of sxhkd modes -- e.g. media mode is now displayed by the sxhkd module instead. The only remaining mode is resize for the moment.
![mode](.assets/polybar/i3-mode.png) -- focus on workspace 3, 'Media' mode active
Workspaces can be cycled with the mouse-wheel when hovering over the module, or can be invoked by clicking on the icons.
## sxhkd modes
The current mode of the desktop is being passed from sxhkd to polybar for display.
Its look is based on the i3 workspace mode display, though by default they appear to the right of the workspaces.
![sxhkd mode](.assets/polybar/sxhkd_mode.png) -- academia sxhkd mode activated
## Current track information
By default, the track information panel is very minimal. It simply displays a note when something is currently playing, a pause symbol when the current track is pause, and nothing at all when no track is currently available. (no media player open, all tracks stopped, etc.)
When clicked, the track metadata is revealed, displaying track artist and title. Another click toggles it off again.
![mpris](.assets/polybar/mpris.png)
When right-clicked, the current track can be toggled between playing and paused.
The `poly-mprisdisplay` script implementation requires `playerctl` available on the system to be run. It will return with an error message if the binary is not found. Symbols used can be easily customized in the script.
## Date
The standard polybar date display. Displays current date (DD/MM) and current time (24-hours) by default. On click, toggles to an expanded date display with current weekday and current week of the year.
![clock](.assets/polybar/clock.png)
![extended clock](.assets/polybar/clock_alt.png)
## Upcoming Bibtex readings
Depends on the [`bibtex`](bibtex/) module being installed, more specifically:
* the `bib-due` script accessible as a program
* a `$BIBFILE` environment variable pointing to the bibtex library (or at least, the relevant library of the system)
* optionally: `rofi` (or `dmenu`) to enable listing of readings on click
Displays the library readings remaining for the week in simple numerical fashion. On click invokes the full `bib_due` script to show further information on the upcoming readings, requiring either `dmenu` or `rofi` to display them.
## System information
Contains various system-relevant details.
![system info](.assets/polybar/system.png)
If the network has activity, it shows upload and download speeds (dynamically switching between displaying Kb/s, Mb/s). The script `poly-networkspeed` as of now uses hard-coded network interface names. If network interfaces have a different name, this will need to be adjusted.
If updates for arch packages are available (from repositories or aur) it displays the number of available updates. The script `poly-archupdates` requires `yay` to be available. If checkupdates is available it will use this to check for repo packages, which can avoid partial arch updates in rare circumstances. (contained in `pacman-contrib` package)
The volume module simply displays the current pulseaudio volume as a ramped version of the volume symbol. On click it toggles mute and un-mute.
If xbacklight is available, the current display brightness is displayed as a symbol between a moon (dark) and a sun (bright).
If a battery is available, it will display its current status, percentage, and whether it is charging.
The cpu load is displayed as a simple vertical bar, changing color at specific intervals to be more noticeable. When the cpu gets warm, a temperature warning will be displayed, along with current numeric temperature value (in °C). The correct sensor may have to be changed in the polybar config file; as well as useful limits for the display of temperature information.

View file

@ -0,0 +1,112 @@
#!/usr/bin/env bash
# Both standalone script and qutebrowser userscript that opens a rofi menu with
# all files from the download directory and opens the selected file. It works
# both as a userscript and a standalone script that is called from outside of
# qutebrowser.
#
# Suggested keybinding (for "show downloads"):
# spawn --userscript ~/.config/qutebrowser/open_download
# sd
#
# Requirements:
# - rofi (in a recent version), or bemenu
# - xdg-open and xdg-mime
# - You should configure qutebrowser to download files to a single directory
# - It comes in handy if you enable downloads.remove_finished. If you want to
# see the recent downloads, just press "sd".
#
# Thorsten Wißmann, 2015 (thorsten` on Libera Chat)
# Refactored to work with bemenu by Marty Oehme, 2021 (@martyo@matrix.org on Matrix)
# Any feedback is welcome!
set -e
# open a file from the download directory using rofi
DOWNLOAD_DIR=${DOWNLOAD_DIR:-${QUTE_DOWNLOAD_DIR:-$HOME/downloads}}
# the name of the rofi-like command
if [ -n "$ROFI_CMD" ]; then
:
elif command -v rofi >/dev/null 2>&1; then
ROFI_CMD="rofi"
ROFI_ARGS=${ROFI_ARGS:-(
-monitor -2 # place above window
-location 6 # aligned at the bottom
-width 100 # use full window width
-i
-no-custom
-format i # make rofi return the index
-l 10
-p 'Open download:' -dmenu
)}
elif command -v bemenu >/dev/null 2>&1; then
ROFI_CMD="bemenu"
ROFI_ARGS="${ROFI_ARGS:--il 10}"
fi
msg() {
local cmd="$1"
shift
local msg="$*"
if [ -z "$QUTE_FIFO" ]; then
echo "$cmd: $msg" >&2
else
echo "message-$cmd '${msg//\'/\\\'}'" >>"$QUTE_FIFO"
fi
}
die() {
msg error "$*"
if [ -n "$QUTE_FIFO" ]; then
# when run as a userscript, the above error message already informs the
# user about the failure, and no additional "userscript exited with status
# 1" is needed.
exit 0
else
exit 1
fi
}
if ! [ -d "$DOWNLOAD_DIR" ]; then
die "Download directory »$DOWNLOAD_DIR« not found!"
fi
if ! command -v "${ROFI_CMD}" >/dev/null; then
die "Rofi command »${ROFI_CMD}« not found in PATH!"
fi
crop-first-column() {
cut -d' ' -f2
}
ls-files() {
# add the slash at the end of the download dir enforces to follow the
# symlink, if the DOWNLOAD_DIR itself is a symlink
# sort by newest
find "${DOWNLOAD_DIR}/" -maxdepth 1 -type f -printf "%T+ %f\n" | sort -r
}
mapfile -t entries < <(ls-files)
# we need to manually check that there are items, because rofi doesn't show up
# if there are no items and -no-custom is passed to rofi.
if [ "${#entries[@]}" -eq 0 ]; then
die "Download directory »${DOWNLOAD_DIR}« empty"
fi
line=$(printf '%s\n' "${entries[@]}" |
crop-first-column |
$ROFI_CMD "${ROFI_ARGS[@]}") || true
if [ -z "$line" ]; then
exit 0
fi
msg info "file is $line"
path="$DOWNLOAD_DIR/$line"
filetype=$(xdg-mime query filetype "$path")
application=$(xdg-mime query default "$filetype")
if [ -z "$application" ]; then
die "Do not know how to open »$line« of type $filetype"
fi
msg info "Opening »$line« (of type $filetype) with ${application%.desktop}"
xdg-open "$path" &

View file

@ -1,73 +0,0 @@
#!/usr/bin/env sh
# Custom key bindings do not work in script-mode, use a wrapper instead
# Script at .local/bin/rofi-gopass
OLD_GOPASS_GPG_OPTS="$GOPASS_GPG_OPTS"
break_out() {
if [ "$1" -eq 1 ]; then
exit
fi
}
has_xclip() {
if (type xclip >/dev/null 2>&1); then
printf "Your system does not appear to support pasting to clipboard via xclip."
exit 1
else
return 0
fi
}
to_clipboard() {
has_xclip
value="$(gopass show "$1" "$2")"
printf "%s" "$value" | xclip -selection clipboard
notify-send "Password" "Copied pass for $2 to clipboard.\n"
exit
}
show_secrets() {
printf "%s" "$(gopass ls -fo)"
}
# get_key() {
# return echo "$*" | gpg --passphrase-fd 0 --pinentry-mode loopback --batch --export-secret-keys 2>&1
# }
# check_gpg_key() {
# check_keyphrase=$(echo "$*" | gpg --passphrase-fd 0 --pinentry-mode loopback --batch --export-secret-keys 2>&1)
# if echo "$check_keyphrase" | grep -q -e '.*<.*@.*>'; then
# printf "\x00prompt\x1fLogin> \n"
# show_secrets
# elif echo "$check_keyphrase" | grep -q -e "can't get input" - || echo "$check_keyphrase" | grep -q -e "error receiving key" -; then
# printf "\x00prompt\x1fMaster Passphrase> \n"
# printf "%s" "$check_keyphrase"
# else
# echo "passphrase successfully input, $check_keyphrase"
# fi
# }
# has_selected_login() {
# echo "this is passed to ls: $*"
# echo "grep reveals: $(gopass ls -f | grep -e "$*" -)"
# if grep "$(gopass ls -f | grep -q -e "$*" -)"; then
# echo "ls found something"
# true
# else
# false
# fi
# }
# if [ -z "$*" ]; then
# check_gpg_key "$*"
# elif has_selected_login "$*"; then
# echo "has selected login $*"
# else
# check_gpg_key "$*"
# fi
main() {
show_secrets
}
main

View file

@ -1,92 +0,0 @@
#!/usr/bin/env bash
#### Environment Variable Options ###
# Interface options
# ROFI_POWERMENU_SHOW_ICONS=1
# ROFI_POWERMENU_SHOW_TEXT=0
# ROFI_POWERMENU_SHOW_UPTIME=1
# ROFI_POWERMENU_SEARCHABLE=0
# Command options
# ROFI_POWERMENU_SHUTDOWN_CMD=""
# ROFI_POWERMENU_REBOOT_CMD=""
# ROFI_POWERMENU_LOCKSCREEN_CMD=""
# ROFI_POWERMENU_LOGOUT_CMD=""
# ROFI_POWERMENU_SUSPEND_CMD=""
#### Menu Options ###
if [ "${ROFI_POWERMENU_SHOW_TEXT:-0}" -eq 0 ] && [ "${ROFI_POWERMENU_SHOW_ICONS:-1}" -eq 0 ]; then
echo "You disabled both text and icons for rofi-powermenu, nothing can be shown."
exit 1
elif [ "${ROFI_POWERMENU_SHOW_ICONS:-1}" -eq 1 ]; then
power_off_btn=""
reboot_btn=""
lock_btn=""
suspend_btn="鈴"
logout_btn=""
fi
if [ "${ROFI_POWERMENU_SHOW_TEXT:-0}" -eq 1 ]; then
power_off_btn="${power_off_btn} Shut Down"
reboot_btn="${reboot_btn} Restart"
lock_btn="${lock_btn} Lock Screen"
suspend_btn="${suspend_btn} Suspend"
logout_btn="${logout_btn} Log Out"
fi
# FIXME does not hide pango comments anymore for some reason
if [ "${ROFI_POWERMENU_SEARCHABLE:-1}" -eq 1 ]; then
power_off_btn="${power_off_btn} <!-- Shutdown Poweroff -->"
reboot_btn="${reboot_btn} <!-- Reboot Restart -->"
lock_btn="${lock_btn} <!-- Lockscreen -->"
suspend_btn="${suspend_btn} <!-- Suspend Sleep -->"
logout_btn="${logout_btn} <!-- Exit X Logout -->"
fi
# grep -a since it assumes with our nullcodes etc that this is a binary file
# grep -o to only leave the things we grep for
case "$*" in
"Shutdown" | "$power_off_btn")
if [ -n "$ROFI_POWERMENU_SHUTDOWN_CMD" ]; then eval "$ROFI_POWERMENU_SHUTDOWN_CMD"; else
systemctl poweroff
fi
;;
"Reboot" | "$reboot_btn")
if [ -n "$ROFI_POWERMENU_REBOOT_CMD" ]; then eval "$ROFI_POWERMENU_REBOOT_CMD"; else
systemctl reboot
fi
;;
"Lockscreen" | "$lock_btn")
# Completely detach from the parent script
# If in/outputs are not redirected, rofi will wait for the forked process as well.
if [ -n "$ROFI_POWERMENU_LOCKSCREEN_CMD" ]; then eval "$ROFI_POWERMENU_LOCKSCREEN_CMD"; else
lockscreen rofi </dev/null >/dev/null 2>/dev/null &
fi
;;
"Logout" | "$logout_btn")
if [ -n "$ROFI_POWERMENU_LOGOUT_CMD" ]; then eval "$ROFI_POWERMENU_LOGOUT_CMD"; else
i3-msg exit
fi
;;
"Suspend" | "$suspend_btn")
if [ -n "$ROFI_POWERMENU_SUSPEND_CMD" ]; then eval "$ROFI_POWERMENU_SUSPEND_CMD"; else
lockscreen rofi </dev/null >/dev/null 2>/dev/null &
systemctl hibernate
fi
;;
esac
if [ "${ROFI_POWERMENU_SHOW_UPTIME:-1}" -eq 1 ]; then
prompt="Uptime: $(uptime -p | sed -e 's/up //g')"
else
prompt="Power"
fi
if [ -z "$*" ]; then
printf "\0prompt\x1f%s\n" "$prompt"
printf "\0markup\x1ftrue\n"
printf "%s\n" "$power_off_btn"
printf "%s\n" "$reboot_btn"
printf "%s\n" "$lock_btn"
printf "%s\n" "$suspend_btn"
printf "%s\n" "$logout_btn"
printf "\0markup-rows\x1ftrue\n"
fi

View file

@ -1,53 +0,0 @@
#!/usr/bin/env sh
# Brightness control script using xbacklight
# Will use notify-send to create brightness notifications, if dunst is used
# or the notification daemon supports tag stacks, will automatically update
# the same notifications and not create new ones.
#
# inspired from https://gist.github.com/Blaradox/030f06d165a82583ae817ee954438f2e
usage() {
echo "usage: control-brightness up|down [step], where step can be any int value
or: control-brightness set target, where target can be an int value 0-100"
}
direction=$1
step=${2:-10}
get_brightness() {
xbacklight -get | cut -d. -f1
}
send_notification() {
icon="preferences-system-brightness-lock"
brightness=$(get_brightness)
if type dunstify 1>/dev/null 2>/dev/null; then
notcmd="dunstify -h string:x-dunst-stack-tag:brightness"
else
notcmd="notify-send -h string:x-dunst-stack-tag:brightness"
fi
$notcmd -a "changeVolume" -u low -i "$icon" \
-h int:value:"$brightness" "Brightness: $brightness%"
}
case $direction in
up)
xbacklight -inc "$step"
send_notification
;;
down)
xbacklight -dec "$step"
send_notification
;;
set)
if [ -z "$step" ]; then
echo "set option requires target brightness to be specified."
return 1
fi
xbacklight -set "$step"
send_notification
;;
*)
echo "usage: control-brightness up|down [step], where step can be any int value"
;;
esac

View file

@ -1,97 +0,0 @@
#!/usr/bin/env sh
# change Volume in an easy and unified way
direction=$1
step=${2:-5dB}
# amixer channel to target
amixer_quiet() {
amixer -c 0 "$@" >/dev/null
}
amixer_noisy="amixer -c 0 "
# Query amixer for the current volume
get_volume() {
$amixer_noisy get Master | tail -1 | awk '{print $4}' | sed 's/[^0-9]*//g'
}
# query amixer for mute state (off=muted)
get_mute() {
$amixer_noisy get Master | tail -1 | awk '{print $6}' | sed 's/[^a-z]*//g'
}
set_volume() {
# Change the volume using alsa(might differ if you use pulseaudio)
amixer_quiet set Master "$@" >/dev/null
# Play the volume changed sound
# -- this is *extremely* laggy (>8s) on my system, no idea why and no time to find out
# canberra-gtk-play -i audio-volume-change -d "changeVolume"
}
# set mute state (off=mute)
set_mute() {
[ "$(get_mute)" = "on" ] && toggleto=off || toggleto=on
if [ "$1" = 'off' ]; then
amixer_quiet set Master mute
elif [ "$1" = 'on' ]; then
amixer_quiet set Master unmute
# the following is needed, see https://superuser.com/questions/805525/why-is-unmute-not-working-with-amixer-command
amixer_quiet set Speaker unmute
amixer_quiet set Headphone unmute
else
amixer_quiet set Master "$toggleto"
amixer_quiet set Speaker "$toggleto"
amixer_quiet set Headphone "$toggleto"
fi
}
usage() {
echo "control-volume up|down [step], with step any int value
or: control-brightness set [target], with target any int value 0-100"
}
send_notification() {
if type dunstify 1>/dev/null 2>/dev/null; then
notcmd="dunstify -h string:x-dunst-stack-tag:brightness"
else
notcmd="notify-send -h string:x-dunst-stack-tag:brightness"
fi
vol="$(get_volume)"
if [ "$vol" -eq 0 ] || [ "$(get_mute)" = "off" ]; then
# Show the sound muted notification
$notcmd -a "changeVolume" -u low -i audio-volume-muted "Volume muted"
else
# Show the volume notification
$notcmd -a "changeVolume" -u low -i audio-volume-high \
-h int:value:"$vol" "Volume: $vol%"
fi
}
case $direction in
up)
set_volume "${step}+"
;;
down)
set_volume "${step}-"
;;
mute)
set_mute "$step"
;;
mutetoggle)
set_mute
;;
set)
if [ -z "$step" ]; then
echo "set option requires target brightness to be specified."
return 1
fi
set_volume "$step"
;;
*)
usage
;;
esac
send_notification

View file

@ -1,12 +1,23 @@
#!/usr/bin/env sh
#!/usr/bin/env bash
# Example locker script -- demonstrates how to use the --transfer-sleep-lock
# option with i3lock's forking mode to delay sleep until the screen is locked.
# locker script -- makes sure that x does not give up the lock easily (using i3lock)
# simply locks the screen on wayland (using waylock)
## CONFIGURATION ##############################################################
is_wayland() {
# alternative $(</proc/self/sessionid), see
# https://stackoverflow.com/questions/3214935/can-a-bash-script-tell-if-its-being-run-via-cron
if loginctl show-session "$(loginctl show-user "$(whoami)" -p Display --value)" -p Type --value | grep -q wayland; then
true
else
false
fi
}
# Options to pass to i3lock
i3lock_options="-e -f -c 1d2021"
waylock_options="--init-color #223344 --input-color #224444 --fail-color #554444"
# Run before starting the locker
pre_lock() {
@ -26,18 +37,21 @@ post_lock() {
pre_lock
# We set a trap to kill the locker if we get killed, then start the locker and
if is_wayland; then
# shellcheck disable=SC2086
waylock $waylock_options
elif [ -e "/dev/fd/${XSS_SLEEP_LOCK_FD:--1}" ]; then
# On X, we set a trap to kill the locker if we get killed, then start the locker and
# wait for it to exit. The waiting is not that straightforward when the locker
# forks, so we use this polling only if we have a sleep lock to deal with.
if [ -e /dev/fd/${XSS_SLEEP_LOCK_FD:--1} ]; then
kill_i3lock() {
pkill -xu $EUID "$@" i3lock
pkill -xu "$EUID" "$@" i3lock
}
trap kill_i3lock TERM INT
# we have to make sure the locker does not inherit a copy of the lock fd
i3lock $i3lock_options {XSS_SLEEP_LOCK_FD}<&-
i3lock "$i3lock_options" {XSS_SLEEP_LOCK_FD}<&-
# now close our fd (only remaining copy) to indicate we're ready to sleep
exec {XSS_SLEEP_LOCK_FD}<&-
@ -47,7 +61,7 @@ if [ -e /dev/fd/${XSS_SLEEP_LOCK_FD:--1} ]; then
done
else
trap 'kill %%' TERM INT
i3lock -n $i3lock_options &
i3lock -n "$i3lock_options" &
wait
fi

84
scripts/.local/bin/powermenu Executable file
View file

@ -0,0 +1,84 @@
#!/usr/bin/env bash
# A simple powermenu listing.
# Uses bemenu to display the powermenu on X11, Wayland and terminal.
#### Environment Variable Options ###
# Interface options
# POWERMENU_SHOW_ICONS=1
# POWERMENU_SHOW_TEXT=1
# POWERMENU_SHOW_UPTIME=1
# Command options
# POWERMENU_SHUTDOWN_CMD=""
# POWERMENU_REBOOT_CMD=""
# POWERMENU_LOCKSCREEN_CMD=""
# POWERMENU_LOGOUT_CMD=""
# POWERMENU_SUSPEND_CMD=""
# Command chooser options
# POWERMENU_PICKER_CMD=""
# POWERMENU_PICKER_OPTS=""
#### Menu Options ###
if [ "${POWERMENU_SHOW_TEXT:-0}" -eq 0 ] && [ "${POWERMENU_SHOW_ICONS:-1}" -eq 0 ]; then
echo "You disabled both text and icons for rofi-powermenu, nothing can be shown."
exit 1
elif [ "${POWERMENU_SHOW_ICONS:-1}" -eq 1 ]; then
power_off_btn=""
reboot_btn=""
lock_btn=""
suspend_btn="鈴"
logout_btn=""
fi
if [ "${POWERMENU_SHOW_TEXT:-1}" -eq 1 ]; then
power_off_btn="${power_off_btn} Shut Down"
reboot_btn="${reboot_btn} Restart"
lock_btn="${lock_btn} Lock Screen"
suspend_btn="${suspend_btn} Suspend"
logout_btn="${logout_btn} Log Out"
fi
## SET PROMPT
if [ "${POWERMENU_SHOW_UPTIME:-1}" -eq 1 ]; then
prompt="Uptime $(uptime -p | sed -e 's/up //g') >"
else
prompt="Power >"
fi
selector_program="${POWERMENU_PICKER_CMD:-bemenu}"
selector_opts="${POWERMENU_PICKER_OPTS:--i}"
menu=$(printf "%s\n" "$lock_btn" "$suspend_btn" "$power_off_btn" "$reboot_btn" "$logout_btn")
# shellcheck disable=SC2086
result=$(printf "%s" "$menu" | $selector_program $selector_opts --prompt "$prompt")
# grep -a since it assumes with our nullcodes etc that this is a binary file
# grep -o to only leave the things we grep for
case "$result" in
"Shutdown" | "$power_off_btn")
if [ -n "$POWERMENU_SHUTDOWN_CMD" ]; then eval "$POWERMENU_SHUTDOWN_CMD"; else
systemctl poweroff
fi
;;
"Reboot" | "$reboot_btn")
if [ -n "$POWERMENU_REBOOT_CMD" ]; then eval "$POWERMENU_REBOOT_CMD"; else
systemctl reboot
fi
;;
"Lockscreen" | "$lock_btn")
# Completely detach from the parent script
# If in/outputs are not redirected, rofi will wait for the forked process as well.
if [ -n "$POWERMENU_LOCKSCREEN_CMD" ]; then eval "$POWERMENU_LOCKSCREEN_CMD"; else
lockscreen
fi
;;
"Logout" | "$logout_btn")
if [ -n "$POWERMENU_LOGOUT_CMD" ]; then eval "$POWERMENU_LOGOUT_CMD"; else
command -v i3 >/dev/null 2>&1 && i3-msg exit
command -v riverctl >/dev/null 2>&1 && riverctl exit
fi
;;
"Suspend" | "$suspend_btn")
if [ -n "$POWERMENU_SUSPEND_CMD" ]; then eval "$POWERMENU_SUSPEND_CMD"; else
systemctl hibernate
fi
;;
esac

View file

@ -4,28 +4,75 @@
#
# Examples:
# `sharefile`
# calling without arguments allows you to first select a folder and then
# Calling without arguments allows you to first select a folder and then
# a file from the folder to share.
# `sharefile ~/my-folder/`
# Calling with a folder as argument restricts the file selection to files within.
# `sharefile ~/my-file.zip`
# calling with a file as argument automatically uploads the file and copies
# Calling with a file as argument automatically uploads the file and copies
# share link to clipboard.
# When called with a folder as argument allows you to select file within, uploads it and copies share link.
# `screenshot | sharefile -`
# Calling with a dash as argument gets the file from stdin instead.
# Be aware that this currently only works for files not folders.
OXO_URL="https://0x0.st"
folderpicker() {
selected=$(find "${1:-$HOME}" -type d | fzf)
# use fd if available
if command -v fd >/dev/null 2>&1; then
sharefile_fd_cmd="fd"
else
sharefile_fd_cmd="find"
fi
main() {
if [ $# -eq 0 ]; then
foldpick=$(picker d "")
exit_check $?
picked=$(picker f "$foldpick")
elif [ "$1" = "-" ]; then
while read -r file; do
picked="$file"
done <"/dev/stdin"
elif [ -f "$1" ]; then
picked="$1"
elif [ -d "$1" ]; then
picked=$(picker f "$1")
else
printf "Please only provide a folder or file as the optional argument to sharefile." >&2
exit 1
fi
exit_check $?
url=$(file_to_oxo "$picked")
echo "$url"
url_to_clipboard "$url"
if command -v notify-send >/dev/null 2>&1; then
notify-send "Upload finished" "URL: $url"
fi
exit
}
picker() {
if [ "$sharefile_fd_cmd" = "fd" ]; then
selected=$(fd "$SHAREFILE_FD_OPTS" --type "${1:-f}" . "${2:-$HOME}" | fzf)
elif [ "$sharefile_fd_cmd" = "find" ]; then
selected=$(find "$SHAREFILE_FD_OPTS" "${2:-$HOME}" -type "$1" | fzf)
fi
[ "$?" -eq 130 ] && exit 130
echo "$selected"
}
filepicker() {
selected=$(find "${1:-$HOME}" -type f | fzf)
[ "$?" -eq 130 ] && exit 130
echo "$selected"
url_to_clipboard() {
if command -v wl-copy >/dev/null 2>&1; then
printf "%s" "$@" | wl-copy
elif command -v xsel >/dev/null 2>&1; then
printf "%s" "$@" | xsel --clipboard
elif command -v xclip >/dev/null 2>&1; then
printf "%s" "$@" | xclip -selection clipboard >/dev/null 2>&1
fi
}
filetooxo() {
file_to_oxo() {
curl -F"file=@$1" "$OXO_URL"
}
@ -34,29 +81,4 @@ exit_check() {
[ "$1" -eq 130 ] && exit 130
}
main() {
if [ $# -eq 0 ]; then
foldpick=$(folderpicker "")
exit_check $?
picked=$(filepicker "$foldpick")
elif [ -f "$1" ]; then
picked="$1"
elif [ -d "$1" ]; then
picked=$(filepicker "$1")
else
printf "Please only provide a folder or file as the optional argument to sharefile." >&2
exit 1
fi
exit_check $?
url=$(filetooxo "$picked")
echo "$url"
if command -v notify-send >/dev/null; then
notify-send "Upload finished" "URL: $url"
fi
# printf "%s" "$url" | nohup xclip -i -selection clipboard -r -verbose -loops 2 >/dev/null 2>&1
printf "%s" "$url" | xsel --clipboard
exit
}
main "$@"

View file

@ -1,5 +1,9 @@
#!/usr/bin/env sh
if [ ! "$DISPLAY" ] && [ -n "$XDG_VTNR" ] && [ "$XDG_VTNR" -eq 1 ]; then
exec startx "$XDG_CONFIG_HOME"/xresources/xinitrc
if [ -n "$DISPLAY" ] || [ -z "$XDG_VTNR" ] || [ "$XDG_VTNR" -ne 1 ]; then
return
fi
if command -v river >/dev/null 2>&1; then
river
fi

View file

@ -0,0 +1,62 @@
#!/bin/sh
[ -d "$HOME/.cache/vifm" ] || mkdir -p "$HOME/.cache/vifm"
# $1 action
action="$1"
# $2 panel width
panel_width=$(($2 * 6))
# $3 panel height
panel_height=$(($3 * 14))
# $4 image path
image_file="$4"
PCACHE="$HOME/.cache/vifm/thumbnail.$(stat --printf '%n\0%i\0%F\0%s\0%W\0%Y' -- "$(readlink -f "$PWD/$image_file")" | sha256sum | awk '{print $1}')"
cleanup() {
printf '\33[s\33[5A\33[2K\33[u'
clear
exit 0
}
# recieves image with height
image() {
montage "$1" -geometry "${2}x${3}" sixel:-
}
case "$action" in
"clear")
cleanup
;;
"draw")
[ ! -f "${PCACHE}.jpg" ] && convert "$image_file"'[0]' "${PCACHE}.jpg"
# FILE="$PWD/$image_file"
image "${PCACHE}.jpg" "$panel_width" "$panel_height"
;;
"video")
[ ! -f "${PCACHE}.jpg" ] &&
ffmpegthumbnailer -i "$4" -o "${PCACHE}.jpg" -s 0 -q 5
image "${PCACHE}.jpg" "$panel_width" "$panel_height"
;;
"epub")
[ ! -f "${PCACHE}.jpg" ] &&
epub-thumbnailer "$image_file" "$PCACHE" 1024
image "${PCACHE}.jpg" "$panel_width" "$panel_height"
;;
"pdf")
[ ! -f "${PCACHE}.jpg" ] &&
pdftoppm -jpeg -f 1 -singlefile "$image_file" "$PCACHE"
image "${PCACHE}.jpg" "$panel_width" "$panel_height"
;;
"audio")
[ ! -f "${PCACHE}.jpg" ] &&
ffmpeg -i "$image_file" "${PCACHE}.jpg" -y >/dev/null
image "${PCACHE}.jpg" "$panel_width" "$panel_height"
;;
"font")
[ ! -f "${PCACHE}.jpg" ] &&
fontpreview -i "$image_file" -o "${PCACHE}.jpg"
image "${PCACHE}.jpg" "$panel_width" "$panel_height"
;;
*) ;;
esac

View file

@ -348,6 +348,37 @@ set classify+=' ::*.doc,,*.docx::, ::*.xls,,*.xls[mx]::, ::*.pptx,,*.pp
" You can also add %CLEAR if you want to clear screen before running FUSE
" program.
fileviewer *.pdf
\ vifm-sixel pdf %pw %ph %c %pd
\ %pc
\ vifm-sixel clear
fileviewer *.epub
\ vifm-sixel epub %pw %ph %c %pd
\ %pc
\ vifm-sixel clear
fileviewer <video/*>
\ vifm-sixel video %pw %ph %c %pd
\ %pc
\ vifm-sixel clear
fileviewer <image/*>
\ vifm-sixel draw %pw %ph %c %pd
\ %pc
\ vifm-sixel clear
fileviewer <audio/*>
\ vifm-sixel audio %pw %ph %c %pd
\ %pc
\ vifm-sixel clear
fileviewer <font/*>
\ vifm-sixel font %pw %ph %c %pd
\ %pc
\ vifm-sixel clear
" Pdf
filextype *.pdf
\ { view as rich file }

View file

@ -1,12 +0,0 @@
#!/usr/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'ueberzug==18.1.5','console_scripts','ueberzug'
__requires__ = 'ueberzug==18.1.5'
import re
import sys
from pkg_resources import load_entry_point
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(
load_entry_point('ueberzug==18.1.5', 'console_scripts', 'ueberzug')()
)

View file

@ -1,154 +0,0 @@
#!/usr/bin/env bash
readonly ID_PREVIEW="preview"
#PLAY_GIF="yes"
# By enabling this option the GIF will be animated, by leaving it commented like it
# is now will make the gif previews behave the same way as video previews.
#AUTO_REMOVE="yes"
# By enabling this option the script will remove the preview file after it is drawn
# and by doing so the preview will always be up-to-date with the file.
# This however, requires more CPU and therefore affects the overall performance.
# The messy code below is for moving pages in pdf files in the vifm file preview by
# utilizing the < and > keys which will be bound to `vifmimg inc` or `vifmimg dec`.
PDF_PAGE_CONFIG="$HOME/.config/vifm/vifmimgpdfpage"
PDF_FILE_CONFIG="$HOME/.config/vifm/vifmimgpdffile"
PDF_PAGE=1
PDF_FILE=""
# Initialize the variables and required files
[[ -f "$PDF_PAGE_CONFIG" ]] && PDF_PAGE=$(cat $PDF_PAGE_CONFIG) || touch $PDF_PAGE_CONFIG
[[ -f "$PDF_FILE_CONFIG" ]] && PDF_FILE=$(cat $PDF_FILE_CONFIG) || touch $PDF_FILE_CONFIG
# Create temporary working directory if the directory structure doesn't exist
if [[ ! -d "/tmp$PWD/" ]]; then
mkdir -p "/tmp$PWD/"
fi
function inc() {
VAL="$(cat $PDF_PAGE_CONFIG)"
echo "$(expr $VAL + 1)" > $PDF_PAGE_CONFIG
}
function dec() {
VAL="$(cat $PDF_PAGE_CONFIG)"
echo "$(expr $VAL - 1)" > $PDF_PAGE_CONFIG
if [[ $VAL -le 0 ]]; then
echo 0 > $PDF_PAGE_CONFIG
fi
}
function previewclear() {
declare -p -A cmd=([action]=remove [identifier]="$ID_PREVIEW") \
> "$FIFO_UEBERZUG"
}
function fileclean() {
if [[ -f "/tmp$PWD/$6.png" ]]; then
rm -f "/tmp$PWD/$6.png"
elif [[ -d "/tmp$PWD/$6/" ]]; then
rm -rf "/tmp$PWD/$6/"
fi
}
function preview() {
declare -p -A cmd=([action]=add [identifier]="$ID_PREVIEW"
[x]="$2" [y]="$3" [width]="$4" [height]="$5" \
[path]="$PWD/$6") \
> "$FIFO_UEBERZUG"
}
function previewvideo() {
if [[ ! -f "/tmp$PWD/$6.png" ]]; then
ffmpegthumbnailer -i "$PWD/$6" -o "/tmp$PWD/$6.png" -s 0 -q 10
fi
declare -p -A cmd=([action]=add [identifier]="$ID_PREVIEW"
[x]="$2" [y]="$3" [width]="$4" [height]="$5" \
[path]="/tmp$PWD/$6.png") \
> "$FIFO_UEBERZUG"
}
function previewepub() {
if [[ ! -f "/tmp$PWD/$6.png" ]]; then
epub-thumbnailer "$6" "/tmp$PWD/$6.png" 1024
fi
declare -p -A cmd=([action]=add [identifier]="$ID_PREVIEW"
[x]="$2" [y]="$3" [width]="$4" [height]="$5" \
[path]="/tmp$PWD/$6.png") \
> "$FIFO_UEBERZUG"
}
function previewgif() {
if [[ ! -d "/tmp$PWD/$6/" ]]; then
mkdir -p "/tmp$PWD/$6/"
convert -coalesce "$PWD/$6" "/tmp$PWD/$6/$6.png"
fi
if [[ ! -z "$PLAY_GIF" ]]; then
for frame in $(ls -1 /tmp$PWD/$6/$6*.png | sort -V); do
declare -p -A cmd=([action]=add [identifier]="$ID_PREVIEW"
[x]="$2" [y]="$3" [width]="$4" [height]="$5" \
[path]="$frame") \
> "$FIFO_UEBERZUG"
# Sleep between frames to make the animation smooth.
sleep .07
done
else
declare -p -A cmd=([action]=add [identifier]="$ID_PREVIEW"
[x]="$2" [y]="$3" [width]="$4" [height]="$5" \
[path]="/tmp$PWD/$6/$6-0.png") \
> "$FIFO_UEBERZUG"
fi
}
function previewpdf() {
if [[ ! "$6" == "$PDF_FILE" ]]; then
PDF_PAGE=1
echo 1 > $PDF_PAGE_CONFIG
rm -f "/tmp$PWD/$6.png"
fi
if [[ ! "$PDF_PAGE" == "1" ]] && [[ -f "/tmp$PWD/$6.png" ]]; then
rm -f "/tmp$PWD/$6.png"
fi
if [[ ! -f "/tmp$PWD/$6.png" ]]; then
pdftoppm -png -f $PDF_PAGE -singlefile "$6" "/tmp$PWD/$6"
fi
echo "$6" > $PDF_FILE_CONFIG
declare -p -A cmd=([action]=add [identifier]="$ID_PREVIEW"
[x]="$2" [y]="$3" [width]="$4" [height]="$5" \
[path]="/tmp$PWD/$6.png") \
> "$FIFO_UEBERZUG"
}
function previewmagick() {
if [[ ! -f "/tmp$PWD/$6.png" ]]; then
convert -thumbnail $(identify -format "%wx%h" "$6") "$PWD/$6" "/tmp$PWD/$6.png"
fi
declare -p -A cmd=([action]=add [identifier]="$ID_PREVIEW"
[x]="$2" [y]="$3" [width]="$4" [height]="$5" \
[path]="/tmp$PWD/$6.png") \
> "$FIFO_UEBERZUG"
}
function main() {
case "$1" in
"inc") inc "$@" ;;
"dec") dec "$@" ;;
"clear") previewclear "$@" ;;
"clean") fileclean "$@" ;;
"draw") preview "$@" ;;
"videopreview") previewvideo "$@" ;;
"epubpreview") previewepub "$@" ;;
"gifpreview") previewgif "$@" ;;
"pdfpreview") previewpdf "$@" ;;
"magickpreview") previewmagick "$@" ;;
"*") echo "Unknown command: '$@'" ;;
esac
}
main "$@"

View file

@ -1,15 +0,0 @@
#!/usr/bin/env bash
export FIFO_UEBERZUG="/tmp/vifm-ueberzug-${PPID}"
function cleanup {
rm "$FIFO_UEBERZUG" 2>/dev/null
pkill -P $$ 2>/dev/null
}
pkill -P $$ 2>/dev/null
rm "$FIFO_UEBERZUG" 2>/dev/null
mkfifo "$FIFO_UEBERZUG" >/dev/null
trap cleanup EXIT 2>/dev/null
tail --follow "$FIFO_UEBERZUG" | ueberzug layer --silent --parser bash >/dev/null 2>&1 &
vifm "$@"
cleanup

242
wayland/.config/river/init Executable file
View file

@ -0,0 +1,242 @@
#!/usr/bin/env sh
mod="Mod4"
modemod="Mod1"
term=${TERMINAL:-foot}
## OPTIONS
riverctl spawn "dbus-update-activation-environment SEATD_SOCK DISPLAY WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=river"
riverctl focus-follows-cursor normal
riverctl attach-mode bottom
# Set background and border color
riverctl background-color 0x000000
riverctl border-width 1
riverctl border-color-focused 0xffffff
riverctl border-color-unfocused 0x586e75
# Set repeat rate
riverctl set-repeat 75 300
# Make certain views start floating
riverctl float-filter-add app-id float
# riverctl float-filter-add title "popup title with spaces"
# # Set app-ids and titles of views which should use client side decorations
# riverctl csd-filter-add app-id "gedit"
riverctl csd-filter-add app-id "zathura"
## DEBUG
# Reload river configuration
riverctl map normal $mod+Shift F12 spawn "$HOME/.config/river/init"
## HOTKEYS
# close focused view
riverctl map normal $mod+Shift C close
# Open terminal
riverctl map normal $mod Return spawn "$term"
# Open run menu
riverctl map normal $mod Space spawn "bemenu-run"
# Toggle status bar
riverctl map normal $mod F7 spawn "killall -SIGUSR1 waybar"
# Switch to lockscreen
riverctl map normal $mod X spawn "lockscreen"
# Open logout script
riverctl map normal $mod backspace spawn "powermenu"
# Open Bookmark search
riverctl map normal None XF86Search spawn "qutedmenu"
# Open clipboard history
riverctl map normal $mod+Shift Space spawn "clipman pick --tool=bemenu"
# Open floting calculator
riverctl map normal $mod+Shift R spawn "$term --class float -e qalc"
# Desktop theming
# shellcheck disable=SC2016
riverctl map normal $mod F8 spawn 'styler set $(styler list themes | bemenu)'
# Password dropdown frontend
riverctl map normal $mod+Shift P spawn "pass-pick"
# File upload
riverctl map normal $mod+Shift U spawn "$term --class float -e sharefile | xargs notify-send"
# # Screenshot
riverctl map normal None Print spawn "screenshot"
riverctl map normal Shift Print spawn "screenshot | sharefile -"
riverctl map normal $mod Print spawn "screenshot region"
riverctl map normal $mod+Shift Print spawn "screenshot region | sharefile -"
# # Clear clipboard
# riverctl map normal $mod BackSpace spawn 'wl-copy -c && printf ''|xclip -selection c'
# # PixelColor script
# riverctl map normal "Mod1" C spawn 'bash ~/.config/bin/pixelcolor'
# MOVEMENT
# focus the next/previous view in the layout stack
riverctl map normal $mod J focus-view next
riverctl map normal $mod K focus-view previous
# swap the focused view with the next/previous view in the layout stack
riverctl map normal $mod+Shift J swap next
riverctl map normal $mod+Shift K swap previous
# bump the focused view to the top of the layout stack
riverctl map normal $mod+Shift Return zoom
# decrease/increase the main ratio of layout
riverctl map normal $mod+Shift H send-layout-cmd rivercarro "main-ratio -0.05"
riverctl map normal $mod+Shift L send-layout-cmd rivercarro "main-ratio +0.05"
# increment/decrement the main count of layout
riverctl map normal $mod+Control H send-layout-cmd rivercarro "main-count +1"
riverctl map normal $mod+Control L send-layout-cmd rivercarro "main-count -1"
# change layout orientation
riverctl map normal $mod Up send-layout-cmd rivercarro "main-location top"
riverctl map normal $mod Right send-layout-cmd rivercarro "main-location right"
riverctl map normal $mod Down send-layout-cmd rivercarro "main-location bottom"
riverctl map normal $mod Left send-layout-cmd rivercarro "main-location left"
# Mod+F to toggle fullscreen
riverctl map normal $mod F toggle-fullscreen
# toggle float
riverctl map normal $mod+Shift v toggle-float
# Mod + Left Mouse Button to move views
riverctl map-pointer normal $mod BTN_LEFT move-view
# Mod + Right Mouse Button to resize views
riverctl map-pointer normal $mod BTN_RIGHT resize-view
### Begin resize and moving mode, for floating windows
riverctl declare-mode interact_float
riverctl map normal $modemod R enter-mode interact_float
riverctl map interact_float $modemod R enter-mode normal
# resize views on screen
riverctl map interact_float $mod H resize horizontal -100
riverctl map interact_float $mod J resize vertical 100
riverctl map interact_float $mod K resize vertical -100
riverctl map interact_float $mod L resize horizontal 100
# move views around screen
riverctl map interact_float None H move left 100
riverctl map interact_float None J move down 100
riverctl map interact_float None K move up 100
riverctl map interact_float None L move right 100
# snap views to screen edges
riverctl map interact_float $mod+Shift H snap left
riverctl map interact_float $mod+Shift J snap down
riverctl map interact_float $mod+Shift K snap up
riverctl map interact_float $mod+Shift L snap right
### End resize and moving mode
# focus the next/previous output
riverctl map normal $mod Period focus-output next
riverctl map normal $mod Comma focus-output previous
# send the focused view to the next/previous output
riverctl map normal $mod+Shift Period send-to-output next
riverctl map normal $mod+Shift Comma send-to-output previous
# set up 10 tags (with '0' opening the 10th one)
for i in $(seq 0 9); do
tags=$((1 << (i - 1)))
if [ "$i" -eq 0 ]; then tags=$((1 << 9)); fi
# Mod+[1-9] to focus tag [0-8]
riverctl map normal $mod "$i" set-focused-tags $tags
# Mod+Shift+[1-9] to tag focused view with tag [0-8]
riverctl map normal $mod+Shift "$i" set-view-tags $tags
# Mod+Ctrl+[1-9] to toggle focus of tag [0-8]
riverctl map normal $mod+Control "$i" toggle-focused-tags $tags
# Mod+Shift+Ctrl+[1-9] to toggle tag [0-8] of focused view
riverctl map normal $mod+Shift+Control "$i" toggle-view-tags $tags
done
# focus all tags
all_tags=$(((1 << 32) - 1))
riverctl map normal $mod equal set-focused-tags $all_tags
# tag focused view with all tags
riverctl map normal $mod+Shift equal set-view-tags $all_tags
# Various media key mapping examples for both normal and locked mode which do
# not have a modifier
for mode in normal locked; do
# Eject the optical drive
riverctl map $mode None XF86Eject spawn 'eject -T'
riverctl map $mode None XF86AudioRaiseVolume spawn 'pactl set-sink-volume @DEFAULT_SINK@ +5%'
riverctl map $mode None XF86AudioLowerVolume spawn 'pactl set-sink-volume @DEFAULT_SINK@ -5%'
riverctl map $mode None XF86AudioMute spawn 'pactl set-sink-mute @DEFAULT_SINK@ toggle'
# Control MPRIS aware media players with playerctl (https://github.com/altdesktop/playerctl)
riverctl map $mode None XF86AudioMedia spawn 'playerctl play-pause'
riverctl map $mode None XF86AudioPlay spawn 'playerctl play-pause'
riverctl map $mode None XF86AudioPrev spawn 'playerctl previous'
riverctl map $mode None XF86AudioNext spawn 'playerctl next'
# You can control screen backlight brighness with light (https://github.com/haikarainen/light); but we prefer brightnessctl
riverctl map $mode None XF86MonBrightnessUp spawn 'brightnessctl set 10%+'
riverctl map $mode None XF86MonBrightnessDown spawn 'brightnessctl set 10%-'
done
# The scratchpad will live on an unused tag. Which tags are used depends on your
# config, but rivers default uses the first 9 tags.
scratch_tag=$((1 << 20))
# Toggle the scratchpad with Super+P
riverctl map normal $mod grave toggle-focused-tags ${scratch_tag}
# Send windows to the scratchpad with Super+Shift+P
riverctl map normal $mod+Shift grave set-view-tags ${scratch_tag}
# Set spawn tagmask to ensure new windows don't have the scratchpad tag unless
# explicitly set.
all_but_scratch_tag=$((((1 << 32) - 1) ^ scratch_tag))
riverctl spawn-tagmask ${all_but_scratch_tag}
# set up scratch pad for todo and 'drop-down' terminal
# call scratchpads to current workspace -- scratchpads started on i3 starting (see end of file)
# bindsym $mod+t [class="scratchpad" title="dropdown-todo"] scratchpad show
# bindsym $mod+Shift+Return [class="scratchpad" title="dropdown-terminal"] scratchpad show
## INPUT
# device (touchscreen)
# enable touch clicking for touchpads
for pad in $(riverctl list-inputs | grep -i touchpad); do
riverctl input "$pad" events enabled
riverctl input "$pad" tap enabled
done
for pad in $(riverctl list-inputs | grep -i touchscreen); do
riverctl input "$pad" events enabled
riverctl input "$pad" tap enabled
riverctl input "$pad" drag enabled
riverctl input "$pad" pointer-accel 0.5
done
setxkbmap -option "compose:menu"
exec swaybg -i ~/pictures/wall.jpg -o '*' -m fill &
# killall mako
# mako &
killall waybar
exec waybar &
killall clipman
exec wl-paste -t text --watch clipman store &
# bash ~/.config/bin/gtktheme # setting our gtk variables
# killall polkit-gnome-authentication-agent-1
# /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 &
# Set and exec into the default layout generator, rivercarro.
# River will send the process group of the init executable SIGTERM on exit.
riverctl default-layout rivercarro &
# start layouting engine
killall rivercarro
exec rivercarro -main-ratio 0.65 -view-padding 6 -outer-padding 6 &
# brightnessctl set 100%

View file

@ -0,0 +1,3 @@
#!/usr/bin/env sh
export XKB_DEFAULT_OPTIONS='compose:menu'

View file

@ -0,0 +1,170 @@
{
"layer": "top",
"modules-left": ["river/tags"],
"modules-center": ["clock", ],
"modules-right": ["custom/events", "custom/media", "custom/wireguard", "custom/archupdates", "pulseaudio", "backlight", "network", "cpu", "memory", "temperature", "battery", "tray"],
"custom/archupdates": {
"format": "{} {icon}",
"format-alt-click": "right",
"format-icons": {
"default": ""
},
"return-type": "json",
"exec": "~/.config/waybar/modules/archupdates 5 json",
"interval": 3600,
"on-click": "alacritty --class float -e topgrade"
},
"backlight": {
"device": "intel_backlight",
"format": "{percent}% {icon}",
"format-icons": ["滋", "", "", ""],
"on-scroll-up": "brightnessctl set 1%+",
"on-scroll-down": "brightnessctl set 1%-"
},
"battery": {
"format": "{capacity}% {icon}",
"format-alt":"{capacity}% ({time}) {icon}",
"format-alt-click": "click-right",
"format-icons": ["", "", "", "", ""],
"interval": 60,
"states": {
"warning": 30,
"critical": 15
},
},
"clock": {
"format-alt": "{:%a, %d. %b %H:%M}",
"format-alt-click": "click-right",
"on-click": "gsimplecal"
},
"cpu": {
"interval": 10,
"format": "{usage}% ",
"max-length": 10,
"states": {
"warning": 50,
"critical": 80
},
"on-click": "alacritty --class float -e top",
"on-click-right": "alacritty --class float -e glances"
},
"custom/events": {
"format": "{}",
"interval": 300,
"format-icons": {
"default": ""
},
"exec": "~/.config/waybar/modules/khal.py 2>/dev/null",
"exec-if": "command -v khal >/dev/null 2>&1",
"return-type": "json"
},
"memory": {
"interval": 30,
"format": "{avail:0.1f}G ",
"format-alt": "{used:0.1f}G/{total:0.1f}G ",
"format-alt-click": "click-right",
"max-length": 10
},
"mpd": {
"format": "{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}",
"format-disconnected": "ﱙ",
"format-stopped": "",
"interval": 10,
"consume-icons": {
"on": " " // Icon shows only when "consume" is on
},
"random-icons": {
"on": " "
},
"repeat-icons": {
"on": " "
},
"single-icons": {
"on": "1 "
},
"state-icons": {
"paused": "",
"playing": "",
},
"tooltip-format": "{artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) ",
"tooltip-format-disconnected": "MPD (disconnected)"
},
"custom/media": {
"format": "{icon}{}",
"format-alt-click": "right",
"return-type": "json",
"format-icons": {
"Playing": " ",
"Paused": " ",
},
"escape": true,
"max-length":70,
"exec": "playerctl -a metadata --format '{\"text\": \"\", \"tooltip\": \"{{playerName}} : {{markup_escape(title)}}\", \"alt\": \"{{status}}\", \"class\": \"{{status}}\"}' -F",
"exec-if": "command -v playerctl >/dev/null 2>&1",
"on-click": "playerctl play-pause",
"on-click-right": "playerctl stop",
},
"network": {
"interface": "wlp58s0",
"format": "{ifname}",
"format-wifi": "{signalStrength}% ",
"format-ethernet": "{ipaddr}/{cidr} ",
"format-disconnected": "睊",
"tooltip-format": "{ifname} via {gwaddr} ",
"tooltip-format-wifi": "{essid}: {bandwidthDownBits}-{bandwidthUpBits} ({signalStrength}%)  {ifname}",
"tooltip-format-ethernet": "{ifname} ",
"tooltip-format-disconnected": "Disconnected",
"max-length": 50,
"on-click": "alacritty --class float -e nmtui",
// "on-click-right": "sudo rfkill toggle wlan"
},
"pulseaudio": {
"format": "{volume}% {icon}",
"format-bluetooth": "{volume}% {icon}",
"format-muted": "",
"format-icons": {
"headphone": "",
"hands-free": "",
"headset": "",
"phone": "",
"portable": "",
"car": "",
"default": ["", ""]
},
"scroll-step": 1,
"on-click": "alacritty --class float -e pulsemixer",
"on-scroll-up": "pactl set-sink-volume @DEFAULT_SINK@ +1%",
"on-scroll-down": "pactl set-sink-volume @DEFAULT_SINK@ -1%"
},
"river/tags": {
"num-tags": 10,
"tag-labels": [ "", "", "", "", "", "", "", "", "", "" ]
},
"temperature": {
// "thermal-zone": 2,
"hwmon-path": "/sys/class/hwmon/hwmon5/temp1_input",
"critical-threshold": 80,
// "format-critical": "{temperatureC}° ",
"format": "{temperatureC}° ",
"on-click": "alacritty --class float -e watch sensors"
},
"tray": {
"icon-size": 21,
"spacing": 10
},
"custom/weather": {
"exec": "curl 'https://wttr.in/?format=%t'",
"exec-if": "command -v curl >/dev/null 2>&1",
"interval": 3600
},
"custom/wireguard": {
"format-icons": {
"default": "嬨"
},
"exec": "~/.config/waybar/modules/wireguard json",
"exec-if": "command -v nmcli >/dev/null 2>&1",
"return-type": "json",
"signal": 6,
"interval": 60,
}
}

View file

@ -1,15 +1,22 @@
#!/bin/sh
#
# check for available archupdates and return their number
# checks both repositories and aur
# Check for available archupdates and return their number.
# Checks both repositories and aur,
# returns empty string when 0 packages are available, so
# that polybar simply displays nothing.
# Can be used to generate json-like output for waybar.
#
# dependendies: yay, (pacman-contrib optional)
# dependencies: yay, (pacman-contrib optional)
# optional: jq
#
# Takes 2 arguments:
# Takes an optional integer argument, which is the minimum
# numer of package updates for an answer to be returned.
min_upd=${1:-0}
# Takes as second optional argument the output format
# Valid value is "json", everything else returns plain-text.
# json output requires jq.
format=${2:-plain}
# prefer checkupdates since it allows checking w/o partial upgrade
if command -v "checkupdates" >/dev/null; then
@ -30,6 +37,20 @@ updates_aur="$(yay -Qum 2>/dev/null | wc -l)"
# updates_aur=$(rua upgrade --printonly 2> /dev/null | wc -l)
updates=$((updates_repo + updates_aur))
text="${updates}"
alt="${updates_repo}|${updates_aur}"
tooltip="Repositories: ${updates_repo} | AUR: ${updates_aur}"
[ "$updates" -gt "$min_upd" ] && class="available" || class="empty"
if [ "$format" = "json" ]; then
printf "{\"text\": \"%s\", \"alt\": \"%s\", \"tooltip\": \"%s\", \"class\": \"%s\"}" \
"$text" \
"$alt" \
"$tooltip" \
"$class"
exit
fi
if [ "$updates" -gt "$min_upd" ]; then
echo "$updates"
else

View file

@ -0,0 +1,35 @@
#!/usr/bin/env python
# from https://gist.github.com/bjesus/178a9bd3453470d74803945dbbf9ed40
# List upcoming khal events in simple json container fit for waybar
import subprocess
import datetime
import json
from html import escape
data = {}
today = datetime.date.today().strftime("%Y-%m-%d")
next_week = (datetime.date.today() + datetime.timedelta(days=10)).strftime("%Y-%m-%d")
output = subprocess.check_output("khal list now " + next_week, shell=True)
output = output.decode("utf-8")
lines = output.split("\n")
new_lines = []
for line in lines:
clean_line = escape(line).split(" ::")[0]
if len(clean_line) and not clean_line[0] in ["0", "1", "2"]:
clean_line = "\n<b>" + clean_line + "</b>"
new_lines.append(clean_line)
output = "\n".join(new_lines).strip()
if today in output:
data["text"] = "" + output.split("\n")[1]
else:
data["text"] = ""
data["tooltip"] = output
print(json.dumps(data))

View file

@ -0,0 +1,143 @@
#!/usr/bin/env bash
# nmcli WireGuard abstraction layer for use with my waybar module and rofi custom menu script
#
# requires nmcli on your path
# install to the same directory as wireguard-rofi.sh
#
# usage: ./wireguard.sh [menu|toggle NAME]
# no argument: print current connections
# json: print waybar-ready json output
# menu: print all connections
# toggle NAME: toggle connection NAME
if ! command -v nmcli >/dev/null 2>&1; then
echo "err: nmcli not found"
exit 1
fi
nargs=$#
showmenu="no"
dotoggle="no"
printjson="no"
if [[ $nargs == 1 ]]; then
if [[ $1 == "menu" ]]; then
showmenu="yes"
elif [[ $1 == "json" ]]; then
printjson="yes"
fi
elif [[ $nargs == 2 ]]; then
if [[ $1 == "toggle" ]]; then
dotoggle="yes"
conn="$2"
fi
fi
nmclicmd="nmcli connection"
wgconns="$nmclicmd show"
wgactive="$wgconns --active"
connected=()
available=()
function print_as_json() {
text="嬨" # only prints a single icon when connected
# text="${1}" # use this line to show all output in text
alt="${1}"
tooltip="${1}"
[ -n "$1" ] && class="connected" || class="disconnected"
printf "{\"text\": \"%s\", \"alt\": \"%s\", \"tooltip\": \"%s\", \"class\": \"%s\"}" \
"$text" \
"$alt" \
"$tooltip" \
"$class"
}
function get_conns {
while read -r name _ type device; do
if [[ $type != "wireguard" && ($type != "tun" || $device != "proton0") ]]; then
continue
fi
if [[ $device != "--" ]]; then
while read -r key value; do
if [[ $key != "ipv4.addresses:" ]]; then
continue
fi
connected+=("$name: $value")
done < <($wgconns "$name")
else
available+=("$name")
fi
done < <($1)
}
function print_conns {
local first="yes"
local array_print="$1[@]"
local array_print=("${!array_print}")
if [[ $2 == "list" ]]; then
for c in "${array_print[@]}"; do
output="$1: $c"
done
else
output=""
for c in "${array_print[@]}"; do
if [[ "$first" != "yes" ]]; then
output+=" | "
fi
output+="$c"
first="no"
done
fi
if [[ "$printjson" == "yes" ]]; then
print_as_json "$output"
else
echo "$output"
fi
}
function array_contains {
local array_has="$1[@]"
local array_has=("${!array_has}")
local element="$2"
for e in "${array_has[@]}"; do
if [[ "$e" == *"$element"* ]]; then
echo "yes"
return
fi
done
echo "no"
}
if [[ $nargs == 0 ]]; then
get_conns "$wgactive"
print_conns connected
elif [[ $showmenu == "yes" ]]; then
get_conns "$wgconns"
print_conns connected "list"
print_conns available "list"
elif [[ $printjson == "yes" ]]; then
get_conns "$wgactive"
print_conns connected
elif
[[ $dotoggle == "yes" ]]
then
get_conns "$wgconns"
if [[ "$(array_contains connected "$conn")" == "yes" ]]; then
$nmclicmd down "$conn"
elif [[ "$(array_contains available "$conn")" == "yes" ]]; then
$nmclicmd up "$conn"
else
echo "err: connection not found"
exit 1
fi
else
echo "err: wrong args"
exit 1
fi

View file

@ -0,0 +1,152 @@
/* @import "colorscheme.css"; */
* {
border: none;
border-radius: 0;
min-height: 0;
}
window#waybar {
font-size: 15px;
color: #d5c4a1;
background-color: #32302f;
border-bottom: 1px solid #3c3836;
transition-property: background-color;
transition-duration: .5s;
}
window#waybar.hidden {
opacity: 0.2;
}
#tags button {
font-size:17px;
font-weight:900;
background-color: transparent;
color: #665c54;
margin: 0px;
padding: 0px 5px;
/* Use box-shadow instead of border so the text isn't offset */
}
/* /1* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect *1/ */
#tags button:hover {
background: rgba(0, 0, 0, 0.2);
/* box-shadow: inset 0 -1px #d5c4a1; */
box-shadow: inset 0 0;
}
#tags button.occupied {
font-weight: 400;
color: #d5c4a1;
}
#tags button.focused {
font-weight: 400;
color: #83a598;
}
#tags button.urgent {
color: #8ec07c;
}
#clock,
#battery,
#cpu,
#memory,
#disk,
#temperature,
#backlight,
#network,
#pulseaudio,
#tray,
#mode,
#idle_inhibitor,
#mpd,
#custom-archupdates,
#custom-wireguard,
#custom-events,
#custom-media {
padding: 0 10px;
margin: 0 5px;
color: #d5c4a1;
background-color: #3c3836;
}
/* If workspaces is the leftmost module, omit left margin */
.modules-left > widget:first-child > #tags {
margin-left: 0;
}
/* If workspaces is the rightmost module, omit right margin */
.modules-right > widget:last-child > #tags {
margin-right: 0;
}
#battery.charging, #battery.plugged {
background-color: #504945;
}
#battery.warning {
background-color: #fe8019;
color: #32302f;
}
@keyframes blink {
to {
background-color: #fb4934;
color: #32302f;
}
}
#battery.critical:not(.charging) {
color: #d5c4a1;
background-color: #32302f;
animation-name: blink;
animation-duration: 0.5s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#cpu.warning {
color: #32302f;
background-color: #fabd2f;
}
#cpu.critical {
color: #d5c4a1;
background-color: #fb4934;
}
#custom-archupdates.empty {
background-color: transparent;
color: transparent;
font-size: 0;
margin: 0;
padding: 0;
}
#custom-wireguard.disconnected {
background-color: transparent;
color: transparent;
font-size: 0;
margin: 0;
padding: 0;
}
#temperature.critical {
background-color: #fb4934;
}
#tray > .passive {
-gtk-icon-effect: dim;
}
#tray > .needs-attention {
-gtk-icon-effect: highlight;
}
#mpd.disconnected {
background-color: transparent;
color: transparent;
font-size: 0;
margin: 0;
padding: 0;
}

48
wayland/.local/bin/screenshot Executable file
View file

@ -0,0 +1,48 @@
#!/usr/bin/env sh
# Take a screenshot on wayland
# By default takes a screenshot of the whole desktop
# If 'region' or 'area' command is passed in will allow selecting a region to screenshot.
# Example: `screenshot region`
TIME="$(date +%Y-%m-%d-%H-%M-%S)"
readonly TIME
readonly TMPSCREENSHOTDIR="$HOME/.cache/screenshot"
readonly TMPIMGPATH="$TMPSCREENSHOTDIR/img-$TIME.png"
FULLSCREEN=true
if [ "$1" = "area" ] || [ "$1" = "region" ]; then
FULLSCREEN=false
fi
main() {
prepare_cache
take_screenshot "$FULLSCREEN"
if [ -n "$SCREENSHOT_POSTPROCESS" ]; then
eval "$SCREENSHOT_POSTPROCESS"
else
postprocess
fi
}
prepare_cache() {
if [ ! -d "$TMPSCREENSHOTDIR" ]; then
mkdir -p "$TMPSCREENSHOTDIR"
fi
}
take_screenshot() {
if $1; then
grim "$TMPIMGPATH"
else
grim -g "$(slurp)" "$TMPIMGPATH"
fi
}
postprocess() {
notify-send -i "$TMPIMGPATH" "Screenshot taken" "$TMPIMGPATH"
echo "$TMPIMGPATH" | wl-copy
echo "$TMPIMGPATH"
}
main "$@"

110
wayland/README.md Normal file
View file

@ -0,0 +1,110 @@
# wayland
Contains:
[riverwm](https://github.com/riverwm/river)
[waybar](https://github.com/Alexays/Waybar)
My first foray into wayland is based on river,
a tiling window manager somewhat based on bspwm.
This is only a very work-in-progress README file.
Since wayland handles key presses and so on completely differently
from X,
I can't for example use sxhkd which is a shame.
## Missing
not set up:
* [x] lockscreen
* [x] power menu -- rofi on X
* [x] extensive run menu (clipboard, open windows) -- rofi on X
* [x] clipboard manager
* [x] pass frontend dropdown -- clipboard and xdotool
* [ ] investigate [wtype](https://github.com/atx/wtype) over ydotool
* [x] file uploading (works but without url clipboard)
* [x] open_download (qutebrowser script)
* [x] gap regulation
* [x] brightnessctl
* [x] waybar and various status modules
* [ ] include waybar in styler settings
* [x] pacman new packages in status
* [x] personal keyboard layout (ae, oe, ue, ..)
* [x] styler
* still works as before, only less programs respect xresources settings
* works even for foot, if I want to switch to it
* [ ] need to set it up for waybar
* [ ] dropdown terminal and dropdown todo
* [ ] rofimoji emoji dropdown -- clipboard
* [ ] show current mode
* [-] hide cursor
* [-] dropdown calculator -- rofi on X -- could use `qalc` directly
* [-] modes: media, academia (worth?)
* [-] picture in terminal, a-la ueberzug
* ueberzug is X only
* there is sixel rendering for foot, st, xterm, urxvt
* alacritty does *not* support sixel rendering [yet](https://github.com/alacritty/alacritty/issues/910), see also [existing sixel implementation](https://github.com/betaboon/alacritty/tree/graphics).
* We have sixel support enabled in vifm and foot. It is very wonky, however.
### undecided
* [ ] polybar -> waybar / yambar
* [ ] foot / alacritty
## River
River is set up to come close to my old i3 setup.
Of course, some mappings are different
(especially those for movement between windows),
but overall the keys map to the old ones.
Since the window manager now also takes over the task of compositor
and does not pass through all keys to all programs,
it takes over the role of `sxhkd` as well and summons other programs.
I am not entirely sure how I feel about this bundling of tasks into one application,
but so far it works.
Since river is also, mimicking bspwm, using an executable file
(any executable file)
as its configuration file it is also reasonable that the setup can be tamed and refactored better than a single i3 configuration file.
## Waybar
Waybar replaces the old [polybar](https://gitlab.com/marty-oehme/dotfiles/-/tree/89d1402b3e711c4aa473386e47e84f3593e5ae56/polybar) setup.
It displays the first 10 tags on its left,
with tags highlighted that are either occupied by windows or currently in focus.
In the center it displays a clock which can be clicked to open a simple calendar.
![Simple waybar configuration](.assets/waybar/simple.png)
To the right is where most of the info modules are:
If there are upcoming events listed for the khal application, it will display a calendar module here.
If music is playing through an mpris-compatible player, its status is shown here.
If a connection through wireguard or over a vpn tunnel is established, it is shown here.
Then, from left to right, audio, brightness, wifi, cpu, ram, temperature, and battery information are displayed.
Some displays have alternative display states, with for example the battery showing remaining time and ram information showing used and total available.
Clicking on:
* audio opens pulsemixer
* network opens nmtui
* cpu opens top (or glances on right-click)
* temperature shows sensors
## keyd
keyd is set up within `/etc/` and not in the dotfiles themselves.
If using the included `./install.sh` file, there is an option to also set up files outside the home directory, including keyd options.
It is configured through `/etc/keyd/default.cfg`.
Currently, it takes care of mapping `capslock` to both control and escape (depending on if its used alone or with other keys),
as well as adding some German characters that I am otherwise missing on my en_US keyboard.
Lastly, it allows easy clipboard pasting with the `insert` key.
## Swaybg
`swaybg` is used to set the wallpaper from the river configuration file.