Browse Source

Run black on all Python scripts!

master
Geoffrey Frogeye 1 year ago
parent
commit
cd9cbcaa28
Signed by: geoffrey GPG Key ID: C72403E7F82E6AD8
  1. 43
      config/i3/screentime
  2. 17
      config/lemonbar/bar.py
  3. 135
      config/lemonbar/display.py
  4. 146
      config/lemonbar/oldbar.py
  5. 174
      config/lemonbar/pip.py
  6. 232
      config/lemonbar/providers.py
  7. 19
      config/lemonbar/updaters.py
  8. 56
      config/scripts/archive
  9. 50
      config/scripts/compressPictureMovies
  10. 4
      config/scripts/lestrte
  11. 6
      config/scripts/mediaDuration
  12. 350
      config/scripts/mel
  13. 64
      config/scripts/melConf
  14. 8
      config/scripts/music_remove_dashes
  15. 3
      config/scripts/musiqueBof
  16. 28
      config/scripts/ovhcli
  17. 22
      config/scripts/picture_name_date
  18. 36
      config/scripts/pushToTalk
  19. 9
      config/scripts/replayGain
  20. 182
      config/scripts/rmf
  21. 10
      config/scripts/smtpdummy
  22. 2
      config/scripts/spongebob
  23. 7
      config/scripts/syncthingRestore
  24. 3
      config/scripts/tagCreatorPhotos
  25. 19
      config/scripts/ter
  26. 57
      config/scripts/tvshow
  27. 2
      config/scripts/unziptree
  28. 40
      config/scripts/updateCompressedMusic
  29. 6
      config/scripts/vidcmp
  30. 3
      config/scripts/videoQuota

43
config/i3/screentime

@ -20,27 +20,28 @@ class ScreenTime:
line["date"] = now.timestamp()
print("WROTE", line)
with open(self.csv_path, 'a') as typedfd:
with open(self.csv_path, "a") as typedfd:
writer = csv.DictWriter(typedfd, fieldnames=self.FIELDS)
writer.writerow(line)
def on_window_event(self, _: i3ipc.connection.Connection,
e: i3ipc.events.WindowEvent) -> None:
def on_window_event(
self, _: i3ipc.connection.Connection, e: i3ipc.events.WindowEvent
) -> None:
focused = self.i3.get_tree().find_focused()
self.write({
"type": "window_" + e.change,
"class": focused.window_class,
"role": focused.window_role,
"title": focused.window_title,
"instance": focused.window_instance,
})
self.write(
{
"type": "window_" + e.change,
"class": focused.window_class,
"role": focused.window_role,
"title": focused.window_title,
"instance": focused.window_instance,
}
)
def on_mode_event(self, _: i3ipc.connection.Connection,
e: i3ipc.events.ModeEvent) -> None:
self.write({
"type": "mode",
"title": e.change
})
def on_mode_event(
self, _: i3ipc.connection.Connection, e: i3ipc.events.ModeEvent
) -> None:
self.write({"type": "mode", "title": e.change})
def __init__(self) -> None:
self.i3 = i3ipc.Connection()
@ -48,11 +49,11 @@ class ScreenTime:
self.i3.on(i3ipc.Event.MODE, self.on_mode_event)
self.csv_path = os.path.join(
os.path.expanduser(
os.getenv('XDG_CACHE_PATH', '~/.cache/')),
'screentime.csv')
os.path.expanduser(os.getenv("XDG_CACHE_PATH", "~/.cache/")),
"screentime.csv",
)
if not os.path.isfile(self.csv_path):
with open(self.csv_path, 'w') as typedfd:
with open(self.csv_path, "w") as typedfd:
writer = csv.DictWriter(typedfd, fieldnames=self.FIELDS)
writer.writeheader()
self.write({"type": "start"})
@ -61,6 +62,6 @@ class ScreenTime:
self.i3.main()
if __name__ == '__main__':
if __name__ == "__main__":
ST = ScreenTime()
ST.main()

17
config/lemonbar/bar.py

