Preface
Goal: Monitoring widget in statusbar using Lain Library.
Using Lain Library, we can manage monitoring widget, in statusbar.
Table of Content
-
Preface: Table of Content
-
1: Prerequisite
1: Prerequisite
rc.lua
Put the statusbar code at the end of the rc.lua
,
and comment other statusbar.
-- Statusbar: Wibar
--local statusbar = require("statusbar.default.statusbar")
local statusbar = require("statusbar.lain.statusbar")
Prerequisite: The Lain Library
If your distribution does not support lain library,
you can clone Lain
in AwesomeWM configuration directory.
$ git clone https://github.com/lcpz/lain
Now you can include the lain
as any other library.
-- Standard awesome library
local awful = require("awful")
local beautiful = require("beautiful")
-- Wibox handling library
local wibox = require("wibox")
local lain = require("lain")
-- Custom Local Library
require("statusbar.lain.lain")
local gmc = require("themes.gmc")
Artefacts
We need additional lain.lua
.
$ tree ~/.config/awesome/statusbar/lain
/home/epsi/.config/awesome/statusbar/lain
├── helper_default.lua
├── helper_lain.lua
├── lain-battery.lua
├── lain-diskfree.lua
├── lain.lua
├── lain-sound.lua
└── statusbar.lua
Here I refactor long configuration in separate files,
such as battery
, diskfree
, and sound
.
Arrow Decoration
This part can be skipped, but I put it here anyway, just in case anyone looking for it
function WB.initdeco ()
-- Spacer
WB.spacer = wibox.widget.textbox(" ")
WB.spacerline = wibox.widget.textbox(" | ")
-- Separators lain
local separators = lain.util.separators
local arrow_color = gmc.color['red300']
WB.arrow_dl = separators.arrow_left("alpha", arrow_color)
WB.arrow_ld = separators.arrow_left(arrow_color, "alpha")
WB.arrow_dr = separators.arrow_right("alpha", arrow_color)
WB.arrow_rd = separators.arrow_right(arrow_color, "alpha")
end
Code Preview
For you impatient folks out there, here I represent, all modules that we are going to use.
Where the long lain.lua
configuration itself,
will be refactore into separated files as below:
Do not get intimidated with codes above. These can be explained step by step.
2: Simple Example: Memory
The best manual for lain is in the wiki, that you can read in its respective github. For example this Memory:
local mymem = lain.widget.mem()
However the detail implementation might different from, one dotfiles to another ricer.
lain.lua
Step by step, the lain.lua
.
-- Standard awesome library
local awful = require("awful")
local beautiful = require("beautiful")
-- Wibox handling library
local wibox = require("wibox")
local lain = require("lain")
-- Custom Local Library
local gmc = require("themes.gmc")
Since I have to separate files, I have these objects:
local W = {}
clone_widget_set = W -- object name
local I = {}
clone_icon_set = I -- object name
Formatting
Formatting code is cumbersome, so I made these two shortucts.
-- global for all splited
markup = lain.util.markup
Configuring Memory Widget
Now my code is slightly different
W.mem = lain.widget.mem({
settings = function()
widget:set_markup(markup(gmc.color['blue900'], mem_now.used .. "M "))
end
})
You can read more about mem_now.used
in its wiki.
Helper
As usual we put WB
object
-- Custom Local Library
require("statusbar.lain.lain")
local WB = wibox_package
function WB.add_widgets_monitor_left (line, s)
local cws = clone_widget_set
return {
layout = wibox.layout.fixed.horizontal,
-- time
WB.arrow_rd,
cws.mem,
}
end
Icon
If you wish, you can add eye candy icon, just like shown in the figure above.
I.mem = wibox.widget.imagebox(beautiful.widget_mem)
From icons.lua
in theme directory.
theme.widget_mem = icondir .. "memory.png"
And finally the helper
local WB = wibox_package
function WB.add_widgets_monitor_left (line, s)
local cws = clone_widget_set
local cis = clone_icon_set
return {
layout = wibox.layout.fixed.horizontal,
-- time
WB.arrow_rd,
cis.mem, cws.mem,
}
end
3: More Standard Example
With those arrangement above we can setup more widget.
Step by step, the lain.lua
.
CPU
I.cpu = wibox.widget.imagebox()
I.cpu:set_image(beautiful.widget_cpu)
W.cpu = lain.widget.cpu({
settings = function()
widget:set_markup(markup(gmc.color['green900'], cpu_now.usage .. "% "))
end
})
Text Clock
I.clock = wibox.widget.imagebox(beautiful.widget_clock)
W.textclock = awful.widget.textclock(
markup(gmc.color['blue900'], "%A %d %B ")
.. markup(gmc.color['black'], ">")
.. markup(gmc.color['green900'], " %H:%M "))
Weather
I.weather = wibox.widget.imagebox(beautiful.widget_weather)
W.weather = lain.widget.weather({
city_id = 1642911, -- http://openweathermap.org/city/1642911
settings = function()
descr = weather_now["weather"][1]["description"]:lower()
units = math.floor(weather_now["main"]["temp"])
local fg_color = "#000000" -- "#eca4c4"
widget:set_markup(markup(fg_color, descr .. " @ " .. units .. "°C "))
end
})
Network
I.netdown = wibox.widget.imagebox(beautiful.widget_netdown)
W.netdowninfo = wibox.widget.textbox()
W.netupinfo = lain.widget.net({
settings = function()
local fg_color_up = "#000000" -- "#e54c62"
local fg_color_down = "#000000" -- "#87af5f"
widget:set_markup(markup(fg_color_up, net_now.sent .. " "))
W.netdowninfo:set_markup(markup(fg_color_down, net_now.received .. " "))
end
})
Battery
-- Battery from copycat-multicolor
I.bat = wibox.widget.imagebox(beautiful.widget_batt)
W.bat = lain.widget.bat({
settings = function()
if bat_now.perc == "N/A" then
perc = "AC "
else
perc = bat_now.perc .. "% "
end
widget:set_markup(markup(gmc.color['blue900'], perc))
end
})
File system
I.fs = wibox.widget.imagebox(beautiful.widget_fs)
-- Can't create more than one fs widget
W.fs = lain.widget.fs({
settings = function()
widget:set_markup(markup(gmc.color['teal900'], fs_now["/"].percentage .. "% "))
end
})
ALSA
-- ALSA volume from copycat-multicolor
I.volume = wibox.widget.imagebox(beautiful.widget_vol)
W.volume = lain.widget.alsa({
settings = function()
if volume_now.status == "off" then
volume_now.level = volume_now.level .. "M"
end
widget:set_markup(markup(gmc.color['blue900'], volume_now.level .. "% "))
end
})
Music Player Daemon
-- MPD from copycat-multicolor
I.mpd = wibox.widget.imagebox(beautiful.widget_note)
W.mpd = lain.widget.mpd({
settings = function()
mpd_notification_preset = {
text = string.format("%s [%s] - %s\n%s", mpd_now.artist,
mpd_now.album, mpd_now.date, mpd_now.title)
}
if mpd_now.state == "play" then
artist = mpd_now.artist .. " > "
title = mpd_now.title .. " "
I.mpd:set_image(beautiful.widget_note_on)
elseif mpd_now.state == "pause" then
artist = "mpd "
title = "paused "
else
artist = ""
title = ""
I.mpd:set_image(nil)
end
widget:set_markup(markup(gmc.color['blue900'], artist)
.. markup(gmc.color['green900'], title))
end
})
Example One
Consider show the wdiget above in this example below:
function WB.add_widgets_monitor_left (line, s)
local cws = clone_widget_set
local cis = clone_icon_set
return {
layout = wibox.layout.fixed.horizontal,
-- net
WB.arrow_rd,
cis.netdown, cws.netdowninfo,
cis.netup, cws.netupinfo,
-- mem, cpu, files system, temp, batt
WB.arrow_dr, WB.arrow_rd,
cis.mem, cws.mem,
cis.cpu, cws.cpu,
cis.fs, cws.fs,
cis.bat, cws.bat,
-- wheather
WB.arrow_dr, WB.arrow_rd,
cis.weather, cws.weather,
-- at last , you can ignore this line below
WB.spacer,
}
end
Example Two
Or this example below:
function WB.add_widgets_monitor_left (line, s)
local cws = clone_widget_set
local cis = clone_icon_set
return {
layout = wibox.layout.fixed.horizontal,
-- time
WB.arrow_rd,
cis.clock, cws.textclock,
-- mpd
WB.arrow_dr, WB.arrow_rd,
cis.volume, cws.volume,
cis.mpd, cws.mpd,
-- at last , you can ignore this line below
WB.spacer,
}
end
4: Progressbar Widget
This is a little bit harder, since we should dive into container and margin, just to show widget progressbar.
Refactoring
For some reason I prefer to separate code so now we have this lines:
-- progress bar related widgets -- after global markup
local config_path = awful.util.getdir("config") .. "statusbar/lain/"
dofile(config_path .. "lain-diskfree.lua")
dofile(config_path .. "lain-battery.lua")
dofile(config_path .. "lain-sound.lua")
Battery Bar
The battery bar itself is battery_bar
widget.
I.battery = wibox.widget.imagebox(beautiful.monitor_bat)
W.battery_bar = wibox.widget {
forced_height = dpi(1),
forced_width = dpi(59),
color = theme.fg_normal,
background_color = theme.bg_normal,
margins = 1,
paddings = 1,
ticks = true,
ticks_size = dpi(6),
widget = wibox.widget.progressbar,
}
W.battery_margin = wibox.layout.margin(W.battery_bar, 2, 7)
W.battery_margin:set_top(6)
W.battery_margin:set_bottom(9)
W.batbg = wibox.container.background(
W.battery_bar, gmc.color['grey500'], gears.shape.rectangle)
W.battery_bar_widget = wibox.container.margin(
W.batbg, dpi(2), dpi(7), dpi(6), dpi(6))
Battery Updating
We utilize lain.widget.bat
as a trigger to update the battery bar.
-- Update bar, also in widgets popups
local battery_widget_settings = function()
if bat_now.status == "N/A" then return end
perc = tonumber(bat_now.perc)
if perc == nil then return end
if bat_now.status == "Charging" then
I.battery:set_image(beautiful.monitor_ac)
if perc >= 98 then
W.battery_bar:set_color(gmc.color['green300'])
elseif perc > 50 then
W.battery_bar:set_color(gmc.color['blue300'])
elseif perc > 15 then
W.battery_bar:set_color(beautiful.fg_normal)
else
W.battery_bar:set_color(gmc.color['red300'])
end
else
if perc >= 98 then
W.battery_bar:set_color(gmc.color['green300'])
elseif perc > 50 then
W.battery_bar:set_color(gmc.color['blue300'])
I.battery:set_image(beautiful.monitor_bat)
elseif perc > 15 then
W.battery_bar:set_color(beautiful.fg_normal)
I.battery:set_image(beautiful.monitor_bat_low)
else
W.battery_bar:set_color(gmc.color['red300'])
I.battery:set_image(beautiful.monitor_bat_no)
end
end
W.battery_bar:set_value(perc / 100)
end
W.battery_widget_update = lain.widget.bat({
settings = battery_widget_settings
})
Disk Free Bar
The diskfree bar itself is disk_bar
widget.
-- /home fs
I.disk = wibox.widget.imagebox(beautiful.monitor_disk)
W.disk_bar = wibox.widget {
forced_height = dpi(1),
forced_width = dpi(59),
color = theme.fg_normal,
background_color = theme.bg_normal,
margins = 1,
paddings = 1,
ticks = true,
ticks_size = dpi(6),
widget = wibox.widget.progressbar,
}
W.disk_margin = wibox.layout.margin(W.disk_bar, 2, 7)
W.disk_margin:set_top(6)
W.disk_margin:set_bottom(9)
W.disk_bar_widget = wibox.widget.background(W.disk_margin)
W.disk_bar_widget:set_bgimage(beautiful.bar_bg_copland)
W.disk_bg = wibox.container.background(
W.disk_bar, gmc.color['grey500'], gears.shape.rectangle)
W.disk_bar_widget = wibox.container.margin(
W.disk_bg, dpi(2), dpi(7), dpi(6), dpi(6))
Disk Free Update
We utilize lain.widget.fs
as a trigger to update the diskfree bar.
-- Update bar, also in widgets popups
local disk_widget_settings = function()
if fs_now["/"].used < 90 then
W.disk_bar:set_color(gmc.color['red300'])
else
W.disk_bar:set_color(gmc.color['blue300'])
end
W.disk_bar:set_value(fs_now["/"].percentage)
end
W.disk_widget = lain.widget.fs {
notification_preset = { fg = theme.fg_normal, bg = theme.bg_normal, font = "Terminus 10.5" },
settings = disk_widget_settings
}
ALSA Bar
Lain has this alsabar
widget
local volume_wibox_settings = function()
if volume_now.status == "off" then
I.volume_dynamic:set_image(beautiful.monitor_vol_mute)
elseif volume_now.level == 0 then
I.volume_dynamic:set_image(beautiful.monitor_vol_no)
elseif volume_now.level <= 50 then
I.volume_dynamic:set_image(beautiful.monitor_vol_low)
else
I.volume_dynamic:set_image(beautiful.monitor_vol)
end
end
local volume_wibox_colors = {
background = beautiful.bg_normal,
mute = gmc.color['red300'],
unmute = gmc.color['blue300']
}
W.volume_wibox = lain.widget.alsabar({
width = 55, ticks = true, ticks_size = 6, step = "2%",
settings = volume_wibox_settings,
colors = volume_wibox_colors
})
Now we can configure further
-- ALSA volume bar from copycat-copland
I.volume_dynamic = wibox.widget.imagebox(beautiful.monitor_vol)
W.volume_wibox.tooltip.wibox.fg = beautiful.fg_focus
W.volumebg = wibox.container.background(
W.volume_wibox.bar, gmc.color['grey500'], gears.shape.rectangle)
W.volumewidget = wibox.container.margin(
W.volumebg, dpi(2), dpi(7), dpi(6), dpi(6))
ALSA Update
We do not need. It is handled by Lain.
ALSA Volume Button
-- global terminal is required in alsabar, unfortunately
terminal = RC.vars.terminal
W.volume_wibox_buttons = my_table.join (
awful.button({}, 1, function()
awful.spawn(string.format("%s -e alsamixer", terminal))
end),
awful.button({}, 2, function()
os.execute(string.format("%s set %s 100%%", W.volume_wibox.cmd, W.volume_wibox.channel))
W.volume_wibox.update()
end),
awful.button({}, 3, function()
os.execute(string.format("%s set %s toggle", W.volume_wibox.cmd, W.volume_wibox.togglechannel or W.volume_wibox.channel))
W.volume_wibox.update()
end),
awful.button({}, 4, function()
os.execute(string.format("%s set %s 1%%+", W.volume_wibox.cmd, W.volume_wibox.channel))
W.volume_wibox.update()
end),
awful.button({}, 5, function()
os.execute(string.format("%s set %s 1%%-", W.volume_wibox.cmd, W.volume_wibox.channel))
W.volume_wibox.update()
end)
)
W.volume_wibox.bar:buttons(W.volume_wibox_buttons)
Helper
Now here is the alsa volume
, disk free
and battery
,
along with other widget
function WB.add_widgets_monitor_right (line, s)
local cws = clone_widget_set
local cis = clone_icon_set
return {
layout = wibox.layout.fixed.horizontal,
-- volume
WB.arrow_dl, WB.arrow_ld,
cis.volume_dynamic, cws.volumewidget,
-- disk
WB.arrow_dl, WB.arrow_ld,
cis.disk, cws.disk_bar_widget,
-- battery
WB.arrow_dl, WB.arrow_ld,
cis.battery, cws.battery_bar_widget,
-- at last
WB.arrow_dl
}
end
What is Next?
Now that we are done with lain
statusbar,
we can go down with ricing using arrow, lain
widget, and pallete colors.
Consider continue reading [ Awesome WM - Statusbar - Arrow ].