lemonbar
This commit is contained in:
parent
302b0adf39
commit
ca47c8a8a2
0
config/i3/bg.jpg
Executable file → Normal file
0
config/i3/bg.jpg
Executable file → Normal file
Before Width: | Height: | Size: 173 KiB After Width: | Height: | Size: 173 KiB |
157
config/lemonbar/bar.py
Executable file
157
config/lemonbar/bar.py
Executable file
|
@ -0,0 +1,157 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import i3ipc
|
||||
import os
|
||||
import psutil
|
||||
# import alsaaudio
|
||||
from time import time
|
||||
import subprocess
|
||||
|
||||
i3 = i3ipc.Connection()
|
||||
lemonbar = subprocess.Popen(['lemonbar', '-b'], stdin=subprocess.PIPE)
|
||||
|
||||
# Utils
|
||||
def upChart(p):
|
||||
block = ' ▁▂▃▄▅▆▇█'
|
||||
return block[round(p * (len(block)-1))]
|
||||
|
||||
def humanSizeOf(num, suffix='B'): # TODO Credit
|
||||
for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']:
|
||||
if abs(num) < 1024.0:
|
||||
return "%3.0f%2s%s" % (num, unit, suffix)
|
||||
num /= 1024.0
|
||||
return "%.0f%2s%s" % (num, 'Yi', suffix)
|
||||
|
||||
# Values
|
||||
mode = ''
|
||||
container = i3.get_tree().find_focused()
|
||||
workspaces = i3.get_workspaces()
|
||||
outputs = i3.get_outputs()
|
||||
|
||||
username = os.environ['USER']
|
||||
hostname = os.environ['HOSTNAME']
|
||||
if '-' in hostname:
|
||||
hostname = hostname.split('-')[-1]
|
||||
|
||||
oldNetIO = dict()
|
||||
oldTime = time()
|
||||
|
||||
def update():
|
||||
activeOutputs = sorted(sorted(list(filter(lambda o: o.active, outputs)), key=lambda o: o.rect.y), key=lambda o: o.rect.x)
|
||||
z = ''
|
||||
for aOutput in range(len(activeOutputs)):
|
||||
output = activeOutputs[aOutput]
|
||||
# Mode || Workspaces
|
||||
t = []
|
||||
if (mode != ''):
|
||||
t.append(mode)
|
||||
else:
|
||||
t.append(' '.join([(w.name.upper() if w.focused else w.name) for w in workspaces if w.output == output.name]))
|
||||
|
||||
# Windows Title
|
||||
#if container:
|
||||
# t.append(container.name)
|
||||
|
||||
# CPU
|
||||
t.append('C' + ''.join([upChart(p/100) for p in psutil.cpu_percent(percpu=True)]))
|
||||
|
||||
# Memory
|
||||
t.append('M' + str(round(psutil.virtual_memory().percent)) + '% ' +
|
||||
'S' + str(round(psutil.swap_memory().percent)) + '%')
|
||||
|
||||
# Disks
|
||||
d = []
|
||||
for disk in psutil.disk_partitions():
|
||||
e = ''
|
||||
if disk.device.startswith('/dev/sd'):
|
||||
e += 'S' + disk.device[-2:].upper()
|
||||
elif disk.device.startswith('/dev/mmcblk'):
|
||||
e += 'M' + disk.device[-3] + disk.device[-1]
|
||||
else:
|
||||
e += '?'
|
||||
e += ' '
|
||||
e += str(round(psutil.disk_usage(disk.mountpoint).percent)) + '%'
|
||||
d.append(e)
|
||||
t.append(' '.join(d))
|
||||
|
||||
# Network
|
||||
netStats = psutil.net_if_stats()
|
||||
netIO = psutil.net_io_counters(pernic=True)
|
||||
net = []
|
||||
for iface in filter(lambda i: i != 'lo' and netStats[i].isup, netStats.keys()):
|
||||
s = ''
|
||||
if iface.startswith('eth'):
|
||||
s += 'E'
|
||||
elif iface.startswith('wlan'):
|
||||
s += 'W'
|
||||
else:
|
||||
s += '?'
|
||||
|
||||
s += ' '
|
||||
now = time()
|
||||
global oldNetIO, oldTime
|
||||
|
||||
sent = ((oldNetIO[iface].bytes_sent if iface in oldNetIO else 0) - (netIO[iface].bytes_sent if iface in netIO else 0)) / (oldTime - now)
|
||||
recv = ((oldNetIO[iface].bytes_recv if iface in oldNetIO else 0) - (netIO[iface].bytes_recv if iface in netIO else 0)) / (oldTime - now)
|
||||
s += '↓' + humanSizeOf(abs(recv), 'B/s') + ' ↑' + humanSizeOf(abs(sent), 'B/s')
|
||||
|
||||
oldNetIO = netIO
|
||||
oldTime = now
|
||||
|
||||
net.append(s)
|
||||
t.append(' '.join(net))
|
||||
|
||||
# Battery
|
||||
if os.path.isdir('/sys/class/power_supply/BAT0'):
|
||||
with open('/sys/class/power_supply/BAT0/charge_now') as f:
|
||||
charge_now = int(f.read())
|
||||
with open('/sys/class/power_supply/BAT0/charge_full_design') as f:
|
||||
charge_full = int(f.read())
|
||||
t.append('B' + str(round(100*charge_now/charge_full)) + '%')
|
||||
|
||||
# Volume
|
||||
# t.append('V ' + str(alsaaudio.Mixer('Master').getvolume()[0]) + '%')
|
||||
|
||||
t.append(username + '@' + hostname)
|
||||
|
||||
# print(' - '.join(t))
|
||||
# t = [output.name]
|
||||
|
||||
z += ' - '.join(t) + '%{S' + str(aOutput + 1) + '}'
|
||||
#lemonbar.stdin.write(bytes(' - '.join(t), 'utf-8'))
|
||||
#lemonbar.stdin.write(bytes('%{S' + str(aOutput + 1) + '}', 'utf-8'))
|
||||
|
||||
lemonbar.stdin.write(bytes(z+'\n', 'utf-8'))
|
||||
lemonbar.stdin.flush()
|
||||
|
||||
# Event listeners
|
||||
def on_mode(i3, e):
|
||||
global mode
|
||||
if (e.change == 'default'):
|
||||
mode = ''
|
||||
else :
|
||||
mode = e.change
|
||||
update()
|
||||
|
||||
i3.on("mode", on_mode)
|
||||
|
||||
#def on_window_focus(i3, e):
|
||||
# global container
|
||||
# container = e.container
|
||||
# update()
|
||||
#
|
||||
#i3.on("window::focus", on_window_focus)
|
||||
|
||||
def on_workspace_focus(i3, e):
|
||||
global workspaces
|
||||
workspaces = i3.get_workspaces()
|
||||
update()
|
||||
|
||||
i3.on("workspace::focus", on_workspace_focus)
|
||||
|
||||
# Starting
|
||||
|
||||
update()
|
||||
|
||||
|
||||
i3.main()
|
266
config/lemonbar/pip.py
Executable file
266
config/lemonbar/pip.py
Executable file
|
@ -0,0 +1,266 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Beautiful script
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import time
|
||||
import datetime
|
||||
import os
|
||||
import multiprocessing
|
||||
import i3ipc
|
||||
import difflib
|
||||
|
||||
# Constants
|
||||
FONT = "DejaVu Sans Mono for Powerline"
|
||||
|
||||
thm = ['#002b36','#dc322f','#859900','#b58900','#268bd2','#6c71c4','#2aa198','#93a1a1','#657b83','#dc322f','#859900','#b58900','#268bd2','#6c71c4','#2aa198','#fdf6e3']
|
||||
fg = '#93a1a1'
|
||||
bg = '#002b36'
|
||||
|
||||
THEMES = {
|
||||
'CENTER': (fg, bg),
|
||||
'DEFAULT': (thm[0], thm[8]),
|
||||
'1': (thm[0], thm[9]),
|
||||
'2': (thm[0], thm[10]),
|
||||
'3': (thm[0], thm[11]),
|
||||
'4': (thm[0], thm[12]),
|
||||
'5': (thm[0], thm[13]),
|
||||
'6': (thm[0], thm[14]),
|
||||
'7': (thm[0], thm[15]),
|
||||
}
|
||||
|
||||
# Utils
|
||||
|
||||
def fitText(text, size):
|
||||
"""
|
||||
Add spaces or cut a string to be `size` characters long
|
||||
"""
|
||||
if size > 0:
|
||||
if len(text) >= size:
|
||||
return text[:size]
|
||||
else:
|
||||
return ('%' + str(size) + 's') % text
|
||||
else:
|
||||
return ''
|
||||
|
||||
def fgColor(theme):
|
||||
global THEMES
|
||||
return THEMES[theme][0]
|
||||
|
||||
def bgColor(theme):
|
||||
global THEMES
|
||||
return THEMES[theme][1]
|
||||
|
||||
class Section:
|
||||
def __init__(self, theme='DEFAULT'):
|
||||
self.text = ''
|
||||
self.size = 0
|
||||
self.toSize = 0
|
||||
self.theme = theme
|
||||
self.visible = False
|
||||
self.name = ''
|
||||
|
||||
def update(self, text):
|
||||
if text == '':
|
||||
self.toSize = 0
|
||||
else:
|
||||
if len(text) < len(self.text):
|
||||
self.text = text + self.text[len(text):]
|
||||
else:
|
||||
self.text = text
|
||||
self.toSize = len(text) + 3
|
||||
|
||||
def updateSize(self):
|
||||
"""
|
||||
Set the size for the next frame of animation
|
||||
Return if another frame is needed
|
||||
"""
|
||||
if self.toSize > self.size:
|
||||
self.size += 1
|
||||
elif self.toSize < self.size:
|
||||
self.size -= 1
|
||||
self.visible = self.size
|
||||
return self.toSize == self.size
|
||||
|
||||
def draw(self, left=True, nextTheme='DEFAULT'):
|
||||
s = ''
|
||||
if self.visible:
|
||||
if not left:
|
||||
if self.theme == nextTheme:
|
||||
s += ''
|
||||
else:
|
||||
s += '%{F' + bgColor(self.theme) + '}'
|
||||
s += '%{B' + bgColor(nextTheme) + '}'
|
||||
s += ''
|
||||
s += '%{F' + fgColor(self.theme) + '}'
|
||||
s += '%{B' + bgColor(self.theme) + '}'
|
||||
s += ' ' if self.size > 1 else ''
|
||||
s += fitText(self.text, self.size - 3)
|
||||
s += ' ' if self.size > 2 else ''
|
||||
if left:
|
||||
if self.theme == nextTheme:
|
||||
s += ''
|
||||
else:
|
||||
s += '%{F' + bgColor(self.theme) + '}'
|
||||
s += '%{B' + bgColor(nextTheme) + '}'
|
||||
s += ''
|
||||
return s
|
||||
|
||||
# Section definition
|
||||
sTime = Section('3')
|
||||
|
||||
hostname = os.environ['HOSTNAME'].split('.')[0]
|
||||
sHost = Section('2')
|
||||
sHost.update(os.environ['USER'] + '@' + hostname.split('-')[-1] if '-' in hostname else hostname)
|
||||
|
||||
|
||||
# Groups definition
|
||||
gLeft = []
|
||||
gRight = [sTime, sHost]
|
||||
|
||||
# Bar handling
|
||||
bar = subprocess.Popen(['lemonbar', '-f', FONT, '-b'], stdin=subprocess.PIPE)
|
||||
|
||||
def updateBar():
|
||||
global timeLastUpdate, timeUpdate
|
||||
global gLeft, gRight
|
||||
global outputs
|
||||
|
||||
text = ''
|
||||
for oi in range(len(outputs)):
|
||||
output = outputs[oi]
|
||||
gLeftFiltered = list(filter(lambda s: s.visible and (not s.output or s.output == output.name), gLeft))
|
||||
tLeft = ''
|
||||
l = len(gLeftFiltered)
|
||||
for gi in range(l):
|
||||
g = gLeftFiltered[gi]
|
||||
nextTheme = gLeftFiltered[gi + 1].theme if gi + 1 < l else 'CENTER' # Next visible section for transition
|
||||
tLeft = tLeft + g.draw(True, nextTheme)
|
||||
|
||||
tRight = ''
|
||||
for gi in range(len(gRight)):
|
||||
g = gRight[gi]
|
||||
nextTheme = 'CENTER'
|
||||
for gn in gRight[gi+1:]:
|
||||
if gn.visible:
|
||||
nextTheme = gn.theme
|
||||
break
|
||||
tRight = g.draw(False, nextTheme) + tRight
|
||||
text += '%{l}' + tLeft + '%{r}' + tRight + '%{B' + bgColor('CENTER') + '}' + '%{S' + str(oi + 1) + '}'
|
||||
|
||||
bar.stdin.write(bytes(text + '\n', 'utf-8'))
|
||||
bar.stdin.flush()
|
||||
|
||||
# Values
|
||||
i3 = i3ipc.Connection()
|
||||
outputs = []
|
||||
|
||||
def on_output():
|
||||
global outputs
|
||||
outputs = sorted(sorted(list(filter(lambda o: o.active, i3.get_outputs())), key=lambda o: o.rect.y), key=lambda o: o.rect.x)
|
||||
on_output()
|
||||
|
||||
def on_workspace_focus():
|
||||
global i3
|
||||
global gLeft
|
||||
workspaces = i3.get_workspaces()
|
||||
wNames = [w.name for w in workspaces]
|
||||
sNames = [s.name for s in gLeft]
|
||||
|
||||
newGLeft = []
|
||||
def actuate(section, workspace):
|
||||
if workspace:
|
||||
section.name = workspace.name
|
||||
section.output = workspace.output
|
||||
if workspace.visible:
|
||||
section.update(workspace.name)
|
||||
else:
|
||||
section.update(workspace.name.split(' ')[0])
|
||||
|
||||
if workspace.focused:
|
||||
section.theme = '4'
|
||||
elif workspace.urgent:
|
||||
section.theme = '1'
|
||||
else:
|
||||
section.theme = '6'
|
||||
else:
|
||||
section.update('')
|
||||
section.theme = '6'
|
||||
|
||||
for tag, i, j, k, l in difflib.SequenceMatcher(None, sNames, wNames).get_opcodes():
|
||||
if tag == 'equal': # If the workspaces didn't changed
|
||||
for a in range(j-i):
|
||||
workspace = workspaces[k+a]
|
||||
section = gLeft[i+a]
|
||||
actuate(section, workspace)
|
||||
newGLeft.append(section)
|
||||
if tag in ('delete', 'replace'): # If the workspaces were removed
|
||||
for section in gLeft[i:j]:
|
||||
if section.visible:
|
||||
actuate(section, None)
|
||||
newGLeft.append(section)
|
||||
else:
|
||||
del section
|
||||
if tag in ('insert', 'replace'): # If the workspaces were removed
|
||||
for workspace in workspaces[k:l]:
|
||||
section = Section()
|
||||
actuate(section, workspace)
|
||||
newGLeft.append(section)
|
||||
gLeft = newGLeft
|
||||
|
||||
updateBar()
|
||||
on_workspace_focus()
|
||||
|
||||
|
||||
def i3events(i3childPipe):
|
||||
global i3
|
||||
|
||||
# Proxy functions
|
||||
def on_workspace_focus(i3, e):
|
||||
global i3childPipe
|
||||
i3childPipe.send('on_workspace_focus')
|
||||
i3.on("workspace::focus", on_workspace_focus)
|
||||
|
||||
def on_output(i3, e):
|
||||
global i3childPipe
|
||||
i3childPipe.send('on_output')
|
||||
i3.on("output", on_output)
|
||||
|
||||
i3.main()
|
||||
|
||||
i3parentPipe, i3childPipe = multiprocessing.Pipe()
|
||||
i3process = multiprocessing.Process(target=i3events, args=(i3childPipe,))
|
||||
i3process.start()
|
||||
|
||||
def updateValues():
|
||||
# Time
|
||||
now = datetime.datetime.now()
|
||||
sTime.update(now.strftime('%x %X'))
|
||||
|
||||
def updateAnimation():
|
||||
for s in set(gLeft + gRight):
|
||||
s.updateSize()
|
||||
updateBar()
|
||||
|
||||
lastUpdate = 0
|
||||
while True:
|
||||
now = time.time()
|
||||
if i3parentPipe.poll():
|
||||
msg = i3parentPipe.recv()
|
||||
if msg == 'on_workspace_focus':
|
||||
on_workspace_focus()
|
||||
elif msg == 'on_output':
|
||||
on_output()
|
||||
# TODO Restart lemonbar
|
||||
else:
|
||||
print(msg)
|
||||
updateAnimation()
|
||||
if now >= lastUpdate + 1:
|
||||
updateValues()
|
||||
lastUpdate = now
|
||||
|
||||
time.sleep(0.05)
|
||||
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
[user]
|
||||
name = Geoffrey Frogeye
|
||||
name = Geoffrey “Frogeye” Preud'homme
|
||||
email = geoffrey@frogeye.fr
|
||||
signingkey = D8A7ECA00A8CD3DD
|
||||
[core]
|
||||
editor = vim
|
||||
excludesfile = ~/.gitignore
|
||||
|
|
2
vimrc
2
vimrc
|
@ -83,7 +83,7 @@ let g:airline#extensions#tabline#enabled = 1
|
|||
|
||||
let g:airline_section_a = airline#section#create(['mode'])
|
||||
let g:airline_section_b = airline#section#create(['branch', 'hunks'])
|
||||
let g:airline_section_z = airline#section#create(['%B', '@', '%l', ':', '%c'])
|
||||
" let g:airline_section_z = airline#section#create(['%B', '@', '%l', ':', '%c'])
|
||||
let g:airline_theme = 'base16_monokai'
|
||||
|
||||
""" AUTOFORMAT """
|
||||
|
|
Loading…
Reference in a new issue