Продолжение моего т.н. знакомства с WM Awesome
Тут объявляем все виджеты, которые буду использоваться. Сразу стоит отметить баг — при нажатии клавиши «отключить звук» звук исчезает, при повторном нажатии — на виджете отображает, что звук включён, но его нету. Приходится прописывать команду вручную в консоли, странно. Пока не нашёл как его исправить. И ещё смущает отображаение громкости — 90% по факту ~70 единиц в alsamixer, надо бы исправить, но никак не дойдёт руки. Ну а остальное вроде как интуитивно понятно
---------------------
--- Виджеты ---
---------------------
opening_brace = '<span foreground="white" font_desc="Ubuntu">[</span>'
closing_brace = '<span foreground="white" font_desc="Ubuntu">] </span>'
function enbrace(str)
return " "..opening_brace..str..closing_brace..' '
end
function colorify(str, color)
return '<span foreground="'..color..'">'..str..'</span>'
end
function get_colorload(val)
local color = 'green'
if val > 85 then
color = 'red'
elseif val > 60 then
color = 'yellow'
end
return color
end
function format_throughput(val)
if (val < 1000) then
return string.format('%3dKB/s', val)
elseif (val < 10240) then
return string.format('%.1fMB/s', val/1024)
else
return string.format('%3dMB/s', val/1024)
end
end
one_sec_timer = timer{timeout = 1}
ten_sec_timer = timer{timeout = 10}
spacer_big = wibox.widget.textbox()
spacer_big:set_text(' ')
spacer_small = wibox.widget.textbox()
spacer_small:set_text(' ')
volumecfg = {}
volumecfg.cardid = 0
volumecfg.channel = "Master"
volumecfg.widget = wibox.widget.textbox()
vol_color = {}
-- command must start with a space!
volumecfg.mixercommand = function (command)
local fd = io.popen("amixer -c " .. volumecfg.cardid .. command)
local status = fd:read("*all")
fd:close()
local volume = string.match(status, "(%d?%d?%d)%%")
volume = string.format("% 3d", volume)
status = string.match(status, "%[(o[^%]]*)%]")
if string.find(status, "on", 1, true) then
volume = volume .. "%"
vol_color="cyan"
else
volume = volume .. "×"
vol_color = "red"
end
volumecfg.widget:set_markup(enbrace(colorify(volume, vol_color)))
end
volumecfg.update = function ()
volumecfg.mixercommand(" sget " .. volumecfg.channel)
end
volumecfg.up = function ()
volumecfg.mixercommand(" sset " .. volumecfg.channel .. " 1%+")
end
volumecfg.down = function ()
volumecfg.mixercommand(" sset " .. volumecfg.channel .. " 1%-")
end
volumecfg.toggle = function ()
volumecfg.mixercommand(" sset " .. volumecfg.channel .. " toggle")
end
volumecfg.update()
client.connect_signal("manage", function (c, startup)
c.size_hints_honor = false
end)
batterybox = wibox.widget.textbox()
function battery ()
local io_info = io.open("/proc/acpi/battery/BAT0/info")
local io_state = io.open("/proc/acpi/battery/BAT0/state")
local str_info = io_info:read("*a")
local str_state = io_state:read("*a")
io.close(io_info)
io.close(io_state)
local capacity = str_info:match("last full capacity:%s+(%d+)")
local current = str_state:match("remaining capacity:%s+(%d+)")
local state = str_state:match("charging state:%s+(%a+)")
local rate = str_state:match("present rate:%s+(%d+)")
local st_color = 'green'
if state == 'discharging' then
st_color = 'red'
elseif state == 'charging' then
st_color = 'yellow'
end
local remain_time_str = 'inf'
remain_chrg = ((current * 100) / capacity)
if (('discharging' == state) and (nil ~= rate) and (rate > '0')) then
remain_time = current/rate
remain_time_str = string.format('%dh %.2dm', remain_time, remain_time*60%60)
end
local rem_color = 'red'
if remain_chrg > 15 then
rem_color = 'yellow'
end
if remain_chrg > 60 then
rem_color = 'green'
end
batterybox:set_markup( enbrace(colorify('bat: ', 'orange')
..colorify(string.format("%d%%", remain_chrg), rem_color)
..', '
..colorify(remain_time_str, rem_color)
..', '
..colorify(state, st_color)))
end
battery()
ten_sec_timer:connect_signal("timeout", battery)
membox = wibox.widget.textbox()
function memory()
local io_meminfo = io.open("/proc/meminfo")
local str_meminfo = io_meminfo:read("*a")
io.close(io_meminfo)
local total = str_meminfo:match("MemTotal:%s+(%d+)")
local free = str_meminfo:match("MemFree:%s+(%d+)")
local buffers = str_meminfo:match("Buffers:%s+(%d+)")
local cached = str_meminfo:match("Cached:%s+(%d+)")
local swap_total = str_meminfo:match("SwapTotal:%s+(%d+)")
local swap_free = str_meminfo:match("SwapFree:%s+(%d+)")
local swap_cached = str_meminfo:match("SwapCached:%s+(%d+)")
local total_free = free + buffers + cached
local total_swap_free = swap_free + swap_cached
local p_mem = 100*(total - total_free)/total
local mem_color = get_colorload(p_mem)
local sw_mem = 100*(swap_total - total_swap_free)/swap_total
local sw_mem_color = get_colorload(sw_mem)
local p_mem = 100*(total - total_free)/total
local mem_color = get_colorload(p_mem)
local sw_mem = 100*(swap_total - total_swap_free)/swap_total
local sw_mem_color = get_colorload(sw_mem)
membox:set_markup(enbrace(
colorify('mem: ', 'orange')
..colorify(string.format('%2d%%', p_mem), mem_color)
..'('..colorify(string.format('%3dMb', (total - total_free)/1024), mem_color)
..colorify(string.format('/%3dMb', (total)/1024), 'white')
..')'
..' | '
..colorify('swap: ', 'orange')
..colorify(string.format('%2d%%', sw_mem), sw_mem_color)
..'('..colorify(string.format('%3dMb', (swap_total - total_swap_free)/1024), sw_mem_color)
..colorify(string.format('/%3dMb', (swap_total)/1024), 'white')
..')'
)
)
end
memory()
one_sec_timer:connect_signal("timeout", memory)
-- CPU usage widget
cpugraph = awful.widget.graph()
cpugraph:set_width(75)
cpugraph:set_height(25)
cpugraph:set_background_color("#494B4F")
--cpugraph:set_color("#FF5656")
cpugraph:set_color({ type = "horisontal", from = { 0, 0 }, to = { 0, 20 }, stops = { { 0, "#FF5656" }, { 0.5, "#88A175" }, { 1, "#AECF96" } }})
-- Register CPU widget
vicious.register(cpugraph, vicious.widgets.cpu,
function (widget, args)
return args[1]
end)
cpubox = wibox.widget.textbox()
cpubox_img = wibox.widget.imagebox()
cpu_arr = {}
cpu0_arr = {}
cpu1_arr = {}
for i = 0, 4 do
cpu_arr[i] = 0
cpu0_arr[i] = 0
cpu1_arr[i] = 0
end
function parse_cpu(cpu, stat)
local cpu_new = {}
local ret = {}
cpu_new[0], cpu_new[1], cpu_new[2], cpu_new[3], cpu_new[4] = stat:match("cpu%d*%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)")
local idle = (cpu_new[3] - cpu[3]) + (cpu_new[4] - cpu[4])
local user = (cpu_new[1] - cpu[1]) + (cpu_new[0] - cpu[0])
local system = (cpu_new[2] - cpu[2])
local total = idle + user + system
local busy = user + system
ret['busy'] = busy*100/total
ret['sys'] = system*100/total
ret['user'] = user*100/total
ret['cpu'] = cpu_new
return ret
end
function cpu()
local io_stat = io.open("/proc/stat")
local str_stat = io_stat:read("*l")
io.close(io_stat)
local ret = parse_cpu(cpu_arr, str_stat)
cpu_arr = ret['cpu']
cpubox:set_markup (enbrace(colorify('cpu: ', 'orange')
..'('
..colorify(string.format('%3d%%', ret['busy']), get_colorload(ret['busy']))
..') | (u:'
..colorify(string.format('%3d%%', ret['user']), get_colorload(ret['user']))
..', s:'
..colorify(string.format('%3d%%', ret['sys']), get_colorload(ret['sys']))
..')'))
end
cpu()
one_sec_timer:connect_signal("timeout", cpu)
hddbox = wibox.widget.textbox()
hdd_r = 0
hdd_w = 0
hddlist = {'/sys/block/sda/stat', '/sys/block/sdb/stat'}
function hdd()
local new_r = 0
local new_w = 0
for i = 1, 2 do
local io_stat = io.open(hddlist[i])
local str_stat = io_stat:read("*a")
io.close(io_stat)
local rd, wr = str_stat:match("%s+%d+%s+%d+%s+(%d+)%s+%d+%s+%d+%s+%d+%s+(%d+)")
new_w = new_w + wr
new_r = new_r + rd
end
local r = (new_r - hdd_r)/2
local w = (new_w - hdd_w)/2
hdd_w = new_w
hdd_r = new_r
hddbox:set_markup ( enbrace(colorify('i/o: ', 'orange')
..'(r: '
..colorify(format_throughput(r), 'green')
..', w:'
..colorify(format_throughput(w), 'green')
..')'))
end
-- RAM usage widget
memwidget = awful.widget.progressbar()
memwidget:set_width(30)
memwidget:set_height(25)
memwidget:set_vertical(true)
memwidget:set_background_color('#494B4F')
memwidget:set_color('#AECF96')
cpugraph:set_color({ type = "linear", from = { 0, 0 }, to = { 0, 20 }, stops = { { 0, "#AECF96" }, { 0.5, "#88A175" }, { 1, "#FF5656" } }})
vicious.cache(vicious.widgets.mem)
vicious.register(memwidget, vicious.widgets.mem,
function (widget, args)
return args[1]
end, 1)
--update every 13 seconds
hdd()
one_sec_timer:connect_signal("timeout", hdd)
-- Start timers to update widgets
one_sec_timer:start()
ten_sec_timer:start()
-- Часы и дата
text_clock = awful.widget.textclock()
-- Create a systray
systray = wibox.widget.systray()
Знаю, что верхнюю и нижнюю панель можно было создать вместе, а не разделять, и так наверное было бы даже грамотнее, но у меня руки не доходят переписать. Собственно в этой части мы создаём теги и отображаем виджеты.
--------------------------------------------------
--- Декларируем список тэгов #1 ---
--------------------------------------------------
main_wibox = {}
prompt_box = {}
layout_box = {}
tag_list = {}
-- Задаем обработку кнопок мыши для списка тегов
tag_list.buttons = awful.util.table.join(
-- Отобразить тэг
awful.button({ }, left_button, awful.tag.viewonly ),
-- Переместить клиент на данный тэг
awful.button({ modkey }, left_button, awful.client.movetotag ),
-- Отобразить выбранный тэг вместе с текущим
awful.button({ }, right_button, awful.tag.viewtoggle ),
-- Отобразить текущий клиент в текущем и выбранном тэге
awful.button({ modkey }, right_button, awful.client.toggletag ),
-- Следующий тэг
awful.button({ }, plus_button, function(t) awful.tag.viewnext(awful.tag.getscreen(t)) end ),
-- Предыдущий тэг
awful.button({ }, minus_button, function(t) awful.tag.viewprev(awful.tag.getscreen(t)) end )
)
---------------------------------------------------
--- Декларируем список задач #1 ---
---------------------------------------------------
-- Задаем обработку кнопок мыши для списка задач
task_list = {}
task_list.buttons = awful.util.table.join(
-- Левая кнопка
awful.button({ }, left_button, function(c)
-- Если клиент имеет фокус - свернуть его
if c == client.focus then
c.minimized = true
else -- Иначе, передать фокус на клиент не сворачивая
c.minimized = false
-- и ещё вот эта хрень, назначение которой мне пока не ясно
if not c:isvisible() then
awful.tag.viewonly(c:tags()[1])
end
client.focus = c
c:raise()
end
end),
-- Щелчок правой кнопкой
awful.button({ }, right_button, function(c)
if instance then
instance:hide()
instance = nil
else
instance = awful.menu.clients({ width=250 })
end
end),
-- Сместить фокус на следующее окно
awful.button({ }, plus_button, function ()
awful.client.focus.byidx(1)
if client.focus then
client.focus:raise()
end
end),
-- Сместить фокус на предыдущее окно
awful.button({ }, minus_button, function()
awful.client.focus.byidx(-1)
if client.focus then
client.focus:raise()
end
end)
)
--------------------------------------------------------------------------
--- Создаем для каждого экрана панель задач #1 ---
---------------------------------------------------------------------------
-- Цикл, перебирающий все экраны
for s = 1, screen.count() do
-- Список тэгов: передаем номер экрана, и назначения кнопок мыши
tag_list[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, tag_list.buttons)
-- Список запущенных задач: передаем номер экрана, и назначения кнопок мыши
task_list[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, task_list.buttons)
-- Контейнер для всех виджетов - наша панель задач
-- расположенная внизу экрана номер s и шириной
main_wibox[s] = awful.wibox({ position = "top", height = "28", screen = s })
-- Создаем виджеты расположенные слева (левый блок виджетов)
local left_layout = wibox.layout.fixed.horizontal()
-- Добавляем на левый блок виджетов последовательно
left_layout:add(launcher) -- лаунчер (кнопка главного меню)
left_layout:add(tag_list[s]) -- список тэгов
-- Создаем виджеты расположенные справа
local right_layout = wibox.layout.fixed.horizontal()
-- Системный трей делаем почему-то только на первом экране, взято из стандартного конфига
if s == 1 then right_layout:add(wibox.widget.systray()) end
-- Добавляем
right_layout:add(volumecfg.widget)
right_layout:add(text_clock) -- Текстовые часы
-- Создаем контейнер для всей панели задач
local layout = wibox.layout.align.horizontal()
layout:set_left(left_layout)
layout:set_middle(task_list[s])
layout:set_right(right_layout)
main_wibox[s]:set_widget(layout)
end
--------------------------------------------------
--- Декларируем список тэгов #2 ---
--------------------------------------------------
bottom_wibox = {}
bottom_prompt_box = {}
botton_layout_box = {}
---------------------------------------------------------------------------
--- Создаем для каждого экрана панель задач #2 ---
---------------------------------------------------------------------------
-- Цикл, перебирающий все экраны
for s = 1, screen.count() do
-- Кнопка переключения макетов расположения окон
layout_box[s] = awful.widget.layoutbox(s)
-- декларируем для неё назначения кнопок мыши
layout_box[s]:buttons(awful.util.table.join(
-- Переключить на макет вперед
awful.button({ }, left_button, function () awful.layout.inc(layouts, 1) end),
-- Переключить на макет назад
awful.button({ }, right_button, function () awful.layout.inc(layouts, -1) end)
)
)
-- Командная строка - виджет реализующий командную строку на панели задач
bottom_prompt_box[s] = awful.widget.prompt()
-- Контейнер для всех виджетов - наша панель задач
-- расположенная внизу экрана номер s и шириной в px
bottom_wibox[s] = awful.wibox({ position = "bottom", height = "25", screen = s })
-- Создаем виджеты расположенные слева (левый блок виджетов)
local l_layout = wibox.layout.fixed.horizontal()
-- Добавляем на левый блок виджетов последовательно
l_layout:add(bottom_prompt_box[s]) -- командную строку
l_layout:add(spacer_small) -- otstup
l_layout:add(cpubox)
l_layout:add(cpugraph)
l_layout:add(spacer_small)
l_layout:add(membox)
l_layout:add(memwidget)
-- Создаем виджеты расположенные справа
local r_layout = wibox.layout.fixed.horizontal()
r_layout:add(hddbox)
r_layout:add(spacer_small)
r_layout:add(batterybox)
r_layout:add(spacer_small)
r_layout:add(layout_box[s]) -- Кнопку переключения макетов
-- Создаем контейнер для всей панели задач
local lay = wibox.layout.align.horizontal()
lay:set_left(l_layout)
--lay:set_middle()
lay:set_right(r_layout)
bottom_wibox[s]:set_widget(lay)
end
Третья часть здесь
Автор: worm2fed