Skip to content

Commit

Permalink
Consolidate CLI and config
Browse files Browse the repository at this point in the history
  • Loading branch information
vrde committed Feb 17, 2020
1 parent f662fd0 commit 28fa76a
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 38 deletions.
45 changes: 40 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,52 @@ This is accomplished by two scripts, one to enable *quiet-mode*, and another one

## Install

Make sure to install [`i3ipc-python`][3], then copy the two python scripts to your `.config/i3` directory, and configure `i3`. I use `mod+q` to move a window to the quiet workspace, and `mod+shift+q` to move it back to its original place. (I use `mod+Shift+backslash` to kill the focused window.)

My configuration looks like this:
Make sure to install [`i3ipc-python`][3], then copy the two python scripts to your `.config/i3` directory, and configure `i3`. I use `mod+q` to switch to the quiet workspace, and `mod+shift+q` to start the `quiet mode`, see the configuration below:

```
# Quiet mode
bindsym $mod+q exec $HOME/.config/i3/quiet-cmd.py
bindsym $mod+Shift+q exec $HOME/.config/i3/quiet-cmd.py toggle
mode "quiet" {
# These bindings trigger as soon as you enter the resize mode
# Move a window in and out the quiet mode
bindsym q exec ~/.config/i3/quiet-cmd.py toggle
# Resize the window in quiet mode
bindsym s exec ~/.config/i3/quiet-cmd.py resize small
bindsym m exec ~/.config/i3/quiet-cmd.py resize medium
bindsym l exec ~/.config/i3/quiet-cmd.py resize large
# back to normal: Enter or Escape or $mod+r
bindsym Return mode "default"
bindsym Caps_Lock mode "default"
bindsym $mod+d mode "default"
}
bindsym $mod+q exec $HOME/.config/i3/quiet-cmd.py switch
bindsym $mod+Shift+q mode "quiet"
exec_always $HOME/.config/i3/quiet-toggle-bar.py
```

You can also play with the script from the CLI:

```
➜ i3-quiet git:(improve-cli) ✗ ./quiet-cmd.py -h
usage: quiet-cmd.py [-h] {toggle,switch,resize} ...
Control i3-quiet.
optional arguments:
-h, --help show this help message and exit
subcommands:
valid subcommands
{toggle,switch,resize}
additional help
```


[1]: https://i3wm.org/docs/userguide.html#_toggling_fullscreen_mode_for_a_window
[2]: https://github.com/polybar/polybar/
[3]: https://github.com/altdesktop/i3ipc-python/
123 changes: 90 additions & 33 deletions quiet-cmd.py
Original file line number Diff line number Diff line change
@@ -1,70 +1,127 @@
#!/usr/bin/env python3

import argparse
import sys
import json
import subprocess
from subprocess import run, check_output
import os

ZEN_NUMBER = 99
ZEN_NAME = 'zen'
ZEN_WORKSPACE = '{}: {}'.format(ZEN_NUMBER, ZEN_NAME)

WIDTH_PERC=50
MAX_WIDTH=800
HEIGHT_PERC=90
MAX_HEIGHT=1024

SIZES = {
'small': [50, 70, 800, 800],
'medium': [65, 80, 1024, 1024],
'large': [90, 90, 1600, 1600],
}

ZEN_BORDER = 'none'
DEFAULT_BORDER = 'none'
DEFAULT_BORDER = 'normal'

ZEN_FILE_PATH = os.path.join(os.environ['HOME'], '.config/i3/.i3-quiet.json')


