1
0
mirror of https://github.com/alrayyes/dotfiles/ synced 2023-11-14 15:56:30 +00:00

Fix merge

This commit is contained in:
Ryan Kes 2019-12-10 16:19:43 +01:00
commit d6e16ee827
31 changed files with 1542 additions and 484 deletions

1
.gitignore vendored
View File

@ -24,3 +24,4 @@ mutt/.config/mutt/.mailsynclastrun
gtk/.config/gtk-3.0/bookmarks gtk/.config/gtk-3.0/bookmarks
mpd/.config/mpd/pid mpd/.config/mpd/pid
/emacs/.config/doom/configuration.el

View File

@ -1,5 +1,4 @@
The MIT License (MIT) * The MIT License (MIT)
=====================
Copyright (c) `2016` `Ryan Kes` Copyright (c) `2016` `Ryan Kes`

View File

@ -1,57 +0,0 @@
# Dotfiles
A repository of my personal configuration files.
# Requirements
[stow](http://www.gnu.org/software/stow/)
# Installation
```shell
./install.sh
```
# Find & delete orphaned symlinks
```shell
./clean-dead-symlinks
```
# Packages configured
* [dunst](https://dunst-project.org/)
* [firejail](https://firejail.wordpress.com/)
* [git](https://git-scm.com/)
* [gnupg](https://gnupg.org/)
* [gtk](https://www.gtk.org/)
* [lf](https://github.com/gokcehan/lf)
* [mpd](https://www.musicpd.org/)
* [neomutt](https://neomutt.org/)
* [neovim](https://neovim.io/)
* [redshift](http://jonls.dk/redshift/)
* [sxhkd](https://github.com/baskerville/sxhkd)
* [spacemacs](http://spacemacs.org/)
* [tmux](https://tmux.github.io/)
* [vifm](https://vifm.info/)
* [xcompmgr](https://github.com/freedesktop/xcompmgr)
* [xwallpaper](https://github.com/stoeckmann/xwallpaper)
* [weechat](https://weechat.org/)
* [zsh](https://www.zsh.org/)
* [spaceship zsh theme](https://github.com/denysdovhan/spaceship-prompt)
# Custom packages configured
These are custom packages I use (mostly [suckless](https://suckless.org/)).
* [dwm](https://github.com/alrayyes/dwm)
* [slstatus](https://github.com/alrayyes/slstatus)
# Caveats
rcirc doesn't work peroperly with znc
# License
This theme is released under the MIT License. For more information read the [license][license].
[license]: LICENSE.md

37
README.org Normal file
View File

@ -0,0 +1,37 @@
* Dotfiles
A repository of my personal configuration files.
** Requirements
- [[http://www.gnu.org/software/stow/][stow]]
** Installation
#+BEGIN_SRC shell
./install.sh
#+END_SRC
** Find & delete orphaned symlinks
#+BEGIN_SRC shell
./clean-dead-symlinks
#+END_SRC
** Configured Packages
- [[https://github.com/baskerville/bspwm][bspwm]]
- [[https://dunst-project.org/][dunst]]
- [[https://firejail.wordpress.com/][firejail]]
- [[https://git-scm.com/][git]]
- [[https://gnupg.org/][gnupg]]
- [[https://www.gtk.org/][gtk]]
- [[https://github.com/gokcehan/lf][lf]]
- [[https://www.musicpd.org/][mpd]]
- [[https://neomutt.org/][neomutt]]
- [[https://neovim.io/][neovim]]
- [[http://jonls.dk/redshift/][redshift]]
- [[https://github.com/baskerville/sxhkd][sxhkd]]
- [[https://github.com/hlissner/doom-emacs][Doom Emacs]]
- [[https://tmux.github.io/][tmux]]
- [[https://vifm.info/][vifm]]
- [[https://github.com/freedesktop/xcompmgr][xcompmgr]]
- [[https://github.com/stoeckmann/xwallpaper][xwallpaper]]
- [[https://weechat.org/][weechat]]
- [[https://www.zsh.org/][zsh]]
- [[https://github.com/denysdovhan/spaceship-prompt][spaceship zsh
theme]]
** Custom packages
- [[https://github.com/alrayyes/st][st]]

78
bspwm/.config/bspwm/bspwmrc Executable file
View File

@ -0,0 +1,78 @@
#! /bin/sh
sxhkd &
# Set screen orientation if second monitor is connected
SCREENCOUNT=$(xrandr | grep -c "\*")
# If multi screen add special mode for monitor so it supports 1440p over HDMI
if [ "$SCREENCOUNT" -eq 2 ]; then
if [ -f "$HOME/.local/bin/screen_desktop" ]; then
screen_desktop
# Make sure mouse is on main screen so windows are launched there
# xdotool mousemove 3360 1080
bspc monitor DP-1 -d 2 3 4 5 6 7 8 9 10
bspc monitor HDMI-2 -d 1
fi
if [ -f "$HOME/.local/bin/polybar-desktop" ]; then
polybar-desktop
fi
else
if [ -f "$HOME/.local/bin/screen" ]; then
screen
fi
if [ -f "$HOME/.local/bin/polybar-laptop" ]; then
bspc monitor -d 1 2 3 4 5 6 7 8 9 0
polybar-laptop
fi
fi
# lock screen after x minutes and on laptop close lid
xautolock -time 10 -locker ~/.local/bin/lock &
xss-lock -- ~/.local/bin/lock &
xcompmgr &
if [ -e ~/.cache/wall1.png ] && [ -e ~/.cache/wall2.png ]; then
xwallpaper --output HDMI-2 --zoom ~/.cache/wall2.png --output DP-1 --zoom ~/.cache/wall1.png &
elif [ -e ~/.cache/wall1.png ]; then
xwallpaper --output eDP1 --zoom ~/.cache/wall1.png &
fi
# switch off microphones
amixer -c 2 set Mic nocap
amixer -c 3 set Mic nocap
unclutter &
dunst &
slstatus &
redshift-gtk &
nm-applet &
syncthing-gtk &
gpodder &
spotify &
if [ -e /usr/bin/firefox ]; then
firefox &
elif [ -e /usr/bin/iceweasel ]; then
iceweasel &
fi
bspc config border_width 2
bspc config window_gap 12
bspc config split_ratio 0.52
bspc config borderless_monocle true
bspc config gapless_monocle true
bspc rule -a "Syncthing GTK" state=floating
bspc rule -a Gimp state=floating
bspc rule -a Gpodder desktop='^4'
bspc rule -a Spotify desktop='^4'
bspc rule -a Slack desktop='^4'
bspc rule -a Emacs state=tiled
bspc rule -a iceweasel desktop='^9'
bspc rule -a Firefox desktop='^9'
bspc rule -a scratchpad sticky=on state=floating
bspc rule -a scratchmacs sticky=on state=floating

2
bspwm/.local/bin/scratch Executable file
View File

@ -0,0 +1,2 @@
#!/usr/bin/sh
st -c scratchpad

View File

@ -11,4 +11,4 @@ export _JAVA_AWT_WM_NONREPARENTING=1
export AWT_TOOLKIT=MToolkit export AWT_TOOLKIT=MToolkit
wmname LG3D wmname LG3D
exec dwm exec bspwm

View File

@ -1,61 +0,0 @@
#!/bin/sh
# Set working directory to home
cd ~
# Set screen orientation if second monitor is connected
SCREENCOUNT=$(xrandr | grep -c "\*")
# If multi screen add special mode for monitor so it supports 1440p over HDMI
if [ "$SCREENCOUNT" -eq 2 ]
then
if [ -f "$HOME/.local/bin/screen_desktop" ]
then
screen_desktop
# Make sure mouse is on main screen so windows are launched there
xdotool mousemove 3360 1080
fi
else
if [ -f "$HOME/.local/bin/screen" ]
then
screen
fi
fi
# lock screen after x minutes and on laptop close lid
xautolock -time 10 -locker ~/.local/bin/lock &
xss-lock -- ~/.local/bin/lock &
xcompmgr &
sxhkd &
if [ -e ~/.cache/wall1.png ] && [ -e ~/.cache/wall2.png ]
then
xwallpaper --output HDMI-2 --zoom ~/.cache/wall2.png --output DP-1 --zoom ~/.cache/wall1.png &
elif [ -e ~/.cache/wall1.png ]
then
xwallpaper --output eDP1 --zoom ~/.cache/wall1.png &
fi
# switch off microphones
amixer -c 2 set Mic nocap
amixer -c 3 set Mic nocap
unclutter &
dunst &
slstatus &
redshift-gtk &
nm-applet &
syncthing-gtk &
gpodder &
exec st -c tmux -e tmux &
exec spotify &
if [ -e /usr/bin/firefox ]
then
exec firefox &
elif [ -e /usr/bin/iceweasel ]
then
exec iceweasel &
fi

View File

@ -1,56 +1,5 @@
;;; .doom.d/config.el -*- lexical-binding: t; -*- ;;; .doom.d/config.el -*- lexical-binding: t; -*-
;; Place your private configuration here ;; Place your private configuration here
;; General settings
(setq doom-font (font-spec :family "FuraCode Nerd Font Mono" :size 12)
doom-theme 'doom-molokai)
;; projectile (org-babel-load-file "~/.config/doom/configuration.org")
(use-package! projectile
:config
(setq projectile-project-search-path '("~/devel/personal/" "~/devel/andthensome/" "~/Documents/")))
;; irc
(use-package! circe
:config
(setq circe-network-options
`(
("znc-freenode"
:host "irc.higherlearning.eu"
:port "5000"
:tls t
:user "l0rd/freenode"
:server-buffer-name "⇄ Freenode (ZNC)"
:pass (lambda (&rest _) (+pass-get-secret "controlpanel/irc.higherlearning.eu"))
:channels ("#emacs"))
("znc-snoonet"
:host "irc.higherlearning.eu"
:port "5000"
:tls t
:user "l0rd/snoonet"
:server-buffer-name "⇄ Snoonet (ZNC)"
:pass (lambda (&rest _) (+pass-get-secret "controlpanel/irc.higherlearning.eu"))
:channels ("#islam"))
))
:hook (circe-channel-mode . enable-lui-autopaste)
)
;; notmuch
(use-package! notmuch
:config
(setq +notmuch-sync-backend 'mbsync
+notmuch-sync-command "mailsync"
sendmail-program "/usr/bin/msmtp"
message-sendmail-f-is-evil t
message-sendmail-extra-arguments '("--read-envelope-from")
message-send-mail-function 'message-send-mail-with-sendmail)
)
;; org
(after! org
(map! :map org-mode-map
:n "M-j" #'org-metadown
:n "M-k" #'org-metaup)
)
(setq org-directory "~/Documents/org/"
org-log-done 'note)

View File

@ -0,0 +1,87 @@
* General settings
Set fonts to a [[https://www.nerdfonts.com/][Nerd Fonts]] patched version of [[https://github.com/tonsky/FiraCode][Fira Code]]. Theme is set to
doom-molokai from [[https://github.com/hlissner/emacs-doom-themes][doom-themes]]
[[https://raw.githubusercontent.com/hlissner/emacs-doom-themes/screenshots/doom-molokai.png][doom-molokai screenshot]]
#+BEGIN_SRC emacs-lisp
(setq doom-font (font-spec :family "FuraCode Nerd Font Mono" :size 12) ; Set font
doom-theme 'doom-molokai) ; Set theme
#+END_SRC
* [[https://www.projectile.mx/en/latest/][Projectile]]
Set default paths [[https://www.projectile.mx/en/latest/][projectile]] should search
#+BEGIN_SRC emacs-lisp
(use-package! projectile
:config
(setq projectile-project-search-path '("~/devel/personal/" "~/devel/andthensome/" "~/Documents/"))) ; Default paths
#+END_SRC
* [[https://github.com/jorgenschaefer/circe][Circe]]
Connect to [[https://wiki.znc.in/ZNC][ZNC]]. Passwords are gotten from [[https://www.passwordstore.org/][Password Store]].
#+BEGIN_SRC emacs-lisp
(use-package! circe
:config
(setq circe-network-options
`(
("znc-freenode"
:host "irc.higherlearning.eu"
:port "5000"
:tls t ;; Enable tls
:user "l0rd/freenode"
:server-buffer-name "⇄ Freenode (ZNC)"
:pass (lambda (&rest _) (+pass-get-secret "controlpanel/irc.higherlearning.eu")) ;; Get password from pass
:channels ("#emacs"))
("znc-snoonet"
:host "irc.higherlearning.eu"
:port "5000"
:tls t
:user "l0rd/snoonet"
:server-buffer-name "⇄ Snoonet (ZNC)"
:pass (lambda (&rest _) (+pass-get-secret "controlpanel/irc.higherlearning.eu"))
:channels ("#islam"))
))
:hook (circe-channel-mode . enable-lui-autopaste)
)
#+END_SRC
* [[https://notmuchmail.org/notmuch-emacs/][Notmuch Emacs]]
Play nice with [[https://marlam.de/msmtp/][msmtp]] and fetch mail via custom [[https://github.com/alrayyes/dotfiles/blob/master/mutt/.local/bin/mailsync][mailsync]] shell script.
#+BEGIN_SRC emacs-lisp
(use-package! notmuch
:config
(setq +notmuch-sync-backend nil ; Needed to make sure notmuch-sync-command below is run when notmmuch is loaded
+notmuch-sync-command "mailsync" ; Command to fetch email
sendmail-program "/usr/bin/msmtp" ; Use msmtp to send mail
message-sendmail-f-is-evil t; Non-nil means don't add "-f username" to the sendmail command line.
message-sendmail-extra-arguments '("--read-envelope-from") ; Additional arguments to sendmail-program.
message-send-mail-function 'message-send-mail-with-sendmail) ; Function to call to send the current buffer as mail.
)
#+END_SRC
* [[https://orgmode.org/][Org mode]]
When moving entries up and down in the buffer use `j` and `k` instead of `↑` and `↓`
#+BEGIN_SRC emacs-lisp
(after! org
(map! :map org-mode-map
:n "M-j" #'org-metadown
:n "M-k" #'org-metaup)
)
#+END_SRC
- Set default org directory
- When task is set to `DONE` [[https://orgmode.org/manual/Closing-items.html][add timestamp and give the opportunity to type in a note]]
- Show images in buffers as default
#+BEGIN_SRC emacs-lisp
(setq org-directory "~/Documents/org"
org-agenda-files '("~/Documents/org")
org-log-done 'note
org-startup-with-inline-images t)
#+END_SRC
* Spotify
Control Spotify with [[https://github.com/Lautaro-Garcia/counsel-spotify][Counsel Spotify]]
#+BEGIN_SRC emacs-lisp
(setq counsel-spotify-client-id "03f9817b1b6946febf9a0573d28e3831"
counsel-spotify-client-secret "d03c172f1497466a953026f001f1daeb")
#+END_SRC

View File

@ -5,3 +5,4 @@
;; (package! some-package) ;; (package! some-package)
;; (package! another-package :recipe (:host github :repo "username/repo")) ;; (package! another-package :recipe (:host github :repo "username/repo"))
;; (package! builtin-package :disable t) ;; (package! builtin-package :disable t)
(package! counsel-spotify)

View File

@ -0,0 +1,13 @@
# Script: isactive-bluetooth
A script that shows if bluetooth is on or off.
## Module
```ini
[module/isactive-bluetooth]
type = custom/script
exec = ~/polybar-scripts/isactive-bluetooth.sh
interval = 10
```

View File

@ -0,0 +1,7 @@
#!/bin/sh
if [ "$(systemctl is-active bluetooth.service)" = "active" ]; then
echo ""
else
echo ""
fi

View File

@ -0,0 +1,164 @@
# Script: player-mpris-tail
This script displays the current track and the play-pause status without polling. Information is obtained by listening to MPRIS events, so it is updated instantaneously on change.
![player-mpris-tail](screenshots/1.png) ![player-mpris-tail](screenshots/2.png)
## Dependencies
* `python-dbus`
* `python-gobject`
* `python-gi`
## Configuration
The format of the output can be defined by passing an `-f` or `--format` argument. This argument supports metadata replacement using `{tag}` (e.g. `{title}`) as well as more advanced formatting, described below.
Players can be blacklisted by passing a `-b` or `--blacklist` argument. As an example, VLC can be blacklisted by passing `-b vlc`. To get a list of the current running players (and their status), run the script as `player-mpris-tail.py list`.
### Commands
The current player can be controlled by passing one of the following commands:
Command | Description
---|---
play | Play the current track
pause | Pause the currently playing track
play-pause | Play the current track or unpause it if currently paused
stop | Stop playback
previous | Move to the previous track
next | Move to the next track
raise | Tell the current player to focus its window
General information about the current state can be printed using the following commands:
Command | Description
---|---
status | Print the normal output and exit immediately
current | Print the currently detected player and its status
list | List the detected players and their status
metadata | Print the metadata object for the current track
### Arguments
The following arguments are supported:
Argument | Description | Default
---|---|---
-b, --blacklist | Blacklist / Ignore the given player
-f, --format | Use the given `format` string | `{icon} {artist} - {title}`
--truncate-text | Use the given string as the end of truncated text | `…`
--icon-playing | Use the given text as the playing icon | `⏵`
--icon-paused | Use the given text as the paused icon | `⏸`
--icon-stopped | Use the given text as the stopped icon | `⏹`
--icon-none | Use the given text as the icon for when no player is active | ``
### Formatting
Tags can be printed by surrounding them with `{` and `}`. Polybar formatting can also be given and will be passed through, including substituted tags and formatters.
### Tags
The supported tags are:
Tag | Description
---|---
artist | The artist of the current track
album | The album of the current track
title | The title of the current track
track | The track number of the current track
length | The length of the current track
genre | The genre of the current track
disc | The disc number of the current track
date | The date of the current track
year | The year of the current track
cover | The URL of the cover of the current track
icon | The icon for the current status (playing / paused / stopped / none)
icon-reversed | The pause icon when playing, else the play icon
### String formatters
Parts of the `format` string can be manipulated by surrounding them with `{:` and `:}` and prepending a formatter followed by a `:` (e.g. `{:t20:by {artist}:}`)
The following formatters are supported:
Formatter | Argument | Description | Example | Output
---|---|---|---|---
`tag` | | Only print the string if `tag` exists | `{:album: on {album}:}` | ` on Album Name`
w | Number | Limit the width of the string to `number` | `{:w3:Hello:}` | `Hel`
t | Number | Truncate width of the string to `number`. If the string is shorter than or equal to `number` it is printed as given, else the string is truncated and appended a truncator text | `{:t3:Hello:}` | `He…`
## Module
### Basic output
```ini
[module/player-mpris-tail]
type = custom/script
exec = ~/polybar-scripts/player-mpris-tail.py -f '{icon} {artist} - {title}'
tail = true
```
Example: `⏵ Artist - Title`
### Basic output and mouse controls
```ini
[module/player-mpris-tail]
type = custom/script
exec = ~/polybar-scripts/player-mpris-tail.py -f '{icon} {artist} - {title}'
tail = true
click-left = ~/polybar-scripts/player-mpris-tail.py previous &
click-right = ~/polybar-scripts/player-mpris-tail.py next &
click-middle = ~/polybar-scripts/player-mpris-tail.py play-pause &
```
Example: `⏵ Artist - Title`
### Output using formatters
```ini
[module/player-mpris-tail]
type = custom/script
exec = ~/polybar-scripts/player-mpris-tail.py -f '{icon} {:artist:t5:{artist}:}{:artist: - :}{:t4:{title}:}'
tail = true
click-left = ~/polybar-scripts/player-mpris-tail.py previous &
click-right = ~/polybar-scripts/player-mpris-tail.py next &
click-middle = ~/polybar-scripts/player-mpris-tail.py play-pause &
```
Example: `⏵ Artis… - Titl…` or `⏵ Titl…`
### Output using formatters and Polybar action handlers
```ini
[module/player-mpris-tail]
type = custom/script
exec = ~/polybar-scripts/player-mpris-tail.py -f '{icon} {:artist:t18:{artist}:}{:artist: - :}{:t20:{title}:} %{A1:~/polybar-scripts/player-mpris-tail.py previous:} ⏮ %{A} %{A1:~/polybar-scripts/player-mpris-tail.py play-pause:} {icon-reversed} %{A} %{A1:~/polybar-scripts/player-mpris-tail.py next:} ⏭ %{A}'
tail = true
```
Example: `⏵ Artis… - Titl… ⏮ ⏸ ⏭ ` or `⏵ Titl… ⏮ ⏸ ⏭ ` or `⏸ Titl… ⏮ ⏵ ⏭ `
### Output using formatters, Polybar action handlers and blacklisting
```ini
[module/player-mpris-tail]
type = custom/script
exec = ~/polybar-scripts/player-mpris-tail.py -f '{icon} {:artist:t18:{artist}:}{:artist: - :}{:t20:{title}:} %{A1:~/polybar-scripts/player-mpris-tail.py previous -b vlc -b plasma-browser-integration:} ⏮ %{A} %{A1:~/polybar-scripts/player-mpris-tail.py play-pause -b vlc -b plasma-browser-integration:} {icon-reversed} %{A} %{A1:~/polybar-scripts/player-mpris-tail.py next -b vlc -b plasma-browser-integration:} ⏭ %{A}' -b vlc -b plasma-browser-integration
tail = true
```
Example: `⏵ Artis… - Titl… ⏮ ⏸ ⏭ ` or `⏵ Titl… ⏮ ⏸ ⏭ ` or `⏸ Titl… ⏮ ⏵ ⏭ `

View File

@ -0,0 +1,532 @@
#!/usr/bin/env python3
import sys
import dbus
import os
from operator import itemgetter
import argparse
import re
from urllib.parse import unquote
import time
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GLib
DBusGMainLoop(set_as_default=True)
FORMAT_STRING = '{icon} {artist} - {title}'
FORMAT_REGEX = re.compile(r'(\{:(?P<tag>.*?)(:(?P<format>[wt])(?P<formatlen>\d+))?:(?P<text>.*?):\})', re.I)
FORMAT_TAG_REGEX = re.compile(r'(?P<format>[wt])(?P<formatlen>\d+)')
SAFE_TAG_REGEX = re.compile(r'[{}]')
class PlayerManager:
def __init__(self, blacklist = [], connect = True):
self.blacklist = blacklist
self._connect = connect
self._session_bus = dbus.SessionBus()
self.players = {}
self.print_queue = []
self.connected = False
self.player_states = {}
self.refreshPlayerList()
if self._connect:
self.connect()
loop = GLib.MainLoop()
try:
loop.run()
except KeyboardInterrupt:
print("interrupt received, stopping…")
def connect(self):
self._session_bus.add_signal_receiver(self.onOwnerChangedName, 'NameOwnerChanged')
self._session_bus.add_signal_receiver(self.onChangedProperties, 'PropertiesChanged',
path = '/org/mpris/MediaPlayer2',
sender_keyword='sender')
def onChangedProperties(self, interface, properties, signature, sender = None):
if sender in self.players:
player = self.players[sender]
# If we know this player, but haven't been able to set up a signal handler
if 'properties_changed' not in player._signals:
# Then trigger the signal handler manually
player.onPropertiesChanged(interface, properties, signature)
else:
# If we don't know this player, get its name and add it
bus_name = self.getBusNameFromOwner(sender)
self.addPlayer(bus_name, sender)
player = self.players[sender]
player.onPropertiesChanged(interface, properties, signature)
def onOwnerChangedName(self, bus_name, old_owner, new_owner):
if self.busNameIsAPlayer(bus_name):
if new_owner and not old_owner:
self.addPlayer(bus_name, new_owner)
elif old_owner and not new_owner:
self.removePlayer(old_owner)
else:
self.changePlayerOwner(bus_name, old_owner, new_owner)
def getBusNameFromOwner(self, owner):
player_bus_names = [ bus_name for bus_name in self._session_bus.list_names() if self.busNameIsAPlayer(bus_name) ]
for player_bus_name in player_bus_names:
player_bus_owner = self._session_bus.get_name_owner(player_bus_name)
if owner == player_bus_owner:
return player_bus_name
def busNameIsAPlayer(self, bus_name):
return bus_name.startswith('org.mpris.MediaPlayer2') and bus_name.split('.')[3] not in self.blacklist
def refreshPlayerList(self):
player_bus_names = [ bus_name for bus_name in self._session_bus.list_names() if self.busNameIsAPlayer(bus_name) ]
for player_bus_name in player_bus_names:
self.addPlayer(player_bus_name)
if self.connected != True:
self.connected = True
self.printQueue()
def addPlayer(self, bus_name, owner = None):
player = Player(self._session_bus, bus_name, owner = owner, connect = self._connect, _print = self.print)
self.players[player.owner] = player
def removePlayer(self, owner):
if owner in self.players:
self.players[owner].disconnect()
del self.players[owner]
# If there are no more players, clear the output
if len(self.players) == 0:
_printFlush(ICON_NONE)
# Else, print the output of the next active player
else:
players = self.getSortedPlayerOwnerList()
if len(players) > 0:
self.players[players[0]].printStatus()
def changePlayerOwner(self, bus_name, old_owner, new_owner):
player = Player(self._session_bus, bus_name, owner = new_owner, connect = self._connect, _print = self.print)
self.players[new_owner] = player
del self.players[old_owner]
# Get a list of player owners sorted by current status and age
def getSortedPlayerOwnerList(self):
players = [
{
'number': int(owner.split('.')[-1]),
'status': 2 if player.status == 'playing' else 1 if player.status == 'paused' else 0,
'owner': owner
}
for owner, player in self.players.items()
]
return [ info['owner'] for info in reversed(sorted(players, key=itemgetter('status', 'number'))) ]
# Get latest player that's currently playing
def getCurrentPlayer(self):
playing_players = [
player_owner for player_owner in self.getSortedPlayerOwnerList()
if
self.players[player_owner].status == 'playing' or
self.players[player_owner].status == 'paused'
]
return self.players[playing_players[0]] if playing_players else None
def print(self, status, player):
self.player_states[player.bus_name] = status
if self.connected:
current_player = self.getCurrentPlayer()
if current_player != None:
_printFlush(self.player_states[current_player.bus_name])
else:
_printFlush(ICON_STOPPED)
else:
self.print_queue.append([status, player])
def printQueue(self):
for args in self.print_queue:
self.print(args[0], args[1])
self.print_queue.clear()
class Player:
def __init__(self, session_bus, bus_name, owner = None, connect = True, _print = None):
self._session_bus = session_bus
self.bus_name = bus_name
self._disconnecting = False
self.__print = _print
self.metadata = {
'artist' : '',
'album' : '',
'title' : '',
'track' : 0
}
self._rate = 1.
self._positionAtLastUpdate = 0.
self._timeAtLastUpdate = time.time()
self._positionTimerRunning = False
self._metadata = None
self.status = 'stopped'
self.icon = ICON_NONE
self.icon_reversed = ICON_PLAYING
if owner is not None:
self.owner = owner
else:
self.owner = self._session_bus.get_name_owner(bus_name)
self._obj = self._session_bus.get_object(self.bus_name, '/org/mpris/MediaPlayer2')
self._properties_interface = dbus.Interface(self._obj, dbus_interface='org.freedesktop.DBus.Properties')
self._introspect_interface = dbus.Interface(self._obj, dbus_interface='org.freedesktop.DBus.Introspectable')
self._media_interface = dbus.Interface(self._obj, dbus_interface='org.mpris.MediaPlayer2')
self._player_interface = dbus.Interface(self._obj, dbus_interface='org.mpris.MediaPlayer2.Player')
self._introspect = self._introspect_interface.get_dbus_method('Introspect', dbus_interface=None)
self._getProperty = self._properties_interface.get_dbus_method('Get', dbus_interface=None)
self._playerPlay = self._player_interface.get_dbus_method('Play', dbus_interface=None)
self._playerPause = self._player_interface.get_dbus_method('Pause', dbus_interface=None)
self._playerPlayPause = self._player_interface.get_dbus_method('PlayPause', dbus_interface=None)
self._playerStop = self._player_interface.get_dbus_method('Stop', dbus_interface=None)
self._playerPrevious = self._player_interface.get_dbus_method('Previous', dbus_interface=None)
self._playerNext = self._player_interface.get_dbus_method('Next', dbus_interface=None)
self._playerRaise = self._media_interface.get_dbus_method('Raise', dbus_interface=None)
self._signals = {}
self.refreshPosition()
self.refreshStatus()
self.refreshMetadata()
if connect:
self.printStatus()
self.connect()
def play(self):
self._playerPlay()
def pause(self):
self._playerPause()
def playpause(self):
self._playerPlayPause()
def stop(self):
self._playerStop()
def previous(self):
self._playerPrevious()
def next(self):
self._playerNext()
def raisePlayer(self):
self._playerRaise()
def connect(self):
if self._disconnecting is not True:
introspect_xml = self._introspect(self.bus_name, '/')
if 'TrackMetadataChanged' in introspect_xml:
self._signals['track_metadata_changed'] = self._session_bus.add_signal_receiver(self.onMetadataChanged, 'TrackMetadataChanged', self.bus_name)
self._signals['seeked'] = self._player_interface.connect_to_signal('Seeked', self.onSeeked)
self._signals['properties_changed'] = self._properties_interface.connect_to_signal('PropertiesChanged', self.onPropertiesChanged)
def disconnect(self):
self._disconnecting = True
for signal_name, signal_handler in list(self._signals.items()):
signal_handler.remove()
del self._signals[signal_name]
def refreshStatus(self):
# Some clients (VLC) will momentarily create a new player before removing it again
# so we can't be sure the interface still exists
try:
self.status = str(self._getProperty('org.mpris.MediaPlayer2.Player', 'PlaybackStatus')).lower()
self.updateIcon()
self.checkPositionTimer()
except dbus.exceptions.DBusException:
self.disconnect()
def refreshMetadata(self):
# Some clients (VLC) will momentarily create a new player before removing it again
# so we can't be sure the interface still exists
try:
self._metadata = self._getProperty('org.mpris.MediaPlayer2.Player', 'Metadata')
self._parseMetadata()
except dbus.exceptions.DBusException:
self.disconnect()
def updateIcon(self):
self.icon = (
ICON_PLAYING if self.status == 'playing' else
ICON_PAUSED if self.status == 'paused' else
ICON_STOPPED if self.status == 'stopped' else
ICON_NONE
)
self.icon_reversed = (
ICON_PAUSED if self.status == 'playing' else
ICON_PLAYING
)
def _print(self, status):
self.__print(status, self)
def _parseMetadata(self):
if self._metadata != None:
artist = _getProperty(self._metadata, 'xesam:artist', [''])
if artist != None and len(artist):
self.metadata['artist'] = re.sub(SAFE_TAG_REGEX, """\1\1""", artist[0])
else:
artists = _getProperty(self._metadata, 'xesam:artists', [''])
if artists != None and len(artists):
# Note: This only grabs the first artist
self.metadata['artist'] = re.sub(SAFE_TAG_REGEX, """\1\1""", artists[0])
else:
self.metadata['artist'] = '';
self.metadata['album'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _getProperty(self._metadata, 'xesam:album', ''))
self.metadata['title'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _getProperty(self._metadata, 'xesam:title', ''))
self.metadata['track'] = _getProperty(self._metadata, 'xesam:trackNumber', '')
length = str(_getProperty(self._metadata, 'xesam:length', ''))
if not len(length):
length = str(_getProperty(self._metadata, 'mpris:length', ''))
if len(length):
self.metadata['length'] = int(length)
else:
self.metadata['length'] = 0
self.metadata['genre'] = _getProperty(self._metadata, 'xesam:genre', '')
self.metadata['disc'] = _getProperty(self._metadata, 'xesam:discNumber', '')
self.metadata['date'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _getProperty(self._metadata, 'xesam:contentCreated', ''))
self.metadata['year'] = re.sub(SAFE_TAG_REGEX, """\1\1""", self.metadata['date'][0:4])
self.metadata['url'] = _getProperty(self._metadata, 'xesam:url', '')
self.metadata['filename'] = os.path.basename(self.metadata['url'])
cover = _getProperty(self._metadata, 'xesam:artUrl', '')
if not len(cover):
cover = _getProperty(self._metadata, 'mpris:artUrl', '')
if len(cover):
self.metadata['cover'] = re.sub(SAFE_TAG_REGEX, """\1\1""", cover)
else:
self.metadata['cover'] = ''
self.metadata['duration'] = _getDuration(self.metadata['length'])
def onMetadataChanged(self, track_id, metadata):
self.refreshMetadata()
self.printStatus()
def onPropertiesChanged(self, interface, properties, signature):
updated = False
if dbus.String('Metadata') in properties:
_metadata = properties[dbus.String('Metadata')]
if _metadata != self._metadata:
self._metadata = _metadata
self._parseMetadata()
updated = True
if dbus.String('PlaybackStatus') in properties:
status = str(properties[dbus.String('PlaybackStatus')]).lower()
if status != self.status:
self.status = status
self.checkPositionTimer()
self.updateIcon()
updated = True
if dbus.String('Rate') in properties and dbus.String('PlaybackStatus') not in properties:
self.refreshStatus()
if NEEDS_POSITION and dbus.String('Rate') in properties:
rate = properties[dbus.String('Rate')]
if rate != self._rate:
self._rate = rate
self.refreshPosition()
if updated:
self.refreshPosition()
self.printStatus()
def checkPositionTimer(self):
if NEEDS_POSITION and self.status == 'playing' and not self._positionTimerRunning:
self._positionTimerRunning = True
GLib.timeout_add_seconds(1, self._positionTimer)
def onSeeked(self, position):
self.refreshPosition()
self.printStatus()
def _positionTimer(self):
self.printStatus()
self._positionTimerRunning = self.status == 'playing'
return self._positionTimerRunning
def refreshPosition(self):
try:
time_us = self._getProperty('org.mpris.MediaPlayer2.Player', 'Position')
except dbus.exceptions.DBusException:
time_us = 0
self._timeAtLastUpdate = time.time()
self._positionAtLastUpdate = time_us / 1000000
def _getPosition(self):
if self.status == 'playing':
return self._positionAtLastUpdate + self._rate * (time.time() - self._timeAtLastUpdate)
else:
return self._positionAtLastUpdate
def _statusReplace(self, match, metadata):
tag = match.group('tag')
format = match.group('format')
formatlen = match.group('formatlen')
text = match.group('text')
tag_found = False
reversed_tag = False
if tag.startswith('-'):
tag = tag[1:]
reversed_tag = True
if format is None:
tag_is_format_match = re.match(FORMAT_TAG_REGEX, tag)
if tag_is_format_match:
format = tag_is_format_match.group('format')
formatlen = tag_is_format_match.group('formatlen')
tag_found = True
if format is not None:
text = text.format_map(CleanSafeDict(**metadata))
if format == 'w':
formatlen = int(formatlen)
text = text[:formatlen]
elif format == 't':
formatlen = int(formatlen)
if len(text) > formatlen:
text = text[:max(formatlen - len(TRUNCATE_STRING), 0)] + TRUNCATE_STRING
if tag_found is False and tag in metadata and len(metadata[tag]):
tag_found = True
if reversed_tag:
tag_found = not tag_found
if tag_found:
return text
else:
return ''
def printStatus(self):
if self.status in [ 'playing', 'paused' ]:
metadata = { **self.metadata, 'icon': self.icon, 'icon-reversed': self.icon_reversed }
if NEEDS_POSITION:
metadata['position'] = time.strftime("%M:%S", time.gmtime(self._getPosition()))
# replace metadata tags in text
text = re.sub(FORMAT_REGEX, lambda match: self._statusReplace(match, metadata), FORMAT_STRING)
# restore polybar tag formatting and replace any remaining metadata tags after that
try:
text = re.sub(r'􏿿p􏿿(.*?)􏿿p􏿿(.*?)􏿿p􏿿(.*?)􏿿p􏿿', r'%{\1}\2%{\3}', text.format_map(CleanSafeDict(**metadata)))
except:
print("Invalid format string")
self._print(text)
else:
self._print(ICON_STOPPED)
def _dbusValueToPython(value):
if isinstance(value, dbus.Dictionary):
return {_dbusValueToPython(key): _dbusValueToPython(value) for key, value in value.items()}
elif isinstance(value, dbus.Array):
return [ _dbusValueToPython(item) for item in value ]
elif isinstance(value, dbus.Boolean):
return int(value) == 1
elif (
isinstance(value, dbus.Byte) or
isinstance(value, dbus.Int16) or
isinstance(value, dbus.UInt16) or
isinstance(value, dbus.Int32) or
isinstance(value, dbus.UInt32) or
isinstance(value, dbus.Int64) or
isinstance(value, dbus.UInt64)
):
return int(value)
elif isinstance(value, dbus.Double):
return float(value)
elif (
isinstance(value, dbus.ObjectPath) or
isinstance(value, dbus.Signature) or
isinstance(value, dbus.String)
):
return unquote(str(value))
def _getProperty(properties, property, default = None):
value = default
if not isinstance(property, dbus.String):
property = dbus.String(property)
if property in properties:
value = properties[property]
return _dbusValueToPython(value)
else:
return value
def _getDuration(t: int):
seconds = t / 1000000
return time.strftime("%M:%S", time.gmtime(seconds))
class CleanSafeDict(dict):
def __missing__(self, key):
return '{{{}}}'.format(key)
"""
Seems to assure print() actually prints when no terminal is connected
"""
_last_status = ''
def _printFlush(status, **kwargs):
global _last_status
if status != _last_status:
print(status, **kwargs)
sys.stdout.flush()
_last_status = status
parser = argparse.ArgumentParser()
parser.add_argument('command', help="send the given command to the active player",
choices=[ 'play', 'pause', 'play-pause', 'stop', 'previous', 'next', 'status', 'list', 'current', 'metadata', 'raise' ],
default=None,
nargs='?')
parser.add_argument('-b', '--blacklist', help="ignore a player by it's bus name. Can be be given multiple times (e.g. -b vlc -b audacious)",
action='append',
metavar="BUS_NAME",
default=[])
parser.add_argument('-f', '--format', default='{icon} {:artist:{artist} - :}{:title:{title}:}{:-title:{filename}:}')
parser.add_argument('--truncate-text', default='')
parser.add_argument('--icon-playing', default='')
parser.add_argument('--icon-paused', default='')
parser.add_argument('--icon-stopped', default='')
parser.add_argument('--icon-none', default='')
args = parser.parse_args()
FORMAT_STRING = re.sub(r'%\{(.*?)\}(.*?)%\{(.*?)\}', r'􏿿p􏿿\1􏿿p􏿿\2􏿿p􏿿\3􏿿p􏿿', args.format)
NEEDS_POSITION = "{position}" in FORMAT_STRING
TRUNCATE_STRING = args.truncate_text
ICON_PLAYING = args.icon_playing
ICON_PAUSED = args.icon_paused
ICON_STOPPED = args.icon_stopped
ICON_NONE = args.icon_none
if args.command is None:
PlayerManager(blacklist = args.blacklist)
else:
player_manager = PlayerManager(blacklist = args.blacklist, connect = False)
current_player = player_manager.getCurrentPlayer()
if args.command == 'play' and current_player:
current_player.play()
elif args.command == 'pause' and current_player:
current_player.pause()
elif args.command == 'play-pause' and current_player:
current_player.playpause()
elif args.command == 'stop' and current_player:
current_player.stop()
elif args.command == 'previous' and current_player:
current_player.previous()
elif args.command == 'next' and current_player:
current_player.next()
elif args.command == 'status' and current_player:
current_player.printStatus()
elif args.command == 'list':
print("\n".join(sorted([
"{} : {}".format(player.bus_name.split('.')[3], player.status)
for player in player_manager.players.values() ])))
elif args.command == 'current' and current_player:
print("{} : {}".format(current_player.bus_name.split('.')[3], current_player.status))
elif args.command == 'metadata' and current_player:
print(_dbusValueToPython(current_player._metadata))
elif args.command == 'raise' and current_player:
current_player.raisePlayer()

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -0,0 +1,24 @@
# Script: updates-arch-combined
A script that shows if there are updates for Arch Linux and AUR updates.
See also [updates-arch](../updates-arch) and [updates-arch-aur](../updates-arch-aur).
![updates-arch-combined](screenshots/1.png)
## Dependencies
The possibilities depend on your AUR helper. Not all helpers can report the pending updates.
At the moment `trizen` and `cower` are documented. Take a look at the script to see how it works.
## Module
```ini
[module/updates-arch-combined]
type = custom/script
exec = ~/polybar-scripts/updates-arch-combined.sh
interval = 600
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,16 @@
#!/bin/sh
updates_arch=$(checkupdates | wc -l)
# if ! updates_aur=$(cower -u 2> /dev/null | wc -l); then
if ! updates_aur=$(trizen -Su --aur --quiet | wc -l); then
updates_aur=0
fi
updates=$(("$updates_arch" + "$updates_aur"))
if [ "$updates" -gt 0 ]; then
echo "$updates"
else
echo ""
fi

View File

@ -0,0 +1,422 @@
;=====================================================
;
; To learn more about how to configure Polybar
; go to https://github.com/jaagr/polybar
;
; The README contains alot of information
;
;=====================================================
[colors]
;background = ${xrdb:color0:#222}
background = #222
background-alt = #444
;foreground = ${xrdb:color7:#222}
foreground = #dfdfdf
foreground-alt = #555
primary = #ffb52a
secondary = #e60053
alert = #bd2c40
[bar/base]
width = 100%
height = 27
radius = 6.0
fixed-center = false
background = ${colors.background}
foreground = ${colors.foreground}
line-size = 3
line-color = #f00
border-size = 0
border-color = #00000000
padding-left = 0
padding-right = 2
module-margin-left = 1
module-margin-right = 2
scroll-up = bspwm-desknext
scroll-down = bspwm-deskprev
wm-restack = bspwm
[bar/base-laptop]
inherit = "bar/base"
font-0 = FuraCode Nerd Font:pixelsize=14
[bar/base-desktop]
inherit = "bar/base"
font-0 = FuraCode Nerd Font:pixelsize=10
[bar/laptop-bottom]
inherit = bar/base-laptop
bottom = true
monitor = ${env:MONITOR:e-DP1}
modules-center = mpd player-mpris-tail
[bar/laptop-top]
inherit = bar/base-laptop
monitor = ${env:MONITOR:e-DP1}
modules-left = bspwm
modules-center = tun0 tun1 wlan bluetooth
modules-right = github updates-arch-combined battery xbacklight filesystem volume memory cpu temperature date
tray-position = right
tray-padding = 0
[bar/monitor1]
inherit = bar/base-desktop
monitor = ${env:MONITOR:DP-1}
modules-left = bspwm
modules-center = mpd player-mpris-tail
modules-right = github updates-arch-combined bluetooth eth filesystem volume memory cpu temperature date
tray-position = right
tray-padding = 0
[bar/monitor2]
inherit = bar/base-desktop
monitor = ${env:MONITOR:HDMI-2}
modules-left = bspwm
[module/xwindow]
type = internal/xwindow
label = %title:0:30:...%
[module/xkeyboard]
type = internal/xkeyboard
blacklist-0 = num lock
format-prefix = " "
format-prefix-foreground = ${colors.foreground-alt}
format-prefix-underline = ${colors.secondary}
label-layout = %layout%
label-layout-underline = ${colors.secondary}
label-indicator-padding = 2
label-indicator-margin = 1
label-indicator-background = ${colors.secondary}
label-indicator-underline = ${colors.secondary}
[module/filesystem]
type = internal/fs
interval = 25
mount-0 = /
mount-1 = /home
label-mounted = %{F#0a81f5}%mountpoint%%{F-}: %percentage_used%%
label-unmounted = %mountpoint% not mounted
label-unmounted-foreground = ${colors.foreground-alt}
[module/bspwm]
type = internal/bspwm
label-focused-background = ${colors.background-alt}
label-focused-underline= ${colors.primary}
label-focused-padding = 2
label-occupied-padding = 2
label-urgent-background = ${colors.alert}
label-urgent-padding = 2
label-empty-foreground = ${colors.foreground-alt}
label-empty-padding = 2
pin-workspaces = true
[module/mpd]
type = internal/mpd
format-online = <label-song> <icon-prev> <icon-stop> <toggle> <icon-next>
icon-prev = 
icon-stop = 
icon-play = 
icon-pause = 
icon-next = 
label-song-maxlen = 25
label-song-ellipsis = true
[module/xbacklight]
type = internal/xbacklight
format = <label> <bar>
label = 
bar-width = 10
bar-indicator = |
bar-indicator-foreground = #ff
bar-indicator-font = 2
bar-fill = ─
bar-fill-font = 2
bar-fill-foreground = #9f78e1
bar-empty = ─
bar-empty-font = 2
bar-empty-foreground = ${colors.foreground-alt}
[module/backlight-acpi]
inherit = module/xbacklight
type = internal/backlight
card = intel_backlight
[module/cpu]
type = internal/cpu
interval = 2
format-prefix = " "
format-prefix-foreground = ${colors.foreground-alt}
format-underline = #f90000
label = %percentage:2%%
format = <label> <ramp-coreload>
ramp-coreload-0 = ▁
ramp-coreload-1 = ▂
ramp-coreload-2 = ▃
ramp-coreload-3 = ▄
ramp-coreload-4 = ▅
ramp-coreload-5 = ▆
ramp-coreload-6 = ▇
ramp-coreload-7 = █
[module/memory]
type = internal/memory
interval = 2
format-prefix = " "
format-prefix-foreground = ${colors.foreground-alt}
format-underline = #4bffdc
label = %percentage_used%%
ramp-used-0 = ▁
ramp-used-1 = ▂
ramp-used-2 = ▃
ramp-used-3 = ▄
ramp-used-4 = ▅
ramp-used-5 = ▆
ramp-used-6 = ▇
ramp-used-7 = █
[module/wlan]
type = internal/network
interface = wlp4s0
interval = 3.0
format-connected = <ramp-signal> <label-connected>
format-packetloss = <animation-packetloss> <label-connected>
format-disconnected =
format-connected-underline = #55aa55
format-connected-prefix = " "
label-connected = "%essid% %signal% %downspeed:8% %upspeed:8%"
ramp-signal-0 = ▁
ramp-signal-1 = ▂
ramp-signal-2 = ▃
ramp-signal-3 = ▄
ramp-signal-4 = ▅
ramp-signal-5 = ▆
ramp-signal-6 = ▇
ramp-signal-7 = █
animation-packetloss-0 = ⚠
animation-packetloss-1 = 📶
; Framerate in milliseconds
animation-packetloss-framerate = 500
[module/tun0]
type = internal/network
interface = tun0
interval = 3.0
format-connected-underline = #55aa55
format-connected-prefix = "嬨 "
label-connected = "%ifname%"
[module/tun1]
type = internal/network
interface = tun1
interval = 3.0
format-connected-underline = #55aa55
format-connected-prefix = "嬨 "
label-connected = "%ifname%"
[module/eth]
type = internal/network
interface = eno1
interval = 3.0
format-connected-underline = #55aa55
format-connected-prefix = " "
format-connected-prefix-foreground = ${colors.foreground-alt}
label-connected = "%local_ip% %downspeed% %upspeed%"
format-disconnected =
;format-disconnected = <label-disconnected>
;format-disconnected-underline = ${self.format-connected-underline}
;label-disconnected = %ifname% disconnected
;label-disconnected-foreground = ${colors.foreground-alt}
[module/date]
type = internal/date
interval = 5
date =
date-alt = " %d-%m-%Y"
time = %H:%M
time-alt = %H:%M:%S
format-prefix = 
format-prefix-foreground = ${colors.foreground-alt}
format-underline = #0a6cf5
label = %date% %time%
[module/volume]
type = internal/alsa
format-volume = <label-volume> <bar-volume>
label-volume = 蓼
label-volume-foreground = ${root.foreground}
format-muted-prefix = " "
format-muted-foreground = ${colors.foreground-alt}
label-muted = sound muted
bar-volume-width = 10
bar-volume-foreground-0 = #55aa55
bar-volume-foreground-1 = #55aa55
bar-volume-foreground-2 = #55aa55
bar-volume-foreground-3 = #55aa55
bar-volume-foreground-4 = #55aa55
bar-volume-foreground-5 = #f5a70a
bar-volume-foreground-6 = #ff5555
bar-volume-gradient = false
bar-volume-indicator = |
bar-volume-indicator-font = 2
bar-volume-fill = ─
bar-volume-fill-font = 2
bar-volume-empty = ─
bar-volume-empty-font = 2
bar-volume-empty-foreground = ${colors.foreground-alt}
[module/battery]
type = internal/battery
battery = BAT0
adapter = ADP1
full-at = 98
format-charging = <animation-charging> <label-charging>
format-charging-underline = #ffb52a
format-discharging = <ramp-capacity> <label-discharging>
format-discharging-underline = ${self.format-charging-underline}
format-full-prefix = " "
format-full-prefix-foreground = ${colors.foreground-alt}
format-full-underline = ${self.format-charging-underline}
ramp-capacity-0 = 
ramp-capacity-1 = 
ramp-capacity-2 = 
ramp-capacity-foreground = ${colors.foreground-alt}
animation-charging-0 = 
animation-charging-1 = 
animation-charging-2 = 
animation-charging-foreground = ${colors.foreground-alt}
animation-charging-framerate = 750
[module/temperature]
type = internal/temperature
thermal-zone = 0
warn-temperature = 60
format = <ramp> <label>
format-underline = #f50a4d
format-warn = <ramp> <label-warn>
format-warn-underline = ${self.format-underline}
label = %temperature-c%
label-warn = %temperature-c%
label-warn-foreground = ${colors.secondary}
ramp-0 = 
ramp-1 = 
ramp-2 = 
ramp-foreground = ${colors.foreground-alt}
[module/powermenu]
type = custom/menu
expand-right = true
format-spacing = 1
label-open = 
label-open-foreground = ${colors.secondary}
label-close =  cancel
label-close-foreground = ${colors.secondary}
label-separator = |
label-separator-foreground = ${colors.foreground-alt}
menu-0-0 = reboot
menu-0-0-exec = menu-open-1
menu-0-1 = power off
menu-0-1-exec = menu-open-2
menu-1-0 = cancel
menu-1-0-exec = menu-open-0
menu-1-1 = reboot
menu-1-1-exec = sudo reboot
menu-2-0 = power off
menu-2-0-exec = sudo poweroff
menu-2-1 = cancel
menu-2-1-exec = menu-open-0
[module/github]
type = internal/github
token = ${file:~/.github-access-token}
format = <label>
label = " %notifications%"
[module/updates-arch-combined]
type = custom/script
exec = /bin/sh ~/.config/polybar/bin/updates-arch-combined/updates-arch-combined.sh
interval = 600
[module/player-mpris-tail]
type = custom/script
exec = python ~/.config/polybar/bin/player-mpris-tail/player-mpris-tail.py
tail = true
click-left = /bin/sh ~/.config/polybar/bin/player-mpris-tail/player-ctrl.sh previous
click-right = /bin/sh ~/.config/polybar/bin/player-mpris-tail/player-ctrl.sh next
click-middle = /bin/sh ~/.config/polybar/bin/player-mpris-tail/player-ctrl.sh play-pause
[module/bluetooth]
type = custom/script
exec = /bin/sh ~/.config/polybar/bin/isactive-bluetooth/isactive-bluetooth.sh
[settings]
screenchange-reload = true
;compositing-background = xor
;compositing-background = screen
;compositing-foreground = source
;compositing-border = over
[global/wm]
margin-top = 5
margin-bottom = 5
; vim:ft=dosini

View File

@ -0,0 +1,13 @@
#!/usr/bin/env bash
# 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
# Launch bar1 and bar2
polybar monitor1 &
polybar monitor2 &
echo "Bars launched..."

View File

@ -0,0 +1,13 @@
#!/usr/bin/env bash
# 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
# Launch bar1 and bar2
polybar laptop-top &
polybar laptop-bottom &
echo "Bars launched..."

View File

@ -1,303 +0,0 @@
;; -*- mode: emacs-lisp -*-
;; This file is loaded by Spacemacs at startup.
;; It must be stored in your home directory.
(defun dotspacemacs/layers ()
"Configuration Layers declaration.
You should not put any user code in this function besides modifying the variable
values."
(setq-default dotspacemacs-distribution 'spacemacs
dotspacemacs-enable-lazy-installation
'unused
dotspacemacs-ask-for-lazy-installation
t
dotspacemacs-configuration-layer-path
'()
dotspacemacs-configuration-layers
'(yaml javascript
csv
html
rust
helm
auto-completion
better-defaults
dash
docker
elfeed
emacs-lisp
finance
git
(dash :variables helm-dash-docset-newpath
"~/.local/share/Zeal/docsets/" helm-dash-browser-func
'eww)
markdown
mu4e
org
(rcirc : variables
rcirc-enable-znc-support t)
semantic
shell-scripts
spotify
spell-checking
systemd
syntax-checking
themes-megapack)
dotspacemacs-additional-packages
'(helm-ag pkgbuild-mode yasnippet-snippets
elfeed-protocol)
dotspacemacs-frozen-packages
'()
dotspacemacs-excluded-packages
'()
dotspacemacs-install-packages
'used-only))
(defun dotspacemacs/init ()
"Initialization function.
This function is called at the very startup of Spacemacs initialization
before layers configuration.
You should not put any user code in there besides modifying the variable
values."
(setq-default dotspacemacs-elpa-https t
dotspacemacs-elpa-timeout
5
dotspacemacs-check-for-update
`t
dotspacemacs-elpa-subdirectory
nil
dotspacemacs-editing-style
'vim
dotspacemacs-verbose-loading
nil
dotspacemacs-startup-banner
'official
dotspacemacs-startup-lists
'((recents . 5)
(projects . 7))
dotspacemacs-startup-buffer-responsive
t
dotspacemacs-scratch-mode
'text-mode
dotspacemacs-themes
'(spacemacs-dark spacemacs-light)
dotspacemacs-colorize-cursor-according-to-state
t
dotspacemacs-default-font
'("FuraCode Nerd Font Mono" :size 13
:weight normal
:width normal
:powerline-scale 1.1)
dotspacemacs-leader-key
"SPC"
dotspacemacs-emacs-command-key
"SPC"
dotspacemacs-ex-command-key
":"
dotspacemacs-emacs-leader-key
"M-m"
dotspacemacs-major-mode-leader-key
","
dotspacemacs-major-mode-emacs-leader-key
"C-M-m"
dotspacemacs-distinguish-gui-tab
nil
dotspacemacs-remap-Y-to-y$
nil
dotspacemacs-retain-visual-state-on-shift
t
dotspacemacs-visual-line-move-text
nil
dotspacemacs-ex-substitute-global
nil
dotspacemacs-default-layout-name
"Default"
dotspacemacs-display-default-layout
nil
dotspacemacs-auto-resume-layouts
nil
dotspacemacs-large-file-size
1
dotspacemacs-auto-save-file-location
'cache
dotspacemacs-max-rollback-slots
5
dotspacemacs-helm-resize
nil
dotspacemacs-helm-no-header
nil
dotspacemacs-helm-position
'bottom
dotspacemacs-helm-use-fuzzy
'always
dotspacemacs-enable-paste-transient-state
nil
dotspacemacs-which-key-delay
0.4
dotspacemacs-which-key-position
'bottom
dotspacemacs-loading-progress-bar
t
dotspacemacs-fullscreen-at-startup
nil
dotspacemacs-fullscreen-use-non-native
nil
dotspacemacs-maximized-at-startup
nil
dotspacemacs-active-transparency
90
dotspacemacs-inactive-transparency
90
dotspacemacs-show-transient-state-title
t
dotspacemacs-show-transient-state-color-guide
t
dotspacemacs-mode-line-unicode-symbols
t
dotspacemacs-smooth-scrolling
t
dotspacemacs-line-numbers
't
dotspacemacs-folding-method
'evil
dotspacemacs-smartparens-strict-mode
nil
dotspacemacs-smart-closing-parenthesis
nil
dotspacemacs-highlight-delimiters
'all
dotspacemacs-persistent-server
nil
dotspacemacs-search-tools
'("ag" "pt" "ack" "grep")
dotspacemacs-default-package-repository
nil
dotspacemacs-whitespace-cleanup
nil))
(defun dotspacemacs/user-init ()
"Initialization function for user code.
It is called immediately after `dotspacemacs/init', before layer configuration
executes.
This function is mostly useful for variables that need to be set before packages are loaded. If you are unsure, you should try in setting them in
`dotspacemacs/user-config' first.")
(defun dotspacemacs/user-config ()
"Configuration function for user code.
This function is called at the very end of Spacemacs initialization after
layers configuration.
This is the place where most of your configurations should be done. Unless it is
explicitly specified that a variable should be set before a package is loaded,
you should place your code here."
;; rcirc
(setq rcirc-server-alist '(("freenode.higherlearning.eu" :port "5000"
:encryption tls
:auth "l0rd/freenode")
("snoonet.higherlearning.eu" :port "5000"
:encryption tls
:auth "l0rd/snoonet")))
;; mu4e
(setq sendmail-program "/usr/bin/msmtp"
send-mail-function
'smtpmail-send-it
message-sendmail-f-is-evil
t
message-sendmail-extra-arguments
'("--read-envelope-from")
message-send-mail-function
'message-send-mail-with-sendmail)
(with-eval-after-load 'mu4e-alert
(mu4e-alert-set-default-style 'notifications))
(with-eval-after-load 'mu4e-maildirs-extension
(setq mu4e-maildirs-extension-custom-list '("/ryankes/INBOX" "/ryankes/Sent" "/ryankes/Drafts"
"/ryankes/Archive" "/ryankes/Archive.quicknet"
"/gmail/INBOX" "/gmail/Sent" "/gmail/Drafts"
"/gmail/Archive" "/andthensome/INBOX" "/andthensome/Sent"
"/andthensome/Drafts" "/andthensome/Archive")))
(with-eval-after-load 'mu4e
(setq mu4e-maildir "~/.local/share/mail"
mu4e-maildir-shortcuts
'(("/ryankes/INBOX" . ?r)
("/gmail/INBOX" . ?g)
("/andthensome/INBOX" . ?a))
mu4e-update-interval
300
mu4e-get-mail-command
"mailsync"
mu4e-enable-mode-line
t
mu4e-use-fancy-chars
t
mu4e-view-show-images
t
mu4e-context-policy
'pick-first
mu4e-attachment-dir
"~/Downloads/"
mu4e-compose-context-policy
nil
mu4e-contexts
`(,(make-mu4e-context :name "Ryankes"
:match-func (lambda (msg)
(when msg
(string-match-p "^/ryankes"
(mu4e-message-field msg :maildir)))):vars'((user-mail-address . "ryan@ryankes.eu")
(user-full-name . "Ryan")
(mu4e-sent-folder . "/ryankes/Sent")
(mu4e-drafts-folder . "/ryankes/Drafts")
(mu4e-trash-folder . "/ryankes/Trash")
(mu4e-refile-folder . "/ryankes/Archive")))
,(make-mu4e-context :name "Gmail"
:match-func (lambda (msg)
(when msg
(string-match-p "^/gmail"
(mu4e-message-field msg :maildir)))):vars'((user-mail-address . "alrayyes@gmail.com")
(user-full-name . "Ryan")
(mu4e-sent-folder . "/gmail/Sent")
(mu4e-drafts-folder . "/gmail/Drafts")
(mu4e-trash-folder . "/gmail/Trash")
(mu4e-refile-folder . "/gmail/Archive")))
,(make-mu4e-context :name "Andthensome"
:match-func (lambda (msg)
(when msg
(string-match-p "^/andthensome"
(mu4e-message-field msg :maildir)))):vars'((user-mail-address . "ryan@andthensome.nl")
(user-full-name . "Ryan Kes")
(mu4e-sent-folder . "/andthensome/Sent")
(mu4e-drafts-folder . "/andthensome/Drafts")
(mu4e-trash-folder . "/andthensome/Trash")
(mu4e-refile-folder . "/andthensome/Archive")))))
(add-hook 'mu4e-view-mode-hook 'visual-line-mode))
;; elfeed
(with-eval-after-load 'elfeed
(setq elfeed-use-curl t)
(setq elfeed-protocol-ttrss-maxsize 200) ; bigger than 200 is invalid
(elfeed-set-timeout 36000)
(setq elfeed-feeds '(("ttrss+https://alrayyes@rss.higherlearning.eu"
:use-authinfo t)))
(elfeed-protocol-enable)))
;; org
(with-eval-after-load 'org
(setq org-enable-github-support t org-enable-reveal-js-support
t))
;; Do not write anything past this comment. This is where Emacs will
;; auto-generate custom variable definitions.
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(evil-want-Y-yank-to-eol nil)
'(package-selected-packages
(quote
(ledger-mode flycheck-ledger ox-reveal ox-gfm elfeed-protocol elfeed-web elfeed-org elfeed-goodies ace-jump-mode noflet elfeed systemd dockerfile-mode docker tablist docker-tramp zenburn-theme zen-and-art-theme white-sand-theme underwater-theme ujelly-theme twilight-theme twilight-bright-theme twilight-anti-bright-theme toxi-theme tao-theme tangotango-theme tango-plus-theme tango-2-theme sunny-day-theme sublime-themes subatomic256-theme subatomic-theme spacegray-theme soothe-theme solarized-theme soft-stone-theme soft-morning-theme soft-charcoal-theme smyx-theme seti-theme reverse-theme rebecca-theme railscasts-theme purple-haze-theme professional-theme planet-theme phoenix-dark-pink-theme phoenix-dark-mono-theme organic-green-theme omtose-phellack-theme oldlace-theme occidental-theme obsidian-theme noctilux-theme naquadah-theme mustang-theme monokai-theme monochrome-theme molokai-theme moe-theme minimal-theme material-theme majapahit-theme madhat2r-theme lush-theme light-soap-theme jbeans-theme jazz-theme ir-black-theme inkpot-theme heroku-theme hemisu-theme hc-zenburn-theme gruvbox-theme gruber-darker-theme grandshell-theme gotham-theme gandalf-theme flatui-theme flatland-theme farmhouse-theme exotica-theme espresso-theme dracula-theme django-theme darktooth-theme autothemer darkokai-theme darkmine-theme darkburn-theme dakrone-theme cyberpunk-theme color-theme-sanityinc-tomorrow color-theme-sanityinc-solarized clues-theme cherry-blossom-theme busybee-theme bubbleberry-theme birds-of-paradise-plus-theme badwolf-theme apropospriate-theme anti-zenburn-theme ample-zen-theme ample-theme alect-themes afternoon-theme yasnippet-snippets stickyfunc-enhance srefactor slack emojify circe oauth2 websocket darcula-theme yaml-mode web-beautify livid-mode skewer-mode simple-httpd json-mode json-snatcher json-reformat js2-refactor multiple-cursors js2-mode js-doc company-tern dash-functional tern coffee-mode csv-mode web-mode tagedit slim-mode scss-mode sass-mode pug-mode helm-css-scss haml-mode emmet-mode company-web web-completion-data toml-mode racer flycheck-rust cargo rust-mode insert-shebang fish-mode company-shell zeal-at-point helm-dash dash-docs spotify helm-spotify-plus multi mu4e-maildirs-extension mu4e-alert ht rcirc-notify rcirc-color powerline-theme pkgbuild-mode unfill smeargle orgit org-projectile org-category-capture org-present org-pomodoro alert log4e gntp org-mime org-download mwim mmm-mode markdown-toc markdown-mode magit-gitflow magit-popup htmlize helm-gitignore helm-company helm-c-yasnippet gnuplot gitignore-mode gitconfig-mode gitattributes-mode git-timemachine git-messenger git-link gh-md fuzzy flyspell-correct-helm flyspell-correct flycheck-pos-tip pos-tip flycheck evil-magit magit transient git-commit with-editor company-statistics company auto-yasnippet yasnippet auto-dictionary ac-ispell auto-complete ws-butler winum which-key volatile-highlights vi-tilde-fringe uuidgen use-package toc-org spaceline powerline restart-emacs request rainbow-delimiters popwin persp-mode pcre2el paradox spinner org-plus-contrib org-bullets open-junk-file neotree move-text macrostep lorem-ipsum linum-relative link-hint indent-guide hydra lv hungry-delete hl-todo highlight-parentheses highlight-numbers parent-mode highlight-indentation helm-themes helm-swoop helm-projectile projectile pkg-info epl helm-mode-manager helm-make helm-flx helm-descbinds helm-ag google-translate golden-ratio flx-ido flx fill-column-indicator fancy-battery eyebrowse expand-region exec-path-from-shell evil-visualstar evil-visual-mark-mode evil-unimpaired evil-tutor evil-surround evil-search-highlight-persist highlight evil-numbers evil-nerd-commenter evil-mc evil-matchit evil-lisp-state smartparens evil-indent-plus evil-iedit-state iedit evil-exchange evil-escape evil-ediff evil-args evil-anzu anzu evil goto-chg undo-tree eval-sexp-fu elisp-slime-nav dumb-jump f dash s diminish define-word column-enforce-mode clean-aindent-mode bind-map bind-key auto-highlight-symbol auto-compile packed aggressive-indent adaptive-wrap ace-window ace-link ace-jump-helm-line helm avy helm-core popup async)))
'(paradox-github-token t)
'(send-mail-function (quote smtpmail-send-it)))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)

View File

@ -36,10 +36,6 @@ super + z
super + c super + c
yubikey-oath-dmenu --clipboard clipboard --notify yubikey-oath-dmenu --clipboard clipboard --notify
# dmenu application launcher
super + p
dmenu-frecency
# Wireguard # Wireguard
super + w super + w
vpn-switch vpn-switch
@ -54,6 +50,128 @@ XF86Eject
shift + XF86Eject shift + XF86Eject
prompt "Reboot computer?" "sudo -A shutdown -r now" prompt "Reboot computer?" "sudo -A shutdown -r now"
# Open frequent apps # scratchpad
super + o ; {e,w,m,v,h,s,i,n,q,c} alt + {s,e}
{emacs, $TERMINAL -e weather, $TERMINAL -e neomutt, $TERMINAL -e vifm, $TERMINAL -e htop, slack, $TERMINAL -e weechat, $TERMINAL -e newsboat, qtpass, $TERMINAL -e calendar} tdrop -ma -w -4 {-s dropdown st -c scratchpad,emacs}
#
# BSPWM
#
# terminal emulator
super + Return
$TERMINAL
# program launcher
super + @space
dmenu-frecency
# make sxhkd reload its configuration files:
super + Escape
pkill -USR1 -x sxhkd
#
# bspwm hotkeys
#
# quit/restart bspwm
super + alt + {q,r}
bspc {quit,wm -r}
# close and kill
super + {_,shift + }w
bspc node -{c,k}
# alternate between the tiled and monocle layout
super + m
bspc desktop -l next
# send the newest marked node to the newest preselected node
super + y
bspc node newest.marked.local -n newest.!automatic.local
# swap the current node and the biggest node
super + g
bspc node -s biggest
#
# state/flags
#
# set the window state
super + {t,shift + t,s,f}
bspc node -t {tiled,pseudo_tiled,floating,fullscreen}
# set the node flags
super + ctrl + {m,x,y,z}
bspc node -g {marked,locked,sticky,private}
#
# focus/swap
#
# focus the node in the given direction
super + {_,shift + }{h,j,k,l}
bspc node -{f,s} {west,south,north,east}
# focus the node for the given path jump
super + {p,b,comma,period}
bspc node -f @{parent,brother,first,second}
# focus the next/previous node in the current desktop
super + {_,shift + }c
bspc node -f {next,prev}.local
# focus the next/previous desktop in the current monitor
super + bracket{left,right}
bspc desktop -f {prev,next}.local
# focus the last node/desktop
super + {grave,Tab}
bspc {node,desktop} -f last
# focus the older or newer node in the focus history
super + {o,i}
bspc wm -h off; \
bspc node {older,newer} -f; \
bspc wm -h on
# focus or send to the given desktop
super + {_,shift + }{1-9,0}
bspc {desktop -f,node -d} '^{1-9,10}'
#
# preselect
#
# preselect the direction
super + ctrl + {h,j,k,l}
bspc node -p {west,south,north,east}
# preselect the ratio
super + ctrl + {1-9}
bspc node -o 0.{1-9}
# cancel the preselection for the focused node
super + ctrl + space
bspc node -p cancel
# cancel the preselection for the focused desktop
super + ctrl + shift + space
bspc query -N -d | xargs -I id -n 1 bspc node id -p cancel
#
# move/resize
#
# expand a window by moving one of its side outward
super + alt + {h,j,k,l}
bspc node -z {left -20 0,bottom 0 20,top 0 -20,right 20 0}
# contract a window by moving one of its side inward
super + alt + shift + {h,j,k,l}
bspc node -z {right -20 0,top 0 20,bottom 0 -20,left 20 0}
# move a floating window
super + {Left,Down,Up,Right}
bspc node -v {-20 0,0 20,0 -20,20 0}

View File

@ -75,6 +75,9 @@ export EDITOR="nvim"
# Enable password store extensions # Enable password store extensions
export PASSWORD_STORE_ENABLE_EXTENSIONS="true" export PASSWORD_STORE_ENABLE_EXTENSIONS="true"
# This needs to be set for bspwm to see config
export XDG_CONFIG_HOME="$HOME/.config"
# Save history file in proper place # Save history file in proper place
HISTFILE=~/.cache/zsh/history HISTFILE=~/.cache/zsh/history