@ -11,14 +11,23 @@ if __name__ == "__main__":
WORKSPACE_THEME = 0
FOCUS_THEME = 3
URGENT_THEME = 1
CUSTOM_SUFFIXES = '▲■'
CUSTOM_SUFFIXES = "▲■"
customNames = dict()
for i in range(len(CUSTOM_SUFFIXES)):
short = str(i+1)
full = short + ' ' + CUSTOM_SUFFIXES[i]
short = str(i + 1)
full = short + " " + CUSTOM_SUFFIXES[i]
customNames[short] = full
Bar.addSectionAll(I3WorkspacesProvider(theme=WORKSPACE_THEME, themeFocus=FOCUS_THEME, themeUrgent=URGENT_THEME, themeMode=URGENT_THEME, customNames=customNames), BarGroupType.LEFT)
Bar.addSectionAll(
I3WorkspacesProvider(
theme=WORKSPACE_THEME,
themeFocus=FOCUS_THEME,
themeUrgent=URGENT_THEME,
themeMode=URGENT_THEME,
customNames=customNames,
),
BarGroupType.LEFT,
)
# TODO Middle
Bar.addSectionAll(MpdProvider(theme=7), BarGroupType.LEFT)

135
config/lemonbar/display.py

@ -11,7 +11,7 @@ import logging
import coloredlogs
import updaters
coloredlogs.install(level='DEBUG', fmt='%(levelname)s %(message)s')
coloredlogs.install(level="DEBUG", fmt="%(levelname)s %(message)s")
log = logging.getLogger()
@ -62,12 +62,13 @@ class Bar:
Bar.running = True
Section.init()
cmd = ['lemonbar', '-b', '-a', '64']
cmd = ["lemonbar", "-b", "-a", "64"]
for font in Bar.FONTS:
cmd += ["-f", "{}:size={}".format(font, Bar.FONTSIZE)]
Bar.process = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
Bar.stdoutThread = BarStdoutThread()
Bar.process = subprocess.Popen(
cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE
)
Bar.stdoutThread = BarStdoutThread()
Bar.stdoutThread.start()
# Debug
@ -92,7 +93,7 @@ class Bar:
print(88)
try:
i3.on('ipc_shutdown', doStop)
i3.on("ipc_shutdown", doStop)
i3.main()
except BaseException:
print(93)
@ -114,7 +115,7 @@ class Bar:
if function in Bar.actionsF2H.keys():
return Bar.actionsF2H[function]
handle = '{:x}'.format(Bar.nextHandle).encode()
handle = "{:x}".format(Bar.nextHandle).encode()
Bar.nextHandle += 1
Bar.actionsF2H[function] = handle
@ -177,7 +178,7 @@ class Bar:
Bar.string += BarGroup.color(*Section.EMPTY)
# print(Bar.string)
Bar.process.stdin.write(bytes(Bar.string + '\n', 'utf-8'))
Bar.process.stdin.write(bytes(Bar.string + "\n", "utf-8"))
Bar.process.stdin.flush()
@ -196,7 +197,7 @@ class BarGroup:
self.parent = parent
self.sections = list()
self.string = ''
self.string = ""
self.parts = []
#: One of the sections that had their theme or visibility changed
@ -220,11 +221,11 @@ class BarGroup:
@staticmethod
def fgColor(color):
return "%{F" + (color or '-') + "}"
return "%{F" + (color or "-") + "}"
@staticmethod
def bgColor(color):
return "%{B" + (color or '-') + "}"
return "%{B" + (color or "-") + "}"
@staticmethod
def color(fg, bg):
@ -243,8 +244,9 @@ class BarGroup:
oSec = secs[s + 1] if s < lenS - 1 else None
else:
oSec = secs[s - 1] if s > 0 else None
oTheme = Section.THEMES[oSec.theme] \
if oSec is not None else Section.EMPTY
oTheme = (
Section.THEMES[oSec.theme] if oSec is not None else Section.EMPTY
)
if self.groupType == BarGroupType.LEFT:
if s == 0:
@ -263,7 +265,6 @@ class BarGroup:
parts.append(BarGroup.color(*theme))
parts.append(sec)
# TODO OPTI Concatenate successive strings
self.parts = parts
@ -315,11 +316,26 @@ class Section:
# COLORS = ['#272822', '#383830', '#49483e', '#75715e', '#a59f85', '#f8f8f2',
# '#f5f4f1', '#f9f8f5', '#f92672', '#fd971f', '#f4bf75', '#a6e22e',
# '#a1efe4', '#66d9ef', '#ae81ff', '#cc6633']
COLORS = ['#181818', '#AB4642', '#A1B56C', '#F7CA88', '#7CAFC2', '#BA8BAF',
'#86C1B9', '#D8D8D8', '#585858', '#AB4642', '#A1B56C', '#F7CA88',
'#7CAFC2', '#BA8BAF', '#86C1B9', '#F8F8F8']
FGCOLOR = '#F8F8F2'
BGCOLOR = '#272822'
COLORS = [
"#181818",
"#AB4642",
"#A1B56C",
"#F7CA88",
"#7CAFC2",
"#BA8BAF",
"#86C1B9",
"#D8D8D8",
"#585858",
"#AB4642",
"#A1B56C",
"#F7CA88",
"#7CAFC2",
"#BA8BAF",
"#86C1B9",
"#F8F8F8",
]
FGCOLOR = "#F8F8F2"
BGCOLOR = "#272822"
THEMES = list()
EMPTY = (FGCOLOR, BGCOLOR)
@ -347,17 +363,18 @@ class Section:
if theme is None:
theme = Section.lastChosenTheme
Section.lastChosenTheme = (Section.lastChosenTheme + 1) \
% len(Section.THEMES)
Section.lastChosenTheme = (Section.lastChosenTheme + 1) % len(
Section.THEMES
)
self.theme = theme
#: Displayed text
self.curText = ''
self.curText = ""
#: Displayed text size
self.curSize = 0
#: Destination text
self.dstText = Text(' ', Text(), ' ')
self.dstText = Text(" ", Text(), " ")
#: Destination size
self.dstSize = 0
@ -367,13 +384,16 @@ class Section:
self.icon = self.ICON
self.persistent = self.PERSISTENT
def __str__(self):
try:
return "<{}><{}>{:01d}{}{:02d}/{:02d}" \
.format(self.curText, self.dstText,
self.theme, "+" if self.visible else "-",
self.curSize, self.dstSize)
return "<{}><{}>{:01d}{}{:02d}/{:02d}".format(
self.curText,
self.dstText,
self.theme,
"+" if self.visible else "-",
self.curSize,
self.dstSize,
)
except:
return super().__str__()
@ -399,9 +419,15 @@ class Section:
elif isinstance(text, Text) and not len(text.elements):
text = None
self.dstText[0] = None if (text is None and not self.persistent) else ((' ' + self.icon + ' ') if self.icon else ' ')
self.dstText[0] = (
None
if (text is None and not self.persistent)
else ((" " + self.icon + " ") if self.icon else " ")
)
self.dstText[1] = text
self.dstText[2] = ' ' if self.dstText[1] is not None and len(self.dstText[1]) else None
self.dstText[2] = (
" " if self.dstText[1] is not None and len(self.dstText[1]) else None
)
self.dstSize = len(self.dstText)
self.dstText.setSection(self)
@ -481,7 +507,7 @@ class Section:
elif p < 0:
return ramp[0]
else:
return ramp[round(p * (len(ramp)-1))]
return ramp[round(p * (len(ramp) - 1))]
class StatefulSection(Section):
@ -492,10 +518,11 @@ class StatefulSection(Section):
def __init__(self, *args, **kwargs):
Section.__init__(self, *args, **kwargs)
self.state = self.DEFAULT_STATE
if hasattr(self, 'onChangeState'):
if hasattr(self, "onChangeState"):
self.onChangeState(self.state)
self.setDecorators(clickLeft=self.incrementState,
clickRight=self.decrementState)
self.setDecorators(
clickLeft=self.incrementState, clickRight=self.decrementState
)
def incrementState(self):
newState = min(self.state + 1, self.NUMBER_STATES - 1)
@ -509,16 +536,17 @@ class StatefulSection(Section):
assert isinstance(state, int)
assert state < self.NUMBER_STATES
self.state = state
if hasattr(self, 'onChangeState'):
if hasattr(self, "onChangeState"):
self.onChangeState(state)
self.refreshData()
class ColorCountsSection(StatefulSection):
# TODO FEAT Blend colors when not expanded
# TODO FEAT Blend colors with importance of count
# TODO FEAT Allow icons instead of counts
NUMBER_STATES = 3
COLORABLE_ICON = '?'
COLORABLE_ICON = "?"
def __init__(self, theme=None):
StatefulSection.__init__(self, theme=theme)
@ -538,12 +566,12 @@ class ColorCountsSection(StatefulSection):
# Icon + Total
elif self.state == 1 and len(counts) > 1:
total = sum([count for count, color in counts])
return Text(self.COLORABLE_ICON, ' ', total)
return Text(self.COLORABLE_ICON, " ", total)
# Icon + Counts
else:
text = Text(self.COLORABLE_ICON)
for count, color in counts:
text.append(' ', Text(count, fg=color))
text.append(" ", Text(count, fg=color))
return text
@ -586,12 +614,12 @@ class Text:
if self.prefix is not None and self.suffix is not None:
return
self.prefix = ''
self.suffix = ''
self.prefix = ""
self.suffix = ""
def nest(prefix, suffix):
self.prefix = self.prefix + '%{' + prefix + '}'
self.suffix = '%{' + suffix + '}' + self.suffix
self.prefix = self.prefix + "%{" + prefix + "}"
self.suffix = "%{" + suffix + "}" + self.suffix
def getColor(val):
# TODO Allow themes
@ -600,27 +628,27 @@ class Text:
def button(number, function):
handle = Bar.getFunctionHandle(function)
nest('A' + number + ':' + handle.decode() + ':', 'A' + number)
nest("A" + number + ":" + handle.decode() + ":", "A" + number)
for key, val in self.decorators.items():
if val is None:
continue
if key == 'fg':
if key == "fg":
reset = self.section.THEMES[self.section.theme][0]
nest('F' + getColor(val), 'F' + reset)
elif key == 'bg':
nest("F" + getColor(val), "F" + reset)
elif key == "bg":
reset = self.section.THEMES[self.section.theme][1]
nest('B' + getColor(val), 'B' + reset)
nest("B" + getColor(val), "B" + reset)
elif key == "clickLeft":
button('1', val)
button("1", val)
elif key == "clickMiddle":
button('2', val)
button("2", val)
elif key == "clickRight":
button('3', val)
button("3", val)
elif key == "scrollUp":
button('4', val)
button("4", val)
elif key == "scrollDown":
button('5', val)
button("5", val)
else:
log.warn("Unkown decorator: {}".format(key))
@ -652,7 +680,7 @@ class Text:
curString += self.suffix
if pad and remSize > 0:
curString += ' ' * remSize
curString += " " * remSize
curSize += remSize
if size is not None:
@ -688,7 +716,6 @@ class Text:
curSize += len(str(element))
return curSize
def __getitem__(self, index):
return self.elements[index]