def enable_zen_mode(workspace):
width = round(min(workspace['rect']['width'] * WIDTH_PERC / 100, MAX_WIDTH))
height = round(min(workspace['rect']['height'] * HEIGHT_PERC / 100, MAX_HEIGHT))
workspace_name = '{}: {}'.format(ZEN_NUMBER, workspace['name'])
with open(ZEN_FILE_PATH, 'w') as zen_file:
json.dump(workspace, zen_file)
return ';'.join([
'move container to workspace {}'.format(workspace_name),
'workspace {}'.format(workspace_name),
msg = ';'.join([
'move container to workspace {}'.format(ZEN_WORKSPACE),
'workspace {}'.format(ZEN_WORKSPACE),
'floating enable',
'border {}'.format(ZEN_BORDER),
'resize set width {}'.format(width),
'resize set height {}'.format(height),
'move position center'
])
run(['i3-msg', msg])
layout = check_output(['i3-save-tree', '--workspace', ZEN_WORKSPACE])
msg = ';'.join([
'border {}'.format(ZEN_BORDER)
])
run(['i3-msg', msg])
layout = layout.decode()
layout = layout.split('\n')
layout = filter(lambda l: not l.strip().startswith('//'), layout)
layout = json.loads(''.join(layout))

with open(ZEN_FILE_PATH, 'w') as zen_file:
json.dump({'workspace': workspace, 'layout': layout}, zen_file)

def disable_zen_mode(workspace):
return ';'.join([
try:
with open(ZEN_FILE_PATH, 'r') as zen_file:
border = json.load(zen_file)['layout']['border']
except (FileNotFoundError, KeyError):
border = DEFAULT_BORDER

msg = ';'.join([
'move container to workspace number {}'.format(workspace['num']),
'workspace number {}'.format(workspace['num']),
'floating disable',
'border {}'.format(DEFAULT_BORDER)
'border {}'.format(border)
])
run(['i3-msg', msg])

def goto_zen(workspace_name):
return 'workspace {}'.format(workspace_name)
def resize(args):
cw, _, _= get_workspaces()
workspace_width = cw['rect']['width']
workspace_height = cw['rect']['height']
wp, hp, wm, hm = SIZES[args.size]
width = round(min(workspace_width * wp / 100, wm))
height = round(min(workspace_height * hp / 100, hm))
msg = ';'.join([
'resize set width {}'.format(width),
'resize set height {}'.format(height),
'move position center'
])
run(['i3-msg', msg])

out = subprocess.run(['i3-msg', '-t', 'get_workspaces'], capture_output=True)
workspaces = json.loads(out.stdout)
def goto_zen():
msg = 'workspace {}'.format(ZEN_WORKSPACE)
run(['i3-msg', msg])

with open(ZEN_FILE_PATH, 'r') as zen_file:
try:
workspace_previous = json.load(zen_file)
except:
workspace_previous = None
workspace_current = list(filter(lambda w: w['focused'], workspaces))[0]
workspace_zen = list(filter(lambda w: w['num'] == ZEN_NUMBER, workspaces))

if __name__ == '__main__':
if len(sys.argv) > 1:
if len(workspace_zen):
msg = disable_zen_mode(workspace_previous)
def switch_workspace(args):
goto_zen()

def toggle(args):
cw, pw, zw = get_workspaces()
if zw:
disable_zen_mode(pw)
else:
if len(workspace_zen):
msg = goto_zen(workspace_zen[0]['name'])
else:
msg = enable_zen_mode(workspace_current)
print(msg)
subprocess.run(['i3-msg', msg])
enable_zen_mode(cw)

def get_workspaces():
out = run(['i3-msg', '-t', 'get_workspaces'], capture_output=True)
workspaces = json.loads(out.stdout)

try:
with open(ZEN_FILE_PATH, 'r') as zen_file:
workspace_previous = json.load(zen_file)['workspace']
except (FileNotFoundError, KeyError):
workspace_previous = {'num': 1}
workspace_current = list(filter(lambda w: w['focused'], workspaces))[0]
workspace_zen = list(filter(lambda w: w['num'] == ZEN_NUMBER, workspaces))
return workspace_current, workspace_previous, workspace_zen


parser = argparse.ArgumentParser(description='Control i3-quiet.')
parser.set_defaults(func=lambda args: parser.print_help())
subparsers = parser.add_subparsers(title='subcommands',
description='valid subcommands',
help='additional help')
parser_toggle = subparsers.add_parser('toggle')
parser_toggle.set_defaults(func=toggle)
parser_switch = subparsers.add_parser('switch')
parser_switch.set_defaults(func=switch_workspace)
parser_resize = subparsers.add_parser('resize')
parser_resize.add_argument('size', type=str,
help='Size of the window specified as "small", "medium", or "large"')
parser_resize.set_defaults(func=resize)
args = parser.parse_args()

args.func(args)

0 comments on commit 28fa76a

Please sign in to comment.