diff --git a/helpers/client.lua b/helpers/client.lua index fe59edcd..affc3c5f 100644 --- a/helpers/client.lua +++ b/helpers/client.lua @@ -8,53 +8,53 @@ local _client = {} -- Remove current tag from window's tags -- @param c A client function _client.turn_off(c, current_tag) - if current_tag == nil then - current_tag = c.screen.selected_tag - end - local ctags = {} - for k, tag in pairs(c:tags()) do - if tag ~= current_tag then - table.insert(ctags, tag) - end - end - c:tags(ctags) - c.sticky = false + if current_tag == nil then + current_tag = c.screen.selected_tag + end + local ctags = {} + for k, tag in pairs(c:tags()) do + if tag ~= current_tag then + table.insert(ctags, tag) + end + end + c:tags(ctags) + c.sticky = false end --- Turn on passed client (add current tag to window's tags) -- @param c A client function _client.turn_on(c) - local current_tag = c.screen.selected_tag - ctags = { current_tag } - for k, tag in pairs(c:tags()) do - if tag ~= current_tag then - table.insert(ctags, tag) - end - end - c:tags(ctags) - c:raise() - client.focus = c + local current_tag = c.screen.selected_tag + ctags = { current_tag } + for k, tag in pairs(c:tags()) do + if tag ~= current_tag then + table.insert(ctags, tag) + end + end + c:tags(ctags) + c:raise() + client.focus = c end --- Sync two clients -- @param to_c The client to which to write all properties -- @param from_c The client from which to read all properties function _client.sync(to_c, from_c) - if not from_c or not to_c then - return - end - if not from_c.valid or not to_c.valid then - return - end - if from_c.modal then - return - end - to_c.floating = from_c.floating - to_c.maximized = from_c.maximized - to_c.above = from_c.above - to_c.below = from_c.below - to_c:geometry(from_c:geometry()) - -- TODO: Should also copy over the position in a tiling layout + if not from_c or not to_c then + return + end + if not from_c.valid or not to_c.valid then + return + end + if from_c.modal then + return + end + to_c.floating = from_c.floating + to_c.maximized = from_c.maximized + to_c.above = from_c.above + to_c.below = from_c.below + to_c:geometry(from_c:geometry()) + -- TODO: Should also copy over the position in a tiling layout end --- Checks whether the passed client is a childprocess of a given process ID @@ -62,61 +62,54 @@ end -- @param pid The process ID -- @return True if the passed client is a childprocess of the given PID otherwise false function _client.is_child_of(c, pid) - -- io.popen is normally discouraged. Should probably be changed - if not c or not c.valid then - return false - end - if tostring(c.pid) == tostring(pid) then - return true - end - local pid_cmd = [[pstree -T -p -a -s ]] - .. tostring(c.pid) - .. [[ | sed '2q;d' | grep -o '[0-9]*$' | tr -d '\n']] - local handle = io.popen(pid_cmd) - local parent_pid = handle:read("*a") - handle:close() - return tostring(parent_pid) == tostring(pid) - or tostring(parent_pid) == tostring(c.pid) + -- io.popen is normally discouraged. Should probably be changed + if not c or not c.valid then + return false + end + if tostring(c.pid) == tostring(pid) then + return true + end + local pid_cmd = [[pstree -T -p -a -s ]] .. tostring(c.pid) .. [[ | sed '2q;d' | grep -o '[0-9]*$' | tr -d '\n']] + local handle = io.popen(pid_cmd) + local parent_pid = handle:read("*a") + handle:close() + return tostring(parent_pid) == tostring(pid) or tostring(parent_pid) == tostring(c.pid) end --- Finds all clients that satisfy the passed rule -- @param rule The rule to be searched for -- @retrun A list of clients that match the given rule function _client.find(rule) - local function matcher(c) - return awful.rules.match(c, rule) - end - local clients = client.get() - local findex = gears.table.hasitem(clients, client.focus) or 1 - local start = gears.math.cycle(#clients, findex + 1) + local function matcher(c) + return awful.rules.match(c, rule) + end + local clients = client.get() + local findex = gears.table.hasitem(clients, client.focus) or 1 + local start = gears.math.cycle(#clients, findex + 1) - local matches = {} - for c in awful.client.iterate(matcher, start) do - matches[#matches + 1] = c - end + local matches = {} + for c in awful.client.iterate(matcher, start) do + matches[#matches + 1] = c + end - return matches + return matches end --- Gets the next client by direction from the focused one -- @param direction it the direction as a string ("up", "down", "left" or "right") -- @retrun the client in the given direction starting at the currently focused one, nil otherwise function _client.get_by_direction(direction) - local sel = client.focus - if not sel then - return nil - end - local cltbl = sel.screen:get_clients() - local geomtbl = {} - for i, cl in ipairs(cltbl) do - geomtbl[i] = cl:geometry() - end - local target = gears.geometry.rectangle.get_in_direction( - direction, - geomtbl, - sel:geometry() - ) - return cltbl[target] + local sel = client.focus + if not sel then + return nil + end + local cltbl = sel.screen:get_clients() + local geomtbl = {} + for i, cl in ipairs(cltbl) do + geomtbl[i] = cl:geometry() + end + local target = gears.geometry.rectangle.get_in_direction(direction, geomtbl, sel:geometry()) + return cltbl[target] end return _client diff --git a/helpers/color.lua b/helpers/color.lua index 267a0610..bddf8673 100644 --- a/helpers/color.lua +++ b/helpers/color.lua @@ -14,20 +14,20 @@ local _color = {} -- @string color The color with hexadecimal HTML format `"#RRGGBB"`. -- @treturn bool `true` if the color is dark, `false` if it is light. function _color.is_dark(color) - -- Try to determine if the color is dark or light - local numeric_value = 0 - for s in color:gmatch("[a-fA-F0-9][a-fA-F0-9]") do - numeric_value = numeric_value + tonumber("0x" .. s) - end - return (numeric_value < 383) + -- Try to determine if the color is dark or light + local numeric_value = 0 + for s in color:gmatch("[a-fA-F0-9][a-fA-F0-9]") do + numeric_value = numeric_value + tonumber("0x" .. s) + end + return (numeric_value < 383) end function _color.is_opaque(color) - if type(color) == "string" then - color = _color.hex_to_rgba(color) - end + if type(color) == "string" then + color = _color.hex_to_rgba(color) + end - return color.a < 0.01 + return color.a < 0.01 end --- Lighten a color. @@ -35,24 +35,24 @@ end -- @int[opt=26] amount How much light from 0 to 255. Default is around 10%. -- @treturn string The lighter color function _color.lighten(color, amount) - amount = amount or 26 - local c = { - r = tonumber("0x" .. color:sub(2, 3)), - g = tonumber("0x" .. color:sub(4, 5)), - b = tonumber("0x" .. color:sub(6, 7)), - } - - c.r = c.r + amount - c.r = c.r < 0 and 0 or c.r - c.r = c.r > 255 and 255 or c.r - c.g = c.g + amount - c.g = c.g < 0 and 0 or c.g - c.g = c.g > 255 and 255 or c.g - c.b = c.b + amount - c.b = c.b < 0 and 0 or c.b - c.b = c.b > 255 and 255 or c.b - - return string.format("#%02x%02x%02x", c.r, c.g, c.b) + amount = amount or 26 + local c = { + r = tonumber("0x" .. color:sub(2, 3)), + g = tonumber("0x" .. color:sub(4, 5)), + b = tonumber("0x" .. color:sub(6, 7)), + } + + c.r = c.r + amount + c.r = c.r < 0 and 0 or c.r + c.r = c.r > 255 and 255 or c.r + c.g = c.g + amount + c.g = c.g < 0 and 0 or c.g + c.g = c.g > 255 and 255 or c.g + c.b = c.b + amount + c.b = c.b < 0 and 0 or c.b + c.b = c.b > 255 and 255 or c.b + + return string.format("#%02x%02x%02x", c.r, c.g, c.b) end --- Darken a color. @@ -60,22 +60,24 @@ end -- @int[opt=26] amount How much dark from 0 to 255. Default is around 10%. -- @treturn string The darker color function _color.darken(color, amount) - amount = amount or 26 - return _color.lighten(color, -amount) + amount = amount or 26 + return _color.lighten(color, -amount) end -- Returns a value that is clipped to interval edges if it falls outside the interval function _color.clip(num, min_num, max_num) - return max(min(num, max_num), min_num) + return max(min(num, max_num), min_num) end -- Converts the given hex color to rgba function _color.hex_to_rgba(color) - color = color:gsub("#", "") - return { r = tonumber("0x" .. color:sub(1, 2)), - g = tonumber("0x" .. color:sub(3, 4)), - b = tonumber("0x" .. color:sub(5, 6)), - a = #color == 8 and tonumber("0x" .. color:sub(7, 8)) or 255 } + color = color:gsub("#", "") + return { + r = tonumber("0x" .. color:sub(1, 2)), + g = tonumber("0x" .. color:sub(3, 4)), + b = tonumber("0x" .. color:sub(5, 6)), + a = #color == 8 and tonumber("0x" .. color:sub(7, 8)) or 255, + } end -- Converts the given rgba color to hex @@ -84,73 +86,73 @@ function _color.rgba_to_hex(color) local g = _color.clip(color.g or color[2], 0, 255) local b = _color.clip(color.b or color[3], 0, 255) local a = _color.clip(color.a or color[4] or 255, 0, 255) - return "#" .. format("%02x%02x%02x%02x", - floor(r), - floor(g), - floor(b), - floor(a)) + return "#" .. format("%02x%02x%02x%02x", floor(r), floor(g), floor(b), floor(a)) end -- Converts the given hex color to hsv function _color.hex_to_hsv(color) - local color = _color.hex2rgb(color) - local C_max = max(color.r, color.g, color.b) - local C_min = min(color.r, color.g, color.b) - local delta = C_max - C_min - local H, S, V - if delta == 0 then - H = 0 - elseif C_max == color.r then - H = 60 * (((color.g - color.b) / delta) % 6) - elseif C_max == color.g then - H = 60 * (((color.b - color.r) / delta) + 2) - elseif C_max == color.b then - H = 60 * (((color.r - color.g) / delta) + 4) - end - if C_max == 0 then - S = 0 - else - S = delta / C_max - end - V = C_max - - return { h = H, - s = S * 100, - v = V * 100 } + local color = _color.hex2rgb(color) + local C_max = max(color.r, color.g, color.b) + local C_min = min(color.r, color.g, color.b) + local delta = C_max - C_min + local H, S, V + if delta == 0 then + H = 0 + elseif C_max == color.r then + H = 60 * (((color.g - color.b) / delta) % 6) + elseif C_max == color.g then + H = 60 * (((color.b - color.r) / delta) + 2) + elseif C_max == color.b then + H = 60 * (((color.r - color.g) / delta) + 4) + end + if C_max == 0 then + S = 0 + else + S = delta / C_max + end + V = C_max + + return { h = H, s = S * 100, v = V * 100 } end -- Converts the given hsv color to hex function _color.hsv_to_hex(H, S, V) - S = S / 100 - V = V / 100 - if H > 360 then H = 360 end - if H < 0 then H = 0 end - local C = V * S - local X = C * (1 - abs(((H / 60) % 2) - 1)) - local m = V - C - local r_, g_, b_ = 0, 0, 0 - if H >= 0 and H < 60 then - r_, g_, b_ = C, X, 0 - elseif H >= 60 and H < 120 then - r_, g_, b_ = X, C, 0 - elseif H >= 120 and H < 180 then - r_, g_, b_ = 0, C, X - elseif H >= 180 and H < 240 then - r_, g_, b_ = 0, X, C - elseif H >= 240 and H < 300 then - r_, g_, b_ = X, 0, C - elseif H >= 300 and H < 360 then - r_, g_, b_ = C, 0, X - end - local r, g, b = (r_ + m) * 255, (g_ + m) * 255, (b_ + m) * 255 - return ("#%02x%02x%02x"):format(floor(r), floor(g), floor(b)) + S = S / 100 + V = V / 100 + if H > 360 then + H = 360 + end + if H < 0 then + H = 0 + end + local C = V * S + local X = C * (1 - abs(((H / 60) % 2) - 1)) + local m = V - C + local r_, g_, b_ = 0, 0, 0 + if H >= 0 and H < 60 then + r_, g_, b_ = C, X, 0 + elseif H >= 60 and H < 120 then + r_, g_, b_ = X, C, 0 + elseif H >= 120 and H < 180 then + r_, g_, b_ = 0, C, X + elseif H >= 180 and H < 240 then + r_, g_, b_ = 0, X, C + elseif H >= 240 and H < 300 then + r_, g_, b_ = X, 0, C + elseif H >= 300 and H < 360 then + r_, g_, b_ = C, 0, X + end + local r, g, b = (r_ + m) * 255, (g_ + m) * 255, (b_ + m) * 255 + return ("#%02x%02x%02x"):format(floor(r), floor(g), floor(b)) end function _color.multiply(color, amount) - return { _color.clip(color.r * amount, 0, 255), - _color.clip(color.g * amount, 0, 255), - _color.clip(color.b * amount, 0, 255), - 255 } + return { + _color.clip(color.r * amount, 0, 255), + _color.clip(color.g * amount, 0, 255), + _color.clip(color.b * amount, 0, 255), + 255, + } end return _color diff --git a/helpers/filesystem.lua b/helpers/filesystem.lua index e3379186..4c260bb2 100644 --- a/helpers/filesystem.lua +++ b/helpers/filesystem.lua @@ -12,52 +12,44 @@ local _filesystem = {} -- @bool[opt=false] recursive List files from subdirectories -- @staticfct bling.helpers.filesystem.get_random_file_from_dir function _filesystem.list_directory_files(path, exts, recursive) - recursive = recursive or false - local files, valid_exts = {}, {} + recursive = recursive or false + local files, valid_exts = {}, {} - -- Transforms { "jpg", ... } into { [jpg] = #, ... } - if exts then - for i, j in ipairs(exts) do - valid_exts[j:lower()] = i - end - end + -- Transforms { "jpg", ... } into { [jpg] = #, ... } + if exts then + for i, j in ipairs(exts) do + valid_exts[j:lower()] = i + end + end - -- Build a table of files from the path with the required extensions - local file_list = Gio.File.new_for_path(path):enumerate_children( - "standard::*", - 0 - ) - if file_list then - for file in function() - return file_list:next_file() - end do - local file_type = file:get_file_type() - if file_type == "REGULAR" then - local file_name = file:get_display_name() - if - not exts - or valid_exts[file_name:lower():match(".+%.(.*)$") or ""] - then - table.insert(files, file_name) - end - elseif recursive and file_type == "DIRECTORY" then - local file_name = file:get_display_name() - files = gears.table.join( - files, - list_directory_files(file_name, exts, recursive) - ) - end - end - end + -- Build a table of files from the path with the required extensions + local file_list = Gio.File.new_for_path(path):enumerate_children("standard::*", 0) + if file_list then + for file in + function() + return file_list:next_file() + end + do + local file_type = file:get_file_type() + if file_type == "REGULAR" then + local file_name = file:get_display_name() + if not exts or valid_exts[file_name:lower():match(".+%.(.*)$") or ""] then + table.insert(files, file_name) + end + elseif recursive and file_type == "DIRECTORY" then + local file_name = file:get_display_name() + files = gears.table.join(files, list_directory_files(file_name, exts, recursive)) + end + end + end - return files + return files end function _filesystem.save_image_async_curl(url, filepath, callback) - awful.spawn.with_line_callback(string.format("curl -L -s %s -o %s", url, filepath), - { - exit=callback - }) + awful.spawn.with_line_callback(string.format("curl -L -s %s -o %s", url, filepath), { + exit = callback, + }) end return _filesystem diff --git a/helpers/icon_theme.lua b/helpers/icon_theme.lua index ffc71143..b999f130 100644 --- a/helpers/icon_theme.lua +++ b/helpers/icon_theme.lua @@ -9,135 +9,134 @@ local ipairs = ipairs local icon_theme = { mt = {} } -local name_lookup = -{ - ["jetbrains-studio"] = "android-studio" +local name_lookup = { + ["jetbrains-studio"] = "android-studio", } local function get_icon_by_pid_command(self, client, apps) - local pid = client.pid - if pid ~= nil then - local handle = io.popen(string.format("ps -p %d -o comm=", pid)) - local pid_command = handle:read("*a"):gsub("^%s*(.-)%s*$", "%1") - handle:close() - - for _, app in ipairs(apps) do - local executable = app:get_executable() - if executable and executable:find(pid_command, 1, true) then - return self:get_gicon_path(app:get_icon()) - end - end - end + local pid = client.pid + if pid ~= nil then + local handle = io.popen(string.format("ps -p %d -o comm=", pid)) + local pid_command = handle:read("*a"):gsub("^%s*(.-)%s*$", "%1") + handle:close() + + for _, app in ipairs(apps) do + local executable = app:get_executable() + if executable and executable:find(pid_command, 1, true) then + return self:get_gicon_path(app:get_icon()) + end + end + end end local function get_icon_by_icon_name(self, client, apps) - local icon_name = client.icon_name and client.icon_name:lower() or nil - if icon_name ~= nil then - for _, app in ipairs(apps) do - local name = app:get_name():lower() - if name and name:find(icon_name, 1, true) then - return self:get_gicon_path(app:get_icon()) - end - end - end + local icon_name = client.icon_name and client.icon_name:lower() or nil + if icon_name ~= nil then + for _, app in ipairs(apps) do + local name = app:get_name():lower() + if name and name:find(icon_name, 1, true) then + return self:get_gicon_path(app:get_icon()) + end + end + end end local function get_icon_by_class(self, client, apps) - if client.class ~= nil then - local class = name_lookup[client.class] or client.class:lower() - - -- Try to remove dashes - local class_1 = class:gsub("[%-]", "") - - -- Try to replace dashes with dot - local class_2 = class:gsub("[%-]", ".") - - -- Try to match only the first word - local class_3 = class:match("(.-)-") or class - class_3 = class_3:match("(.-)%.") or class_3 - class_3 = class_3:match("(.-)%s+") or class_3 - - local possible_icon_names = { class, class_3, class_2, class_1 } - for _, app in ipairs(apps) do - local id = app:get_id():lower() - for _, possible_icon_name in ipairs(possible_icon_names) do - if id and id:find(possible_icon_name, 1, true) then - return self:get_gicon_path(app:get_icon()) - end - end - end - end + if client.class ~= nil then + local class = name_lookup[client.class] or client.class:lower() + + -- Try to remove dashes + local class_1 = class:gsub("[%-]", "") + + -- Try to replace dashes with dot + local class_2 = class:gsub("[%-]", ".") + + -- Try to match only the first word + local class_3 = class:match("(.-)-") or class + class_3 = class_3:match("(.-)%.") or class_3 + class_3 = class_3:match("(.-)%s+") or class_3 + + local possible_icon_names = { class, class_3, class_2, class_1 } + for _, app in ipairs(apps) do + local id = app:get_id():lower() + for _, possible_icon_name in ipairs(possible_icon_names) do + if id and id:find(possible_icon_name, 1, true) then + return self:get_gicon_path(app:get_icon()) + end + end + end + end end function icon_theme:get_client_icon_path(client) - local apps = Gio.AppInfo.get_all() + local apps = Gio.AppInfo.get_all() - return get_icon_by_pid_command(self, client, apps) or - get_icon_by_icon_name(self, client, apps) or - get_icon_by_class(self, client, apps) or - client.icon or - self:choose_icon({"window", "window-manager", "xfwm4-default", "window_list" }) + return get_icon_by_pid_command(self, client, apps) + or get_icon_by_icon_name(self, client, apps) + or get_icon_by_class(self, client, apps) + or client.icon + or self:choose_icon({ "window", "window-manager", "xfwm4-default", "window_list" }) end function icon_theme:choose_icon(icons_names) - local icon_info = self.gtk_theme:choose_icon(icons_names, self.icon_size, 0); - if icon_info then - local icon_path = icon_info:get_filename() - if icon_path then - return icon_path - end - end - - return "" + local icon_info = self.gtk_theme:choose_icon(icons_names, self.icon_size, 0) + if icon_info then + local icon_path = icon_info:get_filename() + if icon_path then + return icon_path + end + end + + return "" end function icon_theme:get_gicon_path(gicon) - if gicon == nil then - return "" - end - - local icon_info = self.gtk_theme:lookup_by_gicon(gicon, self.icon_size, 0); - if icon_info then - local icon_path = icon_info:get_filename() - if icon_path then - return icon_path - end - end - - return "" + if gicon == nil then + return "" + end + + local icon_info = self.gtk_theme:lookup_by_gicon(gicon, self.icon_size, 0) + if icon_info then + local icon_path = icon_info:get_filename() + if icon_path then + return icon_path + end + end + + return "" end function icon_theme:get_icon_path(icon_name) - local icon_info = self.gtk_theme:lookup_icon(icon_name, self.icon_size, 0) - if icon_info then - local icon_path = icon_info:get_filename() - if icon_path then - return icon_path - end - end - - return "" + local icon_info = self.gtk_theme:lookup_icon(icon_name, self.icon_size, 0) + if icon_info then + local icon_path = icon_info:get_filename() + if icon_path then + return icon_path + end + end + + return "" end local function new(theme_name, icon_size) - local ret = gobject{} - gtable.crush(ret, icon_theme, true) + local ret = gobject({}) + gtable.crush(ret, icon_theme, true) - ret.name = theme_name or nil - ret.icon_size = icon_size or 48 + ret.name = theme_name or nil + ret.icon_size = icon_size or 48 - if theme_name then - ret.gtk_theme = Gtk.IconTheme.new() - Gtk.IconTheme.set_custom_theme(ret.gtk_theme, theme_name); - else - ret.gtk_theme = Gtk.IconTheme.get_default() - end + if theme_name then + ret.gtk_theme = Gtk.IconTheme.new() + Gtk.IconTheme.set_custom_theme(ret.gtk_theme, theme_name) + else + ret.gtk_theme = Gtk.IconTheme.get_default() + end - return ret + return ret end function icon_theme.mt:__call(...) - return new(...) + return new(...) end -return setmetatable(icon_theme, icon_theme.mt) \ No newline at end of file +return setmetatable(icon_theme, icon_theme.mt) diff --git a/helpers/init.lua b/helpers/init.lua index f2c898e7..1190891f 100644 --- a/helpers/init.lua +++ b/helpers/init.lua @@ -1,7 +1,7 @@ return { - client = require(... .. ".client"), - color = require(... .. ".color"), - filesystem = require(... .. ".filesystem"), - shape = require(... .. ".shape"), - time = require(... .. ".time"), + client = require(... .. ".client"), + color = require(... .. ".color"), + filesystem = require(... .. ".filesystem"), + shape = require(... .. ".shape"), + time = require(... .. ".time"), } diff --git a/helpers/shape.lua b/helpers/shape.lua index de21ea13..ee2fc570 100644 --- a/helpers/shape.lua +++ b/helpers/shape.lua @@ -5,25 +5,16 @@ local shape = {} -- Create rounded rectangle shape (in one line) function shape.rrect(radius) - return function(cr, width, height) - gears.shape.rounded_rect(cr, width, height, radius) - end + return function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, radius) + end end -- Create partially rounded rect function shape.prrect(radius, tl, tr, br, bl) - return function(cr, width, height) - gears.shape.partially_rounded_rect( - cr, - width, - height, - tl, - tr, - br, - bl, - radius - ) - end + return function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, tl, tr, br, bl, radius) + end end return shape diff --git a/helpers/time.lua b/helpers/time.lua index c7ab5af3..6d8a289f 100644 --- a/helpers/time.lua +++ b/helpers/time.lua @@ -5,10 +5,10 @@ local time = {} -- @string time The time (`HH:MM:SS`) -- @treturn int The number of seconds since 00:00:00 function time.hhmmss_to_seconds(time) - hour_sec = tonumber(string.sub(time, 1, 2)) * 3600 - min_sec = tonumber(string.sub(time, 4, 5)) * 60 - get_sec = tonumber(string.sub(time, 7, 8)) - return (hour_sec + min_sec + get_sec) + hour_sec = tonumber(string.sub(time, 1, 2)) * 3600 + min_sec = tonumber(string.sub(time, 4, 5)) * 60 + get_sec = tonumber(string.sub(time, 7, 8)) + return (hour_sec + min_sec + get_sec) end --- Get time difference in seconds. @@ -16,8 +16,8 @@ end -- @tparam string base The time to compare to (`HH:MM:SS`). -- @treturn int Number of seconds between the two times. function time.time_diff(base, compare) - local diff = time.hhmmss_to_seconds(base) - time.hhmmss_to_seconds(compare) - return diff + local diff = time.hhmmss_to_seconds(base) - time.hhmmss_to_seconds(compare) + return diff end return time