194 lines
3.2 KiB
Ruby
Executable File
194 lines
3.2 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
|
|
|
|
@my_config = config["mod"][name]
|
|
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 Template
|
|
def initialize(template)
|
|
@template = template
|
|
end
|
|
|
|
def render(config, data)
|
|
@config = config
|
|
@panel_data = data
|
|
|
|
return ERB.new(@template).result(binding())
|
|
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 'erb'
|
|
require 'yaml'
|
|
require 'optparse'
|
|
|
|
panel_data = {}
|
|
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"
|
|
|
|
for m in config['modules'] do
|
|
load("#{config['mod_dir']}/#{m}")
|
|
end
|
|
|
|
pipe_r, pipe_w = IO.pipe
|
|
|
|
Modules.get.each do |k, v|
|
|
Object.const_get(v).new(config, k, pipe_w).run
|
|
end
|
|
|
|
Signal.trap("INT") do cleanup; end
|
|
Signal.trap("TERM") do cleanup; end
|
|
|
|
if config['geometry'] == nil
|
|
config['gap'] ||= 0
|
|
config['height'] ||= 14
|
|
|
|
gap = config['gap'].to_i
|
|
|
|
if config['width'] == nil
|
|
y, x = get_x_dims()
|
|
config['width'] = y.to_i - (gap * 2)
|
|
end
|
|
|
|
config['geometry'] = sprintf("%sx%s+%s+%s", config['width'], config['height'], gap, gap)
|
|
end
|
|
|
|
lemonbar_cmd = [
|
|
"lemonbar",
|
|
"-g", config['geometry'],
|
|
"-f", config['fontspec'],
|
|
"-n", config['window_name'],
|
|
"-a", config['active_areas'],
|
|
"-F", config['colours']['fg'],
|
|
"-B", config['colours']['bg']
|
|
]
|
|
|
|
printf("Launching lemonbar as:\n %s\n", lemonbar_cmd.join(" "))
|
|
|
|
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")
|
|
panel_data[mod_name] = data
|
|
|
|
t = Template.new(config['format'])
|
|
pipe_lb.printf("%s\n", t.render(config, panel_data))
|
|
end
|
|
end
|