configure awesome
@ -106,9 +106,12 @@
|
|||||||
# vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
|
# vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
|
||||||
lm_sensors
|
lm_sensors
|
||||||
brightnessctl
|
brightnessctl
|
||||||
inotify-tools
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
programs.light.enable = true;
|
||||||
|
|
||||||
|
services.acpid.enable = true;
|
||||||
|
|
||||||
# Some programs need SUID wrappers, can be configured further or are
|
# Some programs need SUID wrappers, can be configured further or are
|
||||||
# started in user sessions.
|
# started in user sessions.
|
||||||
# programs.mtr.enable = true;
|
# programs.mtr.enable = true;
|
||||||
|
|||||||
@ -22,20 +22,27 @@
|
|||||||
# For funsies
|
# For funsies
|
||||||
spotify
|
spotify
|
||||||
vesktop
|
vesktop
|
||||||
ncmpcpp
|
|
||||||
mpd
|
|
||||||
mpdris2
|
|
||||||
|
|
||||||
# Other utility
|
# Other utility
|
||||||
mullvad-vpn
|
mullvad-vpn
|
||||||
transmission_4-gtk
|
transmission_4-gtk
|
||||||
imagemagick
|
imagemagick
|
||||||
neofetch
|
neofetch
|
||||||
|
maim
|
||||||
|
xclip
|
||||||
|
slop
|
||||||
|
swappy
|
||||||
|
inotify-tools
|
||||||
];
|
];
|
||||||
|
|
||||||
|
# Clips
|
||||||
|
services.clipmenu.enable = true;
|
||||||
|
|
||||||
# Enable sound control
|
# Enable sound control
|
||||||
services.easyeffects.enable = true;
|
services.easyeffects.enable = true;
|
||||||
|
|
||||||
|
# Enable playerctl daemon
|
||||||
services.playerctld.enable = true;
|
services.playerctld.enable = true;
|
||||||
|
|
||||||
# Home Manager is pretty good at managing dotfiles. The primary way to manage
|
# Home Manager is pretty good at managing dotfiles. The primary way to manage
|
||||||
|
|||||||
@ -28,7 +28,7 @@
|
|||||||
# Utils
|
# Utils
|
||||||
corefonts
|
corefonts
|
||||||
noto-fonts
|
noto-fonts
|
||||||
flameshot
|
maim
|
||||||
];
|
];
|
||||||
|
|
||||||
programs.firefox.enable = true;
|
programs.firefox.enable = true;
|
||||||
|
|||||||
@ -3,6 +3,6 @@
|
|||||||
{
|
{
|
||||||
home.file.".config/awesome" = {
|
home.file.".config/awesome" = {
|
||||||
recursive = true;
|
recursive = true;
|
||||||
source = ./dotfiles;
|
source = ./gruv;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1,230 +0,0 @@
|
|||||||
local helpers = {}
|
|
||||||
local awful = require("awful")
|
|
||||||
local beautiful = require("beautiful")
|
|
||||||
local gears = require("gears")
|
|
||||||
local dpi = beautiful.xresources.apply_dpi
|
|
||||||
local cairo = require("lgi").cairo
|
|
||||||
local gmatrix = require("gears.matrix")
|
|
||||||
local json = require("mods.json")
|
|
||||||
|
|
||||||
helpers.rrect = function(radius)
|
|
||||||
radius = radius or dpi(4)
|
|
||||||
return function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, radius)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.addHover = function(element, bg, hbg)
|
|
||||||
element:connect_signal('mouse::enter', function(self)
|
|
||||||
self.bg = hbg
|
|
||||||
end)
|
|
||||||
element:connect_signal('mouse::leave', function(self)
|
|
||||||
self.bg = bg
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.placeWidget = function(widget)
|
|
||||||
if beautiful.barDir == 'left' then
|
|
||||||
awful.placement.bottom_left(widget, { honor_workarea = true, margins = beautiful.useless_gap * 2 })
|
|
||||||
elseif beautiful.barDir == 'right' then
|
|
||||||
awful.placement.bottom_right(widget, { honor_workarea = true, margins = beautiful.useless_gap * 2 })
|
|
||||||
elseif beautiful.barDir == 'bottom' then
|
|
||||||
awful.placement.bottom(widget, { honor_workarea = true, margins = beautiful.useless_gap * 2 })
|
|
||||||
elseif beautiful.barDir == 'top' then
|
|
||||||
awful.placement.top(widget, { honor_workarea = true, margins = beautiful.useless_gap * 2 })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.prect = function(tl, tr, br, bl, radius)
|
|
||||||
radius = radius or dpi(4)
|
|
||||||
return function(cr, width, height)
|
|
||||||
gears.shape.partially_rounded_rect(cr, width, height, tl, tr, br, bl, radius)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.clickKey = function(c, key)
|
|
||||||
awful.spawn.with_shell("xdotool type --window " .. tostring(c.window) .. " '" .. key .. "'")
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.colorizeText = function(txt, fg)
|
|
||||||
if fg == "" then
|
|
||||||
fg = "#ffffff"
|
|
||||||
end
|
|
||||||
|
|
||||||
return "<span foreground='" .. fg .. "'>" .. txt .. "</span>"
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.cropSurface = function(ratio, surf)
|
|
||||||
local old_w, old_h = gears.surface.get_size(surf)
|
|
||||||
local old_ratio = old_w / old_h
|
|
||||||
if old_ratio == ratio then return surf end
|
|
||||||
|
|
||||||
local new_h = old_h
|
|
||||||
local new_w = old_w
|
|
||||||
local offset_h, offset_w = 0, 0
|
|
||||||
-- quick mafs
|
|
||||||
if (old_ratio < ratio) then
|
|
||||||
new_h = math.ceil(old_w * (1 / ratio))
|
|
||||||
offset_h = math.ceil((old_h - new_h) / 2)
|
|
||||||
else
|
|
||||||
new_w = math.ceil(old_h * ratio)
|
|
||||||
offset_w = math.ceil((old_w - new_w) / 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
local out_surf = cairo.ImageSurface(cairo.Format.ARGB32, new_w, new_h)
|
|
||||||
local cr = cairo.Context(out_surf)
|
|
||||||
cr:set_source_surface(surf, -offset_w, -offset_h)
|
|
||||||
cr.operator = cairo.Operator.SOURCE
|
|
||||||
cr:paint()
|
|
||||||
|
|
||||||
return out_surf
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.inTable = function(t, v)
|
|
||||||
for _, value in ipairs(t) do
|
|
||||||
if value == v then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
helpers.generateId = function()
|
|
||||||
local template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
|
|
||||||
return string.gsub(template, '[xy]', function(c)
|
|
||||||
local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb)
|
|
||||||
return string.format('%x', v)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.find_last = function(haystack, needle)
|
|
||||||
-- Set the third arg to false to allow pattern matching
|
|
||||||
local found = haystack:reverse():find(needle:reverse(), nil, true)
|
|
||||||
if found then
|
|
||||||
return haystack:len() - needle:len() - found + 2
|
|
||||||
else
|
|
||||||
return found
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
helpers.addTables = function(a, b)
|
|
||||||
local result = {}
|
|
||||||
for _, v in pairs(a) do
|
|
||||||
table.insert(result, v)
|
|
||||||
end
|
|
||||||
for _, v in pairs(b) do
|
|
||||||
table.insert(result, v)
|
|
||||||
end
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.hasKey = function(set, key)
|
|
||||||
return set[key] ~= nil
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.trim = function(string)
|
|
||||||
return string:gsub("^%s*(.-)%s*$", "%1")
|
|
||||||
end
|
|
||||||
helpers.indexOf = function(array, value)
|
|
||||||
for i, v in ipairs(array) do
|
|
||||||
if v == value then
|
|
||||||
return i
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.split = function(inputstr, sep)
|
|
||||||
if sep == nil then
|
|
||||||
sep = "%s"
|
|
||||||
end
|
|
||||||
local t = {}
|
|
||||||
for str in string.gmatch(inputstr, "([^" .. sep .. "]+)") do
|
|
||||||
table.insert(t, str)
|
|
||||||
end
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.readFile = function(file)
|
|
||||||
local f = assert(io.open(file, "rb"))
|
|
||||||
local content = f:read("*all")
|
|
||||||
f:close()
|
|
||||||
return content
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.file_exists = function(name)
|
|
||||||
local f = io.open(name, "r")
|
|
||||||
if f ~= nil then
|
|
||||||
io.close(f)
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_widget_geometry(_hierarchy, widget)
|
|
||||||
local width, height = _hierarchy:get_size()
|
|
||||||
if _hierarchy:get_widget() == widget then
|
|
||||||
-- Get the extents of this widget in the device space
|
|
||||||
local x, y, w, h = gmatrix.transform_rectangle(_hierarchy:get_matrix_to_device(), 0, 0, width, height)
|
|
||||||
return { x = x, y = y, width = w, height = h, hierarchy = _hierarchy }
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, child in ipairs(_hierarchy:get_children()) do
|
|
||||||
local ret = get_widget_geometry(child, widget)
|
|
||||||
if ret then
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function helpers.get_widget_geometry(wibox, widget)
|
|
||||||
return get_widget_geometry(wibox._drawable._widget_hierarchy, widget)
|
|
||||||
end
|
|
||||||
|
|
||||||
function helpers.randomColor()
|
|
||||||
local accents = {
|
|
||||||
beautiful.magenta,
|
|
||||||
beautiful.yellow,
|
|
||||||
beautiful.green,
|
|
||||||
beautiful.red,
|
|
||||||
beautiful.blue,
|
|
||||||
}
|
|
||||||
|
|
||||||
local i = math.random(1, #accents)
|
|
||||||
return accents[i]
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.readJson = function(DATA)
|
|
||||||
if helpers.file_exists(DATA) then
|
|
||||||
local f = assert(io.open(DATA, "rb"))
|
|
||||||
local lines = f:read("*all")
|
|
||||||
f:close()
|
|
||||||
local data = json.decode(lines)
|
|
||||||
return data
|
|
||||||
else
|
|
||||||
return {}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.writeJson = function(PATH, DATA)
|
|
||||||
local w = assert(io.open(PATH, "w"))
|
|
||||||
w:write(json.encode(DATA, nil, { pretty = true, indent = " ", align_keys = false, array_newline = true }))
|
|
||||||
w:close()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- this stands for :get_children_by_id
|
|
||||||
helpers.gc = function(widget, id)
|
|
||||||
return widget:get_children_by_id(id)[1]
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.beginsWith = function(str, pattern)
|
|
||||||
return str:find('^' .. pattern) ~= nil
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
return helpers
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
local awful = require "awful"
|
|
||||||
|
|
||||||
local brightness = {}
|
|
||||||
|
|
||||||
brightness.increase = function()
|
|
||||||
local script = [[
|
|
||||||
brightnessctl set 3%+
|
|
||||||
]]
|
|
||||||
|
|
||||||
awful.spawn.with_shell(script)
|
|
||||||
end
|
|
||||||
|
|
||||||
brightness.decrease = function()
|
|
||||||
local script = [[
|
|
||||||
brightnessctl set 3%-
|
|
||||||
]]
|
|
||||||
|
|
||||||
awful.spawn.with_shell(script)
|
|
||||||
end
|
|
||||||
|
|
||||||
return brightness
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
local awful = require "awful"
|
|
||||||
|
|
||||||
local volume = {}
|
|
||||||
|
|
||||||
volume.increase = function()
|
|
||||||
local script = [[
|
|
||||||
pamixer -i 3
|
|
||||||
]]
|
|
||||||
|
|
||||||
awful.spawn.with_shell(script)
|
|
||||||
end
|
|
||||||
|
|
||||||
volume.decrease = function()
|
|
||||||
local script = [[
|
|
||||||
pamixer -d 3
|
|
||||||
]]
|
|
||||||
|
|
||||||
awful.spawn.with_shell(script)
|
|
||||||
end
|
|
||||||
|
|
||||||
volume.mute = function()
|
|
||||||
local script = [[
|
|
||||||
pamixer -t
|
|
||||||
]]
|
|
||||||
|
|
||||||
awful.spawn.with_shell(script)
|
|
||||||
end
|
|
||||||
|
|
||||||
return volume
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
local apps = {
|
|
||||||
terminal = "wezterm",
|
|
||||||
launcher = "rofi -show drun",
|
|
||||||
browser = "firefox",
|
|
||||||
fileManager = "thunar",
|
|
||||||
}
|
|
||||||
|
|
||||||
return apps
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
mpDris2 &
|
|
||||||
xrdb -merge ~/.Xresources
|
|
||||||
picom --config $HOME/.config/picom/picom.conf
|
|
||||||
xss-lock lock
|
|
||||||
mkdir -p ~/.cache/awesome/json/
|
|
||||||
@ -1,230 +0,0 @@
|
|||||||
local awful = require "awful"
|
|
||||||
local gears = require "gears"
|
|
||||||
local naughty = require "naughty"
|
|
||||||
local beautiful = require "beautiful"
|
|
||||||
|
|
||||||
local apps = require "main.apps"
|
|
||||||
|
|
||||||
modkey = "Mod4"
|
|
||||||
|
|
||||||
-- General awesome keybindings
|
|
||||||
awful.keyboard.append_global_keybindings({
|
|
||||||
awful.key({ modkey, "Control" }, "r", awesome.restart,
|
|
||||||
{ description = "reload awesome", group = "awesome" }),
|
|
||||||
awful.key({ modkey, "Shift" }, "q", awesome.quit,
|
|
||||||
{ description = "quit awesome", group = "awesome" }),
|
|
||||||
awful.key({ modkey, }, "Return", function() awful.spawn(apps.terminal) end,
|
|
||||||
{ description = "open a terminal", group = "launcher" }),
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Tag bindings
|
|
||||||
awful.keyboard.append_global_keybindings({
|
|
||||||
awful.key({ modkey, }, "Left", awful.tag.viewprev,
|
|
||||||
{ description = "view previous", group = "tag" }),
|
|
||||||
awful.key({ modkey, }, "Right", awful.tag.viewnext,
|
|
||||||
{ description = "view next", group = "tag" }),
|
|
||||||
awful.key({ modkey, }, "Escape", awful.tag.history.restore,
|
|
||||||
{ description = "go back", group = "tag" }),
|
|
||||||
})
|
|
||||||
|
|
||||||
awful.keyboard.append_global_keybindings({
|
|
||||||
awful.key {
|
|
||||||
modifiers = { modkey },
|
|
||||||
keygroup = "numrow",
|
|
||||||
description = "only view tag",
|
|
||||||
group = "tag",
|
|
||||||
on_press = function(index)
|
|
||||||
local screen = awful.screen.focused()
|
|
||||||
local tag = screen.tags[index]
|
|
||||||
if tag then
|
|
||||||
tag:view_only()
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
awful.key {
|
|
||||||
modifiers = { modkey, "Control" },
|
|
||||||
keygroup = "numrow",
|
|
||||||
description = "toggle tag",
|
|
||||||
group = "tag",
|
|
||||||
on_press = function(index)
|
|
||||||
local screen = awful.screen.focused()
|
|
||||||
local tag = screen.tags[index]
|
|
||||||
if tag then
|
|
||||||
awful.tag.viewtoggle(tag)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
awful.key {
|
|
||||||
modifiers = { modkey, "Shift" },
|
|
||||||
keygroup = "numrow",
|
|
||||||
description = "move focused client to tag",
|
|
||||||
group = "tag",
|
|
||||||
on_press = function(index)
|
|
||||||
if client.focus then
|
|
||||||
local tag = client.focus.screen.tags[index]
|
|
||||||
if tag then
|
|
||||||
client.focus:move_to_tag(tag)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
awful.key {
|
|
||||||
modifiers = { modkey, "Control", "Shift" },
|
|
||||||
keygroup = "numrow",
|
|
||||||
description = "toggle focused client on tag",
|
|
||||||
group = "tag",
|
|
||||||
on_press = function(index)
|
|
||||||
if client.focus then
|
|
||||||
local tag = client.focus.screen.tags[index]
|
|
||||||
if tag then
|
|
||||||
client.focus:toggle_tag(tag)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
awful.key {
|
|
||||||
modifiers = { modkey },
|
|
||||||
keygroup = "numpad",
|
|
||||||
description = "select layout directly",
|
|
||||||
group = "layout",
|
|
||||||
on_press = function(index)
|
|
||||||
local t = awful.screen.focused().selected_tag
|
|
||||||
if t then
|
|
||||||
t.layout = t.layouts[index] or t.layout
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Focus bindings
|
|
||||||
awful.keyboard.append_global_keybindings({
|
|
||||||
awful.key({ modkey, }, "j",
|
|
||||||
function()
|
|
||||||
awful.client.focus.byidx(1)
|
|
||||||
end,
|
|
||||||
{ description = "focus next by index", group = "client" }
|
|
||||||
),
|
|
||||||
awful.key({ modkey, }, "k",
|
|
||||||
function()
|
|
||||||
awful.client.focus.byidx(-1)
|
|
||||||
end,
|
|
||||||
{ description = "focus previous by index", group = "client" }
|
|
||||||
),
|
|
||||||
awful.key({ modkey, }, "Tab",
|
|
||||||
function()
|
|
||||||
awful.client.focus.history.previous()
|
|
||||||
if client.focus then
|
|
||||||
client.focus:raise()
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
{ description = "go back", group = "client" }),
|
|
||||||
awful.key({ modkey, "Control" }, "j", function() awful.screen.focus_relative(1) end,
|
|
||||||
{ description = "focus the next screen", group = "screen" }),
|
|
||||||
awful.key({ modkey, "Control" }, "k", function() awful.screen.focus_relative(-1) end,
|
|
||||||
{ description = "focus the previous screen", group = "screen" }),
|
|
||||||
awful.key({ modkey, "Control" }, "n",
|
|
||||||
function()
|
|
||||||
local c = awful.client.restore()
|
|
||||||
-- Focus restored client
|
|
||||||
if c then
|
|
||||||
c:activate { raise = true, context = "key.unminimize" }
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
{ description = "restore minimized", group = "client" }),
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Layout bindings
|
|
||||||
awful.keyboard.append_global_keybindings({
|
|
||||||
awful.key({ modkey, "Shift" }, "j", function() awful.client.swap.byidx(1) end,
|
|
||||||
{ description = "swap with next client by index", group = "client" }),
|
|
||||||
awful.key({ modkey, "Shift" }, "k", function() awful.client.swap.byidx(-1) end,
|
|
||||||
{ description = "swap with previous client by index", group = "client" }),
|
|
||||||
awful.key({ modkey, }, "u", awful.client.urgent.jumpto,
|
|
||||||
{ description = "jump to urgent client", group = "client" }),
|
|
||||||
awful.key({ modkey, }, "l", function() awful.tag.incmwfact(0.05) end,
|
|
||||||
{ description = "increase master width factor", group = "layout" }),
|
|
||||||
awful.key({ modkey, }, "h", function() awful.tag.incmwfact(-0.05) end,
|
|
||||||
{ description = "decrease master width factor", group = "layout" }),
|
|
||||||
awful.key({ modkey, "Shift" }, "h", function() awful.tag.incnmaster(1, nil, true) end,
|
|
||||||
{ description = "increase the number of master clients", group = "layout" }),
|
|
||||||
awful.key({ modkey, "Shift" }, "l", function() awful.tag.incnmaster(-1, nil, true) end,
|
|
||||||
{ description = "decrease the number of master clients", group = "layout" }),
|
|
||||||
awful.key({ modkey, "Control" }, "h", function() awful.tag.incncol(1, nil, true) end,
|
|
||||||
{ description = "increase the number of columns", group = "layout" }),
|
|
||||||
awful.key({ modkey, "Control" }, "l", function() awful.tag.incncol(-1, nil, true) end,
|
|
||||||
{ description = "decrease the number of columns", group = "layout" }),
|
|
||||||
awful.key({ modkey, }, "space", function() awful.layout.inc(1) end,
|
|
||||||
{ description = "select next", group = "layout" }),
|
|
||||||
awful.key({ modkey, "Shift" }, "space", function() awful.layout.inc(-1) end,
|
|
||||||
{ description = "select previous", group = "layout" }),
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Client bindings
|
|
||||||
client.connect_signal("request::default_keybindings", function()
|
|
||||||
awful.keyboard.append_client_keybindings({
|
|
||||||
awful.key({ modkey, }, "f",
|
|
||||||
function(c)
|
|
||||||
c.fullscreen = not c.fullscreen
|
|
||||||
c:raise()
|
|
||||||
end,
|
|
||||||
{ description = "toggle fullscreen", group = "client" }),
|
|
||||||
awful.key({ modkey, "Shift" }, "c", function(c) c:kill() end,
|
|
||||||
{ description = "close", group = "client" }),
|
|
||||||
awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle,
|
|
||||||
{ description = "toggle floating", group = "client" }),
|
|
||||||
awful.key({ modkey, "Control" }, "Return", function(c) c:swap(awful.client.getmaster()) end,
|
|
||||||
{ description = "move to master", group = "client" }),
|
|
||||||
awful.key({ modkey, }, "o", function(c) c:move_to_screen() end,
|
|
||||||
{ description = "move to screen", group = "client" }),
|
|
||||||
awful.key({ modkey, }, "t", function(c) c.ontop = not c.ontop end,
|
|
||||||
{ description = "toggle keep on top", group = "client" }),
|
|
||||||
awful.key({ modkey, }, "n",
|
|
||||||
function(c)
|
|
||||||
-- The client currently has the input focus, so it cannot be
|
|
||||||
-- minimized, since minimized clients can't have the focus.
|
|
||||||
c.minimized = true
|
|
||||||
end,
|
|
||||||
{ description = "minimize", group = "client" }),
|
|
||||||
awful.key({ modkey, }, "m",
|
|
||||||
function(c)
|
|
||||||
c.maximized = not c.maximized
|
|
||||||
c:raise()
|
|
||||||
end,
|
|
||||||
{ description = "(un)maximize", group = "client" }),
|
|
||||||
awful.key({ modkey, "Control" }, "m",
|
|
||||||
function(c)
|
|
||||||
c.maximized_vertical = not c.maximized_vertical
|
|
||||||
c:raise()
|
|
||||||
end,
|
|
||||||
{ description = "(un)maximize vertically", group = "client" }),
|
|
||||||
awful.key({ modkey, "Shift" }, "m",
|
|
||||||
function(c)
|
|
||||||
c.maximized_horizontal = not c.maximized_horizontal
|
|
||||||
c:raise()
|
|
||||||
end,
|
|
||||||
{ description = "(un)maximize horizontally", group = "client" }),
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Mouse bindings
|
|
||||||
local menu = require("ui.rightclick")
|
|
||||||
awful.mouse.append_global_mousebindings({
|
|
||||||
awful.button({}, 3, function()
|
|
||||||
menu.desktop:toggle()
|
|
||||||
return
|
|
||||||
end),
|
|
||||||
})
|
|
||||||
|
|
||||||
client.connect_signal("request::default_mousebindings", function()
|
|
||||||
awful.mouse.append_client_mousebindings({
|
|
||||||
awful.button({}, 1, function(c)
|
|
||||||
c:activate { context = "mouse_click" }
|
|
||||||
end),
|
|
||||||
awful.button({ modkey }, 1, function(c)
|
|
||||||
c:activate { context = "mouse_click", action = "mouse_move" }
|
|
||||||
end),
|
|
||||||
awful.button({ modkey }, 3, function(c)
|
|
||||||
c:activate { context = "mouse_click", action = "mouse_resize" }
|
|
||||||
end),
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
local awful = require "awful"
|
|
||||||
|
|
||||||
local volume = require "lib.volume"
|
|
||||||
local brightness = require "lib.brightness"
|
|
||||||
|
|
||||||
-- Volume
|
|
||||||
awful.keyboard.append_global_keybindings({
|
|
||||||
awful.key({}, "XF86AudioRaiseVolume", function()
|
|
||||||
volume.increase()
|
|
||||||
awesome.emit_signal("open::osd")
|
|
||||||
end),
|
|
||||||
awful.key({}, "XF86AudioLowerVolume", function()
|
|
||||||
volume.decrease()
|
|
||||||
awesome.emit_signal("open::osd")
|
|
||||||
end),
|
|
||||||
awful.key({}, "XF86AudioMute", function()
|
|
||||||
volume.mute()
|
|
||||||
awesome.emit_signal("open::osd")
|
|
||||||
end)
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Brightness
|
|
||||||
awful.keyboard.append_global_keybindings({
|
|
||||||
awful.key({}, "XF86MonBrightnessUp", function()
|
|
||||||
brightness.increase()
|
|
||||||
awesome.emit_signal("open::osdb")
|
|
||||||
end),
|
|
||||||
|
|
||||||
awful.key({}, "XF86MonBrightnessDown", function()
|
|
||||||
brightness.decrease()
|
|
||||||
awesome.emit_signal("open::osdb")
|
|
||||||
end),
|
|
||||||
awful.key({ modkey, }, "a",
|
|
||||||
function(c)
|
|
||||||
awesome.emit_signal("toggle::launcher")
|
|
||||||
end),
|
|
||||||
awful.key({ modkey, }, "x",
|
|
||||||
function(c)
|
|
||||||
awesome.emit_signal("toggle::exit")
|
|
||||||
end),
|
|
||||||
awful.key({ modkey, }, "q",
|
|
||||||
function(c)
|
|
||||||
awesome.emit_signal("toggle::scrotter")
|
|
||||||
end),
|
|
||||||
})
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
local naughty = require "naughty"
|
|
||||||
|
|
||||||
naughty.connect_signal("request::display_error", function(message, startup)
|
|
||||||
naughty.notification {
|
|
||||||
urgency = "critical",
|
|
||||||
title = "Oops, an error happened"..(startup and " during startup!" or "!"),
|
|
||||||
message = message
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
-- init config
|
|
||||||
require "main.wallpaper"
|
|
||||||
require "main.layout"
|
|
||||||
require "main.rules"
|
|
||||||
require "main.bindings.bindings"
|
|
||||||
require "main.bindings.custom_bindings"
|
|
||||||
require "main.tags"
|
|
||||||
require "main.swallow"
|
|
||||||
require "main.error_handling"
|
|
||||||
require "main.scratch"
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
local awful = require "awful"
|
|
||||||
local gears = require "gears"
|
|
||||||
local beautiful = require "beautiful"
|
|
||||||
|
|
||||||
awful.layout.layouts = {
|
|
||||||
awful.layout.suit.tile,
|
|
||||||
awful.layout.suit.floating,
|
|
||||||
}
|
|
||||||
|
|
||||||
client.connect_signal("mouse::enter", function(c)
|
|
||||||
c:activate { context = "mouse_enter", raise = false }
|
|
||||||
end)
|
|
||||||
|
|
||||||
client.connect_signal("manage", function(c)
|
|
||||||
if awesome.startup then awful.client.setslave(c) end
|
|
||||||
end)
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
local awful = require "awful"
|
|
||||||
local gears = require "gears"
|
|
||||||
local ruled = require "ruled"
|
|
||||||
|
|
||||||
ruled.client.connect_signal("request::rules", function()
|
|
||||||
ruled.client.append_rule {
|
|
||||||
id = "global",
|
|
||||||
rule = {},
|
|
||||||
properties = {
|
|
||||||
focus = awful.client.focus.filter,
|
|
||||||
raise = true,
|
|
||||||
screen = awful.screen.preferred,
|
|
||||||
placement = awful.placement.no_overlap + awful.placement.no_offscreen,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
ruled.client.append_rule {
|
|
||||||
id = "titlebars",
|
|
||||||
rule_any = {
|
|
||||||
type = { "normal", "dialog" },
|
|
||||||
},
|
|
||||||
properties = {
|
|
||||||
titlebars_enabled = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ruled.client.append_rule {
|
|
||||||
id = "desktop",
|
|
||||||
rule_any = {
|
|
||||||
class = {
|
|
||||||
"Nemo-desktop"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
properties = { sticky = true, tag = " " }
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
@ -1,162 +0,0 @@
|
|||||||
local awful = require("awful")
|
|
||||||
local gears = require("gears")
|
|
||||||
local beautiful = require("beautiful")
|
|
||||||
local ruled = require("ruled")
|
|
||||||
|
|
||||||
|
|
||||||
local Scratchpad = { mt = {} } -- scratch init
|
|
||||||
|
|
||||||
-- make a new instance of scratchpad
|
|
||||||
function Scratchpad:new(args)
|
|
||||||
local ret = gears.object {}
|
|
||||||
gears.table.crush(ret, Scratchpad)
|
|
||||||
gears.table.crush(ret, args)
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
local findClient = function(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 matches = {}
|
|
||||||
for c in awful.client.iterate(matcher, start) do
|
|
||||||
matches[#matches + 1] = c
|
|
||||||
end
|
|
||||||
|
|
||||||
return matches
|
|
||||||
end
|
|
||||||
|
|
||||||
function Scratchpad:find()
|
|
||||||
return findClient(self.rule)
|
|
||||||
end
|
|
||||||
|
|
||||||
function Scratchpad:become(c)
|
|
||||||
if not c or not c.valid then return end
|
|
||||||
c.floating = true
|
|
||||||
c.sticky = false
|
|
||||||
c.fullscreen = false
|
|
||||||
c.maximised = false
|
|
||||||
c:geometry({
|
|
||||||
x = (1920 - self.width) / 2,
|
|
||||||
y = (1080 - self.height) / 2,
|
|
||||||
width = self.width,
|
|
||||||
height = self.height
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
function 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
|
|
||||||
end
|
|
||||||
|
|
||||||
function Scratchpad:on()
|
|
||||||
self.client = self:find()[1]
|
|
||||||
if not self.client then
|
|
||||||
local pid = awful.spawn.with_shell(self.command)
|
|
||||||
ruled.client.append_rule({
|
|
||||||
id = "scratch",
|
|
||||||
rule = self.rule,
|
|
||||||
properties = {
|
|
||||||
tag = awful.screen.focused().selected_tag,
|
|
||||||
switch_to_tags = false,
|
|
||||||
hidden = true,
|
|
||||||
minimized = true,
|
|
||||||
},
|
|
||||||
callback = function(c)
|
|
||||||
gears.timer({
|
|
||||||
timeout = 0.1,
|
|
||||||
autostart = true,
|
|
||||||
single_shot = true,
|
|
||||||
callback = function()
|
|
||||||
self.client = c
|
|
||||||
self:become(c)
|
|
||||||
c.hidden = false
|
|
||||||
c.minimized = false
|
|
||||||
|
|
||||||
c:activate({})
|
|
||||||
self:emit_signal("inital_apply", c)
|
|
||||||
if c.name ~= "Discord Updater" then
|
|
||||||
ruled.client.remove_rule("scratch")
|
|
||||||
end
|
|
||||||
c:connect_signal("request::unmanage", function()
|
|
||||||
ruled.client.remove_rule("scratch")
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
})
|
|
||||||
else
|
|
||||||
self.client:raise()
|
|
||||||
client.focus = self.client
|
|
||||||
on(self.client)
|
|
||||||
self:become(self.client)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function turn_off(c)
|
|
||||||
current_tag = c.screen.selected_tag
|
|
||||||
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
|
|
||||||
|
|
||||||
function Scratchpad:off()
|
|
||||||
self.client = self:find()[1]
|
|
||||||
turn_off(self.client)
|
|
||||||
end
|
|
||||||
|
|
||||||
function Scratchpad:toggle()
|
|
||||||
local is_turn_off = client.focus and awful.rules.match(client.focus, self.rule)
|
|
||||||
if is_turn_off then
|
|
||||||
self:off()
|
|
||||||
else
|
|
||||||
self:on()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function Scratchpad.mt:__call(...)
|
|
||||||
return Scratchpad:new(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
local createScratch = function(command, width, height, k)
|
|
||||||
local scratch = Scratchpad:new {
|
|
||||||
--command = 'kitty' .. ' --class "' .. command .. 'pad" -e sh -c "' .. command .. '; $SHELL"',
|
|
||||||
command = 'wezterm start --class ' .. command .. 'pad -e sh -c "' .. command .. '; $SHELL"',
|
|
||||||
rule = { class = command .. 'pad' },
|
|
||||||
height = height,
|
|
||||||
width = width,
|
|
||||||
}
|
|
||||||
awful.keyboard.append_global_keybindings {
|
|
||||||
awful.key {
|
|
||||||
modifiers = { "Mod4" },
|
|
||||||
key = k,
|
|
||||||
description = 'show help',
|
|
||||||
group = 'awesome',
|
|
||||||
on_press = function() scratch:toggle() end,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
awesome.connect_signal("toggle::" .. command .. "pad", function()
|
|
||||||
scratch:toggle()
|
|
||||||
end)
|
|
||||||
return scratch
|
|
||||||
end
|
|
||||||
|
|
||||||
local default = createScratch("clear", 1000, 650, 'v')
|
|
||||||
local ncmpcpp = createScratch("ncmpcpp", 800, 500, 'z')
|
|
||||||
@ -1,83 +0,0 @@
|
|||||||
-- documenting my shit because someone thought i write good code
|
|
||||||
local awful = require("awful")
|
|
||||||
local helpers = require("helpers")
|
|
||||||
local dontSuckMe = {} -- this is for classes that you dont want to be swallowed
|
|
||||||
-- eg local dontSuckMe = {"nemo", "firefox"}
|
|
||||||
|
|
||||||
local checkForSucc = function(child, parent)
|
|
||||||
local canSuc = false
|
|
||||||
if not helpers.inTable(dontSuckMe, child) and parent == "org.wezfurlong.wezterm" and child ~= "org.wezfurlong.wezterm" then -- write the class of your terminal here
|
|
||||||
canSuc = true
|
|
||||||
end
|
|
||||||
return canSuc
|
|
||||||
end
|
|
||||||
|
|
||||||
-- get the terminal window that executed the command maybe
|
|
||||||
local getDaddy = function(child, cb)
|
|
||||||
awful.spawn.easy_async(string.format("pstree -p %s", child), function(output, _, _, _)
|
|
||||||
cb(nil, output)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- this function was straight out ripped from bling
|
|
||||||
-- from what i understand this basically makes the window focused and on top
|
|
||||||
function 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
|
|
||||||
end
|
|
||||||
|
|
||||||
-- move the parent with the child
|
|
||||||
local sync = function(c, p)
|
|
||||||
if not c.valid or not p.valid then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if p.modal then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
c.floating = p.floating
|
|
||||||
c.maximized = p.maximized
|
|
||||||
c.above = p.above
|
|
||||||
c.below = p.below
|
|
||||||
c:geometry(p:geometry())
|
|
||||||
end
|
|
||||||
|
|
||||||
-- this does the opposite off on() and you guessed it, also copied from bling
|
|
||||||
function off(c)
|
|
||||||
current_tag = c.screen.selected_tag
|
|
||||||
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
|
|
||||||
|
|
||||||
-- the main implementation
|
|
||||||
local handle = function(c)
|
|
||||||
local daddy = awful.client.focus.history.get(c.screen, 1) -- read the history to get the parent terminal
|
|
||||||
if not daddy or daddy.type == "dialog" or daddy.type == "splash" then return end
|
|
||||||
getDaddy(c.pid, function(e, pid)
|
|
||||||
if (tostring(pid):find("(" .. tostring(daddy.pid) .. ")")) and checkForSucc(c.class, daddy.class) then -- check if the parent exists and the window can be swallowed
|
|
||||||
c:connect_signal("unmanage", function()
|
|
||||||
if daddy then
|
|
||||||
on(daddy)
|
|
||||||
sync(c, daddy)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
sync(c, daddy)
|
|
||||||
off(daddy)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
client.connect_signal("manage", handle) -- executing it
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
local awful = require "awful"
|
|
||||||
|
|
||||||
screen.connect_signal("request::desktop_decoration", function(s)
|
|
||||||
awful.tag({ "1", "2", "3", " " }, s, awful.layout.layouts[1])
|
|
||||||
end)
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
local gears = require "gears"
|
|
||||||
local beautiful = require "beautiful"
|
|
||||||
local helpeers = require "helpers"
|
|
||||||
|
|
||||||
|
|
||||||
local function set_wall(s)
|
|
||||||
local d = helpeers.readJson(gears.filesystem.get_cache_dir() .. 'json/settings.json')
|
|
||||||
if d.wallpaper == "colorful" then
|
|
||||||
gears.wallpaper.maximized(beautiful.wallpaper, s, beautiful.mbg)
|
|
||||||
else
|
|
||||||
gears.wallpaper.set(beautiful.bg3)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
screen.connect_signal("request::wallpaper", function(s)
|
|
||||||
set_wall(s)
|
|
||||||
end)
|
|
||||||
@ -1,285 +0,0 @@
|
|||||||
-- Copyleft © 2022 Saimoomedits
|
|
||||||
--most stuff copied from guy above
|
|
||||||
|
|
||||||
|
|
||||||
local naughty = require("naughty")
|
|
||||||
local beautiful = require("beautiful")
|
|
||||||
local wibox = require("wibox")
|
|
||||||
local awful = require("awful")
|
|
||||||
local dpi = beautiful.xresources.apply_dpi
|
|
||||||
local helpers = require("helpers")
|
|
||||||
local ruled = require("ruled")
|
|
||||||
local menubar = require("menubar")
|
|
||||||
local animation = require("mods.animation")
|
|
||||||
local gears = require("gears")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
naughty.connect_signal("request::icon", function(n, context, hints)
|
|
||||||
if context ~= "app_icon" then return end
|
|
||||||
|
|
||||||
local path = menubar.utils.lookup_icon(hints.app_icon) or menubar.utils.lookup_icon(hints.app_icon:lower())
|
|
||||||
|
|
||||||
if path then n.icon = path end
|
|
||||||
end)
|
|
||||||
|
|
||||||
|
|
||||||
-- naughty config
|
|
||||||
naughty.config.defaults.ontop = true
|
|
||||||
naughty.config.defaults.screen = awful.screen.focused()
|
|
||||||
naughty.config.defaults.timeout = 10
|
|
||||||
naughty.config.defaults.title = "Ding!"
|
|
||||||
naughty.config.defaults.position = "top_right"
|
|
||||||
|
|
||||||
|
|
||||||
-- Timeouts
|
|
||||||
naughty.config.presets.low.timeout = 10
|
|
||||||
naughty.config.presets.critical.timeout = 0
|
|
||||||
|
|
||||||
-- ruled notification
|
|
||||||
ruled.notification.connect_signal("request::rules", function()
|
|
||||||
ruled.notification.append_rule {
|
|
||||||
rule = {},
|
|
||||||
properties = { screen = awful.screen.preferred, implicit_timeout = 6 }
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- connect to each display
|
|
||||||
--------------------------
|
|
||||||
naughty.connect_signal("request::display", function(n)
|
|
||||||
-- action widget
|
|
||||||
local action_widget = {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
id = "text_role",
|
|
||||||
align = "center",
|
|
||||||
valign = "center",
|
|
||||||
font = beautiful.sans .. " 10",
|
|
||||||
widget = wibox.widget.textbox
|
|
||||||
},
|
|
||||||
left = dpi(6),
|
|
||||||
right = dpi(6),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
bg = beautiful.mbg,
|
|
||||||
forced_height = dpi(30),
|
|
||||||
shape = helpers.rrect(2),
|
|
||||||
widget = wibox.container.background
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
-- actions
|
|
||||||
local actions = wibox.widget {
|
|
||||||
notification = n,
|
|
||||||
base_layout = wibox.widget {
|
|
||||||
spacing = dpi(8),
|
|
||||||
layout = wibox.layout.flex.horizontal
|
|
||||||
},
|
|
||||||
widget_template = action_widget,
|
|
||||||
style = { underline_normal = false, underline_selected = true },
|
|
||||||
widget = naughty.list.actions
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- image
|
|
||||||
local image_n = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
opacity = 0.9,
|
|
||||||
image = n.icon and helpers.cropSurface(1, gears.surface.load_uncached(n.icon)) or
|
|
||||||
gears.filesystem.get_configuration_dir() .. "theme/assets/" .. "bell.png",
|
|
||||||
resize = true,
|
|
||||||
halign = "center",
|
|
||||||
valign = "center",
|
|
||||||
clip_shape = helpers.rrect(50),
|
|
||||||
widget = wibox.widget.imagebox,
|
|
||||||
},
|
|
||||||
strategy = "exact",
|
|
||||||
height = dpi(50),
|
|
||||||
width = dpi(50),
|
|
||||||
widget = wibox.container.constraint,
|
|
||||||
},
|
|
||||||
id = "arc",
|
|
||||||
widget = wibox.container.arcchart,
|
|
||||||
max_value = 100,
|
|
||||||
min_value = 0,
|
|
||||||
value = 100,
|
|
||||||
rounded_edge = true,
|
|
||||||
thickness = dpi(4),
|
|
||||||
start_angle = 4.71238898,
|
|
||||||
bg = beautiful.blue,
|
|
||||||
colors = { beautiful.fg },
|
|
||||||
forced_width = dpi(80),
|
|
||||||
forced_height = dpi(80)
|
|
||||||
}
|
|
||||||
local anim = animation:new {
|
|
||||||
duration = 6,
|
|
||||||
target = 100,
|
|
||||||
reset_on_stop = false,
|
|
||||||
easing = animation.easing.linear,
|
|
||||||
update = function(_, pos)
|
|
||||||
image_n:get_children_by_id('arc')[1].value = pos
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
anim:connect_signal("ended", function()
|
|
||||||
n:destroy()
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- title
|
|
||||||
local title_n = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
markup = n.title,
|
|
||||||
font = beautiful.sans .. " 12",
|
|
||||||
align = "right",
|
|
||||||
valign = "center",
|
|
||||||
widget = wibox.widget.textbox
|
|
||||||
},
|
|
||||||
forced_width = dpi(240),
|
|
||||||
widget = wibox.container.scroll.horizontal,
|
|
||||||
step_function = wibox.container.scroll.step_functions.waiting_nonlinear_back_and_forth,
|
|
||||||
speed = 50
|
|
||||||
},
|
|
||||||
margins = { right = 15 },
|
|
||||||
widget = wibox.container.margin
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
local message_n = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
markup = helpers.colorizeText("<span weight='normal'>" .. n.message .. "</span>", beautiful.fg .. "BF"),
|
|
||||||
font = beautiful.sans .. " 12",
|
|
||||||
align = "left",
|
|
||||||
valign = "center",
|
|
||||||
wrap = "char",
|
|
||||||
widget = wibox.widget.textbox
|
|
||||||
},
|
|
||||||
forced_width = dpi(240),
|
|
||||||
layout = wibox.layout.fixed.horizontal
|
|
||||||
},
|
|
||||||
margins = { right = 15 },
|
|
||||||
widget = wibox.container.margin
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
-- app name
|
|
||||||
local aname = ''
|
|
||||||
if n.app_name ~= '' then
|
|
||||||
aname = n.app_name
|
|
||||||
else
|
|
||||||
aname = 'naughty'
|
|
||||||
end
|
|
||||||
local app_name_n = wibox.widget {
|
|
||||||
markup = helpers.colorizeText(aname, beautiful.fg .. "BF"),
|
|
||||||
font = beautiful.sans .. " 10",
|
|
||||||
align = "left",
|
|
||||||
valign = "center",
|
|
||||||
widget = wibox.widget.textbox
|
|
||||||
}
|
|
||||||
|
|
||||||
local time_n = wibox.widget {
|
|
||||||
{
|
|
||||||
markup = helpers.colorizeText("now", beautiful.fg .. "BF"),
|
|
||||||
font = beautiful.sans .. " 10",
|
|
||||||
align = "right",
|
|
||||||
valign = "center",
|
|
||||||
widget = wibox.widget.textbox
|
|
||||||
},
|
|
||||||
margins = { right = 20 },
|
|
||||||
widget = wibox.container.margin
|
|
||||||
}
|
|
||||||
|
|
||||||
local close = wibox.widget {
|
|
||||||
markup = helpers.colorizeText('', beautiful.red),
|
|
||||||
font = beautiful.icon .. " 12",
|
|
||||||
align = "ceneter",
|
|
||||||
valign = "center",
|
|
||||||
widget = wibox.widget.textbox
|
|
||||||
}
|
|
||||||
|
|
||||||
close:buttons(gears.table.join(
|
|
||||||
awful.button({}, 1, function() n:destroy(naughty.notification_closed_reason.dismissed_by_user) end)))
|
|
||||||
|
|
||||||
|
|
||||||
-- extra info
|
|
||||||
local notif_info = wibox.widget {
|
|
||||||
app_name_n,
|
|
||||||
{
|
|
||||||
widget = wibox.widget.separator,
|
|
||||||
shape = gears.shape.circle,
|
|
||||||
forced_height = dpi(4),
|
|
||||||
forced_width = dpi(4),
|
|
||||||
color = beautiful.fg .. "BF"
|
|
||||||
},
|
|
||||||
time_n,
|
|
||||||
layout = wibox.layout.fixed.horizontal,
|
|
||||||
spacing = dpi(7)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local widget = naughty.layout.box {
|
|
||||||
notification = n,
|
|
||||||
bg = beautiful.bg,
|
|
||||||
shape = helpers.rrect(8),
|
|
||||||
widget_template = {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
-- top bit
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
close,
|
|
||||||
nil,
|
|
||||||
notif_info,
|
|
||||||
layout = wibox.layout.align.horizontal,
|
|
||||||
expand = "none"
|
|
||||||
},
|
|
||||||
margins = { left = dpi(15), right = dpi(15), top = dpi(10), bottom = dpi(10) },
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
widget = wibox.container.background,
|
|
||||||
bg = beautiful.mbg,
|
|
||||||
},
|
|
||||||
layout = wibox.layout.fixed.vertical
|
|
||||||
},
|
|
||||||
{
|
|
||||||
-- body
|
|
||||||
{
|
|
||||||
{
|
|
||||||
title_n,
|
|
||||||
message_n,
|
|
||||||
layout = wibox.layout.fixed.vertical,
|
|
||||||
spacing = dpi(3)
|
|
||||||
},
|
|
||||||
nil,
|
|
||||||
image_n,
|
|
||||||
layout = wibox.layout.align.horizontal,
|
|
||||||
expand = "none"
|
|
||||||
},
|
|
||||||
margins = { left = dpi(15), top = dpi(10), right = dpi(10) },
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
{
|
|
||||||
-- foot
|
|
||||||
actions,
|
|
||||||
margins = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
layout = wibox.layout.fixed.vertical,
|
|
||||||
spacing = dpi(10)
|
|
||||||
},
|
|
||||||
widget = wibox.container.background,
|
|
||||||
shape = helpers.rrect(8),
|
|
||||||
bg = beautiful.bg,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
widget.buttons = {}
|
|
||||||
anim:start()
|
|
||||||
end)
|
|
||||||
@ -1 +0,0 @@
|
|||||||
require("misc.dings.base")
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
local naughty = require("naughty")
|
|
||||||
local bling = require("mods.playerctl")
|
|
||||||
local playerctl = bling.lib()
|
|
||||||
|
|
||||||
playerctl:connect_signal("metadata",
|
|
||||||
function(_, title, artist, album_path, album, new, player_name)
|
|
||||||
if new == true then
|
|
||||||
naughty.notify({ title = 'New Song', text = title .. " by " .. artist, image = album_path })
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
require "misc.titlebar"
|
|
||||||
require "misc.music"
|
|
||||||
require "misc.dings"
|
|
||||||
@ -1,304 +0,0 @@
|
|||||||
local awful = require 'awful'
|
|
||||||
require 'awful.autofocus'
|
|
||||||
local wibox = require 'wibox'
|
|
||||||
local gears = require 'gears'
|
|
||||||
local beautiful = require("beautiful")
|
|
||||||
local ruled = require("ruled")
|
|
||||||
local helpers = require("helpers")
|
|
||||||
local playerctl = require("mods.playerctl").lib()
|
|
||||||
local dpi = beautiful.xresources.apply_dpi
|
|
||||||
|
|
||||||
local art = wibox.widget {
|
|
||||||
image = helpers.cropSurface(1, gears.surface.load_uncached(beautiful.songdefpicture)),
|
|
||||||
clip_shape = helpers.rrect(10),
|
|
||||||
opacity = 0.75,
|
|
||||||
resize = true,
|
|
||||||
forced_height = dpi(60),
|
|
||||||
forced_width = dpi(60),
|
|
||||||
valign = 'center',
|
|
||||||
widget = wibox.widget.imagebox
|
|
||||||
}
|
|
||||||
local leftart = wibox.widget {
|
|
||||||
image = beautiful.songdefpicture,
|
|
||||||
clip_shape = helpers.rrect(10),
|
|
||||||
opacity = 0.75,
|
|
||||||
resize = true,
|
|
||||||
forced_height = dpi(250),
|
|
||||||
forced_width = dpi(250),
|
|
||||||
valign = 'center',
|
|
||||||
widget = wibox.widget.imagebox
|
|
||||||
}
|
|
||||||
local prev = wibox.widget {
|
|
||||||
align = 'center',
|
|
||||||
font = beautiful.icon .. " 24",
|
|
||||||
markup = helpers.colorizeText('', beautiful.fg),
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
buttons = {
|
|
||||||
awful.button({}, 1, function()
|
|
||||||
playerctl:previous()
|
|
||||||
end)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
local next = wibox.widget {
|
|
||||||
align = 'center',
|
|
||||||
font = beautiful.icon .. " 24",
|
|
||||||
markup = helpers.colorizeText('', beautiful.fg),
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
buttons = {
|
|
||||||
awful.button({}, 1, function()
|
|
||||||
playerctl:next()
|
|
||||||
end)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
local play = wibox.widget {
|
|
||||||
align = 'center',
|
|
||||||
font = beautiful.icon .. " 24",
|
|
||||||
markup = helpers.colorizeText('', beautiful.blue),
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
buttons = {
|
|
||||||
awful.button({}, 1, function()
|
|
||||||
playerctl:play_pause()
|
|
||||||
end)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
local shufflebtn = wibox.widget {
|
|
||||||
align = 'center',
|
|
||||||
font = beautiful.icon .. " 13",
|
|
||||||
markup = helpers.colorizeText('', beautiful.fg),
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
buttons = {
|
|
||||||
awful.button({}, 1, function()
|
|
||||||
playerctl:cycle_shuffle()
|
|
||||||
end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
playerctl:connect_signal("shuffle", function(_, shuffle)
|
|
||||||
shufflebtn.markup = shuffle and helpers.colorizeText('', beautiful.blue) or helpers.colorizeText('',
|
|
||||||
beautiful.fg)
|
|
||||||
end)
|
|
||||||
local repeatt = wibox.widget {
|
|
||||||
align = 'center',
|
|
||||||
font = beautiful.icon .. " 13",
|
|
||||||
markup = helpers.colorizeText('', beautiful.fg),
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
buttons = {
|
|
||||||
awful.button({}, 1, function()
|
|
||||||
playerctl:cycle_loop_status()
|
|
||||||
end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
playerctl:connect_signal("loop_status", function(_, loop_status)
|
|
||||||
if loop_status:match('none') then
|
|
||||||
repeatt.markup = helpers.colorizeText('', beautiful.fg)
|
|
||||||
elseif loop_status:match('track') then
|
|
||||||
repeatt.markup = helpers.colorizeText('', beautiful.magenta)
|
|
||||||
else
|
|
||||||
repeatt.markup = helpers.colorizeText('', beautiful.magenta)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
local createHandle = function(width, height, tl, tr, br, bl, radius)
|
|
||||||
return function(cr)
|
|
||||||
gears.shape.partially_rounded_rect(cr, width, height, tl, tr, br, bl, radius)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local slider = wibox.widget {
|
|
||||||
bar_shape = helpers.rrect(0),
|
|
||||||
bar_height = 3,
|
|
||||||
handle_color = beautiful.blue,
|
|
||||||
bar_color = beautiful.blue .. '33',
|
|
||||||
bar_active_color = beautiful.blue,
|
|
||||||
handle_shape = createHandle(18, 3, false, false, false, false, 0),
|
|
||||||
handle_margins = { top = 3 },
|
|
||||||
handle_width = 18,
|
|
||||||
forced_height = 10,
|
|
||||||
maximum = 100,
|
|
||||||
widget = wibox.widget.slider,
|
|
||||||
}
|
|
||||||
|
|
||||||
local songname = wibox.widget {
|
|
||||||
markup = helpers.colorizeText('Nothing Playing', beautiful.fg),
|
|
||||||
align = 'left',
|
|
||||||
valign = 'center',
|
|
||||||
forced_width = dpi(40),
|
|
||||||
font = beautiful.sans .. " 12",
|
|
||||||
widget = wibox.widget.textbox
|
|
||||||
}
|
|
||||||
local leftname = wibox.widget {
|
|
||||||
markup = helpers.colorizeText('Nothing Playing', beautiful.fg),
|
|
||||||
valign = 'center',
|
|
||||||
align = 'center',
|
|
||||||
font = beautiful.sans .. " 16",
|
|
||||||
widget = wibox.widget.textbox
|
|
||||||
}
|
|
||||||
local artistname = wibox.widget {
|
|
||||||
markup = helpers.colorizeText('None', beautiful.fg),
|
|
||||||
align = 'left',
|
|
||||||
valign = 'center',
|
|
||||||
forced_height = dpi(20),
|
|
||||||
font = beautiful.sans .. " 11",
|
|
||||||
widget = wibox.widget.textbox
|
|
||||||
}
|
|
||||||
local leftartist = wibox.widget {
|
|
||||||
markup = helpers.colorizeText('None', beautiful.fg),
|
|
||||||
align = 'center',
|
|
||||||
valign = 'center',
|
|
||||||
forced_height = dpi(20),
|
|
||||||
font = beautiful.sans .. " 11",
|
|
||||||
widget = wibox.widget.textbox
|
|
||||||
}
|
|
||||||
local is_prog_hovered = false
|
|
||||||
slider:connect_signal('mouse::enter', function()
|
|
||||||
is_prog_hovered = true
|
|
||||||
end)
|
|
||||||
slider:connect_signal('mouse::leave', function()
|
|
||||||
is_prog_hovered = false
|
|
||||||
end)
|
|
||||||
slider:connect_signal('property::value', function(_, value)
|
|
||||||
if is_prog_hovered then
|
|
||||||
playerctl:set_position(value)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
playerctl:connect_signal("position", function(_, interval_sec, length_sec)
|
|
||||||
slider.maximum = length_sec or 100
|
|
||||||
slider.value = interval_sec or 0
|
|
||||||
end)
|
|
||||||
|
|
||||||
playerctl:connect_signal("metadata", function(_, title, artist, album_path, album, new, player_name)
|
|
||||||
if player_name == "mpd" then
|
|
||||||
if album_path == "" then
|
|
||||||
album_path = beautiful.songdefpicture
|
|
||||||
end
|
|
||||||
if string.len(title) > 30 then
|
|
||||||
title = string.sub(title, 0, 30) .. "..."
|
|
||||||
end
|
|
||||||
if string.len(artist) > 22 then
|
|
||||||
artist = string.sub(artist, 0, 22) .. "..."
|
|
||||||
end
|
|
||||||
songname:set_markup_silently(helpers.colorizeText(title or "NO", beautiful.fg))
|
|
||||||
leftname:set_markup_silently(helpers.colorizeText(title or "NO", beautiful.fg))
|
|
||||||
leftartist:set_markup_silently(helpers.colorizeText(' ' .. artist or "WT" .. ' ', beautiful.fg))
|
|
||||||
artistname:set_markup_silently(helpers.colorizeText(artist or "HM", beautiful.fg))
|
|
||||||
art:set_image(gears.surface.load_uncached(album_path))
|
|
||||||
leftart:set_image(gears.surface.load_uncached(album_path))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
|
|
||||||
playerctl:connect_signal("playback_status", function(_, playing)
|
|
||||||
play.markup = playing and helpers.colorizeText("", beautiful.blue) or helpers.colorizeText("", beautiful.blue)
|
|
||||||
end)
|
|
||||||
local createTopButton = function(c, icon, click, color)
|
|
||||||
local widget = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
markup = helpers.colorizeText(icon, color),
|
|
||||||
valign = 'center',
|
|
||||||
forced_height = dpi(20),
|
|
||||||
font = beautiful.icon .. " 18",
|
|
||||||
widget = wibox.widget.textbox
|
|
||||||
},
|
|
||||||
margins = {
|
|
||||||
left = 8,
|
|
||||||
right = 8
|
|
||||||
},
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
},
|
|
||||||
buttons = awful.button({}, 1, function()
|
|
||||||
helpers.clickKey(c, click)
|
|
||||||
end),
|
|
||||||
bg = beautiful.mbg,
|
|
||||||
widget = wibox.container.background
|
|
||||||
}
|
|
||||||
return widget
|
|
||||||
end
|
|
||||||
|
|
||||||
local bottom = function(c)
|
|
||||||
local playtab = createTopButton(c, '', '1', beautiful.blue)
|
|
||||||
local vistab = createTopButton(c, '', '8', beautiful.blue)
|
|
||||||
vistab:add_button(awful.button({}, 3, function()
|
|
||||||
helpers.clickKey(c, '8 ')
|
|
||||||
end))
|
|
||||||
awful.titlebar(c, { position = "bottom", size = dpi(100), bg = beautiful.mbg }):setup {
|
|
||||||
slider,
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
art,
|
|
||||||
{
|
|
||||||
{
|
|
||||||
songname,
|
|
||||||
artistname,
|
|
||||||
forced_width = 400,
|
|
||||||
layout = wibox.layout.fixed.vertical,
|
|
||||||
},
|
|
||||||
align = 'center',
|
|
||||||
widget = wibox.container.place
|
|
||||||
},
|
|
||||||
spacing = 13,
|
|
||||||
layout = wibox.layout.fixed.horizontal,
|
|
||||||
},
|
|
||||||
margins = {
|
|
||||||
top = 15,
|
|
||||||
bottom = 15,
|
|
||||||
left = 10,
|
|
||||||
right = 10,
|
|
||||||
},
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
shufflebtn,
|
|
||||||
prev,
|
|
||||||
{
|
|
||||||
{
|
|
||||||
play,
|
|
||||||
margins = 4,
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
shape = helpers.rrect(3),
|
|
||||||
bg = beautiful.blue .. '11',
|
|
||||||
widget = wibox.container.background
|
|
||||||
},
|
|
||||||
next,
|
|
||||||
repeatt,
|
|
||||||
spacing = 15,
|
|
||||||
layout = wibox.layout.fixed.horizontal,
|
|
||||||
},
|
|
||||||
align = 'center',
|
|
||||||
widget = wibox.container.place,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
playtab,
|
|
||||||
vistab,
|
|
||||||
spacing = 10,
|
|
||||||
layout = wibox.layout.fixed.horizontal,
|
|
||||||
},
|
|
||||||
expand = 'none',
|
|
||||||
layout = wibox.layout.align.horizontal,
|
|
||||||
},
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
left = 15,
|
|
||||||
right = 15
|
|
||||||
},
|
|
||||||
layout = wibox.layout.fixed.vertical,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
local final = function(c)
|
|
||||||
bottom(c)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
ruled.client.connect_signal("request::rules", function()
|
|
||||||
ruled.client.append_rule {
|
|
||||||
id = "music",
|
|
||||||
rule_any = {
|
|
||||||
class = { "ncmpcpppad" },
|
|
||||||
role = { "pop-up" },
|
|
||||||
},
|
|
||||||
callback = final
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
STATUS="$(rfkill list | sed -n 2p | awk '{print $3}')"
|
|
||||||
|
|
||||||
|
|
||||||
toggle() {
|
|
||||||
if [[ $STATUS == "no" ]]; then
|
|
||||||
getroot 'pkexec rfkill block all'
|
|
||||||
notify-send --urgency=normal "Airplane Mode" "Airplane mode has been turned on!"
|
|
||||||
else
|
|
||||||
getroot 'pkexec rfkill unblock all'
|
|
||||||
notify-send --urgency=normal "Airplane Mode" "Airplane mode has been turned off!"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if [[ $1 == "--toggle" ]]; then
|
|
||||||
toggle
|
|
||||||
fi
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
toggle() {
|
|
||||||
STATUS="$(bluetoothctl show | grep Powered | awk '{print $2}')"
|
|
||||||
if [ $STATUS == "yes" ]; then
|
|
||||||
bluetoothctl power off
|
|
||||||
notify-send -a "Bluetooth" --urgency=normal "Bluetooth" "Bluetooth has been turned off."
|
|
||||||
else
|
|
||||||
bluetoothctl power on
|
|
||||||
notify-send -a "Bluetooth" --urgency=normal "Bluetooth" "Bluetooth has been turned on."
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if [[ $1 == "--toggle" ]]; then
|
|
||||||
toggle
|
|
||||||
fi
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
toggle(){
|
|
||||||
if [[ ! `pidof picom` ]]; then
|
|
||||||
picom &
|
|
||||||
else
|
|
||||||
pkill -9 picom
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ $1 == "--toggle" ]]; then
|
|
||||||
toggle
|
|
||||||
fi
|
|
||||||
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
is_active=$(cat ~/.cache/redshift)
|
|
||||||
|
|
||||||
toggle() {
|
|
||||||
if [[ $is_active == *"true"* ]]; then
|
|
||||||
redshift -x && echo false > ~/.cache/redshift
|
|
||||||
else
|
|
||||||
redshift -O 4000 && echo true > ~/.cache/redshift
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ $1 == "--toggle" ]]; then
|
|
||||||
toggle
|
|
||||||
fi
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
STATUS=$(nmcli | grep wlan0 | awk 'FNR == 1 {print $2}')
|
|
||||||
SSID=$(iwgetid -r)
|
|
||||||
STRENGTH=$(awk 'NR==3 {printf("%.0f",$3*10/7)}' /proc/net/wireless)
|
|
||||||
|
|
||||||
toggle() {
|
|
||||||
if [[ $STATUS == "connected" ]]; then
|
|
||||||
nmcli radio wifi off
|
|
||||||
notify-send -a "wifi" --urgency=normal "Wi-Fi" "Wi-Fi has been turned off!"
|
|
||||||
else
|
|
||||||
nmcli radio wifi on
|
|
||||||
notify-send -a "wifi" --urgency=normal "Wi-Fi" "Wi-Fi has been turned on, you are back online!"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if [[ $1 == "--toggle" ]]; then
|
|
||||||
toggle
|
|
||||||
fi
|
|
||||||
@ -1,103 +0,0 @@
|
|||||||
local awful = require "awful"
|
|
||||||
local gears = require "gears"
|
|
||||||
local wibox = require "wibox"
|
|
||||||
local beautiful = require "beautiful"
|
|
||||||
local helpers = require "helpers"
|
|
||||||
local getIcon = require "mods.getIcon"
|
|
||||||
local dpi = beautiful.xresources.apply_dpi
|
|
||||||
|
|
||||||
----- Titlebar
|
|
||||||
local get_titlebar = function(c)
|
|
||||||
-- Button
|
|
||||||
local buttons = gears.table.join({
|
|
||||||
awful.button({}, 1, function()
|
|
||||||
c:activate { context = "titlebar", action = "mouse_move" }
|
|
||||||
end),
|
|
||||||
awful.button({}, 3, function()
|
|
||||||
c:activate { context = "titlebar", action = "mouse_resize" }
|
|
||||||
end)
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Titlebar's decorations
|
|
||||||
local left = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
awful.titlebar.widget.closebutton(c),
|
|
||||||
awful.titlebar.widget.maximizedbutton(c),
|
|
||||||
awful.titlebar.widget.minimizebutton(c),
|
|
||||||
spacing = dpi(5),
|
|
||||||
layout = wibox.layout.fixed.horizontal,
|
|
||||||
},
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
margins = 8
|
|
||||||
},
|
|
||||||
shape = helpers.rrect(5),
|
|
||||||
widget = wibox.container.background,
|
|
||||||
bg = beautiful.mbg
|
|
||||||
}
|
|
||||||
|
|
||||||
local middle = wibox.widget {
|
|
||||||
buttons = buttons,
|
|
||||||
layout = wibox.layout.fixed.horizontal,
|
|
||||||
}
|
|
||||||
|
|
||||||
local right = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
widget = wibox.widget.imagebox,
|
|
||||||
image = getIcon(c, c.class, c.class),
|
|
||||||
forced_width = 30,
|
|
||||||
clip_shape = helpers.rrect(100),
|
|
||||||
resize = true,
|
|
||||||
},
|
|
||||||
widget = wibox.container.place,
|
|
||||||
halign = "center",
|
|
||||||
},
|
|
||||||
margins = dpi(5),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
bg = beautiful.mbg,
|
|
||||||
shape = helpers.rrect(5),
|
|
||||||
widget = wibox.container.background
|
|
||||||
}
|
|
||||||
|
|
||||||
local container = wibox.widget {
|
|
||||||
bg = beautiful.bar,
|
|
||||||
shape = function(cr, w, h) gears.shape.partially_rounded_rect(cr, w, h, true, true, false, false, 0) end,
|
|
||||||
widget = wibox.container.background,
|
|
||||||
}
|
|
||||||
|
|
||||||
c:connect_signal("focus", function() container.bg = beautiful.bg end)
|
|
||||||
c:connect_signal("unfocus", function() container.bg = beautiful.bg end)
|
|
||||||
|
|
||||||
return wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
left,
|
|
||||||
middle,
|
|
||||||
right,
|
|
||||||
layout = wibox.layout.align.horizontal,
|
|
||||||
},
|
|
||||||
margins = { top = dpi(5), bottom = dpi(5), left = dpi(5), right = dpi(5) },
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
},
|
|
||||||
widget = container,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
local function top(c)
|
|
||||||
local titlebar = awful.titlebar(c, {
|
|
||||||
position = 'top',
|
|
||||||
size = dpi(50),
|
|
||||||
bg = beautiful.transparent
|
|
||||||
})
|
|
||||||
|
|
||||||
titlebar:setup {
|
|
||||||
widget = get_titlebar(c)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
client.connect_signal("request::titlebars", function(c)
|
|
||||||
top(c)
|
|
||||||
end)
|
|
||||||
@ -1,239 +0,0 @@
|
|||||||
-------------------------------------------
|
|
||||||
-- @author https://github.com/Kasper24
|
|
||||||
-- @copyright 2021-2022 Kasper24
|
|
||||||
-------------------------------------------
|
|
||||||
|
|
||||||
local GLib = require("lgi").GLib
|
|
||||||
local gobject = require("gears.object")
|
|
||||||
local gtable = require("gears.table")
|
|
||||||
local subscribable = require("mods.animation.subscribable")
|
|
||||||
local tween = require("mods.animation.tween")
|
|
||||||
local ipairs = ipairs
|
|
||||||
local table = table
|
|
||||||
local pairs = pairs
|
|
||||||
|
|
||||||
local animation_manager = {}
|
|
||||||
animation_manager.easing =
|
|
||||||
{
|
|
||||||
linear = "linear",
|
|
||||||
inQuad = "inQuad",
|
|
||||||
outQuad = "outQuad",
|
|
||||||
inOutQuad = "inOutQuad",
|
|
||||||
outInQuad = "outInQuad",
|
|
||||||
inCubic = "inCubic",
|
|
||||||
outCubic = "outCubic",
|
|
||||||
inOutCubic = "inOutCubic",
|
|
||||||
outInCubic = "outInCubic",
|
|
||||||
inQuart = "inQuart",
|
|
||||||
outQuart = "outQuart",
|
|
||||||
inOutQuart = "inOutQuart",
|
|
||||||
outInQuart = "outInQuart",
|
|
||||||
inQuint = "inQuint",
|
|
||||||
outQuint = "outQuint",
|
|
||||||
inOutQuint = "inOutQuint",
|
|
||||||
outInQuint = "outInQuint",
|
|
||||||
inSine = "inSine",
|
|
||||||
outSine = "outSine",
|
|
||||||
inOutSine = "inOutSine",
|
|
||||||
outInSine = "outInSine",
|
|
||||||
inExpo = "inExpo",
|
|
||||||
outExpo = "outExpo",
|
|
||||||
inOutExpo = "inOutExpo",
|
|
||||||
outInExpo = "outInExpo",
|
|
||||||
inCirc = "inCirc",
|
|
||||||
outCirc = "outCirc",
|
|
||||||
inOutCirc = "inOutCirc",
|
|
||||||
outInCirc = "outInCirc",
|
|
||||||
inElastic = "inElastic",
|
|
||||||
outElastic = "outElastic",
|
|
||||||
inOutElastic = "inOutElastic",
|
|
||||||
outInElastic = "outInElastic",
|
|
||||||
inBack = "inBack",
|
|
||||||
outBack = "outBack",
|
|
||||||
inOutBack = "inOutBack",
|
|
||||||
outInBack = "outInBack",
|
|
||||||
inBounce = "inBounce",
|
|
||||||
outBounce = "outBounce",
|
|
||||||
inOutBounce = "inOutBounce",
|
|
||||||
outInBounce = "outInBounce"
|
|
||||||
}
|
|
||||||
|
|
||||||
local animation = {}
|
|
||||||
|
|
||||||
local instance = nil
|
|
||||||
|
|
||||||
local ANIMATION_FRAME_DELAY = 5
|
|
||||||
|
|
||||||
local function micro_to_milli(micro)
|
|
||||||
return micro / 1000
|
|
||||||
end
|
|
||||||
|
|
||||||
local function second_to_micro(sec)
|
|
||||||
return sec * 1000000
|
|
||||||
end
|
|
||||||
|
|
||||||
local function second_to_milli(sec)
|
|
||||||
return sec * 1000
|
|
||||||
end
|
|
||||||
|
|
||||||
function animation:start(args)
|
|
||||||
args = args or {}
|
|
||||||
|
|
||||||
-- Awestoer/Rubbto compatibility
|
|
||||||
-- I'd rather this always be a table, but Awestoer/Rubbto
|
|
||||||
-- except the :set() method to have 1 number value parameter
|
|
||||||
-- used to set the target
|
|
||||||
local is_table = type(args) == "table"
|
|
||||||
local initial = is_table and (args.pos or self.pos) or self.pos
|
|
||||||
local subject = is_table and (args.subject or self.subject) or self.subject
|
|
||||||
local target = is_table and (args.target or self.target) or args
|
|
||||||
local duration = is_table and (args.duration or self.duration) or self.duration
|
|
||||||
local easing = is_table and (args.easing or self.easing) or self.easing
|
|
||||||
|
|
||||||
duration = self._private.anim_manager._private.instant == true and 0.01 or duration
|
|
||||||
|
|
||||||
if self.tween == nil or self.reset_on_stop == true then
|
|
||||||
self.tween = tween.new
|
|
||||||
{
|
|
||||||
initial = initial,
|
|
||||||
subject = subject,
|
|
||||||
target = target,
|
|
||||||
duration = second_to_micro(duration),
|
|
||||||
easing = easing
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
if self._private.anim_manager._private.animations[self.index] == nil then
|
|
||||||
table.insert(self._private.anim_manager._private.animations, self)
|
|
||||||
end
|
|
||||||
|
|
||||||
self.state = true
|
|
||||||
self.last_elapsed = GLib.get_monotonic_time()
|
|
||||||
|
|
||||||
self.started:fire()
|
|
||||||
self:emit_signal("started")
|
|
||||||
end
|
|
||||||
|
|
||||||
function animation:set(args)
|
|
||||||
self:start(args)
|
|
||||||
self:emit_signal("set")
|
|
||||||
end
|
|
||||||
|
|
||||||
function animation:stop()
|
|
||||||
self.state = false
|
|
||||||
self:emit_signal("stopped")
|
|
||||||
end
|
|
||||||
|
|
||||||
function animation:abort(reset)
|
|
||||||
animation:stop(reset)
|
|
||||||
self:emit_signal("aborted")
|
|
||||||
end
|
|
||||||
|
|
||||||
function animation:initial()
|
|
||||||
return self._private.initial
|
|
||||||
end
|
|
||||||
|
|
||||||
function animation_manager:set_instant(value)
|
|
||||||
self._private.instant = value
|
|
||||||
end
|
|
||||||
|
|
||||||
function animation_manager:new(args)
|
|
||||||
args = args or {}
|
|
||||||
|
|
||||||
args.pos = args.pos or 0
|
|
||||||
args.subject = args.subject or nil
|
|
||||||
args.target = args.target or nil
|
|
||||||
args.duration = args.duration or 0
|
|
||||||
args.easing = args.easing or nil
|
|
||||||
args.loop = args.loop or false
|
|
||||||
args.signals = args.signals or {}
|
|
||||||
args.update = args.update or nil
|
|
||||||
args.reset_on_stop = args.reset_on_stop == nil and true or args.reset_on_stop
|
|
||||||
|
|
||||||
-- Awestoer/Rubbto compatibility
|
|
||||||
args.subscribed = args.subscribed or nil
|
|
||||||
local ret = subscribable()
|
|
||||||
ret.started = subscribable()
|
|
||||||
ret.ended = subscribable()
|
|
||||||
if args.subscribed ~= nil then
|
|
||||||
ret:subscribe(args.subscribed)
|
|
||||||
end
|
|
||||||
|
|
||||||
for sig, sigfun in pairs(args.signals) do
|
|
||||||
ret:connect_signal(sig, sigfun)
|
|
||||||
end
|
|
||||||
if args.update ~= nil then
|
|
||||||
ret:connect_signal("update", args.update)
|
|
||||||
end
|
|
||||||
|
|
||||||
gtable.crush(ret, args, true)
|
|
||||||
gtable.crush(ret, animation, true)
|
|
||||||
|
|
||||||
ret._private = {}
|
|
||||||
ret._private.anim_manager = self
|
|
||||||
ret._private.initial = args.pos
|
|
||||||
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
local function new()
|
|
||||||
local ret = gobject {}
|
|
||||||
gtable.crush(ret, animation_manager, true)
|
|
||||||
|
|
||||||
ret._private = {}
|
|
||||||
ret._private.animations = {}
|
|
||||||
ret._private.instant = false
|
|
||||||
|
|
||||||
GLib.timeout_add
|
|
||||||
(
|
|
||||||
GLib.PRIORITY_DEFAULT,
|
|
||||||
ANIMATION_FRAME_DELAY,
|
|
||||||
function()
|
|
||||||
for index, animation in ipairs(ret._private.animations) do
|
|
||||||
if animation.state == true then
|
|
||||||
-- compute delta time
|
|
||||||
local time = GLib.get_monotonic_time()
|
|
||||||
local delta = time - animation.last_elapsed
|
|
||||||
animation.last_elapsed = time
|
|
||||||
|
|
||||||
-- If pos is true, the animation has ended
|
|
||||||
local pos = animation.tween:update(delta)
|
|
||||||
if pos == true then
|
|
||||||
-- Loop the animation, don't end it.
|
|
||||||
-- Useful for widgets like the spinning cicle
|
|
||||||
if animation.loop == true then
|
|
||||||
animation.tween:reset()
|
|
||||||
else
|
|
||||||
-- Snap to end
|
|
||||||
animation.pos = animation.tween.target
|
|
||||||
animation:fire(animation.pos)
|
|
||||||
animation:emit_signal("update", animation.pos)
|
|
||||||
|
|
||||||
animation.state = false
|
|
||||||
animation.ended:fire(pos)
|
|
||||||
table.remove(ret._private.animations, index)
|
|
||||||
animation:emit_signal("ended", animation.pos)
|
|
||||||
end
|
|
||||||
-- Animation in process, keep updating
|
|
||||||
else
|
|
||||||
animation.pos = pos
|
|
||||||
animation:fire(animation.pos)
|
|
||||||
animation:emit_signal("update", animation.pos)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
table.remove(ret._private.animations, index)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- call again the function after cooldown
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
if not instance then
|
|
||||||
instance = new()
|
|
||||||
end
|
|
||||||
return instance
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
-------------------------------------------
|
|
||||||
-- @author https://github.com/Kasper24
|
|
||||||
-- @copyright 2021-2022 Kasper24
|
|
||||||
-- Adopted from rubato
|
|
||||||
-------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
local gobject = require("gears.object")
|
|
||||||
|
|
||||||
-- Kidna copying awesotre's stores on a surface level for added compatibility
|
|
||||||
local function subscribable(args)
|
|
||||||
local ret = gobject {}
|
|
||||||
local subscribed = {}
|
|
||||||
|
|
||||||
-- Subscrubes a function to the object so that it's called when `fire` is
|
|
||||||
-- Calls subscribe_callback if it exists as well
|
|
||||||
function ret:subscribe(func)
|
|
||||||
local id = tostring(func):gsub("function: ", "")
|
|
||||||
subscribed[id] = func
|
|
||||||
|
|
||||||
if self.subscribe_callback then self.subscribe_callback(func) end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Unsubscribes a function and calls unsubscribe_callback if it exists
|
|
||||||
function ret:unsubscribe(func)
|
|
||||||
if not func then
|
|
||||||
subscribed = {}
|
|
||||||
else
|
|
||||||
local id = tostring(func):gsub("function: ", "")
|
|
||||||
subscribed[id] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.unsubscribe_callback then self.unsubscribe_callback(func) end
|
|
||||||
end
|
|
||||||
|
|
||||||
function ret:fire(...) for _, func in pairs(subscribed) do func(...) end end
|
|
||||||
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
return subscribable
|
|
||||||
@ -1,527 +0,0 @@
|
|||||||
-------------------------------------------
|
|
||||||
-- @author https://github.com/Kasper24
|
|
||||||
-- @copyright 2021-2022 Kasper24
|
|
||||||
-------------------------------------------
|
|
||||||
|
|
||||||
-- easing
|
|
||||||
|
|
||||||
-- Adapted from https://github.com/EmmanuelOga/easing. See LICENSE.txt for credits.
|
|
||||||
-- For all easing functions:
|
|
||||||
-- t = time == how much time has to pass for the tweening to complete
|
|
||||||
-- b = begin == starting property value
|
|
||||||
-- c = change == ending - beginning
|
|
||||||
-- d = duration == running time. How much time has passed *right now*
|
|
||||||
|
|
||||||
local gobject = require("gears.object")
|
|
||||||
local gtable = require("gears.table")
|
|
||||||
|
|
||||||
local tween = {
|
|
||||||
_VERSION = 'tween 2.1.1',
|
|
||||||
_DESCRIPTION = 'tweening for lua',
|
|
||||||
_URL = 'https://github.com/kikito/tween.lua',
|
|
||||||
_LICENSE = [[
|
|
||||||
MIT LICENSE
|
|
||||||
Copyright (c) 2014 Enrique García Cota, Yuichi Tateno, Emmanuel Oga
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
The above copyright notice and this permission notice shall be included
|
|
||||||
in all copies or substantial portions of the Software.
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
]]
|
|
||||||
}
|
|
||||||
|
|
||||||
local pow, sin, cos, pi, sqrt, abs, asin = math.pow, math.sin, math.cos, math.pi, math.sqrt, math.abs, math.asin
|
|
||||||
|
|
||||||
-- linear
|
|
||||||
local function linear(t, b, c, d)
|
|
||||||
return c * t / d + b
|
|
||||||
end
|
|
||||||
|
|
||||||
-- quad
|
|
||||||
local function inQuad(t, b, c, d)
|
|
||||||
return c * pow(t / d, 2) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outQuad(t, b, c, d)
|
|
||||||
t = t / d
|
|
||||||
return -c * t * (t - 2) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function inOutQuad(t, b, c, d)
|
|
||||||
t = t / d * 2
|
|
||||||
if t < 1 then
|
|
||||||
return c / 2 * pow(t, 2) + b
|
|
||||||
end
|
|
||||||
return -c / 2 * ((t - 1) * (t - 3) - 1) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outInQuad(t, b, c, d)
|
|
||||||
if t < d / 2 then
|
|
||||||
return outQuad(t * 2, b, c / 2, d)
|
|
||||||
end
|
|
||||||
return inQuad((t * 2) - d, b + c / 2, c / 2, d)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- cubic
|
|
||||||
local function inCubic(t, b, c, d)
|
|
||||||
return c * pow(t / d, 3) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outCubic(t, b, c, d)
|
|
||||||
return c * (pow(t / d - 1, 3) + 1) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function inOutCubic(t, b, c, d)
|
|
||||||
t = t / d * 2
|
|
||||||
if t < 1 then
|
|
||||||
return c / 2 * t * t * t + b
|
|
||||||
end
|
|
||||||
t = t - 2
|
|
||||||
return c / 2 * (t * t * t + 2) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outInCubic(t, b, c, d)
|
|
||||||
if t < d / 2 then
|
|
||||||
return outCubic(t * 2, b, c / 2, d)
|
|
||||||
end
|
|
||||||
return inCubic((t * 2) - d, b + c / 2, c / 2, d)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- quart
|
|
||||||
local function inQuart(t, b, c, d)
|
|
||||||
return c * pow(t / d, 4) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outQuart(t, b, c, d)
|
|
||||||
return -c * (pow(t / d - 1, 4) - 1) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function inOutQuart(t, b, c, d)
|
|
||||||
t = t / d * 2
|
|
||||||
if t < 1 then
|
|
||||||
return c / 2 * pow(t, 4) + b
|
|
||||||
end
|
|
||||||
return -c / 2 * (pow(t - 2, 4) - 2) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outInQuart(t, b, c, d)
|
|
||||||
if t < d / 2 then
|
|
||||||
return outQuart(t * 2, b, c / 2, d)
|
|
||||||
end
|
|
||||||
return inQuart((t * 2) - d, b + c / 2, c / 2, d)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- quint
|
|
||||||
local function inQuint(t, b, c, d)
|
|
||||||
return c * pow(t / d, 5) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outQuint(t, b, c, d)
|
|
||||||
return c * (pow(t / d - 1, 5) + 1) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function inOutQuint(t, b, c, d)
|
|
||||||
t = t / d * 2
|
|
||||||
if t < 1 then
|
|
||||||
return c / 2 * pow(t, 5) + b
|
|
||||||
end
|
|
||||||
return c / 2 * (pow(t - 2, 5) + 2) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outInQuint(t, b, c, d)
|
|
||||||
if t < d / 2 then
|
|
||||||
return outQuint(t * 2, b, c / 2, d)
|
|
||||||
end
|
|
||||||
return inQuint((t * 2) - d, b + c / 2, c / 2, d)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- sine
|
|
||||||
local function inSine(t, b, c, d)
|
|
||||||
return -c * cos(t / d * (pi / 2)) + c + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outSine(t, b, c, d)
|
|
||||||
return c * sin(t / d * (pi / 2)) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function inOutSine(t, b, c, d)
|
|
||||||
return -c / 2 * (cos(pi * t / d) - 1) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outInSine(t, b, c, d)
|
|
||||||
if t < d / 2 then
|
|
||||||
return outSine(t * 2, b, c / 2, d)
|
|
||||||
end
|
|
||||||
return inSine((t * 2) - d, b + c / 2, c / 2, d)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- expo
|
|
||||||
local function inExpo(t, b, c, d)
|
|
||||||
if t == 0 then
|
|
||||||
return b
|
|
||||||
end
|
|
||||||
return c * pow(2, 10 * (t / d - 1)) + b - c * 0.001
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outExpo(t, b, c, d)
|
|
||||||
if t == d then
|
|
||||||
return b + c
|
|
||||||
end
|
|
||||||
return c * 1.001 * (-pow(2, -10 * t / d) + 1) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function inOutExpo(t, b, c, d)
|
|
||||||
if t == 0 then
|
|
||||||
return b
|
|
||||||
end
|
|
||||||
if t == d then
|
|
||||||
return b + c
|
|
||||||
end
|
|
||||||
t = t / d * 2
|
|
||||||
if t < 1 then
|
|
||||||
return c / 2 * pow(2, 10 * (t - 1)) + b - c * 0.0005
|
|
||||||
end
|
|
||||||
return c / 2 * 1.0005 * (-pow(2, -10 * (t - 1)) + 2) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outInExpo(t, b, c, d)
|
|
||||||
if t < d / 2 then
|
|
||||||
return outExpo(t * 2, b, c / 2, d)
|
|
||||||
end
|
|
||||||
return inExpo((t * 2) - d, b + c / 2, c / 2, d)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- circ
|
|
||||||
local function inCirc(t, b, c, d)
|
|
||||||
return (-c * (sqrt(1 - pow(t / d, 2)) - 1) + b)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outCirc(t, b, c, d)
|
|
||||||
return (c * sqrt(1 - pow(t / d - 1, 2)) + b)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function inOutCirc(t, b, c, d)
|
|
||||||
t = t / d * 2
|
|
||||||
if t < 1 then
|
|
||||||
return -c / 2 * (sqrt(1 - t * t) - 1) + b
|
|
||||||
end
|
|
||||||
t = t - 2
|
|
||||||
return c / 2 * (sqrt(1 - t * t) + 1) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outInCirc(t, b, c, d)
|
|
||||||
if t < d / 2 then
|
|
||||||
return outCirc(t * 2, b, c / 2, d)
|
|
||||||
end
|
|
||||||
return inCirc((t * 2) - d, b + c / 2, c / 2, d)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- elastic
|
|
||||||
local function calculatePAS(p, a, c, d)
|
|
||||||
p, a = p or d * 0.3, a or 0
|
|
||||||
if a < abs(c) then
|
|
||||||
return p, c, p / 4
|
|
||||||
end -- p, a, s
|
|
||||||
return p, a, p / (2 * pi) * asin(c / a) -- p,a,s
|
|
||||||
end
|
|
||||||
|
|
||||||
local function inElastic(t, b, c, d, a, p)
|
|
||||||
local s
|
|
||||||
if t == 0 then
|
|
||||||
return b
|
|
||||||
end
|
|
||||||
t = t / d
|
|
||||||
if t == 1 then
|
|
||||||
return b + c
|
|
||||||
end
|
|
||||||
p, a, s = calculatePAS(p, a, c, d)
|
|
||||||
t = t - 1
|
|
||||||
return -(a * pow(2, 10 * t) * sin((t * d - s) * (2 * pi) / p)) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outElastic(t, b, c, d, a, p)
|
|
||||||
local s
|
|
||||||
if t == 0 then
|
|
||||||
return b
|
|
||||||
end
|
|
||||||
t = t / d
|
|
||||||
if t == 1 then
|
|
||||||
return b + c
|
|
||||||
end
|
|
||||||
p, a, s = calculatePAS(p, a, c, d)
|
|
||||||
return a * pow(2, -10 * t) * sin((t * d - s) * (2 * pi) / p) + c + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function inOutElastic(t, b, c, d, a, p)
|
|
||||||
local s
|
|
||||||
if t == 0 then
|
|
||||||
return b
|
|
||||||
end
|
|
||||||
t = t / d * 2
|
|
||||||
if t == 2 then return b + c end
|
|
||||||
p, a, s = calculatePAS(p, a, c, d)
|
|
||||||
t = t - 1
|
|
||||||
if t < 0 then
|
|
||||||
return -0.5 * (a * pow(2, 10 * t) * sin((t * d - s) * (2 * pi) / p)) + b
|
|
||||||
end
|
|
||||||
return a * pow(2, -10 * t) * sin((t * d - s) * (2 * pi) / p) * 0.5 + c + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outInElastic(t, b, c, d, a, p)
|
|
||||||
if t < d / 2 then
|
|
||||||
return outElastic(t * 2, b, c / 2, d, a, p)
|
|
||||||
end
|
|
||||||
return inElastic((t * 2) - d, b + c / 2, c / 2, d, a, p)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- back
|
|
||||||
local function inBack(t, b, c, d, s)
|
|
||||||
s = s or 1.70158
|
|
||||||
t = t / d
|
|
||||||
return c * t * t * ((s + 1) * t - s) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outBack(t, b, c, d, s)
|
|
||||||
s = s or 1.70158
|
|
||||||
t = t / d - 1
|
|
||||||
return c * (t * t * ((s + 1) * t + s) + 1) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function inOutBack(t, b, c, d, s)
|
|
||||||
s = (s or 1.70158) * 1.525
|
|
||||||
t = t / d * 2
|
|
||||||
if t < 1 then
|
|
||||||
return c / 2 * (t * t * ((s + 1) * t - s)) + b
|
|
||||||
end
|
|
||||||
t = t - 2
|
|
||||||
return c / 2 * (t * t * ((s + 1) * t + s) + 2) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outInBack(t, b, c, d, s)
|
|
||||||
if t < d / 2 then
|
|
||||||
return outBack(t * 2, b, c / 2, d, s)
|
|
||||||
end
|
|
||||||
return inBack((t * 2) - d, b + c / 2, c / 2, d, s)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- bounce
|
|
||||||
local function outBounce(t, b, c, d)
|
|
||||||
t = t / d
|
|
||||||
if t < 1 / 2.75 then
|
|
||||||
return c * (7.5625 * t * t) + b
|
|
||||||
end
|
|
||||||
if t < 2 / 2.75 then
|
|
||||||
t = t - (1.5 / 2.75)
|
|
||||||
return c * (7.5625 * t * t + 0.75) + b
|
|
||||||
elseif t < 2.5 / 2.75 then
|
|
||||||
t = t - (2.25 / 2.75)
|
|
||||||
return c * (7.5625 * t * t + 0.9375) + b
|
|
||||||
end
|
|
||||||
t = t - (2.625 / 2.75)
|
|
||||||
return c * (7.5625 * t * t + 0.984375) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function inBounce(t, b, c, d)
|
|
||||||
return c - outBounce(d - t, 0, c, d) + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function inOutBounce(t, b, c, d)
|
|
||||||
if t < d / 2 then
|
|
||||||
return inBounce(t * 2, 0, c, d) * 0.5 + b
|
|
||||||
end
|
|
||||||
return outBounce(t * 2 - d, 0, c, d) * 0.5 + c * .5 + b
|
|
||||||
end
|
|
||||||
|
|
||||||
local function outInBounce(t, b, c, d)
|
|
||||||
if t < d / 2 then
|
|
||||||
return outBounce(t * 2, b, c / 2, d)
|
|
||||||
end
|
|
||||||
return inBounce((t * 2) - d, b + c / 2, c / 2, d)
|
|
||||||
end
|
|
||||||
|
|
||||||
tween.easing =
|
|
||||||
{
|
|
||||||
linear = linear,
|
|
||||||
inQuad = inQuad, outQuad = outQuad, inOutQuad = inOutQuad, outInQuad = outInQuad,
|
|
||||||
inCubic = inCubic, outCubic = outCubic, inOutCubic = inOutCubic, outInCubic = outInCubic,
|
|
||||||
inQuart = inQuart, outQuart = outQuart, inOutQuart = inOutQuart, outInQuart = outInQuart,
|
|
||||||
inQuint = inQuint, outQuint = outQuint, inOutQuint = inOutQuint, outInQuint = outInQuint,
|
|
||||||
inSine = inSine, outSine = outSine, inOutSine = inOutSine, outInSine = outInSine,
|
|
||||||
inExpo = inExpo, outExpo = outExpo, inOutExpo = inOutExpo, outInExpo = outInExpo,
|
|
||||||
inCirc = inCirc, outCirc = outCirc, inOutCirc = inOutCirc, outInCirc = outInCirc,
|
|
||||||
inElastic = inElastic, outElastic = outElastic, inOutElastic = inOutElastic, outInElastic = outInElastic,
|
|
||||||
inBack = inBack, outBack = outBack, inOutBack = inOutBack, outInBack = outInBack,
|
|
||||||
inBounce = inBounce, outBounce = outBounce, inOutBounce = inOutBounce, outInBounce = outInBounce
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Private interface
|
|
||||||
local function copyTables(destination, keysTable, valuesTable)
|
|
||||||
valuesTable = valuesTable or keysTable
|
|
||||||
local mt = getmetatable(keysTable)
|
|
||||||
if mt and getmetatable(destination) == nil then
|
|
||||||
setmetatable(destination, mt)
|
|
||||||
end
|
|
||||||
|
|
||||||
for k, v in pairs(keysTable) do
|
|
||||||
if type(v) == 'table' then
|
|
||||||
destination[k] = copyTables({}, v, valuesTable[k])
|
|
||||||
else
|
|
||||||
destination[k] = valuesTable[k]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return destination
|
|
||||||
end
|
|
||||||
|
|
||||||
local function checkSubjectAndTargetRecursively(subject, target, path)
|
|
||||||
path = path or {}
|
|
||||||
local targetType, newPath
|
|
||||||
for k, targetValue in pairs(target) do
|
|
||||||
targetType, newPath = type(targetValue), copyTables({}, path)
|
|
||||||
table.insert(newPath, tostring(k))
|
|
||||||
if targetType == 'number' then
|
|
||||||
assert(type(subject[k]) == 'number',
|
|
||||||
"Parameter '" .. table.concat(newPath, '/') .. "' is missing from subject or isn't a number")
|
|
||||||
elseif targetType == 'table' then
|
|
||||||
checkSubjectAndTargetRecursively(subject[k], targetValue, newPath)
|
|
||||||
else
|
|
||||||
assert(targetType == 'number',
|
|
||||||
"Parameter '" .. table.concat(newPath, '/') .. "' must be a number or table of numbers")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function checkNewParams(initial, duration, subject, target, easing)
|
|
||||||
-- assert(type(initial) == 'number' and duration > 0, "duration must be a positive number. Was " .. tostring(duration))
|
|
||||||
-- assert(type(duration) == 'number' and duration > 0, "duration must be a positive number. Was " .. tostring(duration))
|
|
||||||
assert(type(easing) == 'function', "easing must be a function. Was " .. tostring(easing))
|
|
||||||
|
|
||||||
if subject and target then
|
|
||||||
local tsubject = type(subject)
|
|
||||||
assert(tsubject == 'table' or tsubject == 'userdata',
|
|
||||||
"subject must be a table or userdata. Was " .. tostring(subject))
|
|
||||||
assert(type(target) == 'table', "target must be a table. Was " .. tostring(target))
|
|
||||||
checkSubjectAndTargetRecursively(subject, target)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getEasingFunction(easing)
|
|
||||||
easing = easing or "linear"
|
|
||||||
if type(easing) == 'string' then
|
|
||||||
local name = easing
|
|
||||||
easing = tween.easing[name]
|
|
||||||
if type(easing) ~= 'function' then
|
|
||||||
error("The easing function name '" .. name .. "' is invalid")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return easing
|
|
||||||
end
|
|
||||||
|
|
||||||
local function performEasingOnSubject(subject, target, initial, clock, duration, easing)
|
|
||||||
local t, b, c, d
|
|
||||||
for k, v in pairs(target) do
|
|
||||||
if type(v) == 'table' then
|
|
||||||
performEasingOnSubject(subject[k], v, initial[k], clock, duration, easing)
|
|
||||||
else
|
|
||||||
t, b, c, d = clock, initial[k], v - initial[k], duration
|
|
||||||
subject[k] = easing(t, b, c, d)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function performEasing(table, initial, target, clock, duration, easing)
|
|
||||||
if type(target) == "table" then
|
|
||||||
local t, b, c, d
|
|
||||||
for k, v in pairs(target) do
|
|
||||||
if type(v) == 'table' then
|
|
||||||
table[k] = {}
|
|
||||||
performEasing(table[k], initial[k], v, clock, duration, easing)
|
|
||||||
else
|
|
||||||
t, b, c, d = clock, initial[k], v - initial[k], duration
|
|
||||||
table[k] = easing(t, b, c, d)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return table
|
|
||||||
else
|
|
||||||
local t, b, c, d = clock, initial, target - initial, duration
|
|
||||||
return easing(t, b, c, d)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Public interface
|
|
||||||
local Tween = {}
|
|
||||||
|
|
||||||
function Tween:set(clock)
|
|
||||||
assert(type(clock) == 'number', "clock must be a positive number or 0")
|
|
||||||
|
|
||||||
if self.subject and self.initial == 0 then
|
|
||||||
self.initial = copyTables({}, self.target, self.subject)
|
|
||||||
end
|
|
||||||
|
|
||||||
self.clock = clock
|
|
||||||
|
|
||||||
if self.clock <= 0 then
|
|
||||||
self.clock = 0
|
|
||||||
if self.subject then
|
|
||||||
copyTables(self.subject, self.initial)
|
|
||||||
end
|
|
||||||
elseif self.clock >= self.duration then -- the tween has expired
|
|
||||||
self.clock = self.duration
|
|
||||||
|
|
||||||
if self.subject then
|
|
||||||
copyTables(self.subject, self.target)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if self.subject then
|
|
||||||
performEasingOnSubject(self.subject, self.target, self.initial, self.clock, self.duration, self.easing)
|
|
||||||
else
|
|
||||||
local pos = {}
|
|
||||||
return performEasing(pos, self.initial, self.target, self.clock, self.duration, self.easing)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return self.clock >= self.duration
|
|
||||||
end
|
|
||||||
|
|
||||||
function Tween:update(dt)
|
|
||||||
assert(type(dt) == 'number', "dt must be a number")
|
|
||||||
return self:set(self.clock + dt)
|
|
||||||
end
|
|
||||||
|
|
||||||
function Tween:reset()
|
|
||||||
return self:set(0)
|
|
||||||
end
|
|
||||||
|
|
||||||
function tween.new(args)
|
|
||||||
args = args or {}
|
|
||||||
|
|
||||||
args.initial = args.initial or 0
|
|
||||||
args.subject = args.subject or nil
|
|
||||||
args.target = args.target or nil
|
|
||||||
args.duration = args.duration or 0
|
|
||||||
args.easing = args.easing or nil
|
|
||||||
|
|
||||||
args.easing = getEasingFunction(args.easing)
|
|
||||||
checkNewParams(args.initial, args.duration, args.subject, args.target, args.easing)
|
|
||||||
|
|
||||||
local ret = gobject {}
|
|
||||||
ret.clock = 0
|
|
||||||
|
|
||||||
gtable.crush(ret, args, true)
|
|
||||||
gtable.crush(ret, Tween, true)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
return tween
|
|
||||||
@ -1,103 +0,0 @@
|
|||||||
local gfs = require("gears.filesystem")
|
|
||||||
local gears = require("gears")
|
|
||||||
local theme_path = gfs.get_configuration_dir() .. "/theme/"
|
|
||||||
local icon_cache = {}
|
|
||||||
local helpers = require("helpers")
|
|
||||||
local t = helpers.readJson(gears.filesystem.get_cache_dir() .. "json/settings.json").iconTheme
|
|
||||||
|
|
||||||
|
|
||||||
local custom = {
|
|
||||||
{
|
|
||||||
name = "clearpad",
|
|
||||||
to = "terminal"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name = "ncmpcpppad",
|
|
||||||
to = "deepin-music-player"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
local function hasValue(str)
|
|
||||||
local f = false
|
|
||||||
local ind = 0
|
|
||||||
for i, j in ipairs(custom) do
|
|
||||||
if j.name == str then
|
|
||||||
f = true
|
|
||||||
ind = i
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return f, ind
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function Get_icon(client, program_string, class_string)
|
|
||||||
client = client or nil
|
|
||||||
program_string = program_string or nil
|
|
||||||
class_string = class_string or nil
|
|
||||||
|
|
||||||
if (client or program_string or class_string) then
|
|
||||||
local clientName
|
|
||||||
local isCustom, pos = hasValue(class_string)
|
|
||||||
if isCustom == true then
|
|
||||||
clientName = custom[pos].to .. ".svg"
|
|
||||||
elseif client then
|
|
||||||
if client.class then
|
|
||||||
clientName = string.lower(client.class:gsub(" ", "")) .. ".svg"
|
|
||||||
elseif client.name then
|
|
||||||
clientName = string.lower(client.name:gsub(" ", "")) .. ".svg"
|
|
||||||
else
|
|
||||||
if client.icon then
|
|
||||||
return client.icon
|
|
||||||
else
|
|
||||||
return t .. "/apps/default-application.svg"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if program_string then
|
|
||||||
clientName = program_string .. ".svg"
|
|
||||||
else
|
|
||||||
clientName = class_string .. ".svg"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for index, icon in ipairs(icon_cache) do
|
|
||||||
if icon:match(clientName) then
|
|
||||||
return icon
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local iconDir = t .. "/apps/"
|
|
||||||
local ioStream = io.open(iconDir .. clientName, "r")
|
|
||||||
if ioStream ~= nil then
|
|
||||||
icon_cache[#icon_cache + 1] = iconDir .. clientName
|
|
||||||
return iconDir .. clientName
|
|
||||||
else
|
|
||||||
clientName = clientName:gsub("^%l", string.upper)
|
|
||||||
iconDir = t .. "/apps//"
|
|
||||||
ioStream = io.open(iconDir .. clientName, "r")
|
|
||||||
if ioStream ~= nil then
|
|
||||||
icon_cache[#icon_cache + 1] = iconDir .. clientName
|
|
||||||
return iconDir .. clientName
|
|
||||||
elseif not class_string then
|
|
||||||
return t .. "/apps/default-application.svg"
|
|
||||||
else
|
|
||||||
clientName = class_string .. ".svg"
|
|
||||||
iconDir = t .. "/apps/"
|
|
||||||
ioStream = io.open(iconDir .. clientName, "r")
|
|
||||||
if ioStream ~= nil then
|
|
||||||
icon_cache[#icon_cache + 1] = iconDir .. clientName
|
|
||||||
return iconDir .. clientName
|
|
||||||
else
|
|
||||||
return t .. "/apps/default-application.svg"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if client then
|
|
||||||
return t .. "/apps/default-application.svg"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
return Get_icon
|
|
||||||
@ -1,344 +0,0 @@
|
|||||||
local inspect = {
|
|
||||||
_VERSION = 'inspect.lua 3.1.0',
|
|
||||||
_URL = 'http://github.com/kikito/inspect.lua',
|
|
||||||
_DESCRIPTION = 'human-readable representations of tables',
|
|
||||||
_LICENSE = [[
|
|
||||||
MIT LICENSE
|
|
||||||
Copyright (c) 2013 Enrique García Cota
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
The above copyright notice and this permission notice shall be included
|
|
||||||
in all copies or substantial portions of the Software.
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
]]
|
|
||||||
}
|
|
||||||
|
|
||||||
local tostring = tostring
|
|
||||||
|
|
||||||
inspect.KEY = setmetatable({}, { __tostring = function() return 'inspect.KEY' end })
|
|
||||||
inspect.METATABLE = setmetatable({}, { __tostring = function() return 'inspect.METATABLE' end })
|
|
||||||
|
|
||||||
local function rawpairs(t)
|
|
||||||
return next, t, nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Apostrophizes the string if it has quotes, but not aphostrophes
|
|
||||||
-- Otherwise, it returns a regular quoted string
|
|
||||||
local function smartQuote(str)
|
|
||||||
if str:match('"') and not str:match("'") then
|
|
||||||
return "'" .. str .. "'"
|
|
||||||
end
|
|
||||||
return '"' .. str:gsub('"', '\\"') .. '"'
|
|
||||||
end
|
|
||||||
|
|
||||||
-- \a => '\\a', \0 => nil
|
|
||||||
local shortControlCharEscapes = {
|
|
||||||
["\a"] = "\\a",
|
|
||||||
["\b"] = "\\b",
|
|
||||||
["\f"] = "\\f",
|
|
||||||
["\n"] = "\\n",
|
|
||||||
["\r"] = "\\r",
|
|
||||||
["\t"] = "\\t",
|
|
||||||
["\v"] = "\\v",
|
|
||||||
["\127"] = "\\127",
|
|
||||||
}
|
|
||||||
local longControlCharEscapes = { ["\127"] = "\127" } -- \a => nil, \0 => \000, 31 => \031
|
|
||||||
for i = 0, 31 do
|
|
||||||
local ch = string.char(i)
|
|
||||||
if not shortControlCharEscapes[ch] then
|
|
||||||
shortControlCharEscapes[ch] = "\\" .. i
|
|
||||||
longControlCharEscapes[ch] = string.format("\\%03d", i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
--longControlCharEscapes["\127"]="\\127"
|
|
||||||
|
|
||||||
local function escape(str)
|
|
||||||
return (str:gsub("\\", "\\\\")
|
|
||||||
:gsub("(%c)%f[0-9]", longControlCharEscapes)
|
|
||||||
:gsub("%c", shortControlCharEscapes))
|
|
||||||
end
|
|
||||||
|
|
||||||
local function isIdentifier(str)
|
|
||||||
return type(str) == 'string' and str:match("^[_%a][_%a%d]*$")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function isSequenceKey(k, sequenceLength)
|
|
||||||
return type(k) == 'number'
|
|
||||||
and 1 <= k
|
|
||||||
and k <= sequenceLength
|
|
||||||
and math.floor(k) == k
|
|
||||||
end
|
|
||||||
|
|
||||||
local defaultTypeOrders = {
|
|
||||||
['number'] = 1,
|
|
||||||
['boolean'] = 2,
|
|
||||||
['string'] = 3,
|
|
||||||
['table'] = 4,
|
|
||||||
['function'] = 5,
|
|
||||||
['userdata'] = 6,
|
|
||||||
['thread'] = 7
|
|
||||||
}
|
|
||||||
|
|
||||||
local function sortKeys(a, b)
|
|
||||||
local ta, tb = type(a), type(b)
|
|
||||||
|
|
||||||
-- strings and numbers are sorted numerically/alphabetically
|
|
||||||
if ta == tb and (ta == 'string' or ta == 'number') then return a < b end
|
|
||||||
|
|
||||||
local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb]
|
|
||||||
-- Two default types are compared according to the defaultTypeOrders table
|
|
||||||
if dta and dtb then
|
|
||||||
return defaultTypeOrders[ta] < defaultTypeOrders[tb]
|
|
||||||
elseif dta then
|
|
||||||
return true -- default types before custom ones
|
|
||||||
elseif dtb then
|
|
||||||
return false -- custom types after default ones
|
|
||||||
end
|
|
||||||
|
|
||||||
-- custom types are sorted out alphabetically
|
|
||||||
return ta < tb
|
|
||||||
end
|
|
||||||
|
|
||||||
-- For implementation reasons, the behavior of rawlen & # is "undefined" when
|
|
||||||
-- tables aren't pure sequences. So we implement our own # operator.
|
|
||||||
local function getSequenceLength(t)
|
|
||||||
local len = 1
|
|
||||||
local v = rawget(t, len)
|
|
||||||
while v ~= nil do
|
|
||||||
len = len + 1
|
|
||||||
v = rawget(t, len)
|
|
||||||
end
|
|
||||||
return len - 1
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getNonSequentialKeys(t)
|
|
||||||
local keys, keysLength = {}, 0
|
|
||||||
local sequenceLength = getSequenceLength(t)
|
|
||||||
for k, _ in rawpairs(t) do
|
|
||||||
if not isSequenceKey(k, sequenceLength) then
|
|
||||||
keysLength = keysLength + 1
|
|
||||||
keys[keysLength] = k
|
|
||||||
end
|
|
||||||
end
|
|
||||||
table.sort(keys, sortKeys)
|
|
||||||
return keys, keysLength, sequenceLength
|
|
||||||
end
|
|
||||||
|
|
||||||
local function countTableAppearances(t, tableAppearances)
|
|
||||||
tableAppearances = tableAppearances or {}
|
|
||||||
|
|
||||||
if type(t) == 'table' then
|
|
||||||
if not tableAppearances[t] then
|
|
||||||
tableAppearances[t] = 1
|
|
||||||
for k, v in rawpairs(t) do
|
|
||||||
countTableAppearances(k, tableAppearances)
|
|
||||||
countTableAppearances(v, tableAppearances)
|
|
||||||
end
|
|
||||||
countTableAppearances(getmetatable(t), tableAppearances)
|
|
||||||
else
|
|
||||||
tableAppearances[t] = tableAppearances[t] + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return tableAppearances
|
|
||||||
end
|
|
||||||
|
|
||||||
local copySequence = function(s)
|
|
||||||
local copy, len = {}, #s
|
|
||||||
for i = 1, len do copy[i] = s[i] end
|
|
||||||
return copy, len
|
|
||||||
end
|
|
||||||
|
|
||||||
local function makePath(path, ...)
|
|
||||||
local keys = { ... }
|
|
||||||
local newPath, len = copySequence(path)
|
|
||||||
for i = 1, #keys do
|
|
||||||
newPath[len + i] = keys[i]
|
|
||||||
end
|
|
||||||
return newPath
|
|
||||||
end
|
|
||||||
|
|
||||||
local function processRecursive(process, item, path, visited)
|
|
||||||
if item == nil then return nil end
|
|
||||||
if visited[item] then return visited[item] end
|
|
||||||
|
|
||||||
local processed = process(item, path)
|
|
||||||
if type(processed) == 'table' then
|
|
||||||
local processedCopy = {}
|
|
||||||
visited[item] = processedCopy
|
|
||||||
local processedKey
|
|
||||||
|
|
||||||
for k, v in rawpairs(processed) do
|
|
||||||
processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited)
|
|
||||||
if processedKey ~= nil then
|
|
||||||
processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)
|
|
||||||
if type(mt) ~= 'table' then mt = nil end -- ignore not nil/table __metatable field
|
|
||||||
setmetatable(processedCopy, mt)
|
|
||||||
processed = processedCopy
|
|
||||||
end
|
|
||||||
return processed
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
|
|
||||||
local Inspector = {}
|
|
||||||
local Inspector_mt = { __index = Inspector }
|
|
||||||
|
|
||||||
function Inspector:puts(...)
|
|
||||||
local args = { ... }
|
|
||||||
local buffer = self.buffer
|
|
||||||
local len = #buffer
|
|
||||||
for i = 1, #args do
|
|
||||||
len = len + 1
|
|
||||||
buffer[len] = args[i]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function Inspector:down(f)
|
|
||||||
self.level = self.level + 1
|
|
||||||
f()
|
|
||||||
self.level = self.level - 1
|
|
||||||
end
|
|
||||||
|
|
||||||
function Inspector:tabify()
|
|
||||||
self:puts(self.newline, string.rep(self.indent, self.level))
|
|
||||||
end
|
|
||||||
|
|
||||||
function Inspector:alreadyVisited(v)
|
|
||||||
return self.ids[v] ~= nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function Inspector:getId(v)
|
|
||||||
local id = self.ids[v]
|
|
||||||
if not id then
|
|
||||||
local tv = type(v)
|
|
||||||
id = (self.maxIds[tv] or 0) + 1
|
|
||||||
self.maxIds[tv] = id
|
|
||||||
self.ids[v] = id
|
|
||||||
end
|
|
||||||
return tostring(id)
|
|
||||||
end
|
|
||||||
|
|
||||||
function Inspector:putKey(k)
|
|
||||||
if isIdentifier(k) then return self:puts(k) end
|
|
||||||
self:puts("[")
|
|
||||||
self:putValue(k)
|
|
||||||
self:puts("]")
|
|
||||||
end
|
|
||||||
|
|
||||||
function Inspector:putTable(t)
|
|
||||||
if t == inspect.KEY or t == inspect.METATABLE then
|
|
||||||
self:puts(tostring(t))
|
|
||||||
elseif self:alreadyVisited(t) then
|
|
||||||
self:puts('<table ', self:getId(t), '>')
|
|
||||||
elseif self.level >= self.depth then
|
|
||||||
self:puts('{...}')
|
|
||||||
else
|
|
||||||
if self.tableAppearances[t] > 1 then self:puts('<', self:getId(t), '>') end
|
|
||||||
|
|
||||||
local nonSequentialKeys, nonSequentialKeysLength, sequenceLength = getNonSequentialKeys(t)
|
|
||||||
local mt = getmetatable(t)
|
|
||||||
|
|
||||||
self:puts('{')
|
|
||||||
self:down(function()
|
|
||||||
local count = 0
|
|
||||||
for i = 1, sequenceLength do
|
|
||||||
if count > 0 then self:puts(',') end
|
|
||||||
self:puts(' ')
|
|
||||||
self:putValue(t[i])
|
|
||||||
count = count + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
for i = 1, nonSequentialKeysLength do
|
|
||||||
local k = nonSequentialKeys[i]
|
|
||||||
if count > 0 then self:puts(',') end
|
|
||||||
self:tabify()
|
|
||||||
self:putKey(k)
|
|
||||||
self:puts(' = ')
|
|
||||||
self:putValue(t[k])
|
|
||||||
count = count + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
if type(mt) == 'table' then
|
|
||||||
if count > 0 then self:puts(',') end
|
|
||||||
self:tabify()
|
|
||||||
self:puts('<metatable> = ')
|
|
||||||
self:putValue(mt)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
if nonSequentialKeysLength > 0 or type(mt) == 'table' then -- result is multi-lined. Justify closing }
|
|
||||||
self:tabify()
|
|
||||||
elseif sequenceLength > 0 then -- array tables have one extra space before closing }
|
|
||||||
self:puts(' ')
|
|
||||||
end
|
|
||||||
|
|
||||||
self:puts('}')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function Inspector:putValue(v)
|
|
||||||
local tv = type(v)
|
|
||||||
|
|
||||||
if tv == 'string' then
|
|
||||||
self:puts(smartQuote(escape(v)))
|
|
||||||
elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or
|
|
||||||
tv == 'cdata' or tv == 'ctype' then
|
|
||||||
self:puts(tostring(v))
|
|
||||||
elseif tv == 'table' then
|
|
||||||
self:putTable(v)
|
|
||||||
else
|
|
||||||
self:puts('<', tv, ' ', self:getId(v), '>')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
|
|
||||||
function inspect.inspect(root, options)
|
|
||||||
options = options or {}
|
|
||||||
|
|
||||||
local depth = options.depth or math.huge
|
|
||||||
local newline = options.newline or '\n'
|
|
||||||
local indent = options.indent or ' '
|
|
||||||
local process = options.process
|
|
||||||
|
|
||||||
if process then
|
|
||||||
root = processRecursive(process, root, {}, {})
|
|
||||||
end
|
|
||||||
|
|
||||||
local inspector = setmetatable({
|
|
||||||
depth = depth,
|
|
||||||
level = 0,
|
|
||||||
buffer = {},
|
|
||||||
ids = {},
|
|
||||||
maxIds = {},
|
|
||||||
newline = newline,
|
|
||||||
indent = indent,
|
|
||||||
tableAppearances = countTableAppearances(root)
|
|
||||||
}, Inspector_mt)
|
|
||||||
|
|
||||||
inspector:putValue(root)
|
|
||||||
|
|
||||||
return table.concat(inspector.buffer)
|
|
||||||
end
|
|
||||||
|
|
||||||
setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end })
|
|
||||||
|
|
||||||
return inspect
|
|
||||||
@ -1,383 +0,0 @@
|
|||||||
--
|
|
||||||
-- json.lua
|
|
||||||
--
|
|
||||||
-- Copyright (c) 2020 rxi
|
|
||||||
--
|
|
||||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
-- this software and associated documentation files (the "Software"), to deal in
|
|
||||||
-- the Software without restriction, including without limitation the rights to
|
|
||||||
-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
||||||
-- of the Software, and to permit persons to whom the Software is furnished to do
|
|
||||||
-- so, subject to the following conditions:
|
|
||||||
--
|
|
||||||
-- The above copyright notice and this permission notice shall be included in all
|
|
||||||
-- copies or substantial portions of the Software.
|
|
||||||
--
|
|
||||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
-- SOFTWARE.
|
|
||||||
--
|
|
||||||
|
|
||||||
local json = { _version = "0.1.2" }
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- Encode
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
local encode
|
|
||||||
|
|
||||||
local escape_char_map = {
|
|
||||||
["\\"] = "\\",
|
|
||||||
["\""] = "\"",
|
|
||||||
["\b"] = "b",
|
|
||||||
["\f"] = "f",
|
|
||||||
["\n"] = "n",
|
|
||||||
["\r"] = "r",
|
|
||||||
["\t"] = "t",
|
|
||||||
}
|
|
||||||
|
|
||||||
local escape_char_map_inv = { ["/"] = "/" }
|
|
||||||
for k, v in pairs(escape_char_map) do
|
|
||||||
escape_char_map_inv[v] = k
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function escape_char(c)
|
|
||||||
return "\\" .. (escape_char_map[c] or string.format("u%04x", c:byte()))
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_nil(val)
|
|
||||||
return "null"
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_table(val, stack)
|
|
||||||
local res = {}
|
|
||||||
stack = stack or {}
|
|
||||||
|
|
||||||
-- Circular reference?
|
|
||||||
if stack[val] then error("circular reference") end
|
|
||||||
|
|
||||||
stack[val] = true
|
|
||||||
|
|
||||||
if rawget(val, 1) ~= nil or next(val) == nil then
|
|
||||||
-- Treat as array -- check keys are valid and it is not sparse
|
|
||||||
local n = 0
|
|
||||||
for k in pairs(val) do
|
|
||||||
if type(k) ~= "number" then
|
|
||||||
error("invalid table: mixed or invalid key types")
|
|
||||||
end
|
|
||||||
n = n + 1
|
|
||||||
end
|
|
||||||
if n ~= #val then
|
|
||||||
error("invalid table: sparse array")
|
|
||||||
end
|
|
||||||
-- Encode
|
|
||||||
for i, v in ipairs(val) do
|
|
||||||
table.insert(res, encode(v, stack))
|
|
||||||
end
|
|
||||||
stack[val] = nil
|
|
||||||
return "[" .. table.concat(res, ",") .. "]"
|
|
||||||
else
|
|
||||||
-- Treat as an object
|
|
||||||
for k, v in pairs(val) do
|
|
||||||
if type(k) ~= "string" then
|
|
||||||
error("invalid table: mixed or invalid key types")
|
|
||||||
end
|
|
||||||
table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
|
|
||||||
end
|
|
||||||
stack[val] = nil
|
|
||||||
return "{" .. table.concat(res, ",") .. "}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_string(val)
|
|
||||||
return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_number(val)
|
|
||||||
-- Check for NaN, -inf and inf
|
|
||||||
if val ~= val or val <= -math.huge or val >= math.huge then
|
|
||||||
error("unexpected number value '" .. tostring(val) .. "'")
|
|
||||||
end
|
|
||||||
return string.format("%.14g", val)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local type_func_map = {
|
|
||||||
["nil"] = encode_nil,
|
|
||||||
["table"] = encode_table,
|
|
||||||
["string"] = encode_string,
|
|
||||||
["number"] = encode_number,
|
|
||||||
["boolean"] = tostring,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
encode = function(val, stack)
|
|
||||||
local t = type(val)
|
|
||||||
local f = type_func_map[t]
|
|
||||||
if f then
|
|
||||||
return f(val, stack)
|
|
||||||
end
|
|
||||||
error("unexpected type '" .. t .. "'")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function json.encode(val)
|
|
||||||
return (encode(val))
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- Decode
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
local parse
|
|
||||||
|
|
||||||
local function create_set(...)
|
|
||||||
local res = {}
|
|
||||||
for i = 1, select("#", ...) do
|
|
||||||
res[select(i, ...)] = true
|
|
||||||
end
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
|
|
||||||
local space_chars = create_set(" ", "\t", "\r", "\n")
|
|
||||||
local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
|
|
||||||
local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
|
|
||||||
local literals = create_set("true", "false", "null")
|
|
||||||
|
|
||||||
local literal_map = {
|
|
||||||
["true"] = true,
|
|
||||||
["false"] = false,
|
|
||||||
["null"] = nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
local function next_char(str, idx, set, negate)
|
|
||||||
for i = idx, #str do
|
|
||||||
if set[str:sub(i, i)] ~= negate then
|
|
||||||
return i
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return #str + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function decode_error(str, idx, msg)
|
|
||||||
local line_count = 1
|
|
||||||
local col_count = 1
|
|
||||||
for i = 1, idx - 1 do
|
|
||||||
col_count = col_count + 1
|
|
||||||
if str:sub(i, i) == "\n" then
|
|
||||||
line_count = line_count + 1
|
|
||||||
col_count = 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
error(string.format("%s at line %d col %d", msg, line_count, col_count))
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function codepoint_to_utf8(n)
|
|
||||||
-- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
|
|
||||||
local f = math.floor
|
|
||||||
if n <= 0x7f then
|
|
||||||
return string.char(n)
|
|
||||||
elseif n <= 0x7ff then
|
|
||||||
return string.char(f(n / 64) + 192, n % 64 + 128)
|
|
||||||
elseif n <= 0xffff then
|
|
||||||
return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
|
|
||||||
elseif n <= 0x10ffff then
|
|
||||||
return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128,
|
|
||||||
f(n % 4096 / 64) + 128, n % 64 + 128)
|
|
||||||
end
|
|
||||||
error(string.format("invalid unicode codepoint '%x'", n))
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_unicode_escape(s)
|
|
||||||
local n1 = tonumber(s:sub(1, 4), 16)
|
|
||||||
local n2 = tonumber(s:sub(7, 10), 16)
|
|
||||||
-- Surrogate pair?
|
|
||||||
if n2 then
|
|
||||||
return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
|
|
||||||
else
|
|
||||||
return codepoint_to_utf8(n1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_string(str, i)
|
|
||||||
local res = ""
|
|
||||||
local j = i + 1
|
|
||||||
local k = j
|
|
||||||
|
|
||||||
while j <= #str do
|
|
||||||
local x = str:byte(j)
|
|
||||||
|
|
||||||
if x < 32 then
|
|
||||||
decode_error(str, j, "control character in string")
|
|
||||||
elseif x == 92 then -- `\`: Escape
|
|
||||||
res = res .. str:sub(k, j - 1)
|
|
||||||
j = j + 1
|
|
||||||
local c = str:sub(j, j)
|
|
||||||
if c == "u" then
|
|
||||||
local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1)
|
|
||||||
or str:match("^%x%x%x%x", j + 1)
|
|
||||||
or decode_error(str, j - 1, "invalid unicode escape in string")
|
|
||||||
res = res .. parse_unicode_escape(hex)
|
|
||||||
j = j + #hex
|
|
||||||
else
|
|
||||||
if not escape_chars[c] then
|
|
||||||
decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string")
|
|
||||||
end
|
|
||||||
res = res .. escape_char_map_inv[c]
|
|
||||||
end
|
|
||||||
k = j + 1
|
|
||||||
elseif x == 34 then -- `"`: End of string
|
|
||||||
res = res .. str:sub(k, j - 1)
|
|
||||||
return res, j + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
j = j + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
decode_error(str, i, "expected closing quote for string")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_number(str, i)
|
|
||||||
local x = next_char(str, i, delim_chars)
|
|
||||||
local s = str:sub(i, x - 1)
|
|
||||||
local n = tonumber(s)
|
|
||||||
if not n then
|
|
||||||
decode_error(str, i, "invalid number '" .. s .. "'")
|
|
||||||
end
|
|
||||||
return n, x
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_literal(str, i)
|
|
||||||
local x = next_char(str, i, delim_chars)
|
|
||||||
local word = str:sub(i, x - 1)
|
|
||||||
if not literals[word] then
|
|
||||||
decode_error(str, i, "invalid literal '" .. word .. "'")
|
|
||||||
end
|
|
||||||
return literal_map[word], x
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_array(str, i)
|
|
||||||
local res = {}
|
|
||||||
local n = 1
|
|
||||||
i = i + 1
|
|
||||||
while 1 do
|
|
||||||
local x
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
-- Empty / end of array?
|
|
||||||
if str:sub(i, i) == "]" then
|
|
||||||
i = i + 1
|
|
||||||
break
|
|
||||||
end
|
|
||||||
-- Read token
|
|
||||||
x, i = parse(str, i)
|
|
||||||
res[n] = x
|
|
||||||
n = n + 1
|
|
||||||
-- Next token
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
local chr = str:sub(i, i)
|
|
||||||
i = i + 1
|
|
||||||
if chr == "]" then break end
|
|
||||||
if chr ~= "," then decode_error(str, i, "expected ']' or ','") end
|
|
||||||
end
|
|
||||||
return res, i
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_object(str, i)
|
|
||||||
local res = {}
|
|
||||||
i = i + 1
|
|
||||||
while 1 do
|
|
||||||
local key, val
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
-- Empty / end of object?
|
|
||||||
if str:sub(i, i) == "}" then
|
|
||||||
i = i + 1
|
|
||||||
break
|
|
||||||
end
|
|
||||||
-- Read key
|
|
||||||
if str:sub(i, i) ~= '"' then
|
|
||||||
decode_error(str, i, "expected string for key")
|
|
||||||
end
|
|
||||||
key, i = parse(str, i)
|
|
||||||
-- Read ':' delimiter
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
if str:sub(i, i) ~= ":" then
|
|
||||||
decode_error(str, i, "expected ':' after key")
|
|
||||||
end
|
|
||||||
i = next_char(str, i + 1, space_chars, true)
|
|
||||||
-- Read value
|
|
||||||
val, i = parse(str, i)
|
|
||||||
-- Set
|
|
||||||
res[key] = val
|
|
||||||
-- Next token
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
local chr = str:sub(i, i)
|
|
||||||
i = i + 1
|
|
||||||
if chr == "}" then break end
|
|
||||||
if chr ~= "," then decode_error(str, i, "expected '}' or ','") end
|
|
||||||
end
|
|
||||||
return res, i
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local char_func_map = {
|
|
||||||
['"'] = parse_string,
|
|
||||||
["0"] = parse_number,
|
|
||||||
["1"] = parse_number,
|
|
||||||
["2"] = parse_number,
|
|
||||||
["3"] = parse_number,
|
|
||||||
["4"] = parse_number,
|
|
||||||
["5"] = parse_number,
|
|
||||||
["6"] = parse_number,
|
|
||||||
["7"] = parse_number,
|
|
||||||
["8"] = parse_number,
|
|
||||||
["9"] = parse_number,
|
|
||||||
["-"] = parse_number,
|
|
||||||
["t"] = parse_literal,
|
|
||||||
["f"] = parse_literal,
|
|
||||||
["n"] = parse_literal,
|
|
||||||
["["] = parse_array,
|
|
||||||
["{"] = parse_object,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
parse = function(str, idx)
|
|
||||||
local chr = str:sub(idx, idx)
|
|
||||||
local f = char_func_map[chr]
|
|
||||||
if f then
|
|
||||||
return f(str, idx)
|
|
||||||
end
|
|
||||||
decode_error(str, idx, "unexpected character '" .. chr .. "'")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function json.decode(str)
|
|
||||||
if type(str) ~= "string" then
|
|
||||||
error("expected argument of type string, got " .. type(str))
|
|
||||||
end
|
|
||||||
local res, idx = parse(str, next_char(str, 1, space_chars, true))
|
|
||||||
idx = next_char(str, idx, space_chars, true)
|
|
||||||
if idx <= #str then
|
|
||||||
decode_error(str, idx, "trailing garbage")
|
|
||||||
end
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
|
|
||||||
return json
|
|
||||||
@ -1,342 +0,0 @@
|
|||||||
local awful = require("awful")
|
|
||||||
local gtable = require("gears.table")
|
|
||||||
local gtimer = require("gears.timer")
|
|
||||||
local wibox = require("wibox")
|
|
||||||
local beautiful = require("beautiful")
|
|
||||||
local helpers = require("helpers")
|
|
||||||
local dpi = beautiful.xresources.apply_dpi
|
|
||||||
local setmetatable = setmetatable
|
|
||||||
local ipairs = ipairs
|
|
||||||
local capi = { awesome = awesome, mouse = mouse, tag = tag }
|
|
||||||
|
|
||||||
local menu = { mt = {} }
|
|
||||||
|
|
||||||
function menu:set_pos(args)
|
|
||||||
args = args or {}
|
|
||||||
|
|
||||||
local coords = args.coords
|
|
||||||
local wibox = args.wibox
|
|
||||||
local widget = args.widget
|
|
||||||
local offset = args.offset or { x = 0, y = 0 }
|
|
||||||
|
|
||||||
if offset.x == nil then
|
|
||||||
offset.x = 0
|
|
||||||
end
|
|
||||||
if offset.y == nil then
|
|
||||||
offset.y = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
local screen_workarea = awful.screen.focused().workarea
|
|
||||||
local screen_w = screen_workarea.x + screen_workarea.width
|
|
||||||
local screen_h = screen_workarea.y + screen_workarea.height
|
|
||||||
|
|
||||||
if not coords and wibox and widget then
|
|
||||||
coords = helpers.get_widget_geometry(wibox, widget)
|
|
||||||
else
|
|
||||||
coords = args.coords or capi.mouse.coords()
|
|
||||||
end
|
|
||||||
|
|
||||||
if coords.x + self.width > screen_w then
|
|
||||||
if self.parent_menu ~= nil then
|
|
||||||
self.x = coords.x - (self.width * 2) - offset.x
|
|
||||||
else
|
|
||||||
self.x = coords.x - self.width + offset.x
|
|
||||||
end
|
|
||||||
else
|
|
||||||
self.x = coords.x + offset.x
|
|
||||||
end
|
|
||||||
|
|
||||||
if coords.y + self.height > screen_h then
|
|
||||||
self.y = screen_h - self.height + offset.y
|
|
||||||
else
|
|
||||||
self.y = coords.y + offset.y
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function menu:hide_parents_menus()
|
|
||||||
if self.parent_menu ~= nil then
|
|
||||||
self.parent_menu:hide(true)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function menu:hide_children_menus()
|
|
||||||
if self.widget then
|
|
||||||
for _, button in ipairs(self.widget.children) do
|
|
||||||
if button.sub_menu ~= nil then
|
|
||||||
button.sub_menu:hide()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function menu:hide(hide_parents)
|
|
||||||
if self.visible == false then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Hide self
|
|
||||||
self.visible = false
|
|
||||||
|
|
||||||
-- Hides all child menus
|
|
||||||
self:hide_children_menus()
|
|
||||||
|
|
||||||
if hide_parents == true then
|
|
||||||
self:hide_parents_menus()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function menu:show(args)
|
|
||||||
if self.visible == true then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
self.can_hide = false
|
|
||||||
|
|
||||||
gtimer({
|
|
||||||
timeout = 0.1,
|
|
||||||
autostart = true,
|
|
||||||
call_now = false,
|
|
||||||
single_shot = true,
|
|
||||||
callback = function()
|
|
||||||
self.can_hide = true
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Hide sub menus belonging to the menu of self
|
|
||||||
if self.parent_menu ~= nil then
|
|
||||||
for _, button in ipairs(self.parent_menu.widget.children) do
|
|
||||||
if button.sub_menu ~= nil and button.sub_menu ~= self then
|
|
||||||
button.sub_menu:hide()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
self:set_pos(args)
|
|
||||||
self.visible = true
|
|
||||||
|
|
||||||
capi.awesome.emit_signal("menu::toggled_on", self)
|
|
||||||
end
|
|
||||||
|
|
||||||
function menu:toggle(args)
|
|
||||||
if self.visible == true then
|
|
||||||
self:hide()
|
|
||||||
else
|
|
||||||
self:show(args)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function menu:add(widget)
|
|
||||||
if widget.sub_menu then
|
|
||||||
widget.sub_menu.parent_menu = self
|
|
||||||
end
|
|
||||||
widget.menu = self
|
|
||||||
self.widget:add(widget)
|
|
||||||
end
|
|
||||||
|
|
||||||
function menu:remove(widget)
|
|
||||||
self.widget:remove(widget)
|
|
||||||
end
|
|
||||||
|
|
||||||
function menu:reset()
|
|
||||||
self.widget:reset()
|
|
||||||
end
|
|
||||||
|
|
||||||
function menu.menu(widgets, width)
|
|
||||||
local widget = awful.popup({
|
|
||||||
x = 32500,
|
|
||||||
type = "menu",
|
|
||||||
visible = false,
|
|
||||||
ontop = true,
|
|
||||||
minimum_width = width or dpi(300),
|
|
||||||
maximum_width = width or dpi(300),
|
|
||||||
shape = helpers.rrect(9),
|
|
||||||
bg = beautiful.main_menu_bg,
|
|
||||||
widget = wibox.layout.fixed.vertical,
|
|
||||||
})
|
|
||||||
gtable.crush(widget, menu, true)
|
|
||||||
|
|
||||||
awful.mouse.append_client_mousebinding(awful.button({ "Any" }, 1, function(c)
|
|
||||||
if widget.can_hide == true then
|
|
||||||
widget:hide(true)
|
|
||||||
end
|
|
||||||
end))
|
|
||||||
|
|
||||||
awful.mouse.append_client_mousebinding(awful.button({ "Any" }, 3, function(c)
|
|
||||||
if widget.can_hide == true then
|
|
||||||
widget:hide(true)
|
|
||||||
end
|
|
||||||
end))
|
|
||||||
|
|
||||||
awful.mouse.append_global_mousebinding(awful.button({ "Any" }, 1, function(c)
|
|
||||||
if widget.can_hide == true then
|
|
||||||
widget:hide(true)
|
|
||||||
end
|
|
||||||
end))
|
|
||||||
|
|
||||||
awful.mouse.append_global_mousebinding(awful.button({ "Any" }, 3, function(c)
|
|
||||||
if widget.can_hide == true then
|
|
||||||
widget:hide(true)
|
|
||||||
end
|
|
||||||
end))
|
|
||||||
|
|
||||||
capi.tag.connect_signal("property::selected", function(t)
|
|
||||||
widget:hide(true)
|
|
||||||
end)
|
|
||||||
|
|
||||||
capi.awesome.connect_signal("menu::toggled_on", function(menu)
|
|
||||||
if menu ~= widget and menu.parent_menu == nil then
|
|
||||||
widget:hide(true)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
for _, menu_widget in ipairs(widgets) do
|
|
||||||
widget:add(menu_widget)
|
|
||||||
end
|
|
||||||
|
|
||||||
return widget
|
|
||||||
end
|
|
||||||
|
|
||||||
function menu.sub_menu_button(args)
|
|
||||||
args = args or {}
|
|
||||||
|
|
||||||
args.icon = args.icon or nil
|
|
||||||
args.icon_size = args.icon_size or 16
|
|
||||||
args.text = args.text or ""
|
|
||||||
args.text_size = args.text_size or 12
|
|
||||||
args.sub_menu = args.sub_menu or nil
|
|
||||||
|
|
||||||
local icon = args.icon ~= nil
|
|
||||||
and wibox.widget {
|
|
||||||
font = args.icon.font .. " " .. args.icon_size,
|
|
||||||
markup = helpers.colorizeText(args.icon.icon, helpers.randomColor()),
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
halign = "start",
|
|
||||||
forced_width = 40,
|
|
||||||
} or nil
|
|
||||||
|
|
||||||
local widget = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
layout = wibox.layout.align.horizontal,
|
|
||||||
forced_width = dpi(270),
|
|
||||||
{
|
|
||||||
layout = wibox.layout.fixed.horizontal,
|
|
||||||
spacing = dpi(10),
|
|
||||||
icon,
|
|
||||||
{
|
|
||||||
font = beautiful.sans .. " " .. args.text_size,
|
|
||||||
markup = args.text,
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
halign = "start"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
nil,
|
|
||||||
{
|
|
||||||
font = beautiful.icon .. " " .. "18",
|
|
||||||
markup = "",
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
halign = "start"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
margins = 10
|
|
||||||
},
|
|
||||||
bg = beautiful.bg,
|
|
||||||
forced_height = 48,
|
|
||||||
shape = helpers.rrect(9),
|
|
||||||
widget = wibox.container.background,
|
|
||||||
}
|
|
||||||
widget:connect_signal("mouse::enter", function(self)
|
|
||||||
local coords = helpers.get_widget_geometry(self.menu, self)
|
|
||||||
coords.x = coords.x + self.menu.x + self.menu.width
|
|
||||||
coords.y = coords.y + self.menu.y
|
|
||||||
args.sub_menu:show({ coords = coords, offset = { x = -5 } })
|
|
||||||
end)
|
|
||||||
widget.sub_menu = args.sub_menu
|
|
||||||
|
|
||||||
return widget
|
|
||||||
end
|
|
||||||
|
|
||||||
function menu.button(args)
|
|
||||||
args = args or {}
|
|
||||||
|
|
||||||
args.icon = args.icon or nil
|
|
||||||
args.icon_size = args.icon_size or 16
|
|
||||||
args.image = args.image
|
|
||||||
args.text = args.text or ""
|
|
||||||
args.text_size = args.text_size or 12
|
|
||||||
args.on_press = args.on_press or nil
|
|
||||||
|
|
||||||
local icon = nil
|
|
||||||
|
|
||||||
if args.icon ~= nil then
|
|
||||||
icon = wibox.widget {
|
|
||||||
font = args.icon.font .. " " .. args.icon_size,
|
|
||||||
markup = helpers.colorizeText(args.icon.icon, helpers.randomColor()),
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
halign = "start"
|
|
||||||
}
|
|
||||||
elseif args.image ~= nil then
|
|
||||||
icon = wibox.widget({
|
|
||||||
widget = wibox.widget.imagebox,
|
|
||||||
image = args.image,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
local text_widget = wibox.widget {
|
|
||||||
font = beautiful.sans .. " " .. args.text_size,
|
|
||||||
markup = args.text,
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
halign = "start"
|
|
||||||
}
|
|
||||||
|
|
||||||
local widget = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
layout = wibox.layout.fixed.horizontal,
|
|
||||||
spacing = dpi(15),
|
|
||||||
icon,
|
|
||||||
text_widget,
|
|
||||||
},
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
margins = 10
|
|
||||||
},
|
|
||||||
bg = beautiful.bg,
|
|
||||||
forced_height = 48,
|
|
||||||
shape = helpers.rrect(9),
|
|
||||||
buttons = {
|
|
||||||
awful.button({}, 1, function()
|
|
||||||
args.on_press(menu, text_widget)
|
|
||||||
menu:hide(true)
|
|
||||||
end)
|
|
||||||
},
|
|
||||||
widget = wibox.container.background,
|
|
||||||
}
|
|
||||||
widget:connect_signal("mouse::enter", function(self)
|
|
||||||
if self.menu.widget then self.menu:hide_children_menus() end
|
|
||||||
end)
|
|
||||||
return widget
|
|
||||||
end
|
|
||||||
|
|
||||||
function menu.separator()
|
|
||||||
return wibox.widget({
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
top = 10,
|
|
||||||
bottom = 10,
|
|
||||||
left = 40,
|
|
||||||
right = 40,
|
|
||||||
{
|
|
||||||
widget = wibox.widget.separator,
|
|
||||||
forced_height = dpi(2),
|
|
||||||
orientation = "horizontal",
|
|
||||||
thickness = dpi(1),
|
|
||||||
color = beautiful.fg .. "29",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
function menu.mt:__call(...)
|
|
||||||
return menu.menu(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
return setmetatable(menu, menu.mt)
|
|
||||||
@ -1,534 +0,0 @@
|
|||||||
-------------------------------------------
|
|
||||||
-- @author https://github.com/Kasper24
|
|
||||||
-- @copyright 2021-2022 Kasper24
|
|
||||||
-------------------------------------------
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
-- A layout that allows its children to take more space than what's available
|
|
||||||
-- in the surrounding container. If the content does exceed the available
|
|
||||||
-- size, a scrollbar is added and scrolling behavior enabled.
|
|
||||||
--
|
|
||||||
-- @DOC_wibox_layout_defaults_overflow_EXAMPLE@
|
|
||||||
-- @author Lucas Schwiderski
|
|
||||||
-- @copyright 2021 Lucas Schwiderski
|
|
||||||
-- @layoutmod wibox.layout.overflow
|
|
||||||
-- @supermodule wibox.layout.fixed
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
local base = require('wibox.widget.base')
|
|
||||||
local fixed = require('wibox.layout.fixed')
|
|
||||||
local separator = require('wibox.widget.separator')
|
|
||||||
local gtable = require('gears.table')
|
|
||||||
local gshape = require('gears.shape')
|
|
||||||
local gobject = require('gears.object')
|
|
||||||
local beautiful = require('beautiful')
|
|
||||||
local dpi = beautiful.xresources.apply_dpi
|
|
||||||
local mousegrabber = mousegrabber
|
|
||||||
|
|
||||||
local overflow = {
|
|
||||||
mt = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Determine the required space to draw the layout's children and, if necessary,
|
|
||||||
-- the scrollbar.
|
|
||||||
function overflow:fit(context, orig_width, orig_height)
|
|
||||||
local widgets = self._private.widgets
|
|
||||||
local num_widgets = #widgets
|
|
||||||
if num_widgets < 1 then
|
|
||||||
return 0, 0
|
|
||||||
end
|
|
||||||
|
|
||||||
local width, height = orig_width, orig_height
|
|
||||||
local scrollbar_width = self._private.scrollbar_width
|
|
||||||
local scrollbar_enabled = self._private.scrollbar_enabled
|
|
||||||
local used_in_dir, used_max = 0, 0
|
|
||||||
local is_y = self._private.dir == "y"
|
|
||||||
local avail_in_dir = is_y and orig_height or orig_width
|
|
||||||
|
|
||||||
-- Set the direction covered by scrolling to the maximum value
|
|
||||||
-- to allow widgets to take as much space as they want.
|
|
||||||
if is_y then
|
|
||||||
height = math.huge
|
|
||||||
else
|
|
||||||
width = math.huge
|
|
||||||
end
|
|
||||||
|
|
||||||
-- First, determine widget sizes.
|
|
||||||
-- Only when the content doesn't fit and needs scrolling should
|
|
||||||
-- we reduce content size to make space for a scrollbar.
|
|
||||||
for _, widget in ipairs(widgets) do
|
|
||||||
local w, h = base.fit_widget(self, context, widget, width, height)
|
|
||||||
|
|
||||||
if is_y then
|
|
||||||
used_max = math.max(used_max, w)
|
|
||||||
used_in_dir = used_in_dir + h
|
|
||||||
else
|
|
||||||
used_max = math.max(used_max, h)
|
|
||||||
used_in_dir = used_in_dir + w
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local spacing = self._private.spacing * (num_widgets - 1)
|
|
||||||
used_in_dir = used_in_dir + spacing
|
|
||||||
|
|
||||||
local need_scrollbar = scrollbar_enabled and used_in_dir > avail_in_dir
|
|
||||||
|
|
||||||
-- Even if `used_max == orig_(width|height)` already, `base.fit_widget`
|
|
||||||
-- will clamp return values, so we can "overextend" here.
|
|
||||||
if need_scrollbar then
|
|
||||||
used_max = used_max + scrollbar_width
|
|
||||||
end
|
|
||||||
|
|
||||||
if is_y then
|
|
||||||
return used_max, used_in_dir
|
|
||||||
else
|
|
||||||
return used_in_dir, used_max
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Layout children, scrollbar and spacing widgets.
|
|
||||||
-- Only those widgets that are currently visible will be placed.
|
|
||||||
function overflow:layout(context, orig_width, orig_height)
|
|
||||||
local result = {}
|
|
||||||
local is_y = self._private.dir == "y"
|
|
||||||
local widgets = self._private.widgets
|
|
||||||
local avail_in_dir = is_y and orig_height or orig_width
|
|
||||||
local scrollbar_width = self._private.scrollbar_width
|
|
||||||
local scrollbar_enabled = self._private.scrollbar_enabled
|
|
||||||
local scrollbar_position = self._private.scrollbar_position
|
|
||||||
local width, height = orig_width, orig_height
|
|
||||||
local widget_x, widget_y = 0, 0
|
|
||||||
local used_in_dir, used_max = 0, 0
|
|
||||||
|
|
||||||
-- Set the direction covered by scrolling to the maximum value
|
|
||||||
-- to allow widgets to take as much space as they want.
|
|
||||||
if is_y then
|
|
||||||
height = math.huge
|
|
||||||
else
|
|
||||||
width = math.huge
|
|
||||||
end
|
|
||||||
|
|
||||||
-- First, determine widget sizes.
|
|
||||||
-- Only when the content doesn't fit and needs scrolling should
|
|
||||||
-- we reduce content size to make space for a scrollbar.
|
|
||||||
for _, widget in pairs(widgets) do
|
|
||||||
local w, h = base.fit_widget(self, context, widget, width, height)
|
|
||||||
|
|
||||||
if is_y then
|
|
||||||
used_max = math.max(used_max, w)
|
|
||||||
used_in_dir = used_in_dir + h
|
|
||||||
else
|
|
||||||
used_max = math.max(used_max, h)
|
|
||||||
used_in_dir = used_in_dir + w
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
used_in_dir = used_in_dir + self._private.spacing * (#widgets - 1)
|
|
||||||
|
|
||||||
-- Save size for scrolling behavior
|
|
||||||
self._private.avail_in_dir = avail_in_dir
|
|
||||||
self._private.used_in_dir = used_in_dir
|
|
||||||
|
|
||||||
local need_scrollbar = used_in_dir > avail_in_dir and scrollbar_enabled
|
|
||||||
|
|
||||||
local scroll_position = self._private.scroll_factor
|
|
||||||
|
|
||||||
if need_scrollbar then
|
|
||||||
local scrollbar_widget = self._private.scrollbar_widget
|
|
||||||
local bar_x, bar_y = 0, 0
|
|
||||||
local bar_w, bar_h
|
|
||||||
-- The percentage of how much of the content can be visible within
|
|
||||||
-- the available space
|
|
||||||
local visible_percent = avail_in_dir / used_in_dir
|
|
||||||
-- Make scrollbar length reflect `visible_percent`
|
|
||||||
-- TODO: Apply a default minimum length
|
|
||||||
local bar_length = math.floor(visible_percent * avail_in_dir)
|
|
||||||
local bar_pos = (avail_in_dir - bar_length) * self._private.scroll_factor
|
|
||||||
|
|
||||||
if is_y then
|
|
||||||
bar_w, bar_h = base.fit_widget(self, context, scrollbar_widget, scrollbar_width, bar_length)
|
|
||||||
bar_y = bar_pos
|
|
||||||
|
|
||||||
if scrollbar_position == "left" then
|
|
||||||
widget_x = widget_x + bar_w
|
|
||||||
elseif scrollbar_position == "right" then
|
|
||||||
bar_x = orig_width - bar_w
|
|
||||||
end
|
|
||||||
|
|
||||||
self._private.bar_length = bar_h
|
|
||||||
|
|
||||||
width = width - bar_w
|
|
||||||
else
|
|
||||||
bar_w, bar_h = base.fit_widget(self, context, scrollbar_widget, bar_length, scrollbar_width)
|
|
||||||
bar_x = bar_pos
|
|
||||||
|
|
||||||
if scrollbar_position == "top" then
|
|
||||||
widget_y = widget_y + bar_h
|
|
||||||
elseif scrollbar_position == "bottom" then
|
|
||||||
bar_y = orig_height - bar_h
|
|
||||||
end
|
|
||||||
|
|
||||||
self._private.bar_length = bar_w
|
|
||||||
|
|
||||||
height = height - bar_h
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(result, base.place_widget_at(scrollbar_widget, math.floor(bar_x), math.floor(bar_y),
|
|
||||||
math.floor(bar_w), math.floor(bar_h)))
|
|
||||||
end
|
|
||||||
|
|
||||||
local pos, spacing = 0, self._private.spacing
|
|
||||||
local interval = used_in_dir - avail_in_dir
|
|
||||||
|
|
||||||
local spacing_widget = self._private.spacing_widget
|
|
||||||
if spacing_widget then
|
|
||||||
if is_y then
|
|
||||||
local _
|
|
||||||
_, spacing = base.fit_widget(self, context, spacing_widget, width, spacing)
|
|
||||||
else
|
|
||||||
spacing = base.fit_widget(self, context, spacing_widget, spacing, height)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for i, w in ipairs(widgets) do
|
|
||||||
local content_x, content_y
|
|
||||||
local content_w, content_h = base.fit_widget(self, context, w,
|
|
||||||
need_scrollbar and width - self._private.scrollbar_spacing or width, height)
|
|
||||||
|
|
||||||
-- When scrolling down, the content itself moves up -> substract
|
|
||||||
local scrolled_pos = pos - (scroll_position * interval)
|
|
||||||
|
|
||||||
-- Stop processing completely once we're passed the visible portion
|
|
||||||
if scrolled_pos > avail_in_dir then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
if is_y then
|
|
||||||
content_x, content_y = widget_x, scrolled_pos
|
|
||||||
pos = pos + content_h + spacing
|
|
||||||
|
|
||||||
if self._private.fill_space then
|
|
||||||
content_w = width
|
|
||||||
end
|
|
||||||
else
|
|
||||||
content_x, content_y = scrolled_pos, widget_y
|
|
||||||
pos = pos + content_w + spacing
|
|
||||||
|
|
||||||
if self._private.fill_space then
|
|
||||||
content_h = height
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local is_in_view = is_y and (scrolled_pos + content_h > 0) or (scrolled_pos + content_w > 0)
|
|
||||||
|
|
||||||
if is_in_view then
|
|
||||||
-- Add the spacing widget, but not before the first widget
|
|
||||||
if i > 1 and spacing_widget then
|
|
||||||
table.insert(result,
|
|
||||||
base.place_widget_at(spacing_widget, -- The way how spacing is added for regular widgets
|
|
||||||
-- and the `spacing_widget` is disconnected:
|
|
||||||
-- The offset for regular widgets is added to `pos` one
|
|
||||||
-- iteration _before_ the one where the widget is actually
|
|
||||||
-- placed.
|
|
||||||
-- Because of that, the placement for the spacing widget
|
|
||||||
-- needs to substract that offset to be placed right after
|
|
||||||
-- the previous regular widget.
|
|
||||||
math.floor(is_y and content_x or (content_x - spacing)),
|
|
||||||
math.floor(is_y and (content_y - spacing) or content_y),
|
|
||||||
math.floor(is_y and content_w or spacing), math.floor(is_y and spacing or content_h)))
|
|
||||||
end
|
|
||||||
table.insert(result, base.place_widget_at(w, math.floor(content_x), math.floor(content_y),
|
|
||||||
math.floor(need_scrollbar and content_w - self._private.scrollbar_spacing or content_w),
|
|
||||||
math.floor(content_h)))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
function overflow:before_draw_children(_, cr, width, height)
|
|
||||||
-- Clip drawing for children to the space we're allowed to draw in
|
|
||||||
cr:rectangle(0, 0, width, height)
|
|
||||||
cr:clip()
|
|
||||||
end
|
|
||||||
|
|
||||||
--- The amount of units to advance per scroll event.
|
|
||||||
--
|
|
||||||
-- This affects calls to `scroll` and the default mouse wheel handler.
|
|
||||||
--
|
|
||||||
-- The default is `10`.
|
|
||||||
--
|
|
||||||
-- @property step
|
|
||||||
-- @tparam number step The step size.
|
|
||||||
function overflow:set_step(step)
|
|
||||||
self._private.step = step
|
|
||||||
-- We don't need to emit enything here, since changing step only really
|
|
||||||
-- takes effect the next time the user scrolls
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Scroll the layout's content by `amount * step`.
|
|
||||||
--
|
|
||||||
-- A positive amount scroll down/right, a negative amount scrolls up/left.
|
|
||||||
--
|
|
||||||
-- The amount of units scrolled is affected by `step`.
|
|
||||||
--
|
|
||||||
-- @method overflow:scroll
|
|
||||||
-- @tparam number amount The amount to scroll by.
|
|
||||||
-- @emits property::overflow::scroll_factor
|
|
||||||
-- @emitstparam property::overflow::scroll_factor number scroll_factor The new
|
|
||||||
-- scroll factor.
|
|
||||||
-- @emits widget::layout_changed
|
|
||||||
-- @emits widget::redraw_needed
|
|
||||||
function overflow:scroll(amount)
|
|
||||||
if amount == 0 then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local interval = self._private.used_in_dir
|
|
||||||
local delta = self._private.step / interval
|
|
||||||
|
|
||||||
local factor = self._private.scroll_factor + (delta * amount)
|
|
||||||
self:set_scroll_factor(factor)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- The scroll factor.
|
|
||||||
--
|
|
||||||
-- The scroll factor represents how far the layout's content is currently
|
|
||||||
-- scrolled. It is represented as a fraction from `0` to `1`, where `0` is the
|
|
||||||
-- start of the content and `1` is the end.
|
|
||||||
--
|
|
||||||
-- @property scroll_factor
|
|
||||||
-- @tparam number scroll_factor The scroll factor.
|
|
||||||
-- @propemits true false
|
|
||||||
|
|
||||||
function overflow:set_scroll_factor(factor)
|
|
||||||
local current = self._private.scroll_factor
|
|
||||||
local interval = self._private.used_in_dir - self._private.avail_in_dir
|
|
||||||
if current == factor -- the content takes less space than what is available, i.e. everything
|
|
||||||
-- is already visible
|
|
||||||
or interval <= 0 -- the scroll factor is out of range
|
|
||||||
or (current <= 0 and factor < 0) or (current >= 1 and factor > 1) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
self._private.scroll_factor = math.min(1, math.max(factor, 0))
|
|
||||||
|
|
||||||
self:emit_signal("widget::layout_changed")
|
|
||||||
self:emit_signal("property::scroll_factor", factor)
|
|
||||||
end
|
|
||||||
|
|
||||||
function overflow:get_scroll_factor()
|
|
||||||
return self._private.scroll_factor
|
|
||||||
end
|
|
||||||
|
|
||||||
--- The scrollbar width.
|
|
||||||
--
|
|
||||||
-- For horizontal scrollbars, this is the scrollbar height
|
|
||||||
--
|
|
||||||
-- The default is `5`.
|
|
||||||
--
|
|
||||||
-- @DOC_wibox_layout_overflow_scrollbar_width_EXAMPLE@
|
|
||||||
--
|
|
||||||
-- @property scrollbar_width
|
|
||||||
-- @tparam number scrollbar_width The scrollbar width.
|
|
||||||
-- @propemits true false
|
|
||||||
|
|
||||||
function overflow:set_scrollbar_width(width)
|
|
||||||
if self._private.scrollbar_width == width then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
self._private.scrollbar_width = width
|
|
||||||
|
|
||||||
self:emit_signal("widget::layout_changed")
|
|
||||||
self:emit_signal("property::scrollbar_width", width)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- The scrollbar position.
|
|
||||||
--
|
|
||||||
-- For horizontal scrollbars, this can be `"top"` or `"bottom"`,
|
|
||||||
-- for vertical scrollbars this can be `"left"` or `"right"`.
|
|
||||||
-- The default is `"right"`/`"bottom"`.
|
|
||||||
--
|
|
||||||
-- @DOC_wibox_layout_overflow_scrollbar_position_EXAMPLE@
|
|
||||||
--
|
|
||||||
-- @property scrollbar_position
|
|
||||||
-- @tparam string scrollbar_position The scrollbar position.
|
|
||||||
-- @propemits true false
|
|
||||||
|
|
||||||
function overflow:set_scrollbar_position(position)
|
|
||||||
if self._private.scrollbar_position == position then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
self._private.scrollbar_position = position
|
|
||||||
|
|
||||||
self:emit_signal("widget::layout_changed")
|
|
||||||
self:emit_signal("property::scrollbar_position", position)
|
|
||||||
end
|
|
||||||
|
|
||||||
function overflow:get_scrollbar_position()
|
|
||||||
return self._private.scrollbar_position
|
|
||||||
end
|
|
||||||
|
|
||||||
--- The scrollbar visibility.
|
|
||||||
--
|
|
||||||
-- If this is set to `false`, no scrollbar will be rendered, even if the layout's
|
|
||||||
-- content overflows. Mouse wheel scrolling will work regardless.
|
|
||||||
--
|
|
||||||
-- The default is `true`.
|
|
||||||
--
|
|
||||||
-- @property scrollbar_enabled
|
|
||||||
-- @tparam boolean scrollbar_enabled The scrollbar visibility.
|
|
||||||
-- @propemits true false
|
|
||||||
|
|
||||||
function overflow:set_scrollbar_enabled(enabled)
|
|
||||||
if self._private.scrollbar_enabled == enabled then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
self._private.scrollbar_enabled = enabled
|
|
||||||
|
|
||||||
self:emit_signal("widget::layout_changed")
|
|
||||||
self:emit_signal("property::scrollbar_enabled", enabled)
|
|
||||||
end
|
|
||||||
|
|
||||||
function overflow:get_scrollbar_enabled()
|
|
||||||
return self._private.scrollbar_enabled
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Wraps a callback function for `mousegrabber` that is capable of
|
|
||||||
-- updating the scroll factor.
|
|
||||||
local function build_grabber(container, initial_x, initial_y, geo)
|
|
||||||
local is_y = container._private.dir == "y"
|
|
||||||
local bar_interval = container._private.avail_in_dir - container._private.bar_length
|
|
||||||
local start_pos = container._private.scroll_factor * bar_interval
|
|
||||||
local start = is_y and initial_y or initial_x
|
|
||||||
|
|
||||||
-- Calculate a matrix transforming from screen coordinates into widget
|
|
||||||
-- coordinates.
|
|
||||||
-- This is required for mouse movement to work when the widget has been
|
|
||||||
-- transformed by something like `wibox.container.rotate`.
|
|
||||||
local matrix_from_device = geo.hierarchy:get_matrix_from_device()
|
|
||||||
local wgeo = geo.drawable.drawable:geometry()
|
|
||||||
local matrix = matrix_from_device:translate( -wgeo.x, -wgeo.y)
|
|
||||||
|
|
||||||
return function(mouse)
|
|
||||||
if not mouse.buttons[1] then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local x, y = matrix:transform_point(mouse.x, mouse.y)
|
|
||||||
local pos = is_y and y or x
|
|
||||||
container:set_scroll_factor((start_pos + (pos - start)) / bar_interval)
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Applies a mouse button signal using `build_grabber` to a scrollbar widget.
|
|
||||||
local function apply_scrollbar_mouse_signal(container, w)
|
|
||||||
w:connect_signal('button::press', function(_, x, y, button_id, _, geo)
|
|
||||||
if button_id ~= 1 then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
mousegrabber.run(build_grabber(container, x, y, geo), "fleur")
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- The scrollbar widget.
|
|
||||||
-- This widget is rendered as the scrollbar element.
|
|
||||||
--
|
|
||||||
-- The default is `wibox.widget.separator{ shape = gears.shape.rectangle }`.
|
|
||||||
--
|
|
||||||
-- @DOC_wibox_layout_overflow_scrollbar_widget_EXAMPLE@
|
|
||||||
--
|
|
||||||
-- @property scrollbar_widget
|
|
||||||
-- @tparam widget scrollbar_widget The scrollbar widget.
|
|
||||||
-- @propemits true false
|
|
||||||
|
|
||||||
function overflow:set_scrollbar_widget(widget)
|
|
||||||
local w = base.make_widget_from_value(widget)
|
|
||||||
|
|
||||||
apply_scrollbar_mouse_signal(self, w)
|
|
||||||
|
|
||||||
self._private.scrollbar_widget = w
|
|
||||||
|
|
||||||
self:emit_signal("widget::layout_changed")
|
|
||||||
self:emit_signal("property::scrollbar_widget", widget)
|
|
||||||
end
|
|
||||||
|
|
||||||
function overflow:get_scrollbar_widget()
|
|
||||||
return self._private.scrollbar_widget
|
|
||||||
end
|
|
||||||
|
|
||||||
function overflow:set_scrollbar_spacing(spacing)
|
|
||||||
self._private.scrollbar_spacing = spacing
|
|
||||||
|
|
||||||
self:emit_signal("widget::layout_changed")
|
|
||||||
self:emit_signal("property::scrollbar_spacing", spacing)
|
|
||||||
end
|
|
||||||
|
|
||||||
function overflow:get_scrollbar_spacing()
|
|
||||||
return self._private.scrollbar_spacing
|
|
||||||
end
|
|
||||||
|
|
||||||
local function new(dir, ...)
|
|
||||||
local ret = fixed[dir](...)
|
|
||||||
|
|
||||||
gtable.crush(ret, overflow, true)
|
|
||||||
ret.widget_name = gobject.modulename(2)
|
|
||||||
-- Tell the widget system to prevent clicks outside the layout's extends
|
|
||||||
-- to register with child widgets, even if they actually extend that far.
|
|
||||||
-- This prevents triggering button presses on hidden/clipped widgets.
|
|
||||||
ret.clip_child_extends = true
|
|
||||||
|
|
||||||
-- Manually set the scroll factor here. We don't know the bounding size yet.
|
|
||||||
ret._private.scroll_factor = 0
|
|
||||||
|
|
||||||
-- Apply defaults. Bypass setters to avoid signals.
|
|
||||||
ret._private.step = 10
|
|
||||||
ret._private.fill_space = true
|
|
||||||
ret._private.scrollbar_width = 5
|
|
||||||
ret._private.scrollbar_enabled = true
|
|
||||||
ret._private.scrollbar_position = dir == "vertical" and "right" or "bottom"
|
|
||||||
ret._private.scrollbar_spacing = dpi(15)
|
|
||||||
|
|
||||||
local scrollbar_widget = separator({
|
|
||||||
shape = gshape.rectangle
|
|
||||||
})
|
|
||||||
apply_scrollbar_mouse_signal(ret, scrollbar_widget)
|
|
||||||
ret._private.scrollbar_widget = scrollbar_widget
|
|
||||||
|
|
||||||
ret:connect_signal('button::press', function(self, _, _, button)
|
|
||||||
if button == 4 then
|
|
||||||
self:scroll( -1)
|
|
||||||
elseif button == 5 then
|
|
||||||
self:scroll(1)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns a new horizontal overflow layout.
|
|
||||||
-- Child widgets are placed similar to `wibox.layout.fixed`, except that
|
|
||||||
-- they may take as much width as they want. If the total width of all child
|
|
||||||
-- widgets exceeds the width available whithin the layout's outer container
|
|
||||||
-- a scrollbar will be added and scrolling behavior enabled.
|
|
||||||
-- @tparam widget ... Widgets that should be added to the layout.
|
|
||||||
-- @constructorfct wibox.layout.overflow.horizontal
|
|
||||||
function overflow.horizontal(...)
|
|
||||||
return new("horizontal", ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns a new vertical overflow layout.
|
|
||||||
-- Child widgets are placed similar to `wibox.layout.fixed`, except that
|
|
||||||
-- they may take as much height as they want. If the total height of all child
|
|
||||||
-- widgets exceeds the height available whithin the layout's outer container
|
|
||||||
-- a scrollbar will be added and scrolling behavior enabled.
|
|
||||||
-- @tparam widget ... Widgets that should be added to the layout.
|
|
||||||
-- @constructorfct wibox.layout.overflow.horizontal
|
|
||||||
function overflow.vertical(...)
|
|
||||||
return new("vertical", ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
return setmetatable(overflow, overflow.mt)
|
|
||||||
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
local awful = require("awful")
|
|
||||||
local gtimer = require("gears.timer")
|
|
||||||
local beautiful = require("beautiful")
|
|
||||||
local naughty = require("naughty")
|
|
||||||
|
|
||||||
-- Use CLI backend as default as it is supported on most if not all systems
|
|
||||||
local backend_config = beautiful.playerctl_backend or "playerctl_cli"
|
|
||||||
local backends = {
|
|
||||||
playerctl_cli = require(... .. ".playerctl_cli"),
|
|
||||||
playerctl_lib = require(... .. ".playerctl_lib"),
|
|
||||||
}
|
|
||||||
|
|
||||||
local backend = nil
|
|
||||||
|
|
||||||
local function enable_wrapper(args)
|
|
||||||
local open = naughty.action { name = "Open" }
|
|
||||||
|
|
||||||
open:connect_signal("invoked", function()
|
|
||||||
awful.spawn("xdg-open https://blingcorp.github.io/bling/#/signals/pctl")
|
|
||||||
end)
|
|
||||||
|
|
||||||
gtimer.delayed_call(function()
|
|
||||||
naughty.notify({
|
|
||||||
title = "Bling Error",
|
|
||||||
text = "Global signals are deprecated! Please take a look at the playerctl documentation.",
|
|
||||||
app_name = "Bling Error",
|
|
||||||
app_icon = "system-error",
|
|
||||||
actions = { open }
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
|
|
||||||
backend_config = (args and args.backend) or backend_config
|
|
||||||
backend = backends[backend_config](args)
|
|
||||||
return backend
|
|
||||||
end
|
|
||||||
|
|
||||||
local function disable_wrapper()
|
|
||||||
backend:disable()
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
lib = backends.playerctl_lib,
|
|
||||||
cli = backends.playerctl_cli,
|
|
||||||
enable = enable_wrapper,
|
|
||||||
disable = disable_wrapper
|
|
||||||
}
|
|
||||||
@ -1,355 +0,0 @@
|
|||||||
-- Playerctl signals
|
|
||||||
--
|
|
||||||
-- Provides:
|
|
||||||
-- metadata
|
|
||||||
-- title (string)
|
|
||||||
-- artist (string)
|
|
||||||
-- album_path (string)
|
|
||||||
-- album (string)
|
|
||||||
-- player_name (string)
|
|
||||||
-- position
|
|
||||||
-- interval_sec (number)
|
|
||||||
-- length_sec (number)
|
|
||||||
-- playback_status
|
|
||||||
-- playing (boolean)
|
|
||||||
-- volume
|
|
||||||
-- volume (number)
|
|
||||||
-- loop_status
|
|
||||||
-- loop_status (string)
|
|
||||||
-- shuffle
|
|
||||||
-- shuffle (bool)
|
|
||||||
-- no_players
|
|
||||||
-- (No parameters)
|
|
||||||
|
|
||||||
local awful = require("awful")
|
|
||||||
local gobject = require("gears.object")
|
|
||||||
local gtable = require("gears.table")
|
|
||||||
local gtimer = require("gears.timer")
|
|
||||||
local gstring = require("gears.string")
|
|
||||||
local beautiful = require("beautiful")
|
|
||||||
local setmetatable = setmetatable
|
|
||||||
local tonumber = tonumber
|
|
||||||
local ipairs = ipairs
|
|
||||||
local type = type
|
|
||||||
local capi = { awesome = awesome }
|
|
||||||
|
|
||||||
local playerctl = { mt = {} }
|
|
||||||
|
|
||||||
local function save_image_async_curl(url, filepath, callback)
|
|
||||||
awful.spawn.with_line_callback(string.format("curl -L -s %s -o %s", url, filepath),
|
|
||||||
{
|
|
||||||
exit = callback
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:disable()
|
|
||||||
self._private.metadata_timer:stop()
|
|
||||||
self._private.metadata_timer = nil
|
|
||||||
awful.spawn.with_shell("killall playerctl")
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:pause(player)
|
|
||||||
if player ~= nil then
|
|
||||||
awful.spawn.with_shell("playerctl --player=" .. player .. " pause")
|
|
||||||
else
|
|
||||||
awful.spawn.with_shell(self._private.cmd .. "pause")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:play(player)
|
|
||||||
if player ~= nil then
|
|
||||||
awful.spawn.with_shell("playerctl --player=" .. player .. " play")
|
|
||||||
else
|
|
||||||
awful.spawn.with_shell(self._private.cmd .. "play")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:stop(player)
|
|
||||||
if player ~= nil then
|
|
||||||
awful.spawn.with_shell("playerctl --player=" .. player .. " stop")
|
|
||||||
else
|
|
||||||
awful.spawn.with_shell(self._private.cmd .. "stop")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:play_pause(player)
|
|
||||||
if player ~= nil then
|
|
||||||
awful.spawn.with_shell("playerctl --player=" .. player .. " play-pause")
|
|
||||||
else
|
|
||||||
awful.spawn.with_shell(self._private.cmd .. "play-pause")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:previous(player)
|
|
||||||
if player ~= nil then
|
|
||||||
awful.spawn.with_shell("playerctl --player=" .. player .. " previous")
|
|
||||||
else
|
|
||||||
awful.spawn.with_shell(self._private.cmd .. "previous")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:next(player)
|
|
||||||
if player ~= nil then
|
|
||||||
awful.spawn.with_shell("playerctl --player=" .. player .. " next")
|
|
||||||
else
|
|
||||||
awful.spawn.with_shell(self._private.cmd .. "next")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:set_loop_status(loop_status, player)
|
|
||||||
if player ~= nil then
|
|
||||||
awful.spawn.with_shell("playerctl --player=" .. player .. " loop " .. loop_status)
|
|
||||||
else
|
|
||||||
awful.spawn.with_shell(self._private.cmd .. "loop " .. loop_status)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:cycle_loop_status(player)
|
|
||||||
local function set_loop_status(loop_status)
|
|
||||||
if loop_status == "None" then
|
|
||||||
self:set_loop_status("Track")
|
|
||||||
elseif loop_status == "Track" then
|
|
||||||
self:set_loop_status("Playlist")
|
|
||||||
elseif loop_status == "Playlist" then
|
|
||||||
self:set_loop_status("None")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if player ~= nil then
|
|
||||||
awful.spawn.easy_async_with_shell("playerctl --player=" .. player .. " loop", function(stdout)
|
|
||||||
set_loop_status(stdout)
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
set_loop_status(self._private.loop_status)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:set_position(position, player)
|
|
||||||
if player ~= nil then
|
|
||||||
awful.spawn.with_shell("playerctl --player=" .. player .. " position " .. position)
|
|
||||||
else
|
|
||||||
awful.spawn.with_shell(self._private.cmd .. "position " .. position)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:set_shuffle(shuffle, player)
|
|
||||||
shuffle = shuffle and "on" or "off"
|
|
||||||
|
|
||||||
if player ~= nil then
|
|
||||||
awful.spawn.with_shell("playerctl --player=" .. player .. " shuffle " .. shuffle)
|
|
||||||
else
|
|
||||||
awful.spawn.with_shell(self._private.cmd .. "shuffle " .. shuffle)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:cycle_shuffle(player)
|
|
||||||
if player ~= nil then
|
|
||||||
awful.spawn.easy_async_with_shell("playerctl --player=" .. player .. " shuffle", function(stdout)
|
|
||||||
local shuffle = stdout == "on" and true or false
|
|
||||||
self:set_shuffle(not self._private.shuffle)
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
self:set_shuffle(not self._private.shuffle)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:set_volume(volume, player)
|
|
||||||
if player ~= nil then
|
|
||||||
awful.spawn.with_shell("playerctl --player=" .. player .. " volume " .. volume)
|
|
||||||
else
|
|
||||||
awful.spawn.with_shell(self._private.cmd .. "volume " .. volume)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function emit_player_metadata(self)
|
|
||||||
local metadata_cmd = self._private.cmd ..
|
|
||||||
"metadata --format 'title_{{title}}artist_{{artist}}art_url_{{mpris:artUrl}}player_name_{{playerName}}album_{{album}}' -F"
|
|
||||||
|
|
||||||
awful.spawn.with_line_callback(metadata_cmd, {
|
|
||||||
stdout = function(line)
|
|
||||||
local title = gstring.xml_escape(line:match('title_(.*)artist_')) or ""
|
|
||||||
local artist = gstring.xml_escape(line:match('artist_(.*)art_url_')) or ""
|
|
||||||
local art_url = line:match('art_url_(.*)player_name_') or ""
|
|
||||||
local player_name = line:match('player_name_(.*)album_') or ""
|
|
||||||
local album = gstring.xml_escape(line:match('album_(.*)')) or ""
|
|
||||||
|
|
||||||
art_url = art_url:gsub('%\n', '')
|
|
||||||
if player_name == "spotify" then
|
|
||||||
art_url = art_url:gsub("open.spotify.com", "i.scdn.co")
|
|
||||||
end
|
|
||||||
|
|
||||||
if self._private.metadata_timer
|
|
||||||
and self._private.metadata_timer.started
|
|
||||||
then
|
|
||||||
self._private.metadata_timer:stop()
|
|
||||||
end
|
|
||||||
|
|
||||||
self._private.metadata_timer = gtimer {
|
|
||||||
timeout = self.debounce_delay,
|
|
||||||
autostart = true,
|
|
||||||
single_shot = true,
|
|
||||||
callback = function()
|
|
||||||
if title and title ~= "" then
|
|
||||||
if art_url ~= "" then
|
|
||||||
local art_path = os.tmpname()
|
|
||||||
save_image_async_curl(art_url, art_path, function()
|
|
||||||
self:emit_signal("metadata", title, artist, art_path, album, player_name)
|
|
||||||
capi.awesome.emit_signal("bling::playerctl::title_artist_album", title, artist, art_path)
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
self:emit_signal("metadata", title, artist, "", album, player_name)
|
|
||||||
capi.awesome.emit_signal("bling::playerctl::title_artist_album", title, artist, "")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
self:emit_signal("no_players")
|
|
||||||
capi.awesome.emit_signal("bling::playerctl::no_players")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
collectgarbage("collect")
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
local function emit_player_position(self)
|
|
||||||
local position_cmd = self._private.cmd .. "position"
|
|
||||||
local length_cmd = self._private.cmd .. "metadata mpris:length"
|
|
||||||
|
|
||||||
awful.widget.watch(position_cmd, self.interval, function(_, interval)
|
|
||||||
awful.spawn.easy_async_with_shell(length_cmd, function(length)
|
|
||||||
local length_sec = tonumber(length) -- in microseconds
|
|
||||||
local interval_sec = tonumber(interval) -- in seconds
|
|
||||||
if length_sec and interval_sec then
|
|
||||||
if interval_sec >= 0 and length_sec > 0 then
|
|
||||||
self:emit_signal("position", interval_sec, length_sec / 1000000)
|
|
||||||
capi.awesome.emit_signal("bling::playerctl::position", interval_sec, length_sec / 1000000)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
collectgarbage("collect")
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function emit_player_playback_status(self)
|
|
||||||
local status_cmd = self._private.cmd .. "status -F"
|
|
||||||
|
|
||||||
awful.spawn.with_line_callback(status_cmd, {
|
|
||||||
stdout = function(line)
|
|
||||||
if line:find("Playing") then
|
|
||||||
self:emit_signal("playback_status", true)
|
|
||||||
capi.awesome.emit_signal("bling::playerctl::status", true)
|
|
||||||
else
|
|
||||||
self:emit_signal("playback_status", false)
|
|
||||||
capi.awesome.emit_signal("bling::playerctl::status", false)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
local function emit_player_volume(self)
|
|
||||||
local volume_cmd = self._private.cmd .. "volume -F"
|
|
||||||
|
|
||||||
awful.spawn.with_line_callback(volume_cmd, {
|
|
||||||
stdout = function(line)
|
|
||||||
self:emit_signal("volume", tonumber(line))
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
local function emit_player_loop_status(self)
|
|
||||||
local loop_status_cmd = self._private.cmd .. "loop -F"
|
|
||||||
|
|
||||||
awful.spawn.with_line_callback(loop_status_cmd, {
|
|
||||||
stdout = function(line)
|
|
||||||
self._private.loop_status = line
|
|
||||||
self:emit_signal("loop_status", line:lower())
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
local function emit_player_shuffle(self)
|
|
||||||
local shuffle_cmd = self._private.cmd .. "shuffle -F"
|
|
||||||
|
|
||||||
awful.spawn.with_line_callback(shuffle_cmd, {
|
|
||||||
stdout = function(line)
|
|
||||||
if line:find("On") then
|
|
||||||
self._private.shuffle = true
|
|
||||||
self:emit_signal("shuffle", true)
|
|
||||||
else
|
|
||||||
self._private.shuffle = false
|
|
||||||
self:emit_signal("shuffle", false)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
local function parse_args(self, args)
|
|
||||||
if args.player then
|
|
||||||
self._private.cmd = self._private.cmd .. "--player="
|
|
||||||
|
|
||||||
if type(args.player) == "string" then
|
|
||||||
self._private.cmd = self._private.cmd .. args.player .. " "
|
|
||||||
elseif type(args.player) == "table" then
|
|
||||||
for index, player in ipairs(args.player) do
|
|
||||||
self._private.cmd = self._private.cmd .. player
|
|
||||||
if index < #args.player then
|
|
||||||
self._private.cmd = self._private.cmd .. ","
|
|
||||||
else
|
|
||||||
self._private.cmd = self._private.cmd .. " "
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if args.ignore then
|
|
||||||
self._private.cmd = self._private.cmd .. "--ignore-player="
|
|
||||||
|
|
||||||
if type(args.ignore) == "string" then
|
|
||||||
self._private.cmd = self._private.cmd .. args.ignore .. " "
|
|
||||||
elseif type(args.ignore) == "table" then
|
|
||||||
for index, player in ipairs(args.ignore) do
|
|
||||||
self._private.cmd = self._private.cmd .. player
|
|
||||||
if index < #args.ignore then
|
|
||||||
self._private.cmd = self._private.cmd .. ","
|
|
||||||
else
|
|
||||||
self._private.cmd = self._private.cmd .. " "
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function new(args)
|
|
||||||
args = args or {}
|
|
||||||
|
|
||||||
local ret = gobject {}
|
|
||||||
gtable.crush(ret, playerctl, true)
|
|
||||||
|
|
||||||
ret.interval = args.interval or beautiful.playerctl_position_update_interval or 1
|
|
||||||
ret.debounce_delay = args.debounce_delay or beautiful.playerctl_debounce_delay or 0.35
|
|
||||||
|
|
||||||
ret._private = {}
|
|
||||||
ret._private.metadata_timer = nil
|
|
||||||
ret._private.cmd = "playerctl "
|
|
||||||
parse_args(ret, args)
|
|
||||||
|
|
||||||
emit_player_metadata(ret)
|
|
||||||
emit_player_position(ret)
|
|
||||||
emit_player_playback_status(ret)
|
|
||||||
emit_player_volume(ret)
|
|
||||||
emit_player_loop_status(ret)
|
|
||||||
emit_player_shuffle(ret)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl.mt:__call(...)
|
|
||||||
return new(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- On startup instead of on playerctl object init to make it
|
|
||||||
-- possible to have more than one of these running
|
|
||||||
awful.spawn.with_shell("killall playerctl")
|
|
||||||
|
|
||||||
return setmetatable(playerctl, playerctl.mt)
|
|
||||||
@ -1,569 +0,0 @@
|
|||||||
-- Playerctl signals
|
|
||||||
--
|
|
||||||
-- Provides:
|
|
||||||
-- metadata
|
|
||||||
-- title (string)
|
|
||||||
-- artist (string)
|
|
||||||
-- album_path (string)
|
|
||||||
-- album (string)
|
|
||||||
-- new (bool)
|
|
||||||
-- player_name (string)
|
|
||||||
-- position
|
|
||||||
-- interval_sec (number)
|
|
||||||
-- length_sec (number)
|
|
||||||
-- player_name (string)
|
|
||||||
-- playback_status
|
|
||||||
-- playing (boolean)
|
|
||||||
-- player_name (string)
|
|
||||||
-- seeked
|
|
||||||
-- position (number)
|
|
||||||
-- player_name (string)
|
|
||||||
-- volume
|
|
||||||
-- volume (number)
|
|
||||||
-- player_name (string)
|
|
||||||
-- loop_status
|
|
||||||
-- loop_status (string)
|
|
||||||
-- player_name (string)
|
|
||||||
-- shuffle
|
|
||||||
-- shuffle (boolean)
|
|
||||||
-- player_name (string)
|
|
||||||
-- exit
|
|
||||||
-- player_name (string)
|
|
||||||
-- no_players
|
|
||||||
-- (No parameters)
|
|
||||||
|
|
||||||
local awful = require("awful")
|
|
||||||
local gobject = require("gears.object")
|
|
||||||
local gtable = require("gears.table")
|
|
||||||
local gtimer = require("gears.timer")
|
|
||||||
local gstring = require("gears.string")
|
|
||||||
local beautiful = require("beautiful")
|
|
||||||
local setmetatable = setmetatable
|
|
||||||
local ipairs = ipairs
|
|
||||||
local pairs = pairs
|
|
||||||
local type = type
|
|
||||||
local capi = { awesome = awesome }
|
|
||||||
|
|
||||||
local playerctl = { mt = {} }
|
|
||||||
|
|
||||||
|
|
||||||
local function save_image_async_curl(url, filepath, callback)
|
|
||||||
awful.spawn.with_line_callback(string.format("curl -L -s %s -o %s", url, filepath),
|
|
||||||
{
|
|
||||||
exit = callback
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:disable()
|
|
||||||
-- Restore default settings
|
|
||||||
self.ignore = {}
|
|
||||||
self.priority = {}
|
|
||||||
self.update_on_activity = true
|
|
||||||
self.interval = 1
|
|
||||||
self.debounce_delay = 0.35
|
|
||||||
|
|
||||||
-- Reset timers
|
|
||||||
self._private.manager = nil
|
|
||||||
self._private.metadata_timer:stop()
|
|
||||||
self._private.metadata_timer = nil
|
|
||||||
self._private.position_timer:stop()
|
|
||||||
self._private.position_timer = nil
|
|
||||||
|
|
||||||
-- Reset default values
|
|
||||||
self._private.last_position = -1
|
|
||||||
self._private.last_length = -1
|
|
||||||
self._private.last_player = nil
|
|
||||||
self._private.last_title = ""
|
|
||||||
self._private.last_artist = ""
|
|
||||||
self._private.last_artUrl = ""
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:pause(player)
|
|
||||||
player = player or self._private.manager.players[1]
|
|
||||||
if player then
|
|
||||||
player:pause()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:play(player)
|
|
||||||
player = player or self._private.manager.players[1]
|
|
||||||
if player then
|
|
||||||
player:play()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:stop(player)
|
|
||||||
player = player or self._private.manager.players[1]
|
|
||||||
if player then
|
|
||||||
player:stop()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:play_pause(player)
|
|
||||||
player = player or self._private.manager.players[1]
|
|
||||||
if player then
|
|
||||||
player:play_pause()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:previous(player)
|
|
||||||
player = player or self._private.manager.players[1]
|
|
||||||
if player then
|
|
||||||
player:previous()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:next(player)
|
|
||||||
player = player or self._private.manager.players[1]
|
|
||||||
if player then
|
|
||||||
player:next()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:set_loop_status(loop_status, player)
|
|
||||||
player = player or self._private.manager.players[1]
|
|
||||||
if player then
|
|
||||||
player:set_loop_status(loop_status)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:cycle_loop_status(player)
|
|
||||||
player = player or self._private.manager.players[1]
|
|
||||||
if player then
|
|
||||||
if player.loop_status == "NONE" then
|
|
||||||
player:set_loop_status("TRACK")
|
|
||||||
elseif player.loop_status == "TRACK" then
|
|
||||||
player:set_loop_status("PLAYLIST")
|
|
||||||
elseif player.loop_status == "PLAYLIST" then
|
|
||||||
player:set_loop_status("NONE")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:set_position(position, player)
|
|
||||||
player = player or self._private.manager.players[1]
|
|
||||||
if player then
|
|
||||||
player:set_position(position * 1000000)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:set_shuffle(shuffle, player)
|
|
||||||
player = player or self._private.manager.players[1]
|
|
||||||
if player then
|
|
||||||
player:set_shuffle(shuffle)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:cycle_shuffle(player)
|
|
||||||
player = player or self._private.manager.players[1]
|
|
||||||
if player then
|
|
||||||
player:set_shuffle(not player.shuffle)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:set_volume(volume, player)
|
|
||||||
player = player or self._private.manager.players[1]
|
|
||||||
if player then
|
|
||||||
player:set_volume(volume)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:get_manager()
|
|
||||||
return self._private.manager
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:get_active_player()
|
|
||||||
return self._private.manager.players[1]
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl:get_player_of_name(name)
|
|
||||||
for _, player in ipairs(self._private.manager.players) do
|
|
||||||
if player.player_name == name then
|
|
||||||
return player
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local function emit_metadata_signal(self, title, artist, artUrl, album, new, player_name)
|
|
||||||
title = gstring.xml_escape(title)
|
|
||||||
artist = gstring.xml_escape(artist)
|
|
||||||
album = gstring.xml_escape(album)
|
|
||||||
|
|
||||||
-- Spotify client doesn't report its art URL's correctly...
|
|
||||||
if player_name == "spotify" then
|
|
||||||
artUrl = artUrl:gsub("open.spotify.com", "i.scdn.co")
|
|
||||||
end
|
|
||||||
|
|
||||||
if artUrl ~= "" then
|
|
||||||
local art_path = os.tmpname()
|
|
||||||
save_image_async_curl(artUrl, art_path, function()
|
|
||||||
self:emit_signal("metadata", title, artist, art_path, album, new, player_name)
|
|
||||||
capi.awesome.emit_signal("bling::playerctl::title_artist_album", title, artist, art_path, player_name)
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
capi.awesome.emit_signal("bling::playerctl::title_artist_album", title, artist, "", player_name)
|
|
||||||
self:emit_signal("metadata", title, artist, "", album, new, player_name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function metadata_cb(self, player, metadata)
|
|
||||||
if self.update_on_activity then
|
|
||||||
self._private.manager:move_player_to_top(player)
|
|
||||||
end
|
|
||||||
|
|
||||||
local data = metadata.value
|
|
||||||
|
|
||||||
local title = data["xesam:title"] or ""
|
|
||||||
local artist = data["xesam:artist"][1] or ""
|
|
||||||
for i = 2, #data["xesam:artist"] do
|
|
||||||
artist = artist .. ", " .. data["xesam:artist"][i]
|
|
||||||
end
|
|
||||||
local artUrl = data["mpris:artUrl"] or ""
|
|
||||||
local album = data["xesam:album"] or ""
|
|
||||||
|
|
||||||
if player == self._private.manager.players[1] then
|
|
||||||
self._private.active_player = player
|
|
||||||
|
|
||||||
-- Callback can be called even though values we care about haven't
|
|
||||||
-- changed, so check to see if they have
|
|
||||||
if
|
|
||||||
player ~= self._private.last_player
|
|
||||||
or title ~= self._private.last_title
|
|
||||||
or artist ~= self._private.last_artist
|
|
||||||
or artUrl ~= self._private.last_artUrl
|
|
||||||
then
|
|
||||||
if (title == "" and artist == "" and artUrl == "") then return end
|
|
||||||
|
|
||||||
if self._private.metadata_timer ~= nil and self._private.metadata_timer.started then
|
|
||||||
self._private.metadata_timer:stop()
|
|
||||||
end
|
|
||||||
|
|
||||||
self._private.metadata_timer = gtimer {
|
|
||||||
timeout = self.debounce_delay,
|
|
||||||
autostart = true,
|
|
||||||
single_shot = true,
|
|
||||||
callback = function()
|
|
||||||
emit_metadata_signal(self, title, artist, artUrl, album, true, player.player_name)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Re-sync with position timer when track changes
|
|
||||||
self._private.position_timer:again()
|
|
||||||
self._private.last_player = player
|
|
||||||
self._private.last_title = title
|
|
||||||
self._private.last_artist = artist
|
|
||||||
self._private.last_artUrl = artUrl
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function position_cb(self)
|
|
||||||
local player = self._private.manager.players[1]
|
|
||||||
if player then
|
|
||||||
local position = player:get_position() / 1000000
|
|
||||||
local length = (player.metadata.value["mpris:length"] or 0) / 1000000
|
|
||||||
if position ~= self._private.last_position or length ~= self._private.last_length then
|
|
||||||
capi.awesome.emit_signal("bling::playerctl::position", position, length, player.player_name)
|
|
||||||
self:emit_signal("position", position, length, player.player_name)
|
|
||||||
self._private.last_position = position
|
|
||||||
self._private.last_length = length
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function playback_status_cb(self, player, status)
|
|
||||||
if self.update_on_activity then
|
|
||||||
self._private.manager:move_player_to_top(player)
|
|
||||||
end
|
|
||||||
|
|
||||||
if player == self._private.manager.players[1] then
|
|
||||||
self._private.active_player = player
|
|
||||||
|
|
||||||
-- Reported as PLAYING, PAUSED, or STOPPED
|
|
||||||
if status == "PLAYING" then
|
|
||||||
self:emit_signal("playback_status", true, player.player_name)
|
|
||||||
capi.awesome.emit_signal("bling::playerctl::status", true, player.player_name)
|
|
||||||
else
|
|
||||||
self:emit_signal("playback_status", false, player.player_name)
|
|
||||||
capi.awesome.emit_signal("bling::playerctl::status", false, player.player_name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function seeked_cb(self, player, position)
|
|
||||||
if self.update_on_activity then
|
|
||||||
self._private.manager:move_player_to_top(player)
|
|
||||||
end
|
|
||||||
|
|
||||||
if player == self._private.manager.players[1] then
|
|
||||||
self._private.active_player = player
|
|
||||||
self:emit_signal("seeked", position / 1000000, player.player_name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function volume_cb(self, player, volume)
|
|
||||||
if self.update_on_activity then
|
|
||||||
self._private.manager:move_player_to_top(player)
|
|
||||||
end
|
|
||||||
|
|
||||||
if player == self._private.manager.players[1] then
|
|
||||||
self._private.active_player = player
|
|
||||||
self:emit_signal("volume", volume, player.player_name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function loop_status_cb(self, player, loop_status)
|
|
||||||
if self.update_on_activity then
|
|
||||||
self._private.manager:move_player_to_top(player)
|
|
||||||
end
|
|
||||||
|
|
||||||
if player == self._private.manager.players[1] then
|
|
||||||
self._private.active_player = player
|
|
||||||
self:emit_signal("loop_status", loop_status:lower(), player.player_name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function shuffle_cb(self, player, shuffle)
|
|
||||||
if self.update_on_activity then
|
|
||||||
self._private.manager:move_player_to_top(player)
|
|
||||||
end
|
|
||||||
|
|
||||||
if player == self._private.manager.players[1] then
|
|
||||||
self._private.active_player = player
|
|
||||||
self:emit_signal("shuffle", shuffle, player.player_name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function exit_cb(self, player)
|
|
||||||
if player == self._private.manager.players[1] then
|
|
||||||
self:emit_signal("exit", player.player_name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Determine if player should be managed
|
|
||||||
local function name_is_selected(self, name)
|
|
||||||
if self.ignore[name.name] then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
if #self.priority > 0 then
|
|
||||||
for _, arg in pairs(self.priority) do
|
|
||||||
if arg == name.name or arg == "%any" then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Create new player and connect it to callbacks
|
|
||||||
local function init_player(self, name)
|
|
||||||
if name_is_selected(self, name) then
|
|
||||||
local player = self._private.lgi_Playerctl.Player.new_from_name(name)
|
|
||||||
self._private.manager:manage_player(player)
|
|
||||||
player.on_metadata = function(player, metadata)
|
|
||||||
metadata_cb(self, player, metadata)
|
|
||||||
end
|
|
||||||
player.on_playback_status = function(player, playback_status)
|
|
||||||
playback_status_cb(self, player, playback_status)
|
|
||||||
end
|
|
||||||
player.on_seeked = function(player, position)
|
|
||||||
seeked_cb(self, player, position)
|
|
||||||
end
|
|
||||||
player.on_volume = function(player, volume)
|
|
||||||
volume_cb(self, player, volume)
|
|
||||||
end
|
|
||||||
player.on_loop_status = function(player, loop_status)
|
|
||||||
loop_status_cb(self, player, loop_status)
|
|
||||||
end
|
|
||||||
player.on_shuffle = function(player, shuffle_status)
|
|
||||||
shuffle_cb(self, player, shuffle_status)
|
|
||||||
end
|
|
||||||
player.on_exit = function(player, shuffle_status)
|
|
||||||
exit_cb(self, player)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Start position timer if its not already running
|
|
||||||
if not self._private.position_timer.started then
|
|
||||||
self._private.position_timer:again()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Determine if a player name comes before or after another according to the
|
|
||||||
-- priority order
|
|
||||||
local function player_compare_name(self, name_a, name_b)
|
|
||||||
local any_index = math.huge
|
|
||||||
local a_match_index = nil
|
|
||||||
local b_match_index = nil
|
|
||||||
|
|
||||||
if name_a == name_b then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
for index, name in ipairs(self.priority) do
|
|
||||||
if name == "%any" then
|
|
||||||
any_index = (any_index == math.huge) and index or any_index
|
|
||||||
elseif name == name_a then
|
|
||||||
a_match_index = a_match_index or index
|
|
||||||
elseif name == name_b then
|
|
||||||
b_match_index = b_match_index or index
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not a_match_index and not b_match_index then
|
|
||||||
return 0
|
|
||||||
elseif not a_match_index then
|
|
||||||
return (b_match_index < any_index) and 1 or -1
|
|
||||||
elseif not b_match_index then
|
|
||||||
return (a_match_index < any_index) and -1 or 1
|
|
||||||
elseif a_match_index == b_match_index then
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
return (a_match_index < b_match_index) and -1 or 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Sorting function used by manager if a priority order is specified
|
|
||||||
local function player_compare(self, a, b)
|
|
||||||
local player_a = self._private.lgi_Playerctl.Player(a)
|
|
||||||
local player_b = self._private.lgi_Playerctl.Player(b)
|
|
||||||
return player_compare_name(self, player_a.player_name, player_b.player_name)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_current_player_info(self, player)
|
|
||||||
local title = player:get_title() or ""
|
|
||||||
local artist = player:get_artist() or ""
|
|
||||||
local artUrl = player:print_metadata_prop("mpris:artUrl") or ""
|
|
||||||
local album = player:get_album() or ""
|
|
||||||
|
|
||||||
emit_metadata_signal(self, title, artist, artUrl, album, false, player.player_name)
|
|
||||||
playback_status_cb(self, player, player.playback_status)
|
|
||||||
volume_cb(self, player, player.volume)
|
|
||||||
loop_status_cb(self, player, player.loop_status)
|
|
||||||
shuffle_cb(self, player, player.shuffle)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function start_manager(self)
|
|
||||||
self._private.manager = self._private.lgi_Playerctl.PlayerManager()
|
|
||||||
|
|
||||||
if #self.priority > 0 then
|
|
||||||
self._private.manager:set_sort_func(function(a, b)
|
|
||||||
return player_compare(self, a, b)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Timer to update track position at specified interval
|
|
||||||
self._private.position_timer = gtimer {
|
|
||||||
timeout = self.interval,
|
|
||||||
callback = function()
|
|
||||||
position_cb(self)
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Manage existing players on startup
|
|
||||||
for _, name in ipairs(self._private.manager.player_names) do
|
|
||||||
init_player(self, name)
|
|
||||||
end
|
|
||||||
|
|
||||||
if self._private.manager.players[1] then
|
|
||||||
get_current_player_info(self, self._private.manager.players[1])
|
|
||||||
end
|
|
||||||
|
|
||||||
local _self = self
|
|
||||||
|
|
||||||
-- Callback to manage new players
|
|
||||||
function self._private.manager:on_name_appeared(name)
|
|
||||||
init_player(_self, name)
|
|
||||||
end
|
|
||||||
|
|
||||||
function self._private.manager:on_player_appeared(player)
|
|
||||||
if player == self.players[1] then
|
|
||||||
_self._private.active_player = player
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function self._private.manager:on_player_vanished(player)
|
|
||||||
if #self.players == 0 then
|
|
||||||
_self._private.metadata_timer:stop()
|
|
||||||
_self._private.position_timer:stop()
|
|
||||||
_self:emit_signal("no_players")
|
|
||||||
capi.awesome.emit_signal("bling::playerctl::no_players")
|
|
||||||
elseif player == _self._private.active_player then
|
|
||||||
_self._private.active_player = self.players[1]
|
|
||||||
get_current_player_info(_self, self.players[1])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function parse_args(self, args)
|
|
||||||
self.ignore = {}
|
|
||||||
if type(args.ignore) == "string" then
|
|
||||||
self.ignore[args.ignore] = true
|
|
||||||
elseif type(args.ignore) == "table" then
|
|
||||||
for _, name in pairs(args.ignore) do
|
|
||||||
self.ignore[name] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
self.priority = {}
|
|
||||||
if type(args.player) == "string" then
|
|
||||||
self.priority[1] = args.player
|
|
||||||
elseif type(args.player) == "table" then
|
|
||||||
self.priority = args.player
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function new(args)
|
|
||||||
args = args or {}
|
|
||||||
|
|
||||||
local ret = gobject {}
|
|
||||||
gtable.crush(ret, playerctl, true)
|
|
||||||
|
|
||||||
-- Grab settings from beautiful variables if not set explicitly
|
|
||||||
args.ignore = args.ignore or beautiful.playerctl_ignore
|
|
||||||
args.player = args.player or beautiful.playerctl_player
|
|
||||||
if args.update_on_activity ~= nil then
|
|
||||||
ret.update_on_activity = args.update_on_activity
|
|
||||||
else
|
|
||||||
ret.update_on_activity = beautiful.playerctl_update_on_activity ~= false
|
|
||||||
end
|
|
||||||
ret.interval = args.interval or beautiful.playerctl_position_update_interval or 1
|
|
||||||
ret.debounce_delay = args.debounce_delay or beautiful.playerctl_debounce_delay or 0.35
|
|
||||||
parse_args(ret, args)
|
|
||||||
|
|
||||||
ret._private = {}
|
|
||||||
|
|
||||||
-- Metadata callback for title, artist, and album art
|
|
||||||
ret._private.last_player = nil
|
|
||||||
ret._private.last_title = ""
|
|
||||||
ret._private.last_artist = ""
|
|
||||||
ret._private.last_artUrl = ""
|
|
||||||
|
|
||||||
-- Track position callback
|
|
||||||
ret._private.last_position = -1
|
|
||||||
ret._private.last_length = -1
|
|
||||||
|
|
||||||
-- Grab playerctl library
|
|
||||||
ret._private.lgi_Playerctl = require("lgi").Playerctl
|
|
||||||
ret._private.manager = nil
|
|
||||||
ret._private.metadata_timer = nil
|
|
||||||
ret._private.position_timer = nil
|
|
||||||
|
|
||||||
-- Ensure main event loop has started before starting player manager
|
|
||||||
gtimer.delayed_call(function()
|
|
||||||
start_manager(ret)
|
|
||||||
end)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
function playerctl.mt:__call(...)
|
|
||||||
return new(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
return setmetatable(playerctl, playerctl.mt)
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
local awful = require "awful"
|
|
||||||
local gears = require "gears"
|
|
||||||
local beautiful = require "beautiful"
|
|
||||||
|
|
||||||
awful.spawn.with_shell("bash ~/.config/awesome/main/autorun.sh")
|
|
||||||
require "setup":generate()
|
|
||||||
|
|
||||||
beautiful.init(gears.filesystem.get_configuration_dir() .. "theme/init.lua")
|
|
||||||
|
|
||||||
require "main"
|
|
||||||
require "awful.autofocus"
|
|
||||||
|
|
||||||
-- init widget
|
|
||||||
require "misc"
|
|
||||||
require "ui"
|
|
||||||
require "signal"
|
|
||||||
|
|
||||||
|
|
||||||
gears.timer {
|
|
||||||
timeout = 5,
|
|
||||||
autostart = true,
|
|
||||||
call_now = true,
|
|
||||||
callback = function()
|
|
||||||
collectgarbage "collect"
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
collectgarbage("setpause", 110)
|
|
||||||
collectgarbage("setstepmul", 1000)
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
local json = require("mods.json")
|
|
||||||
local helpers = require("helpers")
|
|
||||||
local gfs = require("gears.filesystem")
|
|
||||||
|
|
||||||
local M = {}
|
|
||||||
|
|
||||||
M.defaultData = {
|
|
||||||
colorscheme = "cat",
|
|
||||||
gaps = 10,
|
|
||||||
iconTheme = "~/.local/share/icons/hicolor/",
|
|
||||||
openWeatherApi = "KEY_HERE",
|
|
||||||
showDesktopIcons = true,
|
|
||||||
pfp = "/home/" .. string.gsub(os.getenv('USER'), '^%l', string.lower) .. "/.config/awesome/theme/assets/pfp.png",
|
|
||||||
wallpaper = "colorful",
|
|
||||||
}
|
|
||||||
|
|
||||||
M.path = gfs.get_cache_dir() .. "json/settings.json"
|
|
||||||
|
|
||||||
function M:generate()
|
|
||||||
if not helpers.file_exists(self.path) then
|
|
||||||
local w = assert(io.open(self.path, "w"))
|
|
||||||
w:write(json.encode(self.defaultData, nil, { pretty = true, indent = " ", align_keys = false, array_newline = true }))
|
|
||||||
w:close()
|
|
||||||
M.settings = self.defaultData
|
|
||||||
else
|
|
||||||
local r = assert(io.open(self.path, "rb"))
|
|
||||||
local t = r:read("*all")
|
|
||||||
r:close()
|
|
||||||
local settings = json.decode(t)
|
|
||||||
M.settings = settings
|
|
||||||
end
|
|
||||||
|
|
||||||
if not helpers.file_exists(gfs.get_cache_dir() .. "lock/lock.jpg") then
|
|
||||||
os.execute("mkdir -p ~/.cache/awesome/lock")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return M
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
local awful = require('awful')
|
|
||||||
local gears = require('gears')
|
|
||||||
local naughty = require("naughty")
|
|
||||||
|
|
||||||
local function emit_airplane_status()
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
"bash -c \"rfkill list | sed -n 2p | awk '{print $3}'\" ", function(stdout)
|
|
||||||
local status = stdout:match("yes") -- boolean
|
|
||||||
awesome.emit_signal('signal::airplane', status)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
gears.timer {
|
|
||||||
timeout = 2,
|
|
||||||
call_now = true,
|
|
||||||
autostart = true,
|
|
||||||
callback = function()
|
|
||||||
emit_airplane_status()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
local awful = require('awful')
|
|
||||||
local gears = require('gears')
|
|
||||||
|
|
||||||
local function emit_bluetooth_status()
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
"bash -c 'bluetoothctl show | grep -i powered:'", function(stdout)
|
|
||||||
local status = stdout:match("yes") -- boolean
|
|
||||||
awesome.emit_signal('signal::bluetooth', status)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Refreshing
|
|
||||||
-------------
|
|
||||||
gears.timer {
|
|
||||||
timeout = 2,
|
|
||||||
call_now = true,
|
|
||||||
autostart = true,
|
|
||||||
callback = function()
|
|
||||||
emit_bluetooth_status()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
require("signal.connection.wifi")
|
|
||||||
require("signal.connection.bluetooth")
|
|
||||||
require("signal.connection.airplane")
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
local awful = require('awful')
|
|
||||||
local gears = require('gears')
|
|
||||||
|
|
||||||
-- Network Fetching and Signal Emitting
|
|
||||||
---------------------------------------
|
|
||||||
local function emit_network_status()
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
"bash -c 'nmcli networking connectivity check'", function(stdout)
|
|
||||||
local status = not stdout:match("none") -- boolean
|
|
||||||
awesome.emit_signal('signal::network', status)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Refreshing
|
|
||||||
-------------
|
|
||||||
gears.timer {
|
|
||||||
timeout = 2,
|
|
||||||
call_now = true,
|
|
||||||
autostart = true,
|
|
||||||
callback = function()
|
|
||||||
emit_network_status()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
require("signal.system")
|
|
||||||
require("signal.connection")
|
|
||||||
require("signal.stats")
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
local awful = require('awful')
|
|
||||||
local gears = require('gears')
|
|
||||||
local function emit_cpu_status()
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
"bash -c \"roundvalue $(grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage}')\""
|
|
||||||
,
|
|
||||||
function(stdout)
|
|
||||||
stdout = tonumber(stdout)
|
|
||||||
awesome.emit_signal('signal::cpu', stdout)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
gears.timer {
|
|
||||||
timeout = 60,
|
|
||||||
call_now = true,
|
|
||||||
autostart = true,
|
|
||||||
callback = function()
|
|
||||||
emit_cpu_status()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
local awful = require('awful')
|
|
||||||
local gears = require('gears')
|
|
||||||
local function emit_disk_status()
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
"bash -c \"df --output=pcent / | sed '1d;s/^ //;s/%//'\""
|
|
||||||
,
|
|
||||||
function(stdout)
|
|
||||||
stdout = stdout:gsub("%s+", "")
|
|
||||||
stdout = tonumber(stdout)
|
|
||||||
awesome.emit_signal('signal::disk', stdout)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
gears.timer {
|
|
||||||
timeout = 600,
|
|
||||||
call_now = true,
|
|
||||||
autostart = true,
|
|
||||||
callback = function()
|
|
||||||
emit_disk_status()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
require("signal.stats.weather")
|
|
||||||
require("signal.stats.uptime")
|
|
||||||
require("signal.stats.cpu")
|
|
||||||
require("signal.stats.disk")
|
|
||||||
require("signal.stats.memory")
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
local awful = require('awful')
|
|
||||||
local gears = require('gears')
|
|
||||||
local function emit_mem_status()
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
"bash -c \"roundvalue $(free | grep Mem | awk '{print $3/$2 * 100.0}')\""
|
|
||||||
,
|
|
||||||
function(stdout)
|
|
||||||
stdout = tonumber(stdout)
|
|
||||||
awesome.emit_signal('signal::memory', stdout)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
gears.timer {
|
|
||||||
timeout = 60,
|
|
||||||
call_now = true,
|
|
||||||
autostart = true,
|
|
||||||
callback = function()
|
|
||||||
emit_mem_status()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
local awful = require('awful')
|
|
||||||
local gears = require('gears')
|
|
||||||
local function emit_uptime_status()
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
"bash -c \"uptime --pretty | sed 's/up\\s*//g' | sed 's/\\s*days/d/g' | sed 's/\\s*hours/h/g' | sed 's/\\s*minutes/m/g'\""
|
|
||||||
,
|
|
||||||
function(stdout)
|
|
||||||
stdout = stdout:gsub("%s+", "")
|
|
||||||
awesome.emit_signal('signal::uptime', stdout)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
gears.timer {
|
|
||||||
timeout = 60,
|
|
||||||
call_now = true,
|
|
||||||
autostart = true,
|
|
||||||
callback = function()
|
|
||||||
emit_uptime_status()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
@ -1,107 +0,0 @@
|
|||||||
local awful = require("awful")
|
|
||||||
local gears = require("gears")
|
|
||||||
local filesystem = gears.filesystem
|
|
||||||
local json = require("mods.json")
|
|
||||||
local helpers = require("helpers")
|
|
||||||
local icon_dir = filesystem.get_configuration_dir() .. "theme/assets/weather/icons/"
|
|
||||||
local thumb_dir = filesystem.get_configuration_dir() .. "theme/assets/weather/images/"
|
|
||||||
|
|
||||||
local GET_FORECAST_CMD = [[bash -c "curl -s --show-error -X GET '%s'"]]
|
|
||||||
|
|
||||||
local icon_map = {
|
|
||||||
["01d"] = "weather-clear-sky",
|
|
||||||
["02d"] = "weather-few-clouds",
|
|
||||||
["04d"] = "weather-few-clouds",
|
|
||||||
["03d"] = "weather-clouds",
|
|
||||||
["09d"] = "weather-showers-scattered",
|
|
||||||
["09n"] = "weather-showers-scattered",
|
|
||||||
["10d"] = "weather-showers",
|
|
||||||
["11d"] = "weather-strom",
|
|
||||||
["13d"] = "weather-snow",
|
|
||||||
["50d"] = "weather-fog",
|
|
||||||
["01n"] = "weather-clear-night",
|
|
||||||
["02n"] = "weather-few-clouds-night",
|
|
||||||
["03n"] = "weather-clouds-night",
|
|
||||||
["04n"] = "weather-clouds-night",
|
|
||||||
["10n"] = "weather-showers",
|
|
||||||
["11n"] = "weather-strom",
|
|
||||||
["13n"] = "weather-snow",
|
|
||||||
["50n"] = "weather-fog",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
local image_map = {
|
|
||||||
["01d"] = "weather-clear-sky",
|
|
||||||
["02d"] = "weather-clouds",
|
|
||||||
["04d"] = "weather-clouds",
|
|
||||||
["03d"] = "weather-clouds",
|
|
||||||
["09d"] = "weather-showers-scattered",
|
|
||||||
["09n"] = "weather-showers-scattered",
|
|
||||||
["10d"] = "weather-showers",
|
|
||||||
["11d"] = "weather-strom",
|
|
||||||
["13d"] = "weather-snow",
|
|
||||||
["50d"] = "weather-fog",
|
|
||||||
["01n"] = "weather-clear-night",
|
|
||||||
["02n"] = "weather-clouds-night",
|
|
||||||
["03n"] = "weather-clouds-night",
|
|
||||||
["04n"] = "weather-clouds-night",
|
|
||||||
["10n"] = "weather-showers",
|
|
||||||
["11n"] = "weather-strom",
|
|
||||||
["13n"] = "weather-snow",
|
|
||||||
["50n"] = "weather-fog",
|
|
||||||
}
|
|
||||||
|
|
||||||
local api_key = helpers.readJson(gears.filesystem.get_cache_dir() .. "json/settings.json").openWeatherApi
|
|
||||||
local coordinates = { "28.6446772", "77.320955" }
|
|
||||||
|
|
||||||
local show_hourly_forecast = true
|
|
||||||
local show_daily_forecast = true
|
|
||||||
local units = "metric"
|
|
||||||
|
|
||||||
local url = (
|
|
||||||
"https://api.openweathermap.org/data/2.5/onecall"
|
|
||||||
.. "?lat="
|
|
||||||
.. coordinates[1]
|
|
||||||
.. "&lon="
|
|
||||||
.. coordinates[2]
|
|
||||||
.. "&appid="
|
|
||||||
.. api_key
|
|
||||||
.. "&units="
|
|
||||||
.. units
|
|
||||||
.. "&exclude=minutely"
|
|
||||||
.. (show_hourly_forecast == false and ",hourly" or "")
|
|
||||||
.. (show_daily_forecast == false and ",daily" or "")
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
awful.widget.watch(string.format(GET_FORECAST_CMD, url), 600, function(_, stdout, stderr)
|
|
||||||
local result = json.decode(stdout)
|
|
||||||
-- Current weather setup
|
|
||||||
local out = {
|
|
||||||
desc = result.current.weather[1].description:gsub("^%l", string.upper),
|
|
||||||
humidity = result.current.humidity,
|
|
||||||
temp = math.floor(result.current.temp),
|
|
||||||
feelsLike = math.floor(result.current.feels_like),
|
|
||||||
image = icon_dir .. icon_map[result.current.weather[1].icon] .. ".svg",
|
|
||||||
thumb = thumb_dir .. image_map[result.current.weather[1].icon] .. ".jpg",
|
|
||||||
hourly = {
|
|
||||||
result.hourly[1],
|
|
||||||
result.hourly[2],
|
|
||||||
result.hourly[3],
|
|
||||||
result.hourly[4],
|
|
||||||
result.hourly[5],
|
|
||||||
result.hourly[6],
|
|
||||||
},
|
|
||||||
daily = {
|
|
||||||
result.daily[1],
|
|
||||||
result.daily[2],
|
|
||||||
result.daily[3],
|
|
||||||
result.daily[4],
|
|
||||||
result.daily[5],
|
|
||||||
result.daily[6],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
awesome.emit_signal("signal::weather", out)
|
|
||||||
end)
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
local awful = require('awful')
|
|
||||||
local gears = require('gears')
|
|
||||||
local gfs = gears.filesystem
|
|
||||||
|
|
||||||
-- Battery Fetching and Signal Emitting
|
|
||||||
---------------------------------------
|
|
||||||
-- Battery information script
|
|
||||||
local battery_script =
|
|
||||||
"bash -c 'echo $(cat /sys/class/power_supply/BAT0/capacity) echo $(cat /sys/class/power_supply/BAT0/status)'"
|
|
||||||
|
|
||||||
local function battery_emit()
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
battery_script, function(stdout)
|
|
||||||
-- The battery level and status are saved as a string. Then the level
|
|
||||||
-- is stored separately as a string, then converted to int. The status
|
|
||||||
-- is stored as a bool, and also as an int for registering changes in
|
|
||||||
-- battery status.
|
|
||||||
local level = string.match(stdout:match('(%d+)'), '(%d+)')
|
|
||||||
local level_int = tonumber(level) -- integer
|
|
||||||
local power = not stdout:match('Discharging') -- boolean
|
|
||||||
awesome.emit_signal('signal::battery', level_int, power)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Refreshing
|
|
||||||
-------------
|
|
||||||
gears.timer {
|
|
||||||
timeout = 20,
|
|
||||||
call_now = true,
|
|
||||||
autostart = true,
|
|
||||||
callback = function()
|
|
||||||
battery_emit()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
local awful = require('awful')
|
|
||||||
local gears = require('gears')
|
|
||||||
|
|
||||||
local brightness_script =
|
|
||||||
"bash -c 'echo $(($(cat /sys/class/backlight/*/brightness) * 100 / $(cat /sys/class/backlight/*/max_brightness)))'"
|
|
||||||
|
|
||||||
local function emit_brightness()
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
brightness_script, function(stdout)
|
|
||||||
local level_cur = tonumber(stdout)
|
|
||||||
awesome.emit_signal('signal::brightness', level_cur)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Refreshing
|
|
||||||
-------------
|
|
||||||
gears.timer {
|
|
||||||
timeout = 1,
|
|
||||||
call_now = true,
|
|
||||||
autostart = true,
|
|
||||||
callback = function()
|
|
||||||
emit_brightness()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
local gears = require('gears')
|
|
||||||
local naughty = require("naughty")
|
|
||||||
-- Network Fetching and Signal Emitting
|
|
||||||
---------------------------------------
|
|
||||||
local function emit_dnd_status()
|
|
||||||
local status = naughty.is_suspended()
|
|
||||||
awesome.emit_signal('signal::dnd', status)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Refreshing
|
|
||||||
-------------
|
|
||||||
gears.timer {
|
|
||||||
timeout = 2,
|
|
||||||
call_now = true,
|
|
||||||
autostart = true,
|
|
||||||
callback = function()
|
|
||||||
emit_dnd_status()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
require("signal.system.dnd")
|
|
||||||
require("signal.system.brightness")
|
|
||||||
require("signal.system.volume")
|
|
||||||
require("signal.system.battery")
|
|
||||||
require("signal.system.redshift")
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
local awful = require('awful')
|
|
||||||
local gears = require('gears')
|
|
||||||
|
|
||||||
local function mic_emit()
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
"bash -c 'pamixer --source 1 --get-mute'", function(value)
|
|
||||||
local stringtoboolean = { ["true"] = false, ["false"] = true }
|
|
||||||
value = value:gsub("%s+", "")
|
|
||||||
value = stringtoboolean[value]
|
|
||||||
awesome.emit_signal('signal::mic', value) -- integer
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
gears.timer {
|
|
||||||
timeout = 1,
|
|
||||||
call_now = true,
|
|
||||||
autostart = true,
|
|
||||||
callback = function()
|
|
||||||
mic_emit()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
local awful = require('awful')
|
|
||||||
local gears = require('gears')
|
|
||||||
|
|
||||||
local function light_emit()
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
"bash -c 'cat ~/.cache/redshift'", function(stdout)
|
|
||||||
local status = stdout:match("true") -- boolean
|
|
||||||
awesome.emit_signal('signal::redshift', status)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Microphone Fetching and Signal Emitting
|
|
||||||
-- Refreshing
|
|
||||||
-------------
|
|
||||||
gears.timer {
|
|
||||||
timeout = 2,
|
|
||||||
call_now = true,
|
|
||||||
autostart = true,
|
|
||||||
callback = function()
|
|
||||||
light_emit()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
local awful = require('awful')
|
|
||||||
local gears = require('gears')
|
|
||||||
|
|
||||||
local function volume_emit()
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
"bash -c 'pamixer --get-volume'", function(stdout)
|
|
||||||
local volume_int = tonumber(stdout) -- integer
|
|
||||||
awesome.emit_signal('signal::volume', volume_int) -- integer
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Microphone Fetching and Signal Emitting
|
|
||||||
-- Refreshing
|
|
||||||
-------------
|
|
||||||
gears.timer {
|
|
||||||
timeout = 1,
|
|
||||||
call_now = true,
|
|
||||||
autostart = true,
|
|
||||||
callback = function()
|
|
||||||
volume_emit()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
fill="#000000"
|
|
||||||
width="800px"
|
|
||||||
height="800px"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
role="img"
|
|
||||||
version="1.1"
|
|
||||||
id="svg67"
|
|
||||||
sodipodi:docname="awesomewm-svgrepo-com.svg"
|
|
||||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<defs
|
|
||||||
id="defs71" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview69"
|
|
||||||
pagecolor="#505050"
|
|
||||||
bordercolor="#ffffff"
|
|
||||||
borderopacity="1"
|
|
||||||
inkscape:showpageshadow="0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pagecheckerboard="1"
|
|
||||||
inkscape:deskcolor="#505050"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="0.76976952"
|
|
||||||
inkscape:cx="387.12886"
|
|
||||||
inkscape:cy="419.60612"
|
|
||||||
inkscape:window-width="1904"
|
|
||||||
inkscape:window-height="970"
|
|
||||||
inkscape:window-x="8"
|
|
||||||
inkscape:window-y="35"
|
|
||||||
inkscape:window-maximized="0"
|
|
||||||
inkscape:current-layer="svg67" />
|
|
||||||
<path
|
|
||||||
d="M0 24V8.25h16.5V7.5H0V0h24v24h-7.5v-8.25h-9v.75h8.25V24z"
|
|
||||||
id="path65"
|
|
||||||
style="fill:#ffffff" />
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 198 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 707 KiB |
@ -1,513 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="141.5919mm"
|
|
||||||
height="122.80626mm"
|
|
||||||
viewBox="0 0 501.70361 435.14028"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.92.0 r15299"
|
|
||||||
sodipodi:docname="nix-snowflake.svg">
|
|
||||||
<defs
|
|
||||||
id="defs4">
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient5562">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#699ad7;stop-opacity:1"
|
|
||||||
offset="0"
|
|
||||||
id="stop5564" />
|
|
||||||
<stop
|
|
||||||
id="stop5566"
|
|
||||||
offset="0.24345198"
|
|
||||||
style="stop-color:#7eb1dd;stop-opacity:1" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#7ebae4;stop-opacity:1"
|
|
||||||
offset="1"
|
|
||||||
id="stop5568" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient5053">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#415e9a;stop-opacity:1"
|
|
||||||
offset="0"
|
|
||||||
id="stop5055" />
|
|
||||||
<stop
|
|
||||||
id="stop5057"
|
|
||||||
offset="0.23168644"
|
|
||||||
style="stop-color:#4a6baf;stop-opacity:1" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#5277c3;stop-opacity:1"
|
|
||||||
offset="1"
|
|
||||||
id="stop5059" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient5960"
|
|
||||||
inkscape:collect="always">
|
|
||||||
<stop
|
|
||||||
id="stop5962"
|
|
||||||
offset="0"
|
|
||||||
style="stop-color:#637ddf;stop-opacity:1" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#649afa;stop-opacity:1"
|
|
||||||
offset="0.23168644"
|
|
||||||
id="stop5964" />
|
|
||||||
<stop
|
|
||||||
id="stop5966"
|
|
||||||
offset="1"
|
|
||||||
style="stop-color:#719efa;stop-opacity:1" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient5867">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#7363df;stop-opacity:1"
|
|
||||||
offset="0"
|
|
||||||
id="stop5869" />
|
|
||||||
<stop
|
|
||||||
id="stop5871"
|
|
||||||
offset="0.23168644"
|
|
||||||
style="stop-color:#6478fa;stop-opacity:1" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#719efa;stop-opacity:1"
|
|
||||||
offset="1"
|
|
||||||
id="stop5873" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
y2="515.97058"
|
|
||||||
x2="282.26105"
|
|
||||||
y1="338.62445"
|
|
||||||
x1="213.95642"
|
|
||||||
gradientTransform="translate(983.36076,601.38885)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient5855"
|
|
||||||
xlink:href="#linearGradient5960"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<linearGradient
|
|
||||||
y2="515.97058"
|
|
||||||
x2="282.26105"
|
|
||||||
y1="338.62445"
|
|
||||||
x1="213.95642"
|
|
||||||
gradientTransform="translate(-197.75174,-337.1451)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient5855-8"
|
|
||||||
xlink:href="#linearGradient5867"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<linearGradient
|
|
||||||
y2="247.58188"
|
|
||||||
x2="-702.75317"
|
|
||||||
y1="102.74675"
|
|
||||||
x1="-775.20807"
|
|
||||||
gradientTransform="translate(983.36076,601.38885)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient4544"
|
|
||||||
xlink:href="#linearGradient5960"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<clipPath
|
|
||||||
id="clipPath4501"
|
|
||||||
clipPathUnits="userSpaceOnUse">
|
|
||||||
<circle
|
|
||||||
r="241.06563"
|
|
||||||
cy="686.09473"
|
|
||||||
cx="335.13995"
|
|
||||||
id="circle4503"
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#adadad;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
|
||||||
</clipPath>
|
|
||||||
<clipPath
|
|
||||||
id="clipPath5410"
|
|
||||||
clipPathUnits="userSpaceOnUse">
|
|
||||||
<circle
|
|
||||||
r="241.13741"
|
|
||||||
cy="340.98975"
|
|
||||||
cx="335.98114"
|
|
||||||
id="circle5412"
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
|
||||||
</clipPath>
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient5053"
|
|
||||||
id="linearGradient5137"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="translate(864.55062,-2197.497)"
|
|
||||||
x1="-584.19934"
|
|
||||||
y1="782.33563"
|
|
||||||
x2="-496.29703"
|
|
||||||
y2="937.71399" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient5053"
|
|
||||||
id="linearGradient5147"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="translate(864.55062,-2197.497)"
|
|
||||||
x1="-584.19934"
|
|
||||||
y1="782.33563"
|
|
||||||
x2="-496.29703"
|
|
||||||
y2="937.71399" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient5562"
|
|
||||||
id="linearGradient5162"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="translate(70.505061,-1761.3076)"
|
|
||||||
x1="200.59668"
|
|
||||||
y1="351.41116"
|
|
||||||
x2="290.08701"
|
|
||||||
y2="506.18814" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient5562"
|
|
||||||
id="linearGradient5172"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="translate(70.505061,-1761.3076)"
|
|
||||||
x1="200.59668"
|
|
||||||
y1="351.41116"
|
|
||||||
x2="290.08701"
|
|
||||||
y2="506.18814" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient5562"
|
|
||||||
id="linearGradient5182"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="translate(70.505061,-1761.3076)"
|
|
||||||
x1="200.59668"
|
|
||||||
y1="351.41116"
|
|
||||||
x2="290.08701"
|
|
||||||
y2="506.18814" />
|
|
||||||
<linearGradient
|
|
||||||
y2="506.18814"
|
|
||||||
x2="290.08701"
|
|
||||||
y1="351.41116"
|
|
||||||
x1="200.59668"
|
|
||||||
gradientTransform="translate(70.505061,-1761.3076)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient5201"
|
|
||||||
xlink:href="#linearGradient5562"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<linearGradient
|
|
||||||
y2="937.71399"
|
|
||||||
x2="-496.29703"
|
|
||||||
y1="782.33563"
|
|
||||||
x1="-584.19934"
|
|
||||||
gradientTransform="translate(864.55062,-2197.497)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient5205"
|
|
||||||
xlink:href="#linearGradient5053"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient5562"
|
|
||||||
id="linearGradient4328"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="translate(70.650339,-1055.1511)"
|
|
||||||
x1="200.59668"
|
|
||||||
y1="351.41116"
|
|
||||||
x2="290.08701"
|
|
||||||
y2="506.18814" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient5053"
|
|
||||||
id="linearGradient4330"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="translate(864.69589,-1491.3405)"
|
|
||||||
x1="-584.19934"
|
|
||||||
y1="782.33563"
|
|
||||||
x2="-496.29703"
|
|
||||||
y2="937.71399" />
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="0.98318225"
|
|
||||||
inkscape:cx="113.58176"
|
|
||||||
inkscape:cy="-45.193301"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer3"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:window-width="2560"
|
|
||||||
inkscape:window-height="1577"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="0"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:snap-global="true"
|
|
||||||
fit-margin-top="0"
|
|
||||||
fit-margin-left="0"
|
|
||||||
fit-margin-right="0"
|
|
||||||
fit-margin-bottom="0" />
|
|
||||||
<metadata
|
|
||||||
id="metadata7">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title />
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer7"
|
|
||||||
inkscape:label="bg"
|
|
||||||
style="display:none"
|
|
||||||
transform="translate(-23.75651,-24.84972)">
|
|
||||||
<rect
|
|
||||||
transform="translate(-132.5822,958.04022)"
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
|
||||||
id="rect5389"
|
|
||||||
width="1543.4283"
|
|
||||||
height="483.7439"
|
|
||||||
x="132.5822"
|
|
||||||
y="-957.77832" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer6"
|
|
||||||
inkscape:label="logo-guide"
|
|
||||||
style="display:none"
|
|
||||||
transform="translate(-156.33871,933.1905)">
|
|
||||||
<rect
|
|
||||||
y="-958.02759"
|
|
||||||
x="132.65129"
|
|
||||||
height="484.30399"
|
|
||||||
width="550.41602"
|
|
||||||
id="rect5379"
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5c201e;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
|
||||||
inkscape:export-filename="/home/tim/dev/nix/homepage/logo/nix-wiki.png"
|
|
||||||
inkscape:export-xdpi="22.07"
|
|
||||||
inkscape:export-ydpi="22.07" />
|
|
||||||
<rect
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c24a46;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
|
||||||
id="rect5372"
|
|
||||||
width="501.94415"
|
|
||||||
height="434.30405"
|
|
||||||
x="156.12303"
|
|
||||||
y="-933.02759"
|
|
||||||
inkscape:export-filename="/home/tim/dev/nix/homepage/logo/nixos-logo-only-hires-print.png"
|
|
||||||
inkscape:export-xdpi="212.2"
|
|
||||||
inkscape:export-ydpi="212.2" />
|
|
||||||
<rect
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#d98d8a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
|
||||||
id="rect5381"
|
|
||||||
width="24.939611"
|
|
||||||
height="24.939611"
|
|
||||||
x="658.02826"
|
|
||||||
y="-958.04022" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
inkscape:label="print-logo"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
style="display:inline"
|
|
||||||
transform="translate(-156.33871,933.1905)"
|
|
||||||
sodipodi:insensitive="true">
|
|
||||||
<path
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5277c3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
|
||||||
d="m 309.40365,-710.2521 122.19683,211.6751 -56.15706,0.5268 -32.6236,-56.8692 -32.85645,56.5653 -27.90237,-0.011 -14.29086,-24.6896 46.81047,-80.4902 -33.22946,-57.8256 z"
|
|
||||||
id="path4861"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
sodipodi:nodetypes="cccccccccc" />
|
|
||||||
<path
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#7ebae4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
|
||||||
d="m 353.50926,-797.4433 -122.21756,211.6631 -28.53477,-48.37 32.93839,-56.6875 -65.41521,-0.1719 -13.9414,-24.1698 14.23637,-24.721 93.11177,0.2939 33.46371,-57.6903 z"
|
|
||||||
id="use4863"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
sodipodi:nodetypes="cccccccccc" />
|
|
||||||
<path
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#7ebae4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
|
||||||
d="m 362.88537,-628.243 244.41439,0.012 -27.62229,48.8968 -65.56199,-0.1817 32.55876,56.7371 -13.96098,24.1585 -28.52722,0.032 -46.3013,-80.7841 -66.69317,-0.1353 z"
|
|
||||||
id="use4865"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
sodipodi:nodetypes="cccccccccc" />
|
|
||||||
<path
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#7ebae4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
|
||||||
d="m 505.14318,-720.9886 -122.19683,-211.6751 56.15706,-0.5268 32.6236,56.8692 32.85645,-56.5653 27.90237,0.011 14.29086,24.6896 -46.81047,80.4902 33.22946,57.8256 z"
|
|
||||||
id="use4867"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
sodipodi:nodetypes="cccccccccc" />
|
|
||||||
<path
|
|
||||||
sodipodi:nodetypes="cccccccccc"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path4873"
|
|
||||||
d="m 309.40365,-710.2521 122.19683,211.6751 -56.15706,0.5268 -32.6236,-56.8692 -32.85645,56.5653 -27.90237,-0.011 -14.29086,-24.6896 46.81047,-80.4902 -33.22946,-57.8256 z"
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5277c3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
|
||||||
<path
|
|
||||||
sodipodi:nodetypes="cccccccccc"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="use4875"
|
|
||||||
d="m 451.3364,-803.53264 -244.4144,-0.012 27.62229,-48.89685 65.56199,0.18175 -32.55875,-56.73717 13.96097,-24.15851 28.52722,-0.0315 46.3013,80.78414 66.69317,0.13524 z"
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5277c3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
|
||||||
<path
|
|
||||||
sodipodi:nodetypes="cccccccccc"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="use4877"
|
|
||||||
d="m 460.87178,-633.8425 122.21757,-211.66304 28.53477,48.37003 -32.93839,56.68751 65.4152,0.1718 13.9414,24.1698 -14.23636,24.7211 -93.11177,-0.294 -33.46371,57.6904 z"
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5277c3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
|
||||||
<g
|
|
||||||
id="layer2"
|
|
||||||
inkscape:label="guides"
|
|
||||||
style="display:none"
|
|
||||||
transform="translate(72.039038,-1799.4476)">
|
|
||||||
<path
|
|
||||||
d="M 460.60629,594.72881 209.74183,594.7288 84.309616,377.4738 209.74185,160.21882 l 250.86446,1e-5 125.43222,217.255 z"
|
|
||||||
inkscape:randomized="0"
|
|
||||||
inkscape:rounded="0"
|
|
||||||
inkscape:flatsided="true"
|
|
||||||
sodipodi:arg2="1.5707963"
|
|
||||||
sodipodi:arg1="1.0471976"
|
|
||||||
sodipodi:r2="217.25499"
|
|
||||||
sodipodi:r1="250.86446"
|
|
||||||
sodipodi:cy="377.47382"
|
|
||||||
sodipodi:cx="335.17407"
|
|
||||||
sodipodi:sides="6"
|
|
||||||
id="path6032"
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.23600003;fill:#4e4d52;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
sodipodi:type="star" />
|
|
||||||
<path
|
|
||||||
transform="translate(0,-308.26772)"
|
|
||||||
sodipodi:type="star"
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#4e4d52;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="path5875"
|
|
||||||
sodipodi:sides="6"
|
|
||||||
sodipodi:cx="335.17407"
|
|
||||||
sodipodi:cy="685.74158"
|
|
||||||
sodipodi:r1="100.83495"
|
|
||||||
sodipodi:r2="87.32563"
|
|
||||||
sodipodi:arg1="1.0471976"
|
|
||||||
sodipodi:arg2="1.5707963"
|
|
||||||
inkscape:flatsided="true"
|
|
||||||
inkscape:rounded="0"
|
|
||||||
inkscape:randomized="0"
|
|
||||||
d="m 385.59154,773.06721 -100.83495,0 -50.41747,-87.32564 50.41748,-87.32563 100.83495,10e-6 50.41748,87.32563 z" />
|
|
||||||
<path
|
|
||||||
transform="translate(0,-308.26772)"
|
|
||||||
sodipodi:nodetypes="ccccccccc"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path5851"
|
|
||||||
d="m 1216.5591,938.53395 123.0545,228.14035 -42.6807,-1.2616 -43.4823,-79.7725 -39.6506,80.3267 -32.6875,-19.7984 53.4737,-100.2848 -37.1157,-73.88955 z"
|
|
||||||
style="fill:url(#linearGradient5855);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
|
||||||
<rect
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.41499999;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c53a3a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
|
||||||
id="rect5884"
|
|
||||||
width="48.834862"
|
|
||||||
height="226.22897"
|
|
||||||
x="-34.74221"
|
|
||||||
y="446.17056"
|
|
||||||
transform="rotate(-30)" />
|
|
||||||
<path
|
|
||||||
transform="translate(0,-308.26772)"
|
|
||||||
sodipodi:type="star"
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.50899999;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
|
||||||
id="path3428"
|
|
||||||
sodipodi:sides="6"
|
|
||||||
sodipodi:cx="223.93674"
|
|
||||||
sodipodi:cy="878.63831"
|
|
||||||
sodipodi:r1="28.048939"
|
|
||||||
sodipodi:r2="24.291094"
|
|
||||||
sodipodi:arg1="0"
|
|
||||||
sodipodi:arg2="0.52359878"
|
|
||||||
inkscape:flatsided="true"
|
|
||||||
inkscape:rounded="0"
|
|
||||||
inkscape:randomized="0"
|
|
||||||
d="m 251.98568,878.63831 -14.02447,24.29109 h -28.04894 l -14.02447,-24.29109 14.02447,-24.2911 h 28.04894 z" />
|
|
||||||
<use
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
xlink:href="#rect5884"
|
|
||||||
id="use4252"
|
|
||||||
transform="rotate(60,268.29786,489.4515)"
|
|
||||||
width="100%"
|
|
||||||
height="100%" />
|
|
||||||
<rect
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.6507937;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
|
||||||
id="rect4254"
|
|
||||||
width="5.3947482"
|
|
||||||
height="115.12564"
|
|
||||||
x="545.71014"
|
|
||||||
y="467.07007"
|
|
||||||
transform="rotate(30,575.23539,-154.13386)" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer3"
|
|
||||||
inkscape:label="gradient-logo"
|
|
||||||
style="display:inline;opacity:1"
|
|
||||||
sodipodi:insensitive="true"
|
|
||||||
transform="translate(-156.33871,933.1905)">
|
|
||||||
<path
|
|
||||||
sodipodi:nodetypes="cccccccccc"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path3336-6"
|
|
||||||
d="m 309.54892,-710.38827 122.19683,211.67512 -56.15706,0.5268 -32.6236,-56.8692 -32.85645,56.5653 -27.90237,-0.011 -14.29086,-24.6896 46.81047,-80.4901 -33.22946,-57.8257 z"
|
|
||||||
style="opacity:1;fill:url(#linearGradient4328);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
|
||||||
<use
|
|
||||||
height="100%"
|
|
||||||
width="100%"
|
|
||||||
transform="rotate(60,407.11155,-715.78724)"
|
|
||||||
id="use3439-6"
|
|
||||||
inkscape:transform-center-y="151.59082"
|
|
||||||
inkscape:transform-center-x="124.43045"
|
|
||||||
xlink:href="#path3336-6"
|
|
||||||
y="0"
|
|
||||||
x="0" />
|
|
||||||
<use
|
|
||||||
height="100%"
|
|
||||||
width="100%"
|
|
||||||
transform="rotate(-60,407.31177,-715.70016)"
|
|
||||||
id="use3445-0"
|
|
||||||
inkscape:transform-center-y="75.573958"
|
|
||||||
inkscape:transform-center-x="-168.20651"
|
|
||||||
xlink:href="#path3336-6"
|
|
||||||
y="0"
|
|
||||||
x="0" />
|
|
||||||
<use
|
|
||||||
height="100%"
|
|
||||||
width="100%"
|
|
||||||
transform="rotate(180,407.41868,-715.7565)"
|
|
||||||
id="use3449-5"
|
|
||||||
inkscape:transform-center-y="-139.94592"
|
|
||||||
inkscape:transform-center-x="59.669705"
|
|
||||||
xlink:href="#path3336-6"
|
|
||||||
y="0"
|
|
||||||
x="0" />
|
|
||||||
<path
|
|
||||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient4330);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
|
||||||
d="m 309.54892,-710.38827 122.19683,211.67512 -56.15706,0.5268 -32.6236,-56.8692 -32.85645,56.5653 -27.90237,-0.011 -14.29086,-24.6896 46.81047,-80.4901 -33.22946,-57.8256 z"
|
|
||||||
id="path4260-0"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
sodipodi:nodetypes="cccccccccc" />
|
|
||||||
<use
|
|
||||||
height="100%"
|
|
||||||
width="100%"
|
|
||||||
transform="rotate(120,407.33916,-716.08356)"
|
|
||||||
id="use4354-5"
|
|
||||||
xlink:href="#path4260-0"
|
|
||||||
y="0"
|
|
||||||
x="0"
|
|
||||||
style="display:inline" />
|
|
||||||
<use
|
|
||||||
height="100%"
|
|
||||||
width="100%"
|
|
||||||
transform="rotate(-120,407.28823,-715.86995)"
|
|
||||||
id="use4362-2"
|
|
||||||
xlink:href="#path4260-0"
|
|
||||||
y="0"
|
|
||||||
x="0"
|
|
||||||
style="display:inline" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
@ -1 +0,0 @@
|
|||||||
<svg height="16" width="16"><path d="M4.003 4h1 .031a1.04 1.04 0 0 1 .687.312l2.28 2.281 2.312-2.281c.266-.23.446-.305.687-.312h1v1c0 .286-.034.551-.25.75l-2.28 2.281 2.249 2.25c.188.188.281.453.281.719v1h-1c-.265 0-.53-.093-.718-.281l-2.28-2.281-2.28 2.281c-.188.188-.453.281-.718.281h-1v-1c0-.265.093-.531.281-.719l2.28-2.25-2.28-2.281c-.211-.195-.303-.469-.281-.75z" fill="#363636"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 393 B |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
@ -1 +0,0 @@
|
|||||||
<svg height="16" width="16"><path d="M4 7v3h8V7z" fill="#363636"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 73 B |
|
Before Width: | Height: | Size: 202 KiB |
@ -1,3 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<path style="fill:#dfdfdf" d="M 1,8 C 1,11.866 4.134,15 8,15 9.9252,15 11.68,14.117 13,12.715 12.482,12.847 12.034,13 11.5,13 7.9101,13 5,10.09 5,6.5 5,4.267 6.1294,2.19 8,1 4.1145,1 1,4.134 1,8 Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 286 B |
@ -1,3 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<path style="fill:#dfdfdf" d="M 6.9999991,-6.4999999e-8 V 2.085937 a 6,6 0 0 1 1,-0.085937 6,6 0 0 1 1,0.08984 V -6.4999999e-8 Z M 3.0507801,1.6367189 1.6367181,3.050781 3.1132801,4.527344 a 6,6 0 0 1 1.416016,-1.41211 z m 9.8984379,0 -1.476563,1.4765621 a 6,6 0 0 1 1.41211,1.416016 L 14.36328,3.050781 Z M 7.9999991,3 a 5,5 0 0 0 -5,5 5,5 0 0 0 5,5 A 5,5 0 0 0 12.999999,8 5,5 0 0 0 7.9999991,3 Z m -8,4 v 2 h 2.085937 a 6,6 0 0 1 -0.08594,-1 6,6 0 0 1 0.08984,-1 z M 13.914061,7 a 6,6 0 0 1 0.08594,1 6,6 0 0 1 -0.08984,1 h 2.08984 V 7 Z m -10.7988279,4.470703 -1.478515,1.478516 1.414062,1.414062 1.476563,-1.476562 a 6,6 0 0 1 -1.41211,-1.416016 z m 9.7714849,0.002 a 6,6 0 0 1 -1.416016,1.41211 l 1.478516,1.478515 1.414062,-1.414062 z M 6.9999991,13.910156 V 16 h 2 v -2.085938 a 6,6 0 0 1 -1,0.08594 6,6 0 0 1 -1,-0.08984 z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 921 B |
@ -1,8 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<defs>
|
|
||||||
<style id="current-color-scheme" type="text/css">
|
|
||||||
.ColorScheme-Text { color:#dfdfdf; } .ColorScheme-Highlight { color:#4285f4; } .ColorScheme-NeutralText { color:#ff9800; } .ColorScheme-PositiveText { color:#4caf50; } .ColorScheme-NegativeText { color:#f44336; }
|
|
||||||
</style>
|
|
||||||
</defs>
|
|
||||||
<path style="fill:currentColor" class="ColorScheme-Text" d="M 7.736,0.9962 C 4.9732,1.0977 2.4273,2.8008 1.4235,5.5587 0.89934,6.999 0.87974,8.501 1.2653,9.875 1.669,8.557 2.7497,7.542 4.1032,7.192 4.2732,6.9013 4.4747,6.6319 4.693,6.3791 4.7035,5.6688 4.8234,4.9505 5.0797,4.2462 5.5939,2.8336 6.5542,1.7379 7.736,0.9962 Z M 8.086,5.7502 C 6.5323,5.7502 5.2096,6.7011 4.6403,8.047 3.1944,8.262 2.0856,9.494 2.0856,11 2.0856,12.657 3.4287,14 5.0856,14 H 11.461 C 12.91,14 14.086,12.825 14.086,11.375 14.086,10.028 13.073,8.924 11.765,8.774 11.424,7.054 9.906,5.7502 8.086,5.7502 Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 966 B |
@ -1,8 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<defs>
|
|
||||||
<style id="current-color-scheme" type="text/css">
|
|
||||||
.ColorScheme-Text { color:#dfdfdf; } .ColorScheme-Highlight { color:#4285f4; } .ColorScheme-NeutralText { color:#ff9800; } .ColorScheme-PositiveText { color:#4caf50; } .ColorScheme-NegativeText { color:#f44336; }
|
|
||||||
</style>
|
|
||||||
</defs>
|
|
||||||
<path style="fill:currentColor" class="ColorScheme-Text" d="M 7.736,0.9962 C 4.9732,1.0977 2.4273,2.8008 1.4235,5.5587 0.89934,6.999 0.87974,8.501 1.2653,9.875 1.669,8.557 2.7497,7.542 4.1032,7.192 4.2732,6.9013 4.4747,6.6319 4.693,6.3791 4.7035,5.6688 4.8234,4.9505 5.0797,4.2462 5.5939,2.8336 6.5542,1.7379 7.736,0.9962 Z M 8.086,5.7502 C 6.5323,5.7502 5.2096,6.7011 4.6403,8.047 3.1944,8.262 2.0856,9.494 2.0856,11 2.0856,12.657 3.4287,14 5.0856,14 H 11.461 C 12.91,14 14.086,12.825 14.086,11.375 14.086,10.028 13.073,8.924 11.765,8.774 11.424,7.054 9.906,5.7502 8.086,5.7502 Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 966 B |
@ -1,4 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<path style="fill:#dfdfdf" d="M 13.5,16 C 14.88,16 16,14.88 16,13.5 16,12.23 15.04,11.19 13.81,11.03 13.41,9.86 12.31,9 11,9 9.69,9 8.6,9.86 8.19,11.03 6.96,11.19 6,12.23 6,13.5 6,14.88 7.12,16 8.5,16"/>
|
|
||||||
<path style="fill:#dfdfdf" d="M 8,1 C 4.1145,0.999 1,4.134 1,8 1,10.841 2.6956,13.28 5.127,14.377 5.0526,14.095 5,13.804 5,13.5 5,12.309 5.6566,11.348 6.5957,10.758 5.6043,9.6168 5,8.1303 5,6.5 5.0014,4.267 6.1294,2.19 8,1 Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 519 B |
@ -1,3 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<path style="fill:#dfdfdf" d="M 7 0 L 7 2.0859375 A 6 6 0 0 1 8 2 A 6 6 0 0 1 9 2.0898438 L 9 0 L 7 0 z M 3.0507812 1.6367188 L 1.6367188 3.0507812 L 3.1132812 4.5273438 A 6 6 0 0 1 4.5292969 3.1152344 L 3.0507812 1.6367188 z M 12.949219 1.6367188 L 11.472656 3.1132812 A 6 6 0 0 1 12.884766 4.5292969 L 14.363281 3.0507812 L 12.949219 1.6367188 z M 8 3 A 5 5 0 0 0 3 8 A 5 5 0 0 0 5.2949219 12.205078 C 5.713317 11.305716 6.5416242 10.637052 7.5234375 10.322266 C 8.1696152 9.0017204 9.4227843 8 11 8 C 11.732994 8 12.393594 8.2229024 12.958984 8.5878906 A 5 5 0 0 0 13 8 A 5 5 0 0 0 8 3 z M 0 7 L 0 9 L 2.0859375 9 A 6 6 0 0 1 2 8 A 6 6 0 0 1 2.0898438 7 L 0 7 z M 13.914062 7 A 6 6 0 0 1 14 8 A 6 6 0 0 1 13.910156 9 L 16 9 L 16 7 L 13.914062 7 z M 11 9 C 9.69 9 8.5994531 9.8592969 8.1894531 11.029297 C 6.9594531 11.189297 6 12.23 6 13.5 C 6 14.88 7.12 16 8.5 16 L 13.5 16 C 14.88 16 16 14.88 16 13.5 C 16 12.23 15.040547 11.189297 13.810547 11.029297 C 13.410547 9.8592969 12.31 9 11 9 z M 3.1152344 11.470703 L 1.6367188 12.949219 L 3.0507812 14.363281 L 4.5273438 12.886719 A 6 6 0 0 1 3.1152344 11.470703 z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1,3 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<path style="opacity:0.3;fill:#dfdfdf" d="M 2 1 C 1.446 1 1 1.446 1 2 C 1 2.554 1.446 3 2 3 L 8 3 C 8.554 3 9 2.554 9 2 C 9 1.446 8.554 1 8 1 L 2 1 z M 5 5 C 4.446 5 4 5.446 4 6 C 4 6.554 4.446 7 5 7 L 15 7 C 15.554 7 16 6.554 16 6 C 16 5.446 15.554 5 15 5 L 5 5 z M 1 9 C 0.446 9 0 9.446 0 10 C 0 10.554 0.446 11 1 11 L 12 11 C 12.554 11 13 10.554 13 10 C 13 9.446 12.554 9 12 9 L 1 9 z M 3 13 C 2.446 13 2 13.446 2 14 C 2 14.554 2.446 15 3 15 L 15 15 C 15.554 15 16 14.554 16 14 C 16 13.446 15.554 13 15 13 L 3 13 z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 607 B |
@ -1,9 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<defs>
|
|
||||||
<style id="current-color-scheme" type="text/css">
|
|
||||||
.ColorScheme-Text { color:#dfdfdf; } .ColorScheme-Highlight { color:#4285f4; } .ColorScheme-NeutralText { color:#ff9800; } .ColorScheme-PositiveText { color:#4caf50; } .ColorScheme-NegativeText { color:#f44336; }
|
|
||||||
</style>
|
|
||||||
</defs>
|
|
||||||
<path style="fill:currentColor" class="ColorScheme-Text" d="M 8,0 C 5.929,0 4.165,1.27 3.406,3.07 1.478,3.35 0,5 0,7 0,8.94 1.365,10.54 3.187,10.91 3.951,10.13 4.709,9.35 5.5,8.6 6.073,9.14 6.633,9.7 7.187,10.25 7.43,10.18 7.57,9.41 7.906,9.16 8.76,8.29 9.615,7.43 10.5,6.6 11.166,7.22 11.791,7.86 12.437,8.5 13.035,9.07 13.665,9.71 13.875,10.53 13.891,10.59 13.893,10.64 13.906,10.69 15.141,10.15 16,8.94 16,7.5 16,5.71 14.649,4.23 12.906,4.03 12.451,1.74 10.427,0 8,0 Z M 10.5,9.44 C 10.415,9.52 10.335,9.61 10.25,9.69 9.853,10.11 9.351,10.47 9.125,11 H 11.906 C 11.88,10.94 11.85,10.87 11.812,10.82 11.439,10.3 10.933,9.9 10.5,9.44 Z"/>
|
|
||||||
<path style="fill:currentColor" class="ColorScheme-Highlight" d="M 10.5,8 10.156,8.34 8.75,9.75 C 8.297,10.2 8,10.81 8,11.5 8,12.87 9.125,14 10.5,14 11.875,14 13,12.87 13,11.5 13,10.81 12.703,10.2 12.25,9.75 L 10.844,8.34 Z M 5.5,10 5.156,10.34 3.75,11.75 C 3.297,12.2 3,12.81 3,13.5 3,14.87 4.125,16 5.5,16 6.875,16 8,14.87 8,13.5 8,12.81 7.703,12.2 7.25,11.75 L 5.844,10.34 Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB |
@ -1,4 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<path style="fill:#fcc467" d="M 10,8 C 8.69,8 7.6,8.86 7.19,10.03 5.96,10.19 5,11.23 5,12.5 5,13.88 6.12,15 7.5,15 H 12.5 C 13.88,15 15,13.88 15,12.5 15,11.23 14.04,10.19 12.81,10.03 12.41,8.86 11.31,8 10,8 Z"/>
|
|
||||||
<path style="fill:#dfdfdf" d="M 8,0 C 5.93,0 4.1702,1.2705 3.4102,3.0605 1.4802,3.3505 0,4.99 0,7 0,9.21 1.79,11 4,11 H 4.3945 C 4.8388,10.204 5.6169,9.6129 6.5234,9.3223 7.1696,8.0017 8.4228,7 10,7 11.573,7 12.83,7.9972 13.473,9.3203 13.983,9.4834 14.453,9.7437 14.848,10.08 15.551,9.4395 16,8.5242 16,7.5 16,5.7 14.65,4.2293 12.91,4.0293 12.45,1.7393 10.43,0 8,0 Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 669 B |
@ -1,8 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<defs>
|
|
||||||
<style id="current-color-scheme" type="text/css">
|
|
||||||
.ColorScheme-Text { color:#dfdfdf; } .ColorScheme-Highlight { color:#4285f4; } .ColorScheme-NeutralText { color:#ff9800; } .ColorScheme-PositiveText { color:#4caf50; } .ColorScheme-NegativeText { color:#f44336; }
|
|
||||||
</style>
|
|
||||||
</defs>
|
|
||||||
<path style="fill:currentColor" class="ColorScheme-Text" d="M 8,1 C 5.9289,1 4.1653,2.2679 3.4062,4.0625 1.4784,4.3491 0,5.9924 0,8 0,10.209 1.7909,12 4,12 H 4.4062 C 4.8601,11.199 5.6472,10.573 6.5312,10.313 7.151,8.99 8.506,7.974 10,8 11.908,7.969 13.582,9.485 13.875,11.344 14.018,11.389 14.144,11.435 14.281,11.5 15.312,10.891 16,9.784 16,8.5 16,6.7035 14.649,5.2313 12.906,5.0312 12.452,2.7379 10.427,1 8,1 Z M 10,9 C 8.688,9 7.595,9.858 7.188,11.031 5.9567,11.187 5,12.227 5,13.5 5,14.881 6.1193,16 7.5,16 H 13 C 14.105,16 15,15.105 15,14 15,12.895 14.105,12 13,12 13,10.343 11.657,9 10,9 Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 982 B |
@ -1,4 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<path style="fill:#dfdfdf" d="M 8,0 C 5.93,0 4.17,1.27 3.41,3.06 1.48,3.35 0,4.99 0,7 0,7.73 0.2,8.41 0.54,9 H 0.52 C 1.08,9.97 2.04,10.68 3.17,10.91 L 5.5,8.58 7.25,10.33 C 7.43,9.84 7.69,9.39 8.04,9.04 L 10.5,6.58 12.96,9.04 C 13.4,9.48 13.73,10.05 13.89,10.69 H 13.91 V 10.69 L 13.92,10.68 H 13.93 L 13.94,10.67 C 15.16,10.12 16,8.92 16,7.5 16,5.7 14.65,4.23 12.91,4.03 12.45,1.74 10.43,0 8,0 Z"/>
|
|
||||||
<path style="fill:#dfdfdf" d="M 10.5,8 8.75,9.75 C 8.3,10.2 8,10.81 8,11.5 8,12.87 9.13,14 10.5,14 11.87,14 13,12.87 13,11.5 13,10.81 12.7,10.2 12.25,9.75 Z M 5.5,10 3.75,11.75 C 3.3,12.2 3,12.81 3,13.5 3,14.87 4.13,16 5.5,16 6.87,16 8,14.87 8,13.5 8,12.81 7.7,12.2 7.25,11.75 Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 770 B |
@ -1,4 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<path style="fill:#dfdfdf" d="M 8,0 C 5.93,0 4.17,1.27 3.41,3.06 1.48,3.35 0,4.99 0,7 0,9.21 1.79,11 4,11 H 12.5 C 14.43,11 16,9.43 16,7.5 16,5.7 14.65,4.23 12.91,4.03 12.45,1.74 10.43,0 8,0 Z"/>
|
|
||||||
<path style="fill:#dfdfdf" d="M 2.9766,11.994 A 0.5,0.5 0 0 0 2.5527,12.277 L 1.5527,14.277 A 0.5,0.5 0 1 0 2.4473,14.723 L 3.4473,12.723 A 0.5,0.5 0 0 0 2.9766,11.994 Z M 5.4766,11.994 A 0.5,0.5 0 0 0 5.0527,12.277 L 4.0527,14.277 A 0.5,0.5 0 1 0 4.9473,14.723 L 5.9473,12.723 A 0.5,0.5 0 0 0 5.4766,11.994 Z M 7.9766,11.994 A 0.5,0.5 0 0 0 7.5527,12.277 L 6.5527,14.277 A 0.5,0.5 0 1 0 7.4473,14.723 L 8.4473,12.723 A 0.5,0.5 0 0 0 7.9766,11.994 Z M 10.477,11.994 A 0.5,0.5 0 0 0 10.053,12.277 L 9.0527,14.277 A 0.5,0.5 0 1 0 9.9473,14.723 L 10.947,12.723 A 0.5,0.5 0 0 0 10.477,11.994 Z M 12.977,11.994 A 0.5,0.5 0 0 0 12.553,12.277 L 11.553,14.277 A 0.5,0.5 0 1 0 12.447,14.723 L 13.447,12.723 A 0.5,0.5 0 0 0 12.977,11.994 Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1016 B |
@ -1,8 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<defs>
|
|
||||||
<style id="current-color-scheme" type="text/css">
|
|
||||||
.ColorScheme-Text { color:#dfdfdf; } .ColorScheme-Highlight { color:#4285f4; } .ColorScheme-NeutralText { color:#ff9800; } .ColorScheme-PositiveText { color:#4caf50; } .ColorScheme-NegativeText { color:#f44336; }
|
|
||||||
</style>
|
|
||||||
</defs>
|
|
||||||
<path style="fill:currentColor" class="ColorScheme-Text" d="M 8,0.004 C 5.9289,0.004 4.1653,1.2719 3.4062,3.0665 1.4784,3.3531 0,4.9964 0,7.004 0,9.213 1.7909,11.004 4,11.004 H 12.5 C 14.433,11.004 16,9.437 16,7.504 16,5.7075 14.649,4.2353 12.906,4.0353 12.452,1.7419 10.427,0.004 8,0.004 Z M 3.4785,11.992 A 0.50005,0.50005 0 0 0 3.0527,12.275 L 2.0527,14.275 A 0.50025,0.50025 0 0 0 2.9473,14.723 L 3.9473,12.723 A 0.50005,0.50005 0 0 0 3.4785,11.992 Z M 6.4785,11.994 A 0.50005,0.50005 0 0 0 6.0527,12.277 L 5.0527,14.277 A 0.50025,0.50025 0 1 0 5.9473,14.725 L 6.9473,12.725 A 0.50005,0.50005 0 0 0 6.4785,11.994 Z M 11,12 A 1,1 0 0 0 10,13 1,1 0 0 0 11,14 1,1 0 0 0 12,13 1,1 0 0 0 11,12 Z M 9,14 A 1,1 0 0 0 8,15 1,1 0 0 0 9,16 1,1 0 0 0 10,15 1,1 0 0 0 9,14 Z M 13,14 A 1,1 0 0 0 12,15 1,1 0 0 0 13,16 1,1 0 0 0 14,15 1,1 0 0 0 13,14 Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1,8 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<defs>
|
|
||||||
<style id="current-color-scheme" type="text/css">
|
|
||||||
.ColorScheme-Text { color:#dfdfdf; } .ColorScheme-Highlight { color:#4285f4; } .ColorScheme-NeutralText { color:#ff9800; } .ColorScheme-PositiveText { color:#4caf50; } .ColorScheme-NegativeText { color:#f44336; }
|
|
||||||
</style>
|
|
||||||
</defs>
|
|
||||||
<path style="fill:currentColor" class="ColorScheme-Text" d="M 8,0 C 5.9289,0 4.1653,1.2679 3.4062,3.0625 1.4784,3.3491 0,4.9924 0,7 0,9.209 1.7909,11 4,11 H 5.1855 C 5.6024,9.842 6.7062,9 8,9 9.294,9 10.398,9.842 10.814,11 H 12.5 C 14.433,11 16,9.433 16,7.5 16,5.7035 14.649,4.2313 12.906,4.0312 12.452,1.7379 10.427,0 8,0 Z M 8,10 A 2,2 0 0 0 6,12 2,2 0 0 0 8,14 2,2 0 0 0 10,12 2,2 0 0 0 8,10 Z M 3,12 A 2,2 0 0 0 1,14 2,2 0 0 0 3,16 2,2 0 0 0 5,14 2,2 0 0 0 3,12 Z M 13,12 A 2,2 0 0 0 11,14 2,2 0 0 0 13,16 2,2 0 0 0 15,14 2,2 0 0 0 13,12 Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 929 B |
@ -1,8 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<defs>
|
|
||||||
<style id="current-color-scheme" type="text/css">
|
|
||||||
.ColorScheme-Text { color:#dfdfdf; } .ColorScheme-Highlight { color:#4285f4; } .ColorScheme-NeutralText { color:#ff9800; } .ColorScheme-PositiveText { color:#4caf50; } .ColorScheme-NegativeText { color:#f44336; }
|
|
||||||
</style>
|
|
||||||
</defs>
|
|
||||||
<path style="fill:currentColor" class="ColorScheme-Text" d="M 8,0.004 C 5.9289,0.004 4.1653,1.2719 3.4062,3.0665 1.4784,3.3531 0,4.9964 0,7.004 0,9.213 1.7909,11.004 4,11.004 H 12.5 C 14.433,11.004 16,9.437 16,7.504 16,5.7075 14.649,4.2353 12.906,4.0353 12.452,1.7419 10.427,0.004 8,0.004 Z M 4,12 A 1,1 0 0 0 3,13 1,1 0 0 0 4,14 1,1 0 0 0 5,13 1,1 0 0 0 4,12 Z M 8,12 A 1,1 0 0 0 7,13 1,1 0 0 0 8,14 1,1 0 0 0 9,13 1,1 0 0 0 8,12 Z M 12,12 A 1,1 0 0 0 11,13 1,1 0 0 0 12,14 1,1 0 0 0 13,13 1,1 0 0 0 12,12 Z M 2,14 A 1,1 0 0 0 1,15 1,1 0 0 0 2,16 1,1 0 0 0 3,15 1,1 0 0 0 2,14 Z M 6,14 A 1,1 0 0 0 5,15 1,1 0 0 0 6,16 1,1 0 0 0 7,15 1,1 0 0 0 6,14 Z M 10,14 A 1,1 0 0 0 9,15 1,1 0 0 0 10,16 1,1 0 0 0 11,15 1,1 0 0 0 10,14 Z M 14,14 A 1,1 0 0 0 13,15 1,1 0 0 0 14,16 1,1 0 0 0 15,15 1,1 0 0 0 14,14 Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1,9 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<defs>
|
|
||||||
<style id="current-color-scheme" type="text/css">
|
|
||||||
.ColorScheme-Text { color:#dfdfdf; } .ColorScheme-Highlight { color:#4285f4; } .ColorScheme-NeutralText { color:#ff9800; } .ColorScheme-PositiveText { color:#4caf50; } .ColorScheme-NegativeText { color:#f44336; }
|
|
||||||
</style>
|
|
||||||
</defs>
|
|
||||||
<path style="fill:currentColor" class="ColorScheme-Text" d="M 8,0 C 5.93,0 4.17,1.27 3.41,3.07 1.48,3.35 0,5 0,7 0,9.21 1.79,11 4,11 L 6,11 6,8.5 C 6,7.67 6.67,7 7.5,7 8.33,7 9,7.67 9,8.5 l 0,2.5 3.5,0 C 14.43,11 16,9.44 16,7.5 16,5.71 14.65,4.23 12.91,4.03 12.45,1.74 10.43,0 8,0 Z"/>
|
|
||||||
<path style="fill:currentColor" class="ColorScheme-Highlight" d="m 7.34,8.029287 c -0.2,0.07 -0.35,0.28 -0.34,0.5 l 0,3.78 -0.03,0.09 -0.63,0.63 -0.03,0 -1.81,0 -0.22,0 -0.12,0.16 -1,1 c -0.26,0.15 -0.31,0.56 -0.1,0.78 0.22,0.21 0.63,0.16 0.78,-0.1 l 0.85,-0.84 1.31,0 0,1.4 c 0,0.26 0.24,0.51 0.5,0.51 0.26,0 0.5,-0.25 0.5,-0.51 l 0,-1.71 0.69,-0.69 2.12,0 0.75,0.75 -1.4,1.31 c -0.26,0.15 -0.31,0.56 -0.1,0.78 0.22,0.21 0.63,0.16 0.78,-0.1 l 1.41,-1.3 1.41,1.3 c 0.15,0.26 0.56,0.31 0.78,0.1 0.21,-0.22 0.16,-0.63 -0.1,-0.78 l -3,-2.9 -0.12,-0.16 -0.22,0 -2,0 0,-3.5 c 0,-0.3 -0.3,-0.56 -0.59,-0.5 z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1,3 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
|
||||||
<path style="fill:#dfdfdf" d="M 8,16 C 8,16 7,16 7,15 7,14 8,14 8,14 8,14 9,14 9,13 9,12 8,12 8,12 H 1 C 1,12 0,12 0,11 0,10 1,10 1,10 H 8 C 8,10 11,10 11,13 11,16 8,16 8,16 Z M 13,3 C 13,3 12,3 12,4 12,5 13,5 13,5 13,5 14,5 14,6 14,7 13,7 13,7 H 5 C 5,7 4,7 4,8 4,9 5,9 5,9 H 13 C 13,9 16,9 16,6 16,3 13,3 13,3 Z M 8,0 C 8,0 7,0 7,1 7,2 8,2 8,2 8,2 9,2 9,3 9,4 8,4 8,4 H 1 C 1,4 0,4 0,5 0,6 1,6 1,6 H 8 C 8,6 11,6 11,3 11,0 8,0 8,0 Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 524 B |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 25 KiB |
@ -1,17 +0,0 @@
|
|||||||
local m = {}
|
|
||||||
m.type = "dark"
|
|
||||||
m.name = 'biscuit'
|
|
||||||
m.ok = "#989F56"
|
|
||||||
m.warn = "#E46A3A"
|
|
||||||
m.err = "#CA3F3F"
|
|
||||||
m.dis = "#9F569A"
|
|
||||||
m.pri = "#629386"
|
|
||||||
m.bg = "#181515"
|
|
||||||
m.mbg = "#211b1b"
|
|
||||||
m.bg3 = "#2d2424"
|
|
||||||
m.bg4 = "#352a2a"
|
|
||||||
m.fg = "#ffe9c7"
|
|
||||||
m.fg3 = "#D5CAC3"
|
|
||||||
m.fg2 = "#E5D8CB"
|
|
||||||
m.fg4 = "#614f4f"
|
|
||||||
return m
|
|
||||||