dag-amazing 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +202 -0
- data/README.rdoc +72 -0
- data/bin/amazing +19 -0
- data/lib/amazing.rb +24 -0
- data/lib/amazing/awesome.rb +46 -0
- data/lib/amazing/cli.rb +66 -0
- data/lib/amazing/cli/commands.rb +240 -0
- data/lib/amazing/cli/helpers.rb +159 -0
- data/lib/amazing/cli/initializers.rb +60 -0
- data/lib/amazing/config.rb +66 -0
- data/lib/amazing/config/dsl.rb +32 -0
- data/lib/amazing/config/dsl/awesome.rb +26 -0
- data/lib/amazing/config/dsl/awesome/widget.rb +27 -0
- data/lib/amazing/config/yaml.rb +11 -0
- data/lib/amazing/helpers/pango_markup.rb +26 -0
- data/lib/amazing/numeric.rb +50 -0
- data/lib/amazing/options.rb +93 -0
- data/lib/amazing/proc_file.rb +59 -0
- data/lib/amazing/string.rb +19 -0
- data/lib/amazing/widget.rb +140 -0
- data/lib/amazing/widgets.rb +37 -0
- data/lib/amazing/widgets/ac_adapter.rb +31 -0
- data/lib/amazing/widgets/alsa.rb +35 -0
- data/lib/amazing/widgets/battery.rb +51 -0
- data/lib/amazing/widgets/clock.rb +31 -0
- data/lib/amazing/widgets/cpu_info.rb +35 -0
- data/lib/amazing/widgets/cpu_usage.rb +50 -0
- data/lib/amazing/widgets/file.rb +44 -0
- data/lib/amazing/widgets/file_system.rb +42 -0
- data/lib/amazing/widgets/gmail.rb +61 -0
- data/lib/amazing/widgets/maildir.rb +34 -0
- data/lib/amazing/widgets/memory.rb +47 -0
- data/lib/amazing/widgets/moc.rb +80 -0
- data/lib/amazing/widgets/mpd.rb +146 -0
- data/lib/amazing/widgets/net_traffic.rb +50 -0
- data/lib/amazing/widgets/noop.rb +24 -0
- data/lib/amazing/widgets/pacman.rb +34 -0
- data/lib/amazing/widgets/raggle.rb +42 -0
- data/lib/amazing/widgets/sup.rb +38 -0
- data/lib/amazing/x11.rb +15 -0
- data/lib/amazing/x11/display_name.rb +50 -0
- metadata +101 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
# Copyright 2008 Dag Odenhall <dag.odenhall@gmail.com>
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Amazing
|
16
|
+
class CLI
|
17
|
+
module Helpers
|
18
|
+
private
|
19
|
+
|
20
|
+
def parse_options
|
21
|
+
@options.parse
|
22
|
+
end
|
23
|
+
|
24
|
+
def set_loglevel
|
25
|
+
begin
|
26
|
+
@log.level = Logger.const_get(@options[:loglevel].upcase)
|
27
|
+
|
28
|
+
rescue NameError
|
29
|
+
@log.error("Unsupported log level #{@options[:loglevel].inspect}")
|
30
|
+
@log.level = Logger::INFO
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def stop_process(log=true)
|
35
|
+
Process.kill("SIGINT", File.read("#{ENV["HOME"]}/.amazing/pids/#{@display.display}.pid").to_i)
|
36
|
+
@log.warn("Killed older process") if log
|
37
|
+
rescue
|
38
|
+
end
|
39
|
+
|
40
|
+
def load_scripts
|
41
|
+
scripts = @options[:include]
|
42
|
+
|
43
|
+
if @options[:autoinclude]
|
44
|
+
scripts << Dir["#{ENV["HOME"]}/.amazing/widgets/*"]
|
45
|
+
end
|
46
|
+
|
47
|
+
scripts.flatten.each do |script|
|
48
|
+
if File.exist?(script)
|
49
|
+
@log.debug("Loading script #{script.inspect}")
|
50
|
+
|
51
|
+
begin
|
52
|
+
Widgets.module_eval(File.read(script), script)
|
53
|
+
|
54
|
+
rescue SyntaxError => e
|
55
|
+
@log.error("Bad syntax in #{script} at line #{e.to_s.scan(/:(\d+)/)}")
|
56
|
+
end
|
57
|
+
|
58
|
+
else
|
59
|
+
@log.error("No such widget script #{script.inspect}")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def parse_config
|
65
|
+
@log.debug("Parsing configuration file")
|
66
|
+
|
67
|
+
begin
|
68
|
+
@config = Config.new(@options[:config])
|
69
|
+
|
70
|
+
rescue
|
71
|
+
@log.fatal("Unable to parse configuration file, exiting")
|
72
|
+
|
73
|
+
exit 1
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def wait_for_sockets
|
78
|
+
@log.debug("Waiting for awesome control socket for display #{@display.display}")
|
79
|
+
|
80
|
+
begin
|
81
|
+
Timeout.timeout(30) do
|
82
|
+
sleep 1 until File.exist?("#{ENV["HOME"]}/.awesome_ctl.#{@display.display}")
|
83
|
+
@log.debug("Got socket for display #{@display.display}")
|
84
|
+
end
|
85
|
+
|
86
|
+
rescue Timeout::Error
|
87
|
+
@log.fatal("Socket for display #{@display.display} not created within 30 seconds, exiting")
|
88
|
+
|
89
|
+
exit 1
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def save_pid
|
94
|
+
path = "#{ENV["HOME"]}/.amazing/pids"
|
95
|
+
FileUtils.makedirs(path)
|
96
|
+
|
97
|
+
File.open("#{path}/#{@display.display}.pid", "w+") do |f|
|
98
|
+
f.write($$)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def remove_pid
|
103
|
+
File.delete("#{ENV["HOME"]}/.amazing/pids/#{@display.display}.pid") rescue Errno::ENOENT
|
104
|
+
end
|
105
|
+
|
106
|
+
def set_traps
|
107
|
+
trap("SIGINT") do
|
108
|
+
@log.fatal("Received SIGINT, exiting")
|
109
|
+
remove_pid
|
110
|
+
exit
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def update_non_interval
|
115
|
+
@threads << Thread.new do
|
116
|
+
@config[:awesome].each do |awesome|
|
117
|
+
awesome[:widgets].each do |widget|
|
118
|
+
next if widget[:interval]
|
119
|
+
|
120
|
+
@threads << Thread.new(awesome, widget) do |awesome, widget|
|
121
|
+
update_widget(awesome[:screen], awesome[:statusbar], widget)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def update_widget(screen, statusbar, widget, iteration=0)
|
129
|
+
threads = []
|
130
|
+
@log.debug("Updating widget #{widget[:identifier]} of type #{widget[:module]} on screen #{screen}")
|
131
|
+
|
132
|
+
begin
|
133
|
+
mod = Widgets.const_get(widget[:module]).new(widget.merge(:iteration => iteration))
|
134
|
+
|
135
|
+
if widget[:properties].empty?
|
136
|
+
threads << Thread.new(screen, statusbar, widget, mod) do |screen, statusbar, widget, mod|
|
137
|
+
@awesome.widget_tell(screen, statusbar, widget[:identifier], widget[:property], mod.formatize)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
widget[:properties].each do |property, format|
|
142
|
+
threads << Thread.new(screen, statusbar, widget, property, mod, format) do |screen, statusbar, widget, property, mod, format|
|
143
|
+
@awesome.widget_tell(screen, statusbar, widget[:identifier], property, mod.formatize(format))
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
rescue WidgetError => e
|
148
|
+
@log.error(widget[:module]) { e.message }
|
149
|
+
end
|
150
|
+
|
151
|
+
threads.each {|t| t.join }
|
152
|
+
end
|
153
|
+
|
154
|
+
def join_threads
|
155
|
+
@threads.each {|t| t.join }
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Copyright 2008 Dag Odenhall <dag.odenhall@gmail.com>
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Amazing
|
16
|
+
class CLI
|
17
|
+
module Initializers
|
18
|
+
private
|
19
|
+
|
20
|
+
def initialize_threads
|
21
|
+
@threads = []
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize_encoding
|
25
|
+
$KCODE = "utf-8"
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize_logger
|
29
|
+
@log = Logger.new(STDOUT)
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize_options
|
33
|
+
@options = Options.new(@args)
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize_display
|
37
|
+
begin
|
38
|
+
@display = X11::DisplayName.new
|
39
|
+
|
40
|
+
rescue X11::EmptyDisplayName => e
|
41
|
+
@log.warn("#{e.message}, falling back on :0")
|
42
|
+
@display = X11::DisplayName.new(":0")
|
43
|
+
|
44
|
+
rescue X11::InvalidDisplayName => e
|
45
|
+
@log.fatal("#{e.message}, exiting")
|
46
|
+
|
47
|
+
exit 1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize_awesome
|
52
|
+
@awesome = Awesome.new(@display.display)
|
53
|
+
end
|
54
|
+
|
55
|
+
def initialize_exit
|
56
|
+
at_exit { Thread.list.each {|t| t.exit } }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'amazing/string'
|
2
|
+
require 'amazing/config/dsl'
|
3
|
+
require 'amazing/config/yaml'
|
4
|
+
|
5
|
+
module Amazing
|
6
|
+
class Config < Hash
|
7
|
+
def initialize(config)
|
8
|
+
@config = config
|
9
|
+
case File.extname(@config)[1..-1].to_sym
|
10
|
+
when :rb
|
11
|
+
from_dsl
|
12
|
+
when :yml, :yaml
|
13
|
+
from_yaml
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def from_dsl
|
20
|
+
dsl = Dsl.new(@config)
|
21
|
+
self[:awesome] = []
|
22
|
+
dsl.awesome_statusbars.each do |awesome|
|
23
|
+
self[:awesome] << {}
|
24
|
+
self[:awesome][-1][:screen] = awesome.options[:screen] || 0
|
25
|
+
self[:awesome][-1][:statusbar] = awesome.options[:statusbar] || "mystatusbar"
|
26
|
+
self[:awesome][-1][:widgets] = []
|
27
|
+
awesome.widgets.each do |widget|
|
28
|
+
self[:awesome][-1][:widgets] << {}
|
29
|
+
self[:awesome][-1][:widgets][-1][:identifier] = widget.identifier
|
30
|
+
self[:awesome][-1][:widgets][-1][:properties] = widget.properties
|
31
|
+
self[:awesome][-1][:widgets][-1].merge!(widget.options)
|
32
|
+
self[:awesome][-1][:widgets][-1][:module] ||= widget.identifier
|
33
|
+
self[:awesome][-1][:widgets][-1][:property] ||= "text"
|
34
|
+
self[:awesome][-1][:widgets][-1][:module] = self[:awesome][-1][:widgets][-1][:module].to_s.camel_case
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def from_yaml
|
40
|
+
yaml = Yaml.new(@config)
|
41
|
+
self[:awesome] = []
|
42
|
+
yaml["awesome"].each do |awesome|
|
43
|
+
self[:awesome] << {}
|
44
|
+
self[:awesome][-1][:screen] = awesome["screen"] || 0
|
45
|
+
self[:awesome][-1][:statusbar] = awesome["statusbar"] || "mystatusbar"
|
46
|
+
self[:awesome][-1][:widgets] = []
|
47
|
+
awesome["widgets"].each do |widget|
|
48
|
+
self[:awesome][-1][:widgets] << {}
|
49
|
+
case widget
|
50
|
+
when Hash
|
51
|
+
self[:awesome][-1][:widgets][-1][:identifier] = widget.keys[0]
|
52
|
+
widget.values[0].each do |key, value|
|
53
|
+
self[:awesome][-1][:widgets][-1][key.to_sym] = value
|
54
|
+
end
|
55
|
+
self[:awesome][-1][:widgets][-1][:module] ||= widget.keys[0]
|
56
|
+
when String
|
57
|
+
self[:awesome][-1][:widgets][-1][:identifier] = widget
|
58
|
+
self[:awesome][-1][:widgets][-1][:module] = widget
|
59
|
+
end
|
60
|
+
self[:awesome][-1][:widgets][-1][:property] ||= "text"
|
61
|
+
self[:awesome][-1][:widgets][-1][:module] = self[:awesome][-1][:widgets][-1][:module].to_s.camel_case
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'amazing/config/dsl/awesome'
|
2
|
+
require 'amazing/numeric'
|
3
|
+
|
4
|
+
module Amazing
|
5
|
+
class Config < Hash
|
6
|
+
class Dsl
|
7
|
+
attr_reader :awesome_statusbars
|
8
|
+
|
9
|
+
def initialize(config=nil, &block)
|
10
|
+
@awesome_statusbars = []
|
11
|
+
if config
|
12
|
+
config = File.expand_path(config)
|
13
|
+
@relative_path = File.dirname(config)
|
14
|
+
import(config)
|
15
|
+
end
|
16
|
+
import(&block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def import(config=nil, &block)
|
20
|
+
if config
|
21
|
+
config = "#@relative_path/#{config}" if config[0] != ?/
|
22
|
+
instance_eval(File.read(config))
|
23
|
+
end
|
24
|
+
instance_eval(&block) if block
|
25
|
+
end
|
26
|
+
|
27
|
+
def awesome(opts={}, &block)
|
28
|
+
@awesome_statusbars << Awesome.new(opts, &block)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'amazing/config/dsl/awesome/widget'
|
2
|
+
|
3
|
+
module Amazing
|
4
|
+
class Config < Hash
|
5
|
+
class Dsl
|
6
|
+
class Awesome
|
7
|
+
attr_reader :options
|
8
|
+
attr_reader :widgets
|
9
|
+
|
10
|
+
def initialize(opts={}, &block)
|
11
|
+
@options = opts
|
12
|
+
@widgets = []
|
13
|
+
instance_eval(&block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def set(opts)
|
17
|
+
@options.merge!(opts)
|
18
|
+
end
|
19
|
+
|
20
|
+
def widget(identifier, opts={}, &block)
|
21
|
+
@widgets << Widget.new(identifier, opts, &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Amazing
|
2
|
+
class Config < Hash
|
3
|
+
class Dsl
|
4
|
+
class Awesome
|
5
|
+
class Widget
|
6
|
+
attr_reader :options
|
7
|
+
attr_reader :identifier
|
8
|
+
attr_reader :properties
|
9
|
+
|
10
|
+
def initialize(identifier, opts={}, &block)
|
11
|
+
@identifier, @options = identifier, opts
|
12
|
+
@properties = {}
|
13
|
+
instance_eval(&block) if block
|
14
|
+
end
|
15
|
+
|
16
|
+
def set(opts)
|
17
|
+
@options.merge!(opts)
|
18
|
+
end
|
19
|
+
|
20
|
+
def property(name, &block)
|
21
|
+
@properties[name] = block
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Amazing
|
2
|
+
module Helpers
|
3
|
+
module PangoMarkup
|
4
|
+
def span(text, opts)
|
5
|
+
attrs = opts.map {|key, value| "#{key}=#{value.to_s.inspect}" }.join(" ")
|
6
|
+
"<span #{attrs}>#{text}</span>"
|
7
|
+
end
|
8
|
+
|
9
|
+
def background(color, text)
|
10
|
+
span(text, :background => color)
|
11
|
+
end
|
12
|
+
|
13
|
+
def foreground(color, text)
|
14
|
+
span(text, :foreground => color)
|
15
|
+
end
|
16
|
+
|
17
|
+
def underline(text, style=:single)
|
18
|
+
span(text, :underline => style)
|
19
|
+
end
|
20
|
+
|
21
|
+
def bold(text, level=:bold)
|
22
|
+
span(text, :weight => level)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# Copyright 2008 Dag Odenhall <dag.odenhall@gmail.com>
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
class Numeric
|
16
|
+
def seconds
|
17
|
+
self
|
18
|
+
end
|
19
|
+
alias :second :seconds
|
20
|
+
|
21
|
+
def minutes
|
22
|
+
self * 60
|
23
|
+
end
|
24
|
+
alias :minute :minutes
|
25
|
+
|
26
|
+
def hours
|
27
|
+
minutes * 60
|
28
|
+
end
|
29
|
+
alias :hour :hours
|
30
|
+
|
31
|
+
def days
|
32
|
+
hours * 24
|
33
|
+
end
|
34
|
+
alias :day :days
|
35
|
+
|
36
|
+
def weeks
|
37
|
+
days * 7
|
38
|
+
end
|
39
|
+
alias :week :weeks
|
40
|
+
|
41
|
+
def months
|
42
|
+
weeks * 4
|
43
|
+
end
|
44
|
+
alias :month :months
|
45
|
+
|
46
|
+
def years
|
47
|
+
months * 12
|
48
|
+
end
|
49
|
+
alias :year :years
|
50
|
+
end
|