local constants = require 'constants' local settings = require 'config.settings' local utils = require 'utils' local spaces = {} local paddings = {} local focusedWorkspace = nil local swapWatcher = sbar.add('item', { drawing = false, updates = true, }) local currentWorkspaceWatcher = sbar.add('item', { drawing = false, updates = true, }) -- Modify this file with Visual Studio Code - at least vim does have problems with the icons -- copy "Icons" from the nerd fonts cheat sheet and replace icon and name accordingly below -- https://www.nerdfonts.com/cheat-sheet local spaceConfigs = { ['1'] = { icon = '󱞁', name = 'Main' }, ['2'] = { icon = '', name = '' }, ['3'] = { icon = '', name = '' }, ['4'] = { icon = '', name = '' }, ['5'] = { icon = '󰌾', name = 'Misc' }, ['6'] = { icon = '', name = '' }, ['7'] = { icon = '󰎆', name = 'Music' }, ['8'] = { icon = '󰇮', name = 'Mail' }, ['9'] = { icon = '󰭹', name = 'Chat' }, ['10'] = { icon = '󰖟', name = 'Browser' }, ['t'] = { icon = '', name = 'Meeting' }, } -- Track which workspaces have windows local workspaceHasWindows = {} local updateWorkspaceVisibility = utils.coro.async(function() local output = utils.coro.await(utils.coro.exec(constants.aerospace_cmd .. " list-windows --all --format '%{workspace}'")) -- Reset all for ws, _ in pairs(workspaceHasWindows) do workspaceHasWindows[ws] = false end -- Mark workspaces that have windows if output then for ws in output:gmatch '[^\r\n]+' do workspaceHasWindows[ws] = true end end -- Update visibility for each space for workspaceName, _ in pairs(spaceConfigs) do local spaceName = constants.items.SPACES .. '.' .. workspaceName local space = spaces[spaceName] local padding = paddings[spaceName] if space then local hasWindows = workspaceHasWindows[workspaceName] == true local isFocused = focusedWorkspace == workspaceName local shouldShow = hasWindows or isFocused space:set { drawing = shouldShow } if padding then padding:set { drawing = shouldShow } end end end end) local function selectCurrentWorkspace(focusedWorkspaceName) focusedWorkspace = focusedWorkspaceName for workspaceName, _ in pairs(spaceConfigs) do local spaceName = constants.items.SPACES .. '.' .. workspaceName local item = spaces[spaceName] local padding = paddings[spaceName] if item ~= nil then local isSelected = workspaceName == focusedWorkspaceName local hasWindows = workspaceHasWindows[workspaceName] == true local shouldShow = hasWindows or isSelected -- Show/hide based on windows or focus item:set { drawing = shouldShow, icon = { color = isSelected and settings.colors.bg1 or settings.colors.white }, label = { color = isSelected and settings.colors.bg1 or settings.colors.white }, background = { color = isSelected and settings.colors.white or settings.colors.bg1 }, } if padding then padding:set { drawing = shouldShow } end end end updateWorkspaceVisibility() sbar.trigger(constants.events.UPDATE_WINDOWS) end local findAndSelectCurrentWorkspace = utils.coro.async(function() local focusedWorkspaceOutput = utils.coro.await(utils.coro.exec(constants.aerospace.GET_CURRENT_WORKSPACE)) if focusedWorkspaceOutput then local focusedWorkspaceName = focusedWorkspaceOutput:match '[^\r\n]+' selectCurrentWorkspace(focusedWorkspaceName) end end) local function addWorkspaceItem(workspaceName) local spaceName = constants.items.SPACES .. '.' .. workspaceName local spaceConfig = spaceConfigs[workspaceName] -- Skip workspaces without a config entry if not spaceConfig then return end local hasIcon = spaceConfig.icon and spaceConfig.icon ~= '' local hasName = spaceConfig.name and spaceConfig.name ~= '' local icon = hasIcon and spaceConfig.icon or workspaceName local name = hasName and spaceConfig.name or workspaceName local useBold = not hasIcon local fontStyle = useBold and settings.fonts.styles.bold or settings.fonts.styles.regular local iconFont = settings.fonts.text .. ':' .. fontStyle .. ':' .. settings.dimens.text.icon spaces[spaceName] = sbar.add('item', spaceName, { drawing = false, -- start hidden, will show if has windows or is focused label = { width = 0, padding_left = 0, string = name, y_offset = 1, }, icon = { string = icon, font = iconFont, color = settings.colors.white, y_offset = 1, }, background = { color = settings.colors.bg1, }, click_script = constants.aerospace_cmd .. ' workspace ' .. workspaceName, }) spaces[spaceName]:subscribe('mouse.entered', function(env) sbar.animate('tanh', 30, function() spaces[spaceName]:set { label = { width = 'dynamic' } } end) end) spaces[spaceName]:subscribe('mouse.exited', function(env) sbar.animate('tanh', 30, function() spaces[spaceName]:set { label = { width = 0 } } end) end) paddings[spaceName] = sbar.add('item', spaceName .. '.padding', { drawing = false, width = settings.dimens.padding.label, }) end local createWorkspaces = utils.coro.async(function() local workspacesOutput = utils.coro.await(utils.coro.exec(constants.aerospace.LIST_ALL_WORKSPACES)) if workspacesOutput then for workspaceName in workspacesOutput:gmatch '[^\r\n]+' do addWorkspaceItem(workspaceName) end end findAndSelectCurrentWorkspace() end) swapWatcher:subscribe(constants.events.SWAP_MENU_AND_SPACES, function(env) local isShowingSpaces = env.isShowingMenu == 'off' and true or false if isShowingSpaces then updateWorkspaceVisibility() else sbar.set('/' .. constants.items.SPACES .. '\\..*/', { drawing = false }) end end) currentWorkspaceWatcher:subscribe(constants.events.AEROSPACE_WORKSPACE_CHANGED, function(env) selectCurrentWorkspace(env.FOCUSED_WORKSPACE) end) -- Also update on window changes currentWorkspaceWatcher:subscribe('front_app_switched', function(env) updateWorkspaceVisibility() end) createWorkspaces()