SimpleConkyScript/script.lua

1038 lines
31 KiB
Lua

-- HorlogeSkynet's Lua script (for Conky)
-- https://git.forestier.app/HorlogeSkynet/SimpleConkyScript.git
local signal = require('posix.signal')
-----------------------------------------------------------------------------------------
-- Little gaps between screen borders and Conky surface.
local GAP_X, GAP_Y = 10, 10
-- Width of the two 'columns' which will contain all the elements.
local COLUMNS_WIDTH = 310
-- Global x-padding for elements displayed.
local GLOBAL_CELL_BORDER = 10
-- Width of our 'graph' objects.
local GRAPH_WIDTH = COLUMNS_WIDTH - GLOBAL_CELL_BORDER
-- Number of top process to display.
local MAX_TOP_PROCESS = 5
-- Temperature unit.
-- You can set an 'F' (Fahrenheit), but don't forget to adapt the temperature objects thresholds.
local TEMPERATURE_UNIT = 'C'
-- Font used everywhere.
-- /!\ Some special characters used here CAN'T BE displayed with certain fonts...
local FONT_FAMILY = 'Mono'
-- Global font size.
local FONT_SIZE = 15
-- Only begin effective loading only once this number of updates have passed.
local STARTUP_THRESHOLD = 5
-----------------------------------------------------------------------------------------
-- Count the number of available package updates.
local package_updates = {
-- Careful, the command below WILL BE executed anyhow.
-- Additional information : On "recent" Debian, a systemd timer run `aptitude update` regularly.
-- On older system (and or other GNU/Linux distributions), you may wanna run it manually.
command = "aptitude search \'~U\' | wc -l",
-- Only execute the command above each `interval` iterations.
interval = 240,
-- This element will store the effective number of updates.
value = nil
}
-- Retrieves your public IP address on the WWW.
local public_ip = {
-- Careful, the command below WILL BE executed anyhow.
command = "wget -qO- https://ident.me/",
-- Only execute the command above each `interval` iterations.
interval = 240,
-- This element will store the effective public IP.
ip = nil,
-- Special flag for IPv6 addresses...
is_v6 = false
}
-- Computes the brightness level of your screen.
local brightness_level = {
-- File paths towards brightness levels.
files = {
cur_brightness = "/sys/class/backlight/intel_backlight/actual_brightness",
max_brightness = "/sys/class/backlight/intel_backlight/max_brightness"
},
interval = 10,
value = nil
}
-- Determines the GNU/Linux distribution.
local distribution = {
-- Careful, the command below WILL BE executed anyhow.
command = "lsb_release -sirc",
-- Only execute the command above each `interval` iterations.
interval = 240,
-- This element will store the effective distribution information.
value = nil
}
local text_host = {
name = 'nodename',
arg = '',
display_name = 'Hostname'
}
local text_kernel = {
name = 'kernel',
arg = '',
display_name = 'Kernel'
}
local text_architecture = {
name = 'machine',
arg = '',
display_name = 'Architecture'
}
local text_uptime = {
name = 'uptime',
arg = '',
display_name = 'Uptime'
}
local bars_cpu = {
{
name = 'cpu',
arg = 'cpu0',
display_name = 'CPU0'
},
{
name = 'cpu',
arg = 'cpu1',
display_name = 'CPU1'
},
{
name = 'cpu',
arg = 'cpu2',
display_name = 'CPU2'
},
{
name = 'cpu',
arg = 'cpu3',
display_name = 'CPU3'
}
}
local bar_ram = {
name = 'memperc',
arg = '',
display_name = 'RAM'
}
local bar_swap = {
name = 'swapperc',
arg = '',
display_name = 'SWAP'
}
local bar_entropy = {
name = 'entropy_perc',
arg = '',
display_name = 'Entropy'
}
local bars_disk = {
{
name = 'fs_used_perc',
arg = '/',
display_name = "/ usage"
},
{
name = 'fs_used_perc',
arg = '/home/',
display_name = "/home/ usage"
}
}
local graphs_disk_read_write = {
{
graph_read = {
name = 'diskio_read',
arg = '/dev/sda',
values = {}
},
graph_write = {
name = 'diskio_write',
arg = '/dev/sda',
values = {}
},
display_name = '/dev/sda'
}
}
local bar_battery = {
name = 'battery_percent',
arg = 'BAT0',
display_name = 'Battery'
}
local text_running_process = {
name = 'running_processes',
arg = '',
display_name = 'Running processes'
}
local text_process = {
name = 'processes',
arg = '',
display_name = 'Idle processes'
}
local text_running_thread = {
name = 'running_threads',
arg = '',
display_name = 'Running threads'
}
local text_thread = {
name = 'threads',
arg = '',
display_name = 'Idle threads'
}
local text_temperatures = {
temp_cores = {
{
id = '0',
display_name = 'Core_0',
threshold = 70,
value = nil
},
{
id = '1',
display_name = 'Core_1',
threshold = 70,
value = nil
}
},
temp_hdds = {
{
name = '/dev/sda',
display_name = "Hard Disk",
threshold = 50,
value = nil
}
}
}
local graphs_network_interface = {
{
graph_download = {
name = 'downspeedf',
arg = 'enp0s25',
values = {}
},
graph_upload = {
name = 'upspeedf',
arg = 'enp0s25',
values = {}
},
display_name = 'Eth0'
},
{
graph_download = {
name = 'downspeedf',
arg = 'wlo1',
values = {}
},
graph_upload = {
name = 'upspeedf',
arg = 'wlo1',
values = {}
},
display_name = 'Wlan0'
}
}
-----------------------------------------------------------------------------------------
local SimpleConkyScript = {}
-- Internal variable, for performance purposes.
local conky_updates = nil
-- One little function to get the screen definition in only one call !
function SimpleConkyScript.get_screen_definition()
local handle = io.popen("xdpyinfo | grep dimensions")
local width, height = string.match(
handle:read('*all'),
"%s*dimensions:%s*(%d+)x(%d+).*")
io.close(handle)
return tonumber(width), tonumber(height)
end
-- Another one little function to retrieve the gaps set within this module !
function SimpleConkyScript.get_gaps()
return GAP_X, GAP_Y
end
-- The IPv6 addresses are too long for this column size, here is a function to make them "stream" on the screen.
local function _stream_ipv6_address(address)
local quantum = string.len(address) / 2
local cycle = conky_updates % 2
local ip
if cycle ~= 0 then ip = "< " else ip = " " end
ip = ip .. string.sub(address, cycle * quantum + cycle, (cycle + 1) * quantum)
if cycle == 0 then ip = ip .. " >" end
return ip
end
-- Generic function to draw our 'graph' object
local function _draw_graph(display, data, x_pos, y_pos, width)
local height = 25
local line_width = 4
local number_max_values = 25
local current_x_pos = x_pos + width - line_width / 2.
local difference = (width - line_width) / (number_max_values - 1)
local count = table.getn(data['values'])
if count == 0 then return y_pos + height end
if count > number_max_values then
table.remove(data['values'], 1)
count = count - 1
end
local max_of_value = data['values'][1]
for i = 2, count do
if data['values'][i] > max_of_value then max_of_value = data['values'][i] end
end
if max_of_value == 0 then max_of_value = 1 end
cairo_set_line_width(display, line_width)
cairo_set_line_cap(display, CAIRO_LINE_CAP_BUTT)
local value
for i = 1, count do
value = data['values'][count - i + 1]
cairo_move_to(
display, current_x_pos, y_pos + (1 - value / max_of_value) * height)
cairo_line_to(display, current_x_pos, y_pos + height)
current_x_pos = current_x_pos - difference
end
cairo_stroke(display)
return y_pos + height
end
-- Generic function to draw our 'text' object
local function _draw_text(display, text, x_pos, y_pos)
local height = 25
local space = (height - FONT_SIZE) / 2.
cairo_move_to(display, x_pos, y_pos + FONT_SIZE + space)
cairo_show_text(display, text)
cairo_stroke(display)
return y_pos + height
end
-- Generic function to draw our 'bar' object
local function _draw_bar(display, data, x_pos, y_pos, value)
local height = conky_window.height * (5 / 100.)
local line_width = 5
local cursor_height = 10
local cursor_width = 5
local space_text_bar = 5
local space = (
height - FONT_SIZE - space_text_bar - line_width / 2. - cursor_height) / 2.
cairo_move_to(display, x_pos, y_pos + FONT_SIZE + space)
cairo_show_text(display, data['display_name'])
cairo_stroke(display)
local line_y = y_pos + space + FONT_SIZE + space_text_bar + line_width / 2
local begin_x, cursor_x, end_x =
x_pos, x_pos + cursor_width / 2. + value * (GRAPH_WIDTH - cursor_width),
x_pos + GRAPH_WIDTH
cairo_set_line_width(display, line_width)
cairo_set_line_cap(display, CAIRO_LINE_CAP_BUTT)
-- Beginning of the line
cairo_move_to(display, begin_x, line_y)
cairo_line_to(display, cursor_x, line_y)
cairo_stroke(display)
-- Ending of the line
cairo_set_source_rgba(display, 0.4, 0.4, 0.4, 1)
cairo_move_to(display, cursor_x, line_y)
cairo_line_to(display, end_x, line_y)
cairo_stroke(display)
-- Just get back to 'white'
cairo_set_source_rgba(display, 1, 1, 1, 1)
-- Cursor
cairo_set_line_width(display, cursor_width)
cairo_move_to(display, cursor_x, line_y - line_width / 2.)
cairo_line_to(display, cursor_x, line_y + cursor_height)
cairo_stroke(display)
return y_pos + height
end
-- Specific function to draw our section separation
local function _draw_section_separation(display, x_pos, y_pos)
local height = conky_window.height * (2 / 100.)
local line_width = 3
local horizontal_space = 100
local line_y = y_pos + height / 2.
local begin_x, end_x =
x_pos + horizontal_space,
x_pos + GRAPH_WIDTH - horizontal_space
cairo_set_line_width(display, line_width)
cairo_set_line_cap(display, CAIRO_LINE_CAP_BUTT)
cairo_move_to(display, begin_x, line_y)
cairo_line_to(display, end_x, line_y)
cairo_stroke(display)
return y_pos + height
end
-- Specific function to draw time & date
local function _draw_time_date(display, x_pos, y_pos)
-- Clock for the current time
local clock_radius = 60
local clock_border_width = 2
local clock_center_x = x_pos + COLUMNS_WIDTH / 2. - GLOBAL_CELL_BORDER / 2.
local clock_center_y = y_pos + clock_radius + clock_border_width
local gap_border_hour_marks = 5
local mark_length = 10
local mark_width = 3
local second_hand_length = 50
local second_hand_width = 1
local minute_hand_length = 50
local minute_hand_width = 3
local hour_hand_length = 30
local hour_hand_width = 5
cairo_set_line_width(display, clock_border_width)
cairo_arc(display, clock_center_x, clock_center_y, clock_radius, 0, 2 * math.pi)
cairo_stroke(display)
local mark_end_rad = clock_radius - gap_border_hour_marks
local mark_start_rad = mark_end_rad - mark_length
cairo_set_line_cap(display, CAIRO_LINE_CAP_ROUND)
cairo_set_line_width(display, mark_width)
local point, radius, x, y
for i = 1, 12 do
point = (math.pi / 180.) * ((i - 1) * 30)
radius = mark_start_rad
x, y = radius * math.sin(point), -radius * math.cos(point)
cairo_move_to(display, clock_center_x + x, clock_center_y + y)
radius = mark_end_rad
x, y = radius * math.sin(point), -radius * math.cos(point)
cairo_line_to(display, clock_center_x + x, clock_center_y + y)
cairo_stroke(display)
end
local hours = tonumber(os.date('%I'))
local hours_to_second = hours * 60 * 60
local minutes = tonumber(os.date('%M'))
local minutes_to_seconds = minutes * 60
local seconds = tonumber(os.date('%S'))
local hours_seconds = hours_to_second + minutes_to_seconds + seconds
local hours_seconds_degrees = hours_seconds * (360 / (60. * 60. * 12.))
cairo_move_to(display, clock_center_x, clock_center_y)
point = (math.pi / 180.) * hours_seconds_degrees
radius = hour_hand_length
x, y = radius * math.sin(point), -radius * math.cos(point)
cairo_line_to(display, clock_center_x + x, clock_center_y + y)
cairo_set_line_width(display, hour_hand_width)
cairo_set_line_cap(display, CAIRO_LINE_CAP_ROUND)
cairo_stroke(display)
local minutes_seconds = minutes_to_seconds + seconds
local minutes_seconds_degrees = minutes_seconds * 0.1
cairo_move_to(display, clock_center_x, clock_center_y)
point = (math.pi / 180.) * minutes_seconds_degrees
radius = minute_hand_length
x, y = radius * math.sin(point), -radius * math.cos(point)
cairo_line_to(display, clock_center_x + x, clock_center_y + y)
cairo_set_line_width(display, minute_hand_width)
cairo_set_line_cap(display, CAIRO_LINE_CAP_ROUND)
cairo_stroke(display)
local seconds_degrees = seconds * 6
cairo_move_to(display, clock_center_x, clock_center_y)
point = (math.pi / 180.) * seconds_degrees
radius = second_hand_length
x, y = radius * math.sin(point), -radius * math.cos(point)
cairo_line_to(display, clock_center_x + x, clock_center_y + y)
cairo_set_line_width(display,second_hand_width)
cairo_set_source_rgba(display, 1, 0, 0, 1)
cairo_set_line_cap(display, CAIRO_LINE_CAP_ROUND)
cairo_stroke(display)
-- Just get back to 'white'
cairo_set_source_rgba(display, 1, 1, 1, 1)
y_pos = y_pos + 2 * clock_radius + 2 * clock_border_width
-- Text for the current time & date
return _draw_text(display, os.date("%H:%M:%S, %A %d/%m/%Y"), x_pos, y_pos)
end
-----------------------------------------------------------------------------------------
-- Specific function to load the actual and maximum brightness values stored in files
local function _load_brightness(display, x_pos, y_pos)
local do_update = (
not brightness_level.value or
conky_updates % brightness_level.interval == 0)
if do_update then
local handle
handle = io.open(brightness_level.files.cur_brightness)
local cur_brightness = tonumber(handle:read('*all'))
io.close(handle)
handle = io.open(brightness_level.files.max_brightness)
local max_brightness = tonumber(handle:read('*all'))
io.close(handle)
brightness_level.value = cur_brightness / max_brightness
end
return _draw_bar(
display, {display_name = 'Brightness'},
x_pos, y_pos, brightness_level.value)
end
-- Specific function to load the number of updates available in a text file
local function _load_updates(display, x_pos, y_pos)
local do_update = (
not package_updates.value or
conky_updates % package_updates.interval == 0)
if do_update then
local handle = io.popen(package_updates.command)
if handle then
package_updates.value = tonumber(handle:read('*all'))
io.close(handle)
end
end
return _draw_text(
display, "Updates: " .. (package_updates.value or '') .. " available",
x_pos, y_pos)
end
--Specific function to load distribution information
local function _load_distribution(display, x_pos, y_pos)
local do_update = (not distribution.value or conky_updates % 1800 == 0)
if do_update then
local handle = io.popen(distribution.command)
distribution.value = string.gsub(handle:read('*all'), '\n', ' ')
io.close(handle)
end
return _draw_text(
display,
conky_parse(string.format('${sysname}')) .. ": " .. distribution.value,
x_pos, y_pos)
end
--Specific function to load the public IP address
local function _load_public_ip(display, x_pos, y_pos)
local tmp_ip
local do_update = (
(not public_ip.ip and conky_updates % (public_ip.interval / 2) == 0) or
conky_updates % public_ip.interval == 0)
if do_update then
local handle = io.popen(public_ip.command)
if handle then
tmp_ip = handle:read('*all')
io.close(handle)
local _, dotCountIPv4 = string.gsub(tmp_ip, '%.', '')
local _, dotCountIPv6 = string.gsub(tmp_ip, ':', '')
-- Little statements to check whether the string is an IPv4 or IPv6 address (maybe ?).
if dotCountIPv4 == 3 then
public_ip.ip = tmp_ip
public_ip.is_v6 = false
elseif dotCountIPv6 >= 2 and dotCountIPv6 <= 7 then
public_ip.ip = tmp_ip
public_ip.is_v6 = true
else
public_ip.ip = nil
end
end
else
tmp_ip = public_ip.ip
end
-- When dealing with an IPv6, let's make it "stream" on the screen a bit...
if public_ip.ip and public_ip.is_v6 then
tmp_ip = _stream_ipv6_address(tmp_ip)
end
return _draw_text(
display, "Public IP: " .. (tmp_ip or "No Address"),
x_pos, y_pos)
end
-- Specific function to load author & version text
local function _load_author_version(display, x_pos, y_pos)
return _draw_text(
display, "Horloge\'s script on Conky " .. conky_version,
x_pos, y_pos)
end
-- Specific function to load top process
local function _load_top_process(display, x_pos, y_pos)
y_pos = _draw_text(display, "NAME PID CPU MEM", x_pos, y_pos)
local args = {'name', 'pid', 'cpu', 'mem'}
local buffer
for i = 1, MAX_TOP_PROCESS <= 10 and MAX_TOP_PROCESS or 10 do
buffer = ""
for j = 1, #args do
buffer = buffer .. conky_parse(string.format('${top %s %d}', args[j], i))
end
y_pos = _draw_text(display, buffer, x_pos, y_pos)
end
return y_pos
end
-- Specific function to load different temperatures into 'text'
local function _load_temperatures(display, x_pos, y_pos)
local handle, buffer, sensors
-- We'll be effectively reading the temperature values each 5 iterations
local do_update = (conky_updates % 5 == 0)
-- For CPUs temperatures, we only run one time `sensors`...
if do_update then
handle = io.popen("sensors -A | grep \"Core\"")
sensors = handle:read('*all')
io.close(handle)
end
-- ... and iterates over each object specified above
for _, temp_core in pairs(text_temperatures['temp_cores']) do
if do_update then
temp_core['value'] = tonumber(string.match(
sensors, "Core " .. temp_core['id'] .. ":%s+[+|-](%d+.%d+)°.?.*"))
-- Manuel Fahrenheit conversion (because `-f` option of `sensors` is too slow...)
if temp_core['value'] and TEMPERATURE_UNIT == 'F' then
temp_core['value'] = (temp_core['value'] * 9 / 5.) + 32
end
end
buffer = "Temperature " .. temp_core['display_name'] .. ": "
if temp_core['value'] then
buffer = buffer .. temp_core['value'] .. '°' .. TEMPERATURE_UNIT
if temp_core['value'] > temp_core['threshold'] then
buffer = buffer .. ' /!\\'
end
else
buffer = buffer .. ''
end
y_pos = _draw_text(display, buffer, x_pos, y_pos)
end
-- HDD temperatures (with 'hddtemp' daemon running on its default IP & port)
for _, temp_hdd in pairs(text_temperatures['temp_hdds']) do
-- It it's the "good" iteration, we update EACH hard drive entry
if do_update then
handle = io.popen(
"hddtemp \"" .. temp_hdd['name'] .. "\" -n -u " .. TEMPERATURE_UNIT)
temp_hdd['value'] = tonumber(handle:read('*all'))
io.close(handle)
end
buffer = "Temperature " .. temp_hdd['display_name'] .. ": "
if temp_hdd['value'] then
buffer = buffer .. temp_hdd['value'] .. '°' .. TEMPERATURE_UNIT
if temp_hdd['value'] > temp_hdd['threshold'] then
buffer = buffer..' /!\\'
end
else
buffer = buffer .. ''
end
y_pos = _draw_text(display, buffer, x_pos, y_pos)
end
return y_pos
end
-- Generic function to load data in order to print them into 'graph'
local function _load_graph(display, data, x_pos, y_pos, width)
local value = tonumber(
conky_parse(string.format('${%s %s}', data['name'], data['arg'])))
-- Sometimes, at startup, the first non-zero 'value' is equal to 'math.mininteger' or 'math.maxinteger'
-- See issue Conky#340 (https://github.com/brndnmtthws/conky/issues/340)
-- The following statement is here to avoid a huge line drawn on 'graph' objects...
if math.abs(value) < 1.e+18 then table.insert(data['values'], value) end
return _draw_graph(display, data, x_pos, y_pos, width)
end
-- Generic function to load data in order to print them into 'text'
local function _load_text(display, data, x_pos, y_pos)
local value = conky_parse(string.format('${%s %s}', data['name'], data['arg']))
return _draw_text(display, data['display_name'] .. ": " .. value, x_pos, y_pos)
end
-- This function is here to load data of a hard disk ('graph' + 'text')
local function _load_read_write_disk(display, graph_disk_read_write, x_pos, y_pos)
local special_graph_width = GRAPH_WIDTH / 2 - GLOBAL_CELL_BORDER
local special_graph_x_pos = x_pos + special_graph_width + GLOBAL_CELL_BORDER
-- Writes down the interface name
y_pos = _draw_text(
display, graph_disk_read_write['display_name'] .. ": Read / Write",
x_pos, y_pos)
-- Set color to 'blue' for read 'graph'
cairo_set_source_rgba(display, 0 / 255., 127 / 255., 172 / 255., 1)
_load_graph(
display, graph_disk_read_write['graph_read'],
x_pos, y_pos, special_graph_width)
-- Set color to 'orange' for write 'graph'
cairo_set_source_rgba(display, 255 / 255., 114 / 255., 0 / 255., 1)
y_pos = _load_graph(
display, graph_disk_read_write['graph_write'],
special_graph_x_pos, y_pos, special_graph_width)
-- Just get back to 'white'
cairo_set_source_rgba(display, 1, 1, 1, 1)
return y_pos
end
-- This function is here to load data of a network interface ('graph' + 'text')
local function _load_network_interface(display, graph_network_interface, x_pos, y_pos)
local if_name = graph_network_interface['graph_download']['arg']
local if_up = (conky_parse(
string.format('${if_up %s}1${else}0${endif}', if_name)) == '1')
if if_up then
-- A little separation
y_pos = _draw_section_separation(display, x_pos, y_pos)
local special_graph_width = GRAPH_WIDTH / 2 - GLOBAL_CELL_BORDER
local special_graph_x_pos = x_pos + special_graph_width + GLOBAL_CELL_BORDER
-- Writes down the interface name
y_pos = _draw_text(
display,
graph_network_interface['display_name'] .. ": Download / Upload",
x_pos, y_pos)
-- Set color to 'blue' for download 'graph'
cairo_set_source_rgba(display, 0 / 255., 127 / 255., 172 / 255., 1)
_load_graph(
display, graph_network_interface['graph_download'],
x_pos, y_pos, special_graph_width)
-- Set color to 'orange' for upload 'graph'
cairo_set_source_rgba(display, 255 / 255., 114 / 255., 0 / 255., 1)
y_pos = _load_graph(
display, graph_network_interface['graph_upload'],
special_graph_x_pos, y_pos, special_graph_width)
-- Just get back to 'white'
cairo_set_source_rgba(display, 1, 1, 1, 1)
-- Now print the current speed values
_draw_text(
display,
conky_parse(string.format('${downspeedf %s}' .. " KiB", if_name)),
x_pos + (special_graph_width / 4.), y_pos)
y_pos = _draw_text(
display,
conky_parse(string.format('${upspeedf %s}' .. " KiB", if_name)),
special_graph_x_pos + (special_graph_width / 4.), y_pos)
-- Displays the current interface IP addresses
local IPv4 = conky_parse(string.format('${addrs %s}', if_name))
local IPv6 = conky_parse(string.format('${v6addrs %s}', if_name))
local addresses
if IPv4 then
if IPv4 ~= '0.0.0.0' then
addresses = string.gmatch(IPv4, '[0-9.]+')
for address in addresses do
y_pos = _draw_text(display, "IPv4: " .. address, x_pos, y_pos)
end
else
y_pos = _draw_text(display, "IPv4: No Address", x_pos, y_pos)
end
end
if IPv6 then
if IPv6 ~= 'No Address' then
addresses = string.gmatch(IPv6, '[a-zA-Z0-9:]+')
for address in addresses do
y_pos = _draw_text(
display, "IPv6: " .. _stream_ipv6_address(address),
x_pos, y_pos)
end
else
y_pos = _draw_text(display, "IPv6: " .. IPv6, x_pos, y_pos)
end
end
end
return y_pos
end
-- Generic function to load data in order to print them into 'bar'
local function _load_bar(display, data, x_pos, y_pos)
-- Value between 0 and 1 as we get percentage values from Conky variables
local value = tonumber(
conky_parse(string.format('${%s %s}', data['name'], data['arg']))) / 100.
return _draw_bar(display, data, x_pos, y_pos, value)
end
-----------------------------------------------------------------------------------------
-- THE function which call all the other loading and drawing functions
local function _load_everything(display)
-- Initial position, each call updates the `y_pos` in order to place the following elements
local x_pos = GLOBAL_CELL_BORDER
local y_pos = 0
-- Just set color to 'white'
cairo_set_source_rgba(display, 1, 1, 1, 1)
-- Set the font, and its size only one time
cairo_select_font_face(
display, FONT_FAMILY,
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL)
cairo_set_font_size(display, FONT_SIZE)
-- Time & Date
y_pos = _draw_time_date(display, x_pos, y_pos)
-- A little separation
y_pos = _draw_section_separation(display, x_pos, y_pos)
-- Hostname
y_pos = _load_text(display, text_host, x_pos, y_pos)
-- Distribution details
y_pos = _load_distribution(display, x_pos, y_pos)
-- Kernel
y_pos = _load_text(display, text_kernel, x_pos, y_pos)
-- Architecture
y_pos = _load_text(display, text_architecture, x_pos, y_pos)
-- Uptime
y_pos = _load_text(display, text_uptime, x_pos, y_pos)
-- Updates available
y_pos = _load_updates(display, x_pos, y_pos)
-- A little separation
y_pos = _draw_section_separation(display, x_pos, y_pos)
-- Battery bar
y_pos = _load_bar(display, bar_battery, x_pos, y_pos)
-- Brightness bar
y_pos = _load_brightness(display, x_pos, y_pos)
-- Entropy bar
y_pos = _load_bar(display, bar_entropy, x_pos, y_pos)
-- A little separation
y_pos = _draw_section_separation(display, x_pos, y_pos)
-- Process & Threads
y_pos = _load_text(display, text_thread, x_pos, y_pos)
y_pos = _load_text(display, text_running_thread, x_pos, y_pos)
y_pos = _load_text(display, text_process, x_pos, y_pos)
y_pos = _load_text(display, text_running_process, x_pos, y_pos)
-- A little separation
y_pos = _draw_section_separation(display, x_pos, y_pos)
-- Top process
y_pos = _load_top_process(display, x_pos, y_pos)
-- The following elements will be set in the other column
x_pos = conky_window.width - COLUMNS_WIDTH
y_pos = 0
-- CPU bars
for _, bar_cpu in pairs(bars_cpu) do
y_pos = _load_bar(display, bar_cpu, x_pos, y_pos)
end
-- RAM bar
y_pos = _load_bar(display, bar_ram, x_pos, y_pos)
-- SWAP bar
y_pos = _load_bar(display, bar_swap, x_pos, y_pos)
-- A little separation
y_pos = _draw_section_separation(display, x_pos, y_pos)
-- Disk bars
for _, bar_disk in pairs(bars_disk) do
y_pos = _load_bar(display, bar_disk, x_pos, y_pos)
end
-- Disk flow graphs
for _, graph_disk_read_write in pairs(graphs_disk_read_write) do
y_pos = _load_read_write_disk(display, graph_disk_read_write, x_pos, y_pos)
end
-- A little separation
y_pos = _draw_section_separation(display, x_pos, y_pos)
-- Temperatures
y_pos = _load_temperatures(display, x_pos, y_pos)
-- A little separation
y_pos = _draw_section_separation(display, x_pos, y_pos)
-- Public IP address
y_pos = _load_public_ip(display, x_pos, y_pos)
-- Network interfaces
for _, graph_network_interface in pairs(graphs_network_interface) do
y_pos = _load_network_interface(display, graph_network_interface, x_pos, y_pos)
end
-- A little separation
y_pos = _draw_section_separation(display, x_pos, y_pos)
-- Author & Version
y_pos = _load_author_version(display, x_pos, y_pos)
end
-----------------------------------------------------------------------------------------
-- MAIN
function conky_main()
if not conky_window then return end
require('cairo')
local surface = cairo_xlib_surface_create(
conky_window.display, conky_window.drawable, conky_window.visual,
conky_window.width, conky_window.height)
if not surface then return end
local display = cairo_create(surface)
if not display then return end
conky_updates = tonumber(conky_parse('${updates}'))
-- Every 5 updates...
if conky_updates % 5 == 0 then
local screen_width, screen_height = SimpleConkyScript.get_screen_definition()
local border_width = conky_window.border_width + 2 * (
conky_window.border_inner_margin + conky_window.border_outer_margin)
-- ... we check whether the screen definition has changed in order to fetch and fit the new one
if conky_window.width + border_width ~= screen_width and
conky_window.height + border_width ~= screen_height then
-- Let's free the current display and surface
cairo_destroy(display)
cairo_surface_destroy(surface)
-- We may now make Conky reload its configuration
signal.raise(signal.SIGHUP)
-- We have to leave the main here to avoid a segmentation fault with the operations below
return
end
end
-- Loading of the whole list of elements, each update
if conky_updates > STARTUP_THRESHOLD then _load_everything(display) end
-- Delete display and surface before the next update
cairo_destroy(display)
cairo_surface_destroy(surface)
end
return SimpleConkyScript