146
config/lemonbar/oldbar.py

@ -7,150 +7,188 @@ Debugging script
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)
lemonbar = subprocess.Popen(["lemonbar", "-b"], stdin=subprocess.PIPE)
# Utils
def upChart(p):
block = ' ▁▂▃▄▅▆▇█'
return block[round(p * (len(block)-1))]
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']:
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)
return "%.0f%2s%s" % (num, "Yi", suffix)
# Values
mode = ''
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]
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 = ''
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 != ''):
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]))
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:
# if container:
# t.append(container.name)
# CPU
t.append('C' + ''.join([upChart(p/100) for p in psutil.cpu_percent(percpu=True)]))
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)) + '%')
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]
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)) + '%'
e += "?"
e += " "
e += str(round(psutil.disk_usage(disk.mountpoint).percent)) + "%"
d.append(e)
t.append(' '.join(d))
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'
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 += "?"
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')
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))
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:
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:
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)) + '%')
t.append("B" + str(round(100 * charge_now / charge_full)) + "%")
# Volume
# t.append('V ' + str(alsaaudio.Mixer('Master').getvolume()[0]) + '%')
t.append(username + '@' + hostname)
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'))
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.write(bytes(z + "\n", "utf-8"))
lemonbar.stdin.flush()
# Event listeners
def on_mode(i3, e):
global mode
if (e.change == 'default'):
mode = ''
else :
if e.change == "default":
mode = ""
else:
mode = e.change
update()
i3.on("mode", on_mode)
#def on_window_focus(i3, e):
# def on_window_focus(i3, e):
# global container
# container = e.container
# update()
#
#i3.on("window::focus", on_window_focus)
# 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

