Comments (5)
I am using following scripts to manage spaces between windows:
- when stacked, add left padding 40px
- When not stacked, use 8px padding
yabairc
yabai -m signal --add event=window_created action="~/.config/yabai/refresh.sh"
yabai -m signal --add event=window_destroyed action="~/.config/yabai/refresh.sh"
refresh.sh
#!/usr/bin/env bash
number_of_windows=$(yabai -m query --windows --space | ~/.nix-profile/bin/jq 'length')
number_of_stacked=$(yabai -m query --windows --space | ~/.nix-profile/bin/jq -c 'map(select(."stack-index" != 0)) | length')
padding=8
lpadding=40
[[ "$number_of_windows" -eq 1 ]] && padding=0
[[ "$number_of_stacked" = 0 ]] && lpadding=$padding
yabai -m config --space mouse top_padding $padding
yabai -m config --space mouse bottom_padding $padding
yabai -m config --space mouse left_padding $lpadding
yabai -m config --space mouse right_padding $padding
yabai -m config --space mouse window_gap $padding
from stackline.
this works also for the current focused window – independent of where the mouse is at the point:
#!/usr/bin/env sh
number_of_windows=$(yabai -m query --windows --space | /usr/local/bin/jq 'length')
number_of_stacked=$(yabai -m query --windows --space | /usr/local/bin/jq -c 'map(select(."stack-index" != 0)) | length')
currspace=$(yabai -m query --spaces --space | /usr/local/bin/jq '.index')
padding=8
spadding=40
[[ "$number_of_windows" -eq 1 ]] && padding=0
[[ "$number_of_stacked" = 0 ]] && spadding=$padding
yabai -m config --space "$currspace" top_padding $padding
yabai -m config --space "$currspace" bottom_padding $padding
yabai -m config --space "$currspace" left_padding $spadding
yabai -m config --space "$currspace" right_padding $spadding
yabai -m config --space "$currspace" window_gap $padding
from stackline.
@jzelner I've definitely had this same thought!
I'm still working on refactoring for testability. I don't quite see the light at the end of the tunnel yet, but hope to be able to wrap this up shortly after the new year.
In parallel, I've been day-dreaming about rewriting stackline
using a state-machine-esque component model:
- Add a base
component
class that- has a
registerHandler
method that accepts anonChange
function to be called with the old/new state whenever the component's state changes - uses lua's metamethod magic to automatically call all registered
onChange
handlers whenever the component's state changes (inspired by https://github.com/Phrogz/notifitable, but I was able to implement the desired behavior in a much simpler way)
- has a
- Rewrite
stackmanager
stack
,window
, andindicator
classes as subclasses ofcomponent
- Simplify the scarily complicated logic here using rules inspired by state machines. (Of all the ideas so far, this has the highest risk of failing to meet expectations. I'm kind of assuming / hoping that reliable/omnipresent
onChange
handlers will make it possible to simplify that mess) - Expose a public API for end-users to easily register
onSomethingChange
handlers that perform an action when a)stackline
state changes or b) key window management events (such as switching the active space) occur.
Let's tie that ramble together with your idea:
I think that the changes above would make it trivial to implement your suggestion:
- On space change:
- if stack length is zero, execute
yabai
command to set left & right padding to X - otherwise, execute
yabai
command to set left & right padding tostackling.config.appearance.size + X
- if stack length is zero, execute
Since waiting is no fun, below is a snippet that you can place in your ~/.hammerspoon/init.lua
file to get an idea how this might work.
The result is pretty janky, but it should give you an idea.
If you're constantly switching spaces (like I am), the window jitter this causes isn't worth the extra real estate on spaces that don't have any stacked windows. You might be able to minimize the jank by independently maintaining state (e.g., {spaceHasStacks = { 1 = false, 2 = true, 3 = false}
) that's only updated when necessary. I'm not even sure that would help much: I don't think yabai
supports per-space padding, so you'll still need to call out to yabai
when changing to a space with hasStack
value that differs from the previous space.
local function yabai(cmd)
local output
-- NOTE: requires string:split() defined at /stackline/lib/utils.lua:16
local args = cmd:split(' ')
hs.task.new(
stackline.config:get('paths.yabai'),
function(_, stdOut) output = stdOut end,
args
):start():waitUntilExit()
return output
end
local function sidePadding(val)
yabai(string.format('-m config left_padding %s', val))
yabai(string.format('-m config right_padding %s', val))
end
-- See https://www.hammerspoon.org/docs/hs.spaces.watcher.html
hs.spaces.watcher.new(function()
-- Set space padding for each case
-- 'big' is dynamically determined based on current size of stack indicators
-- NOTE: Assumes `showIcons = true`. Should probably factor out function
-- that dynamically determines indicator width:/stackline/stackline/window.lua:45
local small = 10
local big = stackline.config:get('appearance.size') + small
if stackline.manager then -- ensure stackline is initiated
-- Hack: we need to wait ~0.5s before updating padding to ensure that
-- stackline state has finished updating. Otherwise, we'll set the new
-- space's padding based on whether the *previous* space had stacks ☹️
-- The appropriate delay will depend on your personal system's speed.
hs.timer.doAfter(0.4, function()
-- Get number of stacks on current space
-- Remember that running this on space change without a delay gives us outdated data
local stackCount = #stackline.manager:get()
-- DEBUG: uncomment to show notification w/ # of stacks on space change
-- local msg = string.format('This space has %s stacks', stackCount)
-- hs.notify.show('stackline', msg, '')
-- Set the appropriate padding
sidePadding(stackCount > 0 and big or small)
end)
end
end):start()
There might be a better way. Would love to hear any ideas you might have, @jzelner
from stackline.
FYI Yabai does support per-space padding so you can adjust the sidePadding
function of your script to:
local function sidePadding(val)
local space = hs.json.decode(yabai('-m query --spaces --space'))
local space_index = space['index']
yabai(string.format('-m config --space %s left_padding %s', space_index, val))
yabai(string.format('-m config --space %s right_padding %s', space_index, val))
end
This gets pretty good results, only downside I see is the required half a second delay.
from stackline.
@jzelner I've definitely had this same thought!
I'm still working on refactoring for testability. I don't quite see the light at the end of the tunnel yet, but hope to be able to wrap this up shortly after the new year.
In parallel, I've been day-dreaming about rewriting
stackline
using a state-machine-esque component model:
Add a base
component
class that
- has a
registerHandler
method that accepts anonChange
function to be called with the old/new state whenever the component's state changes- uses lua's metamethod magic to automatically call all registered
onChange
handlers whenever the component's state changes (inspired by https://github.com/Phrogz/notifitable, but I was able to implement the desired behavior in a much simpler way)Rewrite
stackmanager
stack
,window
, andindicator
classes as subclasses ofcomponent
Simplify the scarily complicated logic here using rules inspired by state machines. (Of all the ideas so far, this has the highest risk of failing to meet expectations. I'm kind of assuming / hoping that reliable/omnipresent
onChange
handlers will make it possible to simplify that mess)Expose a public API for end-users to easily register
onSomethingChange
handlers that perform an action when a)stackline
state changes or b) key window management events (such as switching the active space) occur.Let's tie that ramble together with your idea:
I think that the changes above would make it trivial to implement your suggestion:
On space change:
- if stack length is zero, execute
yabai
command to set left & right padding to X- otherwise, execute
yabai
command to set left & right padding tostackling.config.appearance.size + X
Since waiting is no fun, below is a snippet that you can place in your
~/.hammerspoon/init.lua
file to get an idea how this might work.The result is pretty janky, but it should give you an idea.
If you're constantly switching spaces (like I am), the window jitter this causes isn't worth the extra real estate on spaces that don't have any stacked windows. You might be able to minimize the jank by independently maintaining state (e.g.,
{spaceHasStacks = { 1 = false, 2 = true, 3 = false}
) that's only updated when necessary. I'm not even sure that would help much: I don't thinkyabai
supports per-space padding, so you'll still need to call out toyabai
when changing to a space withhasStack
value that differs from the previous space.local function yabai(cmd) local output -- NOTE: requires string:split() defined at /stackline/lib/utils.lua:16 local args = cmd:split(' ') hs.task.new( stackline.config:get('paths.yabai'), function(_, stdOut) output = stdOut end, args ):start():waitUntilExit() return output end local function sidePadding(val) yabai(string.format('-m config left_padding %s', val)) yabai(string.format('-m config right_padding %s', val)) end -- See https://www.hammerspoon.org/docs/hs.spaces.watcher.html hs.spaces.watcher.new(function() -- Set space padding for each case -- 'big' is dynamically determined based on current size of stack indicators -- NOTE: Assumes `showIcons = true`. Should probably factor out function -- that dynamically determines indicator width:/stackline/stackline/window.lua:45 local small = 10 local big = stackline.config:get('appearance.size') + small if stackline.manager then -- ensure stackline is initiated -- Hack: we need to wait ~0.5s before updating padding to ensure that -- stackline state has finished updating. Otherwise, we'll set the new -- space's padding based on whether the *previous* space had stacks ☹️ -- The appropriate delay will depend on your personal system's speed. hs.timer.doAfter(0.4, function() -- Get number of stacks on current space -- Remember that running this on space change without a delay gives us outdated data local stackCount = #stackline.manager:get() -- DEBUG: uncomment to show notification w/ # of stacks on space change -- local msg = string.format('This space has %s stacks', stackCount) -- hs.notify.show('stackline', msg, '') -- Set the appropriate padding sidePadding(stackCount > 0 and big or small) end) end end):start()There might be a better way. Would love to hear any ideas you might have, @jzelner
Hey, I was wondering if there was a way to just add a top padding in the stack column, as most of the time it's just the window control buttons being blocked. I don't really want a big left padding as my screen is not very big.
Thanks for this cool project btw!!
from stackline.
Related Issues (20)
- Stackline shows over windows HOT 1
- How do you move the icons to the top right corner?
- Multiple displays (monitors) issues HOT 4
- Not able to make stackline work for yabai HOT 2
- Indicator for the right stack is not visible HOT 1
- Trick — Trigger refreshes using `yabai -m signal` HOT 3
- Rewrite in a performant language e.g. Golang HOT 5
- Appearance configuration per display when using a display in portrait and one in landscape orientation
- Trick — Reduce redraw lag when switching spaces
- Stackline not showing up HOT 1
- Add guide to install it for yabai
- Unable to launch hs.task process HOT 2
- :w:wi
- Issue enabling stackline HOT 1
- Swift implementation
- [Bug] Stackline is not showing Icons on Stack mode HOT 5
- LICENSE file missing
- Merge init() configuration table with default configuration
- Please ignore this issue
- Auto-switch from pill to icon on hover? HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from stackline.