1 # Copyright (C) 2008 Dag Odenhall <dag.odenhall@gmail.com>
2 # Licensed under the Academic Free License version 3.0
5 require 'amazing/options'
6 require 'amazing/x11/display_name'
8 require 'amazing/widget'
9 require 'amazing/proc_file'
10 require 'amazing/widgets'
11 require 'amazing/awesome'
18 # Command line interface runner
24 @log = Logger.new(STDOUT)
25 @options = Options.new(@args)
27 @display = X11::DisplayName.new
28 rescue X11::EmptyDisplayName => e
29 @log.warn("#{e.message}, falling back on :0")
30 @display = X11::DisplayName.new(":0")
31 rescue X11::InvalidDisplayName => e
32 @log.fatal("#{e.message}, exiting")
39 @log.fatal("Received SIGINT, exiting")
44 show_help if @options[:help]
48 list_widgets if @options[:listwidgets]
49 test_widget if @options[:test]
51 @awesome = Awesome.new(@display.display)
52 explicit_updates unless @options[:update].empty?
57 @config["widgets"].each do |screen, widgets|
58 widgets.each do |widget_name, settings|
59 if settings["every"] && count % settings["every"] == 0
60 update_widget(screen, widget_name)
78 @log.level = Logger.const_get(@options[:loglevel].upcase)
80 @log.error("Unsupported log level #{@options[:loglevel].inspect}")
81 @log.level = Logger::INFO
86 scripts = @options[:include]
87 @config["include"].each do |script|
88 script = "#{File.dirname(@options[:config])}/#{script}" if script[0] != ?/
91 if @options[:autoinclude]
92 scripts << Dir["#{ENV["HOME"]}/.amazing/widgets/*"]
94 scripts.flatten.each do |script|
95 if File.exist?(script)
96 @log.debug("Loading script #{script.inspect}")
98 Widgets.module_eval(File.read(script), script)
99 rescue SyntaxError => e
100 @log.error("Bad syntax in #{script} at line #{e.to_s.scan(/:(\d+)/)}")
103 @log.error("No such widget script #{script.inspect}")
109 longest_widget_name = Widgets.constants.inject {|a,b| a.length > b.length ? a : b }.length
110 Widgets.constants.each do |widget|
111 widget_class = Widgets.const_get(widget)
112 puts "%-#{longest_widget_name}s : %s" % [widget, widget_class.description]
113 widget_class.dependencies.each do |name, description|
114 puts "#{" " * longest_widget_name} require '#{name}' # #{description}"
116 widget_class.options.each do |name, info|
117 puts "#{" " * longest_widget_name} #{name}: <#{info[:description]}> || #{info[:default].inspect}"
119 widget_class.fields.each do |name, info|
120 puts "#{" " * longest_widget_name} @#{name} = <#{info[:description]}> || #{info[:default].inspect}"
128 widget = Widgets.const_get(@options[:test])
129 settings = YAML.load("{#{ARGV[0]}}")
130 instance = widget.new("test", settings)
131 longest_field_name = widget.fields.keys.inject {|a,b| a.to_s.length > b.to_s.length ? a : b }.to_s.length
132 widget.fields.keys.each do |field|
133 puts "@%-#{longest_field_name}s = %s" % [field, instance.instance_variable_get("@#{field}".to_sym).inspect]
139 @log.debug("Parsing configuration file")
141 @config = YAML.load_file(@options[:config])
143 @log.fatal("Unable to parse configuration file, exiting")
146 @config["include"] ||= []
150 @log.debug("Waiting for awesome control socket for display #{@display.display}")
152 Timeout.timeout(30) do
153 sleep 1 until File.exist?("#{ENV["HOME"]}/.awesome_ctl.#{@display.display}")
154 @log.debug("Got socket for display #{@display.display}")
156 rescue Timeout::Error
157 @log.fatal("Socket for display #{@display.display} not created within 30 seconds, exiting")
163 @config["widgets"].each do |screen, widgets|
164 widgets.each_key do |widget_name|
165 next unless @options[:update].include? widget_name
166 update_widget(screen, widget_name, false)
173 path = "#{ENV["HOME"]}/.amazing/pids"
174 FileUtils.makedirs(path)
175 File.open("#{path}/#{@display.display}.pid", "w+") do |f|
181 File.delete("#{ENV["HOME"]}/.amazing/pids/#{@display.display}.pid") rescue Errno::ENOENT
184 def update_non_interval
185 @config["widgets"].each do |screen, widgets|
186 widgets.each do |widget_name, settings|
187 next if settings["every"]
188 update_widget(screen, widget_name)
193 def update_widget(screen, widget_name, threaded=true)
194 settings = @config["widgets"][screen][widget_name]
196 @log.debug("Updating widget #{widget_name} of type #{settings["type"]} on screen #{screen}")
198 widget = Widgets.const_get(settings["type"]).new(widget_name, settings)
199 @awesome.widget_tell(screen, widget_name, widget.formatize)
206 rescue WidgetError => e
207 @log.error(settings["type"]) { e.message }