174
config/lemonbar/pip.py

@ -16,22 +16,37 @@ import difflib
FONT = "DejaVu Sans Mono for Powerline"
# TODO Update to be in sync with base16
thm = ['#002b36', '#dc322f', '#859900', '#b58900', '#268bd2', '#6c71c4',
'#2aa198', '#93a1a1', '#657b83', '#dc322f', '#859900', '#b58900',
'#268bd2', '#6c71c4', '#2aa198', '#fdf6e3']
fg = '#93a1a1'
bg = '#002b36'
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]),
"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
@ -49,7 +64,7 @@ def fitText(text, size):
diff = size - t
return text + " " * diff
else:
return ''
return ""
def fgColor(theme):
@ -63,20 +78,20 @@ def bgColor(theme):
class Section:
def __init__(self, theme='DEFAULT'):
self.text = ''
def __init__(self, theme="DEFAULT"):
self.text = ""
self.size = 0
self.toSize = 0
self.theme = theme
self.visible = False
self.name = ''
self.name = ""
def update(self, text):
if text == '':
if text == "":
self.toSize = 0
else:
if len(text) < len(self.text):
self.text = text + self.text[len(text):]
self.text = text + self.text[len(text) :]
else:
self.text = text
self.toSize = len(text) + 3
@ -93,39 +108,39 @@ class Section:
self.visible = self.size
return self.toSize == self.size
def draw(self, left=True, nextTheme='DEFAULT'):
s = ''
def draw(self, left=True, nextTheme="DEFAULT"):
s = ""
if self.visible:
if not left:
if self.theme == nextTheme:
s += ''
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 += "%{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 ''
s += " " if self.size > 2 else ""
if left:
if self.theme == nextTheme:
s += ''
s += ""
else:
s += '%{F' + bgColor(self.theme) + '}'
s += '%{B' + bgColor(nextTheme) + '}'
s += ''
s += "%{F" + bgColor(self.theme) + "}"
s += "%{B" + bgColor(nextTheme) + "}"
s += ""
return s
# Section definition
sTime = Section('3')
sTime = Section("3")
hostname = os.environ['HOSTNAME'].split('.')[0]
sHost = Section('2')
hostname = os.environ["HOSTNAME"].split(".")[0]
sHost = Section("2")
sHost.update(
os.environ['USER'] + '@' + hostname.split('-')[-1]
if '-' in hostname else hostname)
os.environ["USER"] + "@" + hostname.split("-")[-1] if "-" in hostname else hostname
)
# Groups definition
@ -133,7 +148,7 @@ gLeft = []
gRight = [sTime, sHost]
# Bar handling
bar = subprocess.Popen(['lemonbar', '-f', FONT, '-b'], stdin=subprocess.PIPE)
bar = subprocess.Popen(["lemonbar", "-f", FONT, "-b"], stdin=subprocess.PIPE)
def updateBar():
@ -141,35 +156,45 @@ def updateBar():
global gLeft, gRight
global outputs
text = ''
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 = ''
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]
# Next visible section for transition
nextTheme = gLeftFiltered[gi + 1].theme if gi + 1 < l else 'CENTER'
nextTheme = gLeftFiltered[gi + 1].theme if gi + 1 < l else "CENTER"
tLeft = tLeft + g.draw(True, nextTheme)
tRight = ''
tRight = ""
for gi in range(len(gRight)):
g = gRight[gi]
nextTheme = 'CENTER'
for gn in gRight[gi + 1:]:
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'))
text += (
"%{l}"
+ tLeft
+ "%{r}"
+ tRight
+ "%{B"
+ bgColor("CENTER")
+ "}"
+ "%{S"
+ str(oi + 1)
+ "}"
)
bar.stdin.write(bytes(text + "\n", "utf-8"))
bar.stdin.flush()
@ -182,12 +207,10 @@ 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)
list(filter(lambda o: o.active, i3.get_outputs())), key=lambda o: o.rect.y
),
key=lambda o: o.rect.x,
)
on_output()
@ -209,34 +232,33 @@ def on_workspace_focus():
if workspace.visible:
section.update(workspace.name)
else:
section.update(workspace.name.split(' ')[0])
section.update(workspace.name.split(" ")[0])
if workspace.focused:
section.theme = '4'
section.theme = "4"
elif workspace.urgent:
section.theme = '1'
section.theme = "1"
else:
section.theme = '6'
section.theme = "6"
else:
section.update('')
section.theme = '6'
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 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
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
if tag in ("insert", "replace"): # If the workspaces were removed
for workspace in workspaces[k:l]:
section = Section()
actuate(section, workspace)
@ -255,12 +277,14 @@ def i3events(i3childPipe):
# Proxy functions
def on_workspace_focus(i3, e):
global i3childPipe
i3childPipe.send('on_workspace_focus')
i3childPipe.send("on_workspace_focus")
i3.on("workspace::focus", on_workspace_focus)
def on_output(i3, e):
global i3childPipe
i3childPipe.send('on_output')
i3childPipe.send("on_output")
i3.on("output", on_output)
i3.main()
@ -274,7 +298,7 @@ i3process.start()
def updateValues():
# Time
now = datetime.datetime.now()
sTime.update(now.strftime('%x %X'))
sTime.update(now.strftime("%x %X"))
def updateAnimation():
@ -288,9 +312,9 @@ while True:
now = time.time()
if i3parentPipe.poll():
msg = i3parentPipe.recv()
if msg == 'on_workspace_focus':
if msg == "on_workspace_focus":
on_workspace_focus()
elif msg == 'on_output':
elif msg == "on_output":
on_output()
# TODO Restart lemonbar
else:

