So I've been meaning to make (semi) detailed notes of my Arch Linux config files for a while now, in the hope that these notes will help me set up my Arch quickly if I ever have to do so from scratch. This is how my Arch currently looks. If you like what you see, read ahead!
The WM and related scripts:
Okay, so first things first, no DEs here (in the interest of being lightweight and productive). Right now I'm running i3wm with small (and dirty) custom scripts to add some common DE-like functionality that I find useful. So what all am I referring to?
First up, modifying i3bar to make it prettier and to extend its functionality. First up, the modifications to the bar settings in the i3config file:
Now for the scripts in the conkyrc file. All the commands/scripts are simple to understand and don't really need any explanation. The only script that probably warrants an explanation is music.sh. I use cmus as my music player so the script as-is will work only for if you use cmus too. However, with a couple of minor modifications, it should be possible to extend this to any music player that supports querying track information from the command line. The testmusic.sh script just tests if cmus is active using cmus-remote and returns 1 if it is active. The interesting script is music.sh:
The intended output is that the first 20 (15) characters of the song (artist) name should be displayed for 10 seconds. Then the rest of the song (artist) name should scroll on the screen, one character at at time, and finally it should pause at the last 20 characters of the song (artist) name for 5 seconds before the same cycle starts again. After we extract the song name, artist and elapsed time, we format the elapsed and total time so that they can be displayed beautifully (8 seconds should be displayed as 00:08 and not 0:8). Then if the song name length is greater than 20 characters, we find out what range of characters need to be displayed depending on the elapsed time (some fairly straightforward math in there), and use cut to pick out those characters. We repeat the same for the artist name. So now we have a working music player widget for our bar!
That's all there is to the beautiful looking i3bar.
Next up, the important bindings in the i3 config file:
I use variety + feh to get the beautiful looking clock on my desktop and to shuffle through my wallpaper collection. To get variety to use feh (this is disabled by default due to some issues in Ubuntu), uncomment the line that executes the feh command in set_wallpaper in your variety config folder. The font used for the clock in the screenshot is called Akbar Plain, and the date font is called Alba Super Regular.
The notification daemon that I use is called dunst; it is nice and simple, and serves all my purposes. I use it primarily to receive notifications about two types of events - volume changes and low battery warnings. This is a simple script that displays the volume as a notification:
The first line gets the volume value and the subsequent call to dunstify displays it. The -u critical/normal flags are just used to display different colors when muted/unmuted. The -r ensures that the volume notification always gets the same notification ID (if there are many calls to the script in a short span of time, the previous notifications shouldn't linger, rather, they should be replaced by the newer notifications).
Now for the low battery warning script:
We check if the battery is discharging, the warning notifications are only displayed then. If the battery is full and discharging, the full battery notification is displayed. The rest is fairly straightforward, the percentage and time remaining and retrieved and displayed. Finally, depending on the percentage value, the script is put to sleep for either a minute, 2 minutes, 4 minutes or 5 minutes.
Two final things: the script /usr/bin/dmenu_run can be modified to detach created processes from their parent shells by changing the execute command to: exec $(dmenu_path | dmenu "$@"), and a command line file manager like ranger can be used to make the task of browsing files easier.
Phew! I guess that covers the WM configuration part. That's all the time I have right now, so I'm going to defer explaining the configuration settings for my terminal emulator (urxvtd+c), text editor (vim), media player + nVidia integration (mpv), music player (cmus) and shell (zsh) to future blog posts.
Home sweet home |
Work in progress |
The WM and related scripts:
Okay, so first things first, no DEs here (in the interest of being lightweight and productive). Right now I'm running i3wm with small (and dirty) custom scripts to add some common DE-like functionality that I find useful. So what all am I referring to?
- A modified i3bar that shows me the information that I require and of course looks good too. There are some scripts in here to fetch and display the information that I require, but I'll get to that in a bit.
- Some custom i3 keyboard bindings to speed common tasks.
- Labelling of workspaces to organize my windows.
- A wallpaper changer to shuffle and display my massive wallpaper collection.
- A notification daemon and scripts to display some useful notifications.
- A modification to dmenu to detach launched processes from their parent shells.
- A good command line file manager.
First up, modifying i3bar to make it prettier and to extend its functionality. First up, the modifications to the bar settings in the i3config file:
bar {
mode dock
font pango:DejaVuSansCondensed regular 6.5
colors {Nothing fancy here, some color settings, an appropriate font and size, and specifying dock mode. The last two lines are important. I am using conky 1.10.0 to add the colors and formatting. The first command tells conky to use the .conkyrc config file in my home folder. This is the file (most of the stuff in there is pretty easy to understand):
# Show status text in light blue color
#statusline #ADD8E6
background #222222
statusline #dddddd
separator #666666
active_workspace #333333 #333333 #888888
focused_workspace #0088CC #0088CC #ffffff
inactive_workspace #333333 #333333 #888888
urgent_workspace #2f343a #900000 #ffffff
}
status_command conky -c ~/.conkyrc
status_command /home/anant/.i3/i3bar-wrapper.sh
}
out_to_x noBefore I get to the scripts mentioned in the conky config file, let me just touch on the last thing, the wrapper for i3bar. The last line in the bar part of the i3 config file points to a wrapper for i3bar that lets it display information from conky. This is the content of i3bar-wrapper.sh:
out_to_console yes
short_units yes
update_interval 1
#use_spacer left
#pad_percents 2
if_up_strictness address
TEXT
[\
# Music:
{"full_text":"${if_match ${exec ~/.i3/testmusic.sh}>=1}♫","color":"\#ffffff","separator":false,"separator_block_width":5},\
{"full_text":"${exec ~/.i3/music.sh}","color":"\#EC3B83","separator":true,"separator_block_width":8},\
{"full_text":"${endif}"},\
# Mounted Devices:
{"full_text":"${if_match ${exec ~/.i3/hasmounted.sh}>=1} USB","color":"\#888888","separator":false,"separator_block_width":6},\
{"full_text":"${exec ~/.i3/getmounteddevices.sh} ","color":"\#F0DC64","separator":true,"separator_block_width":6},\
{"full_text":"${endif}"},\
# Disk Usage:
{"full_text":" 💾","color":"\#aaaaaa","separator":false,"separator_block_width":6},\
{"full_text":"${execi 3600 df -h --output=avail / | tail -n1 | sed -e 's/\s//g'} ","color":"\#FF9933","separator":true,"separator_block_width":6},\
# Internet:
{"full_text":"${if_up enp60s0}"},\
{"full_text":" LAN","color":"\#888888","separator":false,"separator_block_width":6},\
{"full_text":"${addr enp60s0} ","color":"\#00ff00","separator":true,"separator_block_width":9},\
{"full_text":"${endif}"},\
{"full_text":"${if_up br0}"},\
{"full_text":" BRIDGE","color":"\#888888","separator":false,"separator_block_width":6},\
{"full_text":"${addr br0} ","color":"\#00ff00","separator":true,"separator_block_width":9},\
{"full_text":"${endif}"},\
{"full_text":"${if_up enp0s20u1}"},\
{"full_text":" USB","color":"\#888888","separator":false,"separator_block_width":6},\
{"full_text":"${addr enp0s20u1} ","color":"\#00ff00","separator":true,"separator_block_width":9},\
{"full_text":"${endif}"},\
{"full_text":"${if_up wls1}"},\
{"full_text":" Wi-Fi","color":"\#888888","separator":false,"separator_block_width":6},\
{"full_text":"(${exec iwgetid -r})","color":"\#EC3B83","separator":false,"separator_block_width":6},\
{"full_text":"${addr wls1} ","color":"\#00ff00","separator":true,"separator_block_width":9},\
{"full_text":"${endif}"},\
{"full_text":"${if_up enp60s0}"},\
{"full_text":"${else}"},\
{"full_text":"${if_up enp0s20u1}"},\
{"full_text":"${else}"},\
{"full_text":"${if_up br0}"},\
{"full_text":"${else}"},\
{"full_text":"${if_up wls1}"},\
{"full_text":"${else}"},\
{"full_text":" No Internet ","color":"\#ff3300","separator":true,"separator_block_width":9},\
{"full_text":"${endif}${endif}${endif}${endif}"},\
# CPU temperature:
{"full_text":" CPU","color":"\#888888","separator":false,"separator_block_width":6},\
{"full_text":"${if_match ${hwmon 0 temp 1}<50}${hwmon 0 temp 1}","color":"\#AAF096","separator":false,"separator_block_width":0},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${hwmon 0 temp 1}<55}${hwmon 0 temp 1}","color":"\#F0DC64","separator":false,"separator_block_width":0},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${hwmon 0 temp 1}<60}${hwmon 0 temp 1}","color":"\#FF9933","separator":false,"separator_block_width":0},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${hwmon 0 temp 1}>=60}${hwmon 0 temp 1}","color":"\#FF3333","separator":false,"separator_block_width":0},\
{"full_text":"${else}"},\
{"full_text":"${endif}${endif}${endif}${endif}"},\
{"full_text":"°C ","color":"\#7FFFD4","separator":true,"separator_block_width":6},\
# GPU temperature:
{"full_text":" GPU","color":"\#888888","separator":false,"separator_block_width":6},\
{"full_text":"${execi 5 nvidia-settings -q gpucoretemp -t | head -n1}","color":"\#AAF096","separator":false,"separator_block_width":0},\
{"full_text":"°C ","color":"\#7FFFD4","separator":true,"separator_block_width":6},\
# Memory:
{"full_text":" MEM","color":"\#888888","separator":false,"separator_block_width":6},\
{"full_text":"${if_match ${memperc}<30}${mem} / ${memmax} ","color":"\#AAF096","separator":true,"separator_block_width":9},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${memperc}<60}${mem} / ${memmax} ","color":"\#F0DC64","separator":true,"separator_block_width":9},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${memperc}<85}${mem} / ${memmax} ","color":"\#FF9933","separator":true,"separator_block_width":9},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${memperc}>=85}${mem} / ${memmax} ","color":"\#FF3333","separator":true,"separator_block_width":9},\
{"full_text":"${endif}${endif}${endif}${endif}"},\
# CPU:
{"full_text":" 💻","color":"\#aaaaaa","separator":false,"separator_block_width":6},\
{"full_text":"${if_match ${cpu cpu0}<25}${cpu cpu0}","color":"\#AAF096","separator":false,"separator_block_width":0},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${cpu cpu0}<50}${cpu cpu0}","color":"\#F0DC64","separator":false,"separator_block_width":0},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${cpu cpu0}<75}${cpu cpu0}","color":"\#FF9933","separator":false,"separator_block_width":0},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${cpu cpu0}<=100}${cpu cpu0}","color":"\#FF3333","separator":false,"separator_block_width":0},\
{"full_text":"${endif}${endif}${endif}${endif}"},\
{"full_text":"% ","color":"\#EEEEEE","separator":true,"separator_block_width":8},\
# Battery:
{"full_text":"${if_match ${exec ~/.i3/batterystatus.sh}>=2} 🔌","color":"\#aaaaaa","separator":false,"separator_block_width":5},\
{"full_text":"ON ","color":"\#00ff00","separator":true,"separator_block_width":6},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${exec ~/.i3/batterystatus.sh}>=1} 🔌","color":"\#aaaaaa","separator":false,"separator_block_width":5},\
{"full_text":"${else}"},\
{"full_text":" 🔋","color":"\#aaaaaa","separator":false,"separator_block_width":7},\
{"full_text":"${endif}"},\
{"full_text":"${if_match ${battery_percent}>80}${battery_percent}% : ${battery_time} ","color":"\#AAF096","separator":true,"separator_block_width":6},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${battery_percent}>50}${battery_percent}% : ${battery_time} ","color":"\#F0DC64","separator":true,"separator_block_width":6},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${battery_percent}>25}${battery_percent}% : ${battery_time} ","color":"\#FF9933","separator":true,"separator_block_width":6},\
{"full_text":"${else}"},\
{"full_text":"${battery_percent}% : ${battery_time} ","color":"\#FF3333","separator":true,"separator_block_width":6},\
{"full_text":"${endif}${endif}${endif}"},\
{"full_text":"${endif}"},\
# Backlight:
{"full_text":" 🔅","color":"\#FFFFFF","separator":false,"separator_block_width":6},\
{"full_text":"${exec xbacklight | cut -d '.' -f1}% ","color":"\#ff8080","separator":true,"separator_block_width":6},\
# Volume:
{"full_text":" 🔊","color":"\#AAAAAA","separator":false,"separator_block_width":7},\
{"full_text":"${exec ~/.i3/getvolume.sh} ","color":"\#ff8080","separator":true,"separator_block_width":8},\
# Date:
{"full_text":" 📅","color":"\#aaaaaa","separator":false,"separator_block_width":8},\
{"full_text":"${time %D} ${execi 3600 date | cut -d ' ' -f1 | awk '{print toupper($0)}'} ","color":"\#7FFFD4","separator":true,"separator_block_width":8},\
# Time:
{"full_text":" ⏰","color":"\#FFFFFF","separator":false,"separator_block_width":7},\
{"full_text":"${time %r}","color":"\#7FFFD4","separator":true}\
],
#!/bin/sh
echo '{"version":1}'
echo '['So the first line tells i3bar that we are using JSON, and the second line starts the endless array of inputs. Finally the last two lines are the loop part where an empty array of blocks and the information from conky are sent to i3bar.
echo '[],'
exec conky -c /home/$USER/.conkyrc
Now for the scripts in the conkyrc file. All the commands/scripts are simple to understand and don't really need any explanation. The only script that probably warrants an explanation is music.sh. I use cmus as my music player so the script as-is will work only for if you use cmus too. However, with a couple of minor modifications, it should be possible to extend this to any music player that supports querying track information from the command line. The testmusic.sh script just tests if cmus is active using cmus-remote and returns 1 if it is active. The interesting script is music.sh:
#!/bin/shOkay, so what's going on here? Remember those Mp3 players that we used to get in the early 2000s with inbuilt flash memory and small digital displays? Remember how the song names used to scroll on the screen, character by character, at the rate of one character a second? That is exactly what this script does. It returns a substring of the song name and the artist name to conky, and this text when displayed on the screen makes it look like the song text is scrolling.
artist=$(cmus-remote -Q | grep ' artist ' | cut -d ' ' -f3- | sed -e 's/\&/and/g')
song=$(cmus-remote -Q | grep ' title ' | cut -d ' ' -f3- | sed -e 's/\&/and/g')
songlen=${#song}
artistlen=${#artist}
duration=$(cmus-remote -Q | grep duration | cut -d ' ' -f2-)
elapsed=$(cmus-remote -Q | grep position | cut -d ' ' -f2-)
dmin=$(($duration/60))
dsec=$(($duration%60))
if [ "$dsec" -lt "10" ]; then
dsec="0$dsec"
fi
emin=$(($elapsed/60))
esec=$(($elapsed%60))
if [ "$esec" -lt "10" ]; then
esec="0$esec"
fi
if [ "$songlen" -gt "20" ]; then
modlen=$songlen
offset=$(($elapsed % $modlen))
if [ "$offset" -ge "$(($songlen-10))" ]; then
song=$(echo $song | cut -c $(($songlen-19))-)
elif [ "$offset" -gt "10" ]; then
offset=$(($offset - 10))
song=$(echo $song | cut -c $offset-$(($offset+19)))
else
song=$(echo $song | cut -c -20)
fi
fi
if [ "$artistlen" -gt "15" ]; then
modlen=$artistlen
offset=$(($elapsed % $modlen))
if [ "$offset" -ge "$(($artistlen-5))" ]; then
artist=$(echo $artist | cut -c $(($artistlen-14))-)
elif [ "$offset" -gt "10" ]; then
offset=$(($offset - 10))
artist=$(echo $artist | cut -c $offset-$(($offset+14)))
else
artist=$(echo $artist | cut -c -15)
fi
fi
echo "$song -- $artist ($emin:$esec/$dmin:$dsec) "
The intended output is that the first 20 (15) characters of the song (artist) name should be displayed for 10 seconds. Then the rest of the song (artist) name should scroll on the screen, one character at at time, and finally it should pause at the last 20 characters of the song (artist) name for 5 seconds before the same cycle starts again. After we extract the song name, artist and elapsed time, we format the elapsed and total time so that they can be displayed beautifully (8 seconds should be displayed as 00:08 and not 0:8). Then if the song name length is greater than 20 characters, we find out what range of characters need to be displayed depending on the elapsed time (some fairly straightforward math in there), and use cut to pick out those characters. We repeat the same for the artist name. So now we have a working music player widget for our bar!
The result |
That's all there is to the beautiful looking i3bar.
Next up, the important bindings in the i3 config file:
bindsym $mod+Return exec urxvtcNone of this really needs any explaining, but the next few paragraphs will explain some of the referenced scripts.
# hide the i3bar
bindsym $mod+m bar mode toggle
# hide the window titles
bindsym $mod+b border toggle
for_window [class="^.*"] border pixel 1
# Volume controls
bindsym XF86AudioRaiseVolume exec /usr/bin/bash /home/anant/.i3/increasevolume.sh && /usr/bin/bash /home/anant/.i3/volume.sh && killall -SIGUSR1 conky
bindsym XF86AudioLowerVolume exec /usr/bin/bash /home/anant/.i3/decreasevolume.sh && /usr/bin/bash /home/anant/.i3/volume.sh && killall -SIGUSR1 conky
bindsym XF86AudioMute exec amixer -q set Master toggle && killall -SIGUSR1 conky
bindsym XF86MonBrightnessUp exec xbacklight -inc 5 && killall -SIGUSR1 conky
bindsym XF86MonBrightnessDown exec xbacklight -dec 5 && killall -SIGUSR1 conky
# Keyboard backlight scripts for ASUS
bindsym XF86KbdBrightnessUp exec sudo /home/anant/.i3/asus_kbd_backlight_permission.sh && /usr/bin/bash /home/anant/.i3/asus_kbd_backlight.sh inc
bindsym XF86KbdBrightnessDown exec sudo /home/anant/.i3/asus_kbd_backlight_permission.sh && /usr/bin/bash /home/anant/.i3/asus_kbd_backlight.sh dec
bindsym $mod+F2 exec xbacklight -dec 5 && killall -SIGUSR1 conky
bindsym $mod+F3 exec xbacklight -inc 5 && killall -SIGUSR1 conky
# Lock screen shortcut
bindsym Mod4+Shift+l exec i3lock -i /home/anant/.config/variety/Downloaded/wallbase_macro/wallpaper-2684199.png -p default -d -n -f
bindsym Mod4+Shift+s exec systemctl suspend
bindsym $mod+Shift+n exec /usr/bin/variety --next
bindsym $mod+Shift+p exec /usr/bin/variety --previous
exec --no-startup-id /usr/bin/variety
exec --no-startup-id /usr/bin/dunst
exec --no-startup-id /home/anant/.i3/lowbattery.sh
# Creating named workspaces
set $tag1 "1: Web"
bindsym $mod+1 workspace $tag1
bindsym $mod+Shift+1 move container to workspace $tag1
set $tag2 "2: DC++"
bindsym $mod+2 workspace $tag2
bindsym $mod+Shift+2 move container to workspace $tag2
set $tag3 "3: Music"
bindsym $mod+3 workspace $tag3
bindsym $mod+Shift+3 move container to workspace $tag3
set $tag4 "4: Code"
bindsym $mod+4 workspace $tag4
bindsym $mod+Shift+4 move container to workspace $tag4
set $tag5 "5: ToDo"
bindsym $mod+5 workspace $tag5
bindsym $mod+Shift+5 move container to workspace $tag5
# Media controls
bindsym $mod+Shift+Home exec /usr/bin/cmus-remote -n && killall -SIGUSR1 conky
bindsym $mod+Shift+End exec /usr/bin/cmus-remote -r && killall -SIGUSR1 conky
bindsym XF86AudioNext exec /usr/bin/cmus-remote -n && killall -SIGUSR1 conky
bindsym XF86AudioPrev exec /usr/bin/cmus-remote -r && killall -SIGUSR1 conky
bindsym XF86AudioPlay exec /bin/bash /home/anant/.i3/cmusplaypause
bindsym XF86AudioPause exec /usr/bin/cmus-remote -u
bindsym $mod+Shift+Delete exec /bin/bash /home/anant/.i3/cmusplaypause
# Move to left/right workspace
bindsym Control+$mod+Left workspace prev
bindsym Control+$mod+Right workspace next
I use variety + feh to get the beautiful looking clock on my desktop and to shuffle through my wallpaper collection. To get variety to use feh (this is disabled by default due to some issues in Ubuntu), uncomment the line that executes the feh command in set_wallpaper in your variety config folder. The font used for the clock in the screenshot is called Akbar Plain, and the date font is called Alba Super Regular.
The variety clock+date setup |
The notification daemon that I use is called dunst; it is nice and simple, and serves all my purposes. I use it primarily to receive notifications about two types of events - volume changes and low battery warnings. This is a simple script that displays the volume as a notification:
#!/bin/bash
vol=$(amixer get Master | grep % | cut -d ' ' -f7 | cut -c 2- | cut -d ']' -f1 | head -n1)
if amixer get Master | grep -q "off"; then
dunstify -r 999 -u critical -t 1 "Volume: $vol (Muted)"
else
dunstify -r 999 -u normal -t 1 "Volume: $vol"
fi
Volume notifications |
The first line gets the volume value and the subsequent call to dunstify displays it. The -u critical/normal flags are just used to display different colors when muted/unmuted. The -r ensures that the volume notification always gets the same notification ID (if there are many calls to the script in a short span of time, the previous notifications shouldn't linger, rather, they should be replaced by the newer notifications).
Now for the low battery warning script:
#!/bin/bash
while true; do
state=$(acpi -b | cut -d ' ' -f3 | head -c-2)
perc=$(acpi -b | cut -d ' ' -f4 | head -c-3)
if [ "$state" == "Discharging" ]; then
if [ "$perc" -lt "15" ]; then
/usr/bin/dunstify -r 998 -u critical "Battery Critically Low! (${perc}%)\n$(acpi -b | cut -d ' ' -f 5-)"
sleep 60
elif [ "$perc" -lt "20" ]; then
/usr/bin/dunstify -r 998 -u normal "Battery Level Low (${perc}%)\n$(acpi -b | cut -d ' ' -f 5-)"
sleep 120
elif [ "$perc" -lt "30" ]; then
/usr/bin/dunstify -r 998 -u low "Battery Level Low (${perc}%)\n$(acpi -b | cut -d ' ' -f 5-)"
sleep 240
else
sleep 300
fi
else
if [ "$perc" == "100" ]; then
/usr/bin/dunstify -r 998 -u low "Battery Full (100%)"
sleep 600
else
sleep 300
fi
fi
done
We check if the battery is discharging, the warning notifications are only displayed then. If the battery is full and discharging, the full battery notification is displayed. The rest is fairly straightforward, the percentage and time remaining and retrieved and displayed. Finally, depending on the percentage value, the script is put to sleep for either a minute, 2 minutes, 4 minutes or 5 minutes.
Battery notifications using dunst |
Two final things: the script /usr/bin/dmenu_run can be modified to detach created processes from their parent shells by changing the execute command to: exec $(dmenu_path | dmenu "$@"), and a command line file manager like ranger can be used to make the task of browsing files easier.
Phew! I guess that covers the WM configuration part. That's all the time I have right now, so I'm going to defer explaining the configuration settings for my terminal emulator (urxvtd+c), text editor (vim), media player + nVidia integration (mpv), music player (cmus) and shell (zsh) to future blog posts.