moltenbar/moltenbar

210 lines
3.6 KiB
Ruby
Executable File

#!/usr/bin/env ruby
$PROGRAM_NAME = "moltenbar"
# Base worker class
class Worker
@@collector = []
class << self
def instances
return @@collector
end
end
def initialize(config, name, pipe)
@config = config
@name = name
@pipe_in = pipe
if config["mod"][name] != nil
@my_config = config["mod"][name]
end
end
def run()
@wpid = fork do
$PROGRAM_NAME = "moltenbar: worker (#{@name})"
Signal.trap("INT") do; end
mainloop()
end
@@collector << self
return nil
end
def mainloop()
loop do
self.write("I am a dummy")
sleep(1)
end
end
def kill()
begin
if Process.getpgid(@wpid) == Process.getpgid($$)
printf("Killing pid: %s\n", @wpid)
Process.kill("HUP", @wpid)
end
rescue Errno::ESRCH => err
printf("%s: %s\n", err, @wpid)
end
end
def write(data)
@pipe_in.printf("%s\0%s\n", @name, data)
end
end
class DoSystem < Worker
def initialize(name, pipe)
@name = name
@pipe = pipe
end
def mainloop()
@pipe.each do |cmd|
system(cmd)
end
end
end
module Modules
@modules = {}
def self.add(name, class_name)
@modules[name] = class_name
end
def self.get()
return @modules
end
end
class Panel
attr_accessor :modData
def initialize(config)
@modData = {}
@config = config
end
def render
panel = @config["format"]
@modData.each do |modName, modData|
panel = panel.gsub(/@{#{modName}}/, modData)
end
@config["colours"].each do |colName, colValue|
panel = panel.gsub(/C{#{colName}}/, colValue)
end
return panel
end
end
# Kill the workers.
def cleanup
Worker.instances.each do |w|
w.kill
end
exit(0)
end
def get_x_dims()
return `xrandr`.scan(/current (\d+) x (\d+)/).flatten
end
require 'yaml'
require 'optparse'
options = {}
OptionParser.new do |opts|
opts.banner = "Usage: moltenvar [-c]"
opts.on("-cCONFIG_PATH", "--config=CONFIG_PATH", "Specify and alternative config location") do |v|
options[:config_file] = v
end
opts.on("-h", "--help", "Show this message") do
printf("%s", opts)
exit(0)
end
end.parse!
if ENV["XDG_CONFIG_HOME"] == nil
conf_dir = ENV["HOME"] + "/.config/moltenbar"
else
conf_dir = ENV["XDG_CONFIG_HOME"] + "/moltenbar"
end
options[:config_file] ||= conf_dir + "/rc.yaml"
config = YAML.load_file(options[:config_file])
config['mod_dir'] ||= conf_dir + "/mod"
Dir.new("#{config['mod_dir']}").each_child do |m|
printf("Loading module: #{m}\n")
load("#{config['mod_dir']}/#{m}")
end
config["panels"].each do |panelName, panelConf|
pipe_r, pipe_w = IO.pipe
panelConf["modules"].each do |modName, modType|
modClass = Modules.get[modType]
Object.const_get(modClass).new(panelConf, modName, pipe_w).run
end
Signal.trap("INT") do cleanup; end
Signal.trap("TERM") do cleanup; end
if panelConf['geometry'] == nil
panelConf['gap'] ||= 0
panelConf['height'] ||= 14
gap = panelConf['gap'].to_i
if panelConf['width'] == nil
y, x = get_x_dims()
panelConf['width'] = y.to_i - (gap * 2)
end
panelConf['geometry'] = "%{w}x%{h}+%{gap}+%{gap}" % [
w: panelConf['width'],
h: panelConf['height'],
gap: gap
]
end
lemonbar_cmd = [
"lemonbar",
"-g", panelConf['geometry'],
"-f", panelConf['fontspec'],
"-n", panelConf['window_name'],
"-a", panelConf['active_areas'],
"-F", panelConf['colours']['fg'],
"-B", panelConf['colours']['bg']
]
printf("Launching lemonbar as:\n %s\n", lemonbar_cmd.join(" "))
p = Panel.new(panelConf)
IO.popen(lemonbar_cmd, "w+") do |pipe_lb|
pipe_lb.sync = true
DoSystem.new("system", pipe_lb).run
pipe_r.each do |line|
mod_name, data = line.chomp.split("\0")
data ||= ""
p.modData[mod_name] = data
pipe_lb.printf("%s\n", p.render())
end
end
end