232
config/lemonbar/providers.py

@ -16,17 +16,18 @@ import mpd
import random
import math
coloredlogs.install(level='DEBUG', fmt='%(levelname)s %(message)s')
coloredlogs.install(level="DEBUG", fmt="%(levelname)s %(message)s")
log = logging.getLogger()
# TODO Generator class (for I3WorkspacesProvider, NetworkProvider and later
# PulseaudioProvider and MpdProvider)
def humanSize(num):
"""
Returns a string of width 3+3
"""
for unit in ('B ','KiB','MiB','GiB','TiB','PiB','EiB','ZiB'):
for unit in ("B ", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB"):
if abs(num) < 1000:
if num >= 10:
return "{:3d}{}".format(int(num), unit)
@ -35,16 +36,15 @@ def humanSize(num):
num /= 1024.0
return "{:d}YiB".format(num)
def randomColor(seed=0):
random.seed(seed)
return '#{:02x}{:02x}{:02x}'.format(*[random.randint(0, 255) for _ in range(3)])
return "#{:02x}{:02x}{:02x}".format(*[random.randint(0, 255) for _ in range(3)])
class TimeProvider(StatefulSection, PeriodicUpdater):
FORMATS = ["%H:%M",
"%m-%d %H:%M:%S",
"%a %y-%m-%d %H:%M:%S"]
FORMATS = ["%H:%M", "%m-%d %H:%M:%S", "%a %y-%m-%d %H:%M:%S"]
NUMBER_STATES = len(FORMATS)
DEFAULT_STATE = 1
@ -55,18 +55,18 @@ class TimeProvider(StatefulSection, PeriodicUpdater):
def __init__(self, theme=None):
PeriodicUpdater.__init__(self)
StatefulSection.__init__(self, theme)
self.changeInterval(1) # TODO OPTI When state < 1
self.changeInterval(1) # TODO OPTI When state < 1
class AlertLevel(enum.Enum):
NORMAL = 0
WARNING = 1
DANGER = 2
class AlertingSection(StatefulSection):
# TODO EASE Correct settings for themes
THEMES = {AlertLevel.NORMAL: 2,
AlertLevel.WARNING: 3,
AlertLevel.DANGER: 1}
THEMES = {AlertLevel.NORMAL: 2, AlertLevel.WARNING: 3, AlertLevel.DANGER: 1}
PERSISTENT = True
def getLevel(self, quantity):
@ -92,16 +92,16 @@ class AlertingSection(StatefulSection):
class CpuProvider(AlertingSection, PeriodicUpdater):
NUMBER_STATES = 3
ICON = ''
ICON = ""
def fetcher(self):
percent = psutil.cpu_percent(percpu=False)
self.updateLevel(percent/100)
self.updateLevel(percent / 100)
if self.state >= 2:
percents = psutil.cpu_percent(percpu=True)
return ''.join([Section.ramp(p/100) for p in percents])
return "".join([Section.ramp(p / 100) for p in percents])
elif self.state >= 1:
return Section.ramp(percent/100)
return Section.ramp(percent / 100)
def __init__(self, theme=None):
AlertingSection.__init__(self, theme)
@ -113,12 +113,13 @@ class RamProvider(AlertingSection, PeriodicUpdater):
"""
Shows free RAM
"""
NUMBER_STATES = 4
ICON = ''
ICON = ""
def fetcher(self):
mem = psutil.virtual_memory()
freePerc = mem.percent/100
freePerc = mem.percent / 100
self.updateLevel(freePerc)
if self.state < 1:
@ -130,7 +131,7 @@ class RamProvider(AlertingSection, PeriodicUpdater):
text.append(freeStr)
if self.state >= 3:
totalStr = humanSize(mem.total)
text.append('/', totalStr)
text.append("/", totalStr)
return text
@ -146,18 +147,18 @@ class TemperatureProvider(AlertingSection, PeriodicUpdater):
def fetcher(self):
allTemp = psutil.sensors_temperatures()
if 'coretemp' not in allTemp:
if "coretemp" not in allTemp:
# TODO Opti Remove interval
return ''
temp = allTemp['coretemp'][0]
return ""
temp = allTemp["coretemp"][0]
self.warningThresold = temp.high
self.dangerThresold = temp.critical
self.updateLevel(temp.current)
self.icon = Section.ramp(temp.current/temp.high, self.RAMP)
self.icon = Section.ramp(temp.current / temp.high, self.RAMP)
if self.state >= 1:
return '{:.0f}°C'.format(temp.current)
return "{:.0f}°C".format(temp.current)
def __init__(self, theme=None):
AlertingSection.__init__(self, theme)
@ -176,15 +177,16 @@ class BatteryProvider(AlertingSection, PeriodicUpdater):
self.icon = None
return None
self.icon = ("" if bat.power_plugged else "") + \
Section.ramp(bat.percent/100, self.RAMP)
self.icon = ("" if bat.power_plugged else "") + Section.ramp(
bat.percent / 100, self.RAMP
)
self.updateLevel(1-bat.percent/100)
self.updateLevel(1 - bat.percent / 100)
if self.state < 1:
return
t = Text('{:.0f}%'.format(bat.percent))
t = Text("{:.0f}%".format(bat.percent))
if self.state < 2:
return t
@ -200,7 +202,6 @@ class BatteryProvider(AlertingSection, PeriodicUpdater):
self.changeInterval(5)
class PulseaudioProvider(StatefulSection, ThreadedUpdater):
NUMBER_STATES = 3
DEFAULT_STATE = 1
@ -208,28 +209,27 @@ class PulseaudioProvider(StatefulSection, ThreadedUpdater):
def __init__(self, theme=None):
ThreadedUpdater.__init__(self)
StatefulSection.__init__(self, theme)
self.pulseEvents = pulsectl.Pulse('event-handler')
self.pulseEvents = pulsectl.Pulse("event-handler")
self.pulseEvents.event_mask_set(pulsectl.PulseEventMaskEnum.sink)
self.pulseEvents.event_callback_set(self.handleEvent)
self.start()
self.refreshData()
def fetcher(self):
sinks = []
with pulsectl.Pulse('list-sinks') as pulse:
with pulsectl.Pulse("list-sinks") as pulse:
for sink in pulse.sink_list():
if sink.port_active.name == "analog-output-headphones":
icon = ""
elif sink.port_active.name == "analog-output-speaker":
icon = "" if sink.mute else ""
elif sink.port_active.name == "headset-output":
icon = ''
icon = ""
else:
icon = "?"
vol = pulse.volume_get_all_chans(sink)
fg = (sink.mute and '#333333') or (vol > 1 and '#FF0000') or None
fg = (sink.mute and "#333333") or (vol > 1 and "#FF0000") or None
t = Text(icon, fg=fg)
sinks.append(t)
@ -245,7 +245,7 @@ class PulseaudioProvider(StatefulSection, ThreadedUpdater):
vol -= 1
t.append(ramp)
else:
t.append(" {:2.0f}%".format(vol*100))
t.append(" {:2.0f}%".format(vol * 100))
return Text(*sinks)
@ -263,27 +263,27 @@ class NetworkProviderSection(StatefulSection, Updater):
def actType(self):
self.ssid = None
if self.iface.startswith('eth') or self.iface.startswith('enp'):
if 'u' in self.iface:
self.icon = ''
if self.iface.startswith("eth") or self.iface.startswith("enp"):
if "u" in self.iface:
self.icon = ""
else:
self.icon = ''
elif self.iface.startswith('wlan') or self.iface.startswith('wl'):
self.icon = ''
self.icon = ""
elif self.iface.startswith("wlan") or self.iface.startswith("wl"):
self.icon = ""
if self.showSsid:
cmd = ["iwgetid", self.iface, "--raw"]
p = subprocess.run(cmd, stdout=subprocess.PIPE)
self.ssid = p.stdout.strip().decode()
elif self.iface.startswith('tun') or self.iface.startswith('tap'):
self.icon = ''
elif self.iface.startswith('docker'):
self.icon = ''
elif self.iface.startswith('veth'):
self.icon = ''
elif self.iface.startswith('vboxnet'):
self.icon = ''
elif self.iface.startswith("tun") or self.iface.startswith("tap"):
self.icon = ""
elif self.iface.startswith("docker"):
self.icon = ""
elif self.iface.startswith("veth"):
self.icon = ""
elif self.iface.startswith("vboxnet"):
self.icon = ""
else:
self.icon = '?'
self.icon = "?"
def getAddresses(self):
ipv4 = None
@ -298,9 +298,11 @@ class NetworkProviderSection(StatefulSection, Updater):
def fetcher(self):
self.icon = None
self.persistent = False
if self.iface not in self.parent.stats or \
not self.parent.stats[self.iface].isup or \
self.iface.startswith('lo'):
if (
self.iface not in self.parent.stats
or not self.parent.stats[self.iface].isup
or self.iface.startswith("lo")
):
return None
# Get addresses
@ -317,30 +319,36 @@ class NetworkProviderSection(StatefulSection, Updater):
if self.showAddress:
if ipv4:
netStrFull = '{}/{}'.format(ipv4.address, ipv4.netmask)
netStrFull = "{}/{}".format(ipv4.address, ipv4.netmask)
addr = ipaddress.IPv4Network(netStrFull, strict=False)
addrStr = '{}/{}'.format(ipv4.address, addr.prefixlen)
addrStr = "{}/{}".format(ipv4.address, addr.prefixlen)
text.append(addrStr)
# TODO IPV6
# if ipv6:
# text += ' ' + ipv6.address
if self.showSpeed:
recvDiff = self.parent.IO[self.iface].bytes_recv \
recvDiff = (
self.parent.IO[self.iface].bytes_recv
- self.parent.prevIO[self.iface].bytes_recv
sentDiff = self.parent.IO[self.iface].bytes_sent \
)
sentDiff = (
self.parent.IO[self.iface].bytes_sent
- self.parent.prevIO[self.iface].bytes_sent
)
recvDiff /= self.parent.dt
sentDiff /= self.parent.dt
text.append('↓{}↑{}'.format(humanSize(recvDiff),
humanSize(sentDiff)))
text.append("↓{}↑{}".format(humanSize(recvDiff), humanSize(sentDiff)))
if self.showTransfer:
text.append('⇓{}⇑{}'.format(
humanSize(self.parent.IO[self.iface].bytes_recv),
humanSize(self.parent.IO[self.iface].bytes_sent)))
text.append(
"⇓{}⇑{}".format(
humanSize(self.parent.IO[self.iface].bytes_recv),
humanSize(self.parent.IO[self.iface].bytes_sent),
)
)
return ' '.join(text)
return " ".join(text)
def onChangeState(self, state):
self.showSsid = state >= 1
@ -402,32 +410,33 @@ class NetworkProvider(Section, PeriodicUpdater):
self.fetchData()
self.changeInterval(5)
class RfkillProvider(Section, PeriodicUpdater):
# TODO FEAT rfkill doesn't seem to indicate that the hardware switch is
# toggled
PATH = '/sys/class/rfkill'
PATH = "/sys/class/rfkill"
def fetcher(self):
t = Text()
for device in os.listdir(self.PATH):
with open(os.path.join(self.PATH, device, 'soft'), 'rb') as f:
softBlocked = f.read().strip() != b'0'
with open(os.path.join(self.PATH, device, 'hard'), 'rb') as f:
hardBlocked = f.read().strip() != b'0'
with open(os.path.join(self.PATH, device, "soft"), "rb") as f:
softBlocked = f.read().strip() != b"0"
with open(os.path.join(self.PATH, device, "hard"), "rb") as f:
hardBlocked = f.read().strip() != b"0"
if not hardBlocked and not softBlocked: