This commit is contained in:
Harrison DiAmbrosio 2026-03-12 16:27:39 -04:00
commit 9978efd6bc
3 changed files with 283 additions and 0 deletions

14
.luarc.json Normal file
View file

@ -0,0 +1,14 @@
{
"runtime.version": "LuaJIT",
"runtime.path": [
"lua/?.lua",
"lua/?/init.lua"
],
"diagnostics.globals": ["mez"],
"workspace.checkThirdParty": false,
"completion.autoRequire": false,
"workspace.library": [
"/usr/share/mez/runtime",
"./runtime"
]
}

1
README.md Normal file
View file

@ -0,0 +1 @@
# euclid.mez

268
lua/euclid/init.lua Normal file
View file

@ -0,0 +1,268 @@
---@module "mez_types"
---@class Euclid
---@field default_config EuclidConfig
---@field config EuclidConfig
---@field state EuclidState
local M = {}
local utils = {}
---@param view_id integer
---@return integer? view_idx
---@return integer? tag_idx
utils.find_view = function (view_id)
for tag_idx = 1, M.config.tag_count do
for view_idx, v in ipairs(M.state.tags[tag_idx].views) do
if v == view_id then
return view_idx, tag_idx
end
end
end
return nil, nil
end
---@class EuclidConfig
---@field mod_key string
---@field tag_count number
---@field focus_on_spawn boolean
---@field refocus_on_kill boolean
local default_config = {
mod_key = "alt",
tag_count = 5,
focus_on_spawn = true,
refocus_on_kill = true,
}
---@class EuclidTag
---@field views number[]
---@field last_focused number | nil
---@class EuclidState
---@field tag_id number
---@field tags EuclidTag[]
---Add the id of a new view
---@param view_id number
M.add_view = function(view_id)
local tag = M.state.tags[M.state.tag_id]
tag.views[#tag.views + 1] = view_id
local res = mez.output.get_available_area(0)
if res == nil then return end
mez.view.set_geometry(view_id, {
x = (0.25 / 2) * res.width,
y = (0.25 / 2) * res.height,
width = res.width * 0.75,
height = res.height * 0.75
})
if M.config.focus_on_spawn then mez.view.set_focused(view_id) end
end
---Move the focus in a tag to the next view
M.focus_next = function()
local view_id = mez.view.get_focused_id()
if view_id == nil then return end
local view_idx, tag_idx = utils.find_view(view_id)
if view_idx == nil or tag_idx == nil then return end
local tag = M.state.tags[tag_idx]
if view_idx == #tag.views then
mez.view.set_focused(tag.views[1])
else
mez.view.set_focused(tag.views[view_idx + 1])
end
end
---Move the focus in a tag to the previous view
M.focus_prev = function()
local view_id = mez.view.get_focused_id()
if view_id == nil then return end
local view_idx, tag_idx = utils.find_view(view_id)
if view_idx == nil or tag_idx == nil then return end
local tag = M.state.tags[tag_idx]
if view_idx == 1 then
mez.view.set_focused(tag.views[#tag.views])
else
mez.view.set_focused(tag.views[view_idx - 1])
end
end
---Remove a view_id from the layout
---@param view_id integer
M.remove_view = function(view_id)
local view_idx, tag_idx = utils.find_view(view_id)
if view_idx == nil or tag_idx == nil then return end
local tag = M.state.tags[tag_idx]
if M.config.refocus_on_kill then
if #tag.views == 0 then
mez.view.set_focused(nil)
else
mez.view.set_focused(tag.views[#tag.views == view_idx and view_idx - 1 or view_idx])
end
end
end
---Switch to a tag by enabling all views for 1 tag,
---and disabling all the views for the old tag
---@param tag_idx number
M.tag_enable = function (tag_idx)
---@param t number
---@param enabled boolean
local set_tag_enable = function (t, enabled)
local tag = M.state.tags[t]
local focused = mez.view.get_focused_id()
if not enabled and focused ~= nil then
tag.last_focused = focused
end
for _, v in ipairs(tag.views) do
mez.view.set_enabled(v, enabled)
end
end
set_tag_enable(M.state.tag_id, false)
set_tag_enable(tag_idx, true)
M.state.tag_id = tag_idx
end
---@param view_id number
---@param tag_id number
M.send_view = function (view_id, tag_id)
-- if view_id == 0 then view_id = mez.view.get_focused_id() end
-- if tag_id == M.state.tag_id then return end
--
-- local type, _, _ = utils.find_view(view_id)
--
-- local tag = M.state.tags[tag_id]
--
-- M.remove_view(view_id)
--
-- if type == "floating" then
-- table.insert(tag.floating, #tag.floating, view_id)
-- else
-- if tag.master == nil then
-- tag.master = view_id
-- else
-- table.insert(tag.stack, #tag.stack, view_id)
-- end
-- end
--
-- mez.view.set_enabled(view_id, false)
-- M.tile_tag(M.state.tag_id)
-- M.tile_tag(tag_id)
end
M.setup = function()
--- Take a user config
M.config = default_config
M.state = {
tag_id = 1,
tags = {},
}
-- Create all tags for the state
for i = 1, M.config.tag_count do
M.state.tags[i] = {
views = {},
last_focused = nil
}
end
mez.hook.add("ViewMapPre", { callback = function(view_id) M.add_view(view_id) end })
mez.hook.add("ViewUnmapPost", { callback = function(view_id) M.remove_view(view_id) end })
mez.input.add_keymap(M.config.mod_key, "j", { press = function () M.focus_next() end })
mez.input.add_keymap(M.config.mod_key, "k", { press = function () M.focus_prev() end })
local fullscreen = function() mez.view.toggle_fullscreen(0) end
mez.input.add_keymap(M.config.mod_key.."|shift", "F", { press = fullscreen })
mez.hook.add("ViewRequestFullscreen", { callback = fullscreen })
for i = 1, M.config.tag_count do
mez.input.add_keymap(M.config.mod_key, tostring(i), { press = function () M.tag_enable(i) end })
end
mez.input.add_mousemap(M.config.mod_key, "BTN_LEFT", {
press = function () return false end,
drag = function(view_id, pos, _, offset)
if view_id ~= nil then
mez.view.set_geometry(view_id, { x = pos.x - offset.x, y = pos.y - offset.y })
end
end
})
---@type {x: number, y: number}[]
local move_all = {}
mez.input.add_mousemap(M.config.mod_key, "BTN_MIDDLE", {
press = function ()
move_all = {}
for i, v in ipairs(M.state.tags[M.state.tag_id].views) do
local geo = mez.view.get_geometry(v)
move_all[i] = { x = geo.x, y = geo.y }
end
end,
drag = function(_, pos, start, offset)
for i, v in ipairs(M.state.tags[M.state.tag_id].views) do
local geo = move_all[i]
mez.view.set_geometry(v, {
x = geo.x + (pos.x - start.x),
y = geo.y + (pos.y - start.y)
})
end
end
})
mez.input.add_mousemap(M.config.mod_key, "BTN_RIGHT", {
drag = function(view_id, pos, start, offset)
if view_id ~= nil then
local geo = mez.view.get_geometry(view_id)
local width = offset.x + pos.x - start.x
local height = offset.y + pos.y - start.y
if width <= 10 then width = 10 end
if height <= 10 then height = 10 end
mez.view.set_geometry(view_id, { width = width, height = height })
end
end
})
mez.input.add_mousemap(M.config.mod_key, "REL_WHEEL", {
scroll = function (view_id, pos, delta, discrete_delta)
delta = -delta / 250;
mez.output.set_scale(0, mez.output.get_scale(0) + delta)
print(mez.output.get_scale(0))
end
})
mez.input.add_keymap(M.config.mod_key.."|shift", "equal", {
press = function ()
print("pressed")
local _, err = pcall(function ()
mez.output.set_scale(0, mez.output.get_scale(0) + 0.1)
print(mez.output.get_scale(0))
end)
if err then
print(err)
end
end
})
end
return M