mirror of
https://github.com/alrayyes/dotfiles/
synced 2023-11-14 15:56:30 +00:00
Fix merge
This commit is contained in:
commit
d6e16ee827
1
.gitignore
vendored
1
.gitignore
vendored
@ -24,3 +24,4 @@ mutt/.config/mutt/.mailsynclastrun
|
||||
gtk/.config/gtk-3.0/bookmarks
|
||||
|
||||
mpd/.config/mpd/pid
|
||||
/emacs/.config/doom/configuration.el
|
||||
|
@ -1,5 +1,4 @@
|
||||
The MIT License (MIT)
|
||||
=====================
|
||||
* The MIT License (MIT)
|
||||
|
||||
Copyright (c) `2016` `Ryan Kes`
|
||||
|
57
README.md
57
README.md
@ -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
37
README.org
Normal 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
78
bspwm/.config/bspwm/bspwmrc
Executable 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
2
bspwm/.local/bin/scratch
Executable file
@ -0,0 +1,2 @@
|
||||
#!/usr/bin/sh
|
||||
st -c scratchpad
|
@ -11,4 +11,4 @@ export _JAVA_AWT_WM_NONREPARENTING=1
|
||||
export AWT_TOOLKIT=MToolkit
|
||||
wmname LG3D
|
||||
|
||||
exec dwm
|
||||
exec bspwm
|
@ -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
|
@ -1,56 +1,5 @@
|
||||
;;; .doom.d/config.el -*- lexical-binding: t; -*-
|
||||
|
||||
;; Place your private configuration here
|
||||
;; General settings
|
||||
(setq doom-font (font-spec :family "FuraCode Nerd Font Mono" :size 12)
|
||||
doom-theme 'doom-molokai)
|
||||
|
||||
;; projectile
|
||||
(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)
|
||||
(org-babel-load-file "~/.config/doom/configuration.org")
|
||||
|
87
emacs/.config/doom/configuration.org
Normal file
87
emacs/.config/doom/configuration.org
Normal 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
|
@ -5,3 +5,4 @@
|
||||
;; (package! some-package)
|
||||
;; (package! another-package :recipe (:host github :repo "username/repo"))
|
||||
;; (package! builtin-package :disable t)
|
||||
(package! counsel-spotify)
|
||||
|
13
polybar/.config/polybar/bin/isactive-bluetooth/README.md
Normal file
13
polybar/.config/polybar/bin/isactive-bluetooth/README.md
Normal 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
|
||||
```
|
7
polybar/.config/polybar/bin/isactive-bluetooth/isactive-bluetooth.sh
Executable file
7
polybar/.config/polybar/bin/isactive-bluetooth/isactive-bluetooth.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$(systemctl is-active bluetooth.service)" = "active" ]; then
|
||||
echo ""
|
||||
else
|
||||
echo ""
|
||||
fi
|
164
polybar/.config/polybar/bin/player-mpris-tail/README.md
Normal file
164
polybar/.config/polybar/bin/player-mpris-tail/README.md
Normal 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… ⏮ ⏵ ⏭ `
|
532
polybar/.config/polybar/bin/player-mpris-tail/player-mpris-tail.py
Executable file
532
polybar/.config/polybar/bin/player-mpris-tail/player-mpris-tail.py
Executable 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\1p\2p\3p', 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()
|
BIN
polybar/.config/polybar/bin/player-mpris-tail/screenshots/1.png
Normal file
BIN
polybar/.config/polybar/bin/player-mpris-tail/screenshots/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.0 KiB |
BIN
polybar/.config/polybar/bin/player-mpris-tail/screenshots/2.png
Normal file
BIN
polybar/.config/polybar/bin/player-mpris-tail/screenshots/2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.0 KiB |
24
polybar/.config/polybar/bin/updates-arch-combined/README.md
Normal file
24
polybar/.config/polybar/bin/updates-arch-combined/README.md
Normal 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 |
16
polybar/.config/polybar/bin/updates-arch-combined/updates-arch-combined.sh
Executable file
16
polybar/.config/polybar/bin/updates-arch-combined/updates-arch-combined.sh
Executable 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
|
422
polybar/.config/polybar/config
Normal file
422
polybar/.config/polybar/config
Normal 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
|
13
polybar/.local/bin/polybar-desktop
Executable file
13
polybar/.local/bin/polybar-desktop
Executable 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..."
|
13
polybar/.local/bin/polybar-laptop
Executable file
13
polybar/.local/bin/polybar-laptop
Executable 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..."
|
@ -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.
|
||||
)
|
@ -36,10 +36,6 @@ super + z
|
||||
super + c
|
||||
yubikey-oath-dmenu --clipboard clipboard --notify
|
||||
|
||||
# dmenu application launcher
|
||||
super + p
|
||||
dmenu-frecency
|
||||
|
||||
# Wireguard
|
||||
super + w
|
||||
vpn-switch
|
||||
@ -54,6 +50,128 @@ XF86Eject
|
||||
shift + XF86Eject
|
||||
prompt "Reboot computer?" "sudo -A shutdown -r now"
|
||||
|
||||
# Open frequent apps
|
||||
super + o ; {e,w,m,v,h,s,i,n,q,c}
|
||||
{emacs, $TERMINAL -e weather, $TERMINAL -e neomutt, $TERMINAL -e vifm, $TERMINAL -e htop, slack, $TERMINAL -e weechat, $TERMINAL -e newsboat, qtpass, $TERMINAL -e calendar}
|
||||
# scratchpad
|
||||
alt + {s,e}
|
||||
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}
|
||||
|
@ -75,6 +75,9 @@ export EDITOR="nvim"
|
||||
# Enable password store extensions
|
||||
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
|
||||
HISTFILE=~/.cache/zsh/history
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user