rmonitor 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/README.md +49 -40
  4. data/bin/rmonitor +38 -100
  5. data/lib/rmonitor.rb +17 -20
  6. data/lib/rmonitor/actions.rb +30 -0
  7. data/lib/rmonitor/actions/builder.rb +15 -0
  8. data/lib/rmonitor/actions/dsl.rb +23 -0
  9. data/lib/rmonitor/cache.rb +12 -0
  10. data/lib/rmonitor/capabilities.rb +38 -0
  11. data/lib/rmonitor/capabilities/builder.rb +15 -0
  12. data/lib/rmonitor/capabilities/dsl.rb +15 -0
  13. data/lib/rmonitor/commands/cl/base.rb +13 -0
  14. data/lib/rmonitor/commands/cl/invoke.rb +22 -0
  15. data/lib/rmonitor/commands/cl/list.rb +43 -0
  16. data/lib/rmonitor/commands/cl/update.rb +20 -0
  17. data/lib/rmonitor/commands/invoke.rb +23 -0
  18. data/lib/rmonitor/commands/list.rb +13 -0
  19. data/lib/rmonitor/commands/update.rb +18 -0
  20. data/lib/rmonitor/config.rb +27 -0
  21. data/lib/rmonitor/config/builder.rb +21 -0
  22. data/lib/rmonitor/config/dsl.rb +25 -0
  23. data/lib/rmonitor/invoker.rb +9 -0
  24. data/lib/rmonitor/matcher.rb +32 -0
  25. data/lib/rmonitor/profile/builder.rb +15 -0
  26. data/lib/rmonitor/profile/dsl.rb +15 -0
  27. data/lib/rmonitor/selector.rb +14 -0
  28. data/lib/rmonitor/strategies/base.rb +10 -0
  29. data/lib/rmonitor/strategies/optimistic.rb +15 -0
  30. data/lib/rmonitor/strategies/pessimistic.rb +17 -0
  31. data/lib/rmonitor/transformer.rb +38 -0
  32. data/lib/rmonitor/version.rb +1 -1
  33. data/lib/rmonitor/xrandr.rb +16 -0
  34. data/test/actions/builder_test.rb +27 -0
  35. data/test/actions_test.rb +60 -0
  36. data/test/cache_test.rb +30 -0
  37. data/test/capabilities/builder_test.rb +23 -0
  38. data/test/capabilities_test.rb +114 -0
  39. data/test/commands/cl/invoke_test.rb +38 -0
  40. data/test/commands/cl/list_test.rb +36 -0
  41. data/test/commands/cl/update_test.rb +24 -0
  42. data/test/commands/invoke_test.rb +86 -0
  43. data/test/commands/list_test.rb +50 -0
  44. data/test/commands/update_test.rb +67 -0
  45. data/test/config/builder_test.rb +51 -0
  46. data/test/config_test.rb +68 -0
  47. data/test/matcher_test.rb +90 -0
  48. data/test/profile/builder_test.rb +26 -0
  49. data/test/selector_test.rb +30 -0
  50. data/test/strategies/optimistic_test.rb +24 -0
  51. data/test/strategies/pessimistic_test.rb +26 -0
  52. data/test/test_helper.rb +19 -0
  53. data/test/transformer_test.rb +159 -0
  54. data/test/xrandr_test.rb +76 -0
  55. metadata +178 -28
  56. data/.rspec +0 -1
  57. data/Gemfile +0 -3
  58. data/Gemfile.lock +0 -24
  59. data/lib/rmonitor/devices.rb +0 -29
  60. data/lib/rmonitor/helpers/dsl_helpers.rb +0 -38
  61. data/lib/rmonitor/helpers/profile_helpers.rb +0 -48
  62. data/lib/rmonitor/helpers/xrandr_read_helpers.rb +0 -75
  63. data/lib/rmonitor/helpers/xrandr_write_helpers.rb +0 -55
  64. data/lib/rmonitor/profiles.rb +0 -51
  65. data/rmonitor.gemspec +0 -44
  66. data/spec/lib/helpers/dsl_helper_spec.rb +0 -29
  67. data/spec/lib/helpers/profile_helpers_spec.rb +0 -138
  68. data/spec/lib/helpers/xrandr_read_helpers_spec.rb +0 -259
  69. data/spec/lib/helpers/xrandr_write_helpers_spec.rb +0 -158
  70. data/spec/support/device_helper.rb +0 -3
  71. data/spec/support/profile_helper.rb +0 -3
  72. data/spec/support/string_helpers.rb +0 -25
@@ -0,0 +1,15 @@
1
+ require "rmonitor/capabilities/dsl"
2
+
3
+ class RMonitor
4
+ class Capabilities
5
+ class Builder
6
+ class << self
7
+ def define(&block)
8
+ dsl = RMonitor::Capabilities::DSL.new
9
+ dsl.instance_eval(&block)
10
+ dsl.capabilities
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ class RMonitor
2
+ class Capabilities
3
+ class DSL
4
+ attr_accessor :capabilities
5
+
6
+ def initialize
7
+ @capabilities = []
8
+ end
9
+
10
+ def device(name, options = {})
11
+ @capabilities << options.merge(:name => name)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ class RMonitor
2
+ module Commands
3
+ module CL
4
+ class Base
5
+ def initialize(options = {})
6
+ @options = options
7
+ @out = options[:out] || $stdout
8
+ @err = options[:err] || $stderr
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,22 @@
1
+ require "rmonitor/commands/invoke"
2
+
3
+ class RMonitor
4
+ module Commands
5
+ module CL
6
+ class Invoke
7
+ def initialize(options = {})
8
+ @err = options[:err] || $stderr
9
+ @invoke = options[:invoke] || RMonitor::Commands::Invoke.new(options)
10
+ end
11
+
12
+ def execute(name)
13
+ @invoke.execute(name)
14
+ rescue RMonitor::UnknownProfileError
15
+ @err.puts "unknown profile"
16
+ rescue RMonitor::UninvokableProfileError
17
+ @err.puts "profile is not invokable"
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,43 @@
1
+ require "rmonitor/commands/list"
2
+
3
+ class RMonitor
4
+ module Commands
5
+ module CL
6
+ class List
7
+ def initialize(options = {})
8
+ @out = options[:out] || $stdout
9
+ @list = options[:list] || RMonitor::Commands::List.new(options)
10
+ @matcher = options[:matcher] || RMonitor::Matcher.new(options)
11
+ end
12
+
13
+ def execute
14
+ profiles = @list.execute
15
+
16
+ profiles.each do |profile|
17
+ @out.write("#{profile[:name]}\t")
18
+
19
+ if @matcher.invokable?(profile)
20
+ @out.write("invokable")
21
+ else
22
+ @out.write("uninvokable")
23
+ end
24
+
25
+ profile[:devices].each do |device|
26
+ @out.write("\t#{device[:name]}")
27
+
28
+ if device[:mode] && device[:rate]
29
+ @out.write(" (#{device[:mode]} #{device[:rate]})")
30
+ elsif device[:mode]
31
+ @out.write(" (#{device[:mode]})")
32
+ elsif device[:rate]
33
+ @out.write(" (#{device[:rate]})")
34
+ end
35
+ end
36
+
37
+ @out.write("\n")
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,20 @@
1
+ require "rmonitor/commands/update"
2
+
3
+ class RMonitor
4
+ module Commands
5
+ module CL
6
+ class Update
7
+ def initialize(options = {})
8
+ @err = options[:err] || $stderr
9
+ @update = options[:update] || RMonitor::Commands::Update.new(options)
10
+ end
11
+
12
+ def execute
13
+ @update.execute
14
+ rescue RMonitor::NoInvokableProfileError
15
+ @err.puts "no invokable profile"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,23 @@
1
+ class RMonitor
2
+ module Commands
3
+ class Invoke
4
+ def initialize(options = {})
5
+ @profiles = options[:profiles] || Config.new.profiles
6
+ @matcher = options[:matcher] || Matcher.new(options)
7
+ @strategy = options[:strategy] || Strategies::Pessimistic.new(options)
8
+ @factory = options[:factory] || Actions.new(options)
9
+ end
10
+
11
+ def execute(name)
12
+ profile = @profiles.find { |p| p[:name] == name }
13
+
14
+ raise UnknownProfileError unless profile
15
+ raise UninvokableProfileError unless @matcher.invokable?(profile)
16
+
17
+ actions = @factory.create(profile)
18
+
19
+ @strategy.execute(actions)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ class RMonitor
2
+ module Commands
3
+ class List
4
+ def initialize(options = {})
5
+ @profiles = options[:profiles] || Config.new.profiles
6
+ end
7
+
8
+ def execute
9
+ @profiles
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ class RMonitor
2
+ module Commands
3
+ class Update
4
+ def initialize(options = {})
5
+ @invoke = options[:invoke] || Invoke.new(options)
6
+ @selector = options[:selector] || Selector.new(options)
7
+ end
8
+
9
+ def execute
10
+ profile = @selector.first_invokable
11
+
12
+ raise NoInvokableProfileError unless profile
13
+
14
+ @invoke.execute(profile[:name])
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ require "rmonitor/config/builder"
2
+
3
+ class RMonitor
4
+ class Config
5
+ def profiles
6
+ Builder.define read
7
+ end
8
+
9
+ def read
10
+ File.read self.class.config_path
11
+ end
12
+
13
+ class << self
14
+ attr_writer :config_path
15
+
16
+ def config_path
17
+ @config_path || default_config_path
18
+ end
19
+
20
+ private
21
+
22
+ def default_config_path
23
+ File.join(Dir.home, ".config", "rmonitor", "config.rb")
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ require "rmonitor/config/dsl"
2
+
3
+ class RMonitor
4
+ class Config
5
+ class Builder
6
+ class << self
7
+ def define(input = nil, &block)
8
+ dsl = RMonitor::Config::DSL.new
9
+
10
+ if input
11
+ dsl.instance_eval(input)
12
+ else
13
+ dsl.instance_eval(&block)
14
+ end
15
+
16
+ dsl.profiles
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ require "rmonitor/profile/builder"
2
+
3
+ class RMonitor
4
+ class Config
5
+ class DSL
6
+ attr_accessor :profiles
7
+
8
+ def initialize
9
+ @profiles = []
10
+ end
11
+
12
+ def profile(name, options = {}, &block)
13
+ @profiles << RMonitor::Profile::Builder.define(name, options, &block)
14
+
15
+ if @profiles.last.has_key?(:only_if)
16
+ @profiles.last[:only_if] = method(@profiles.last[:only_if])
17
+ end
18
+
19
+ if @profiles.last.has_key?(:not_if)
20
+ @profiles.last[:not_if] = method(@profiles.last[:not_if])
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ class RMonitor
2
+ class Invoker
3
+ def initialize(*); end
4
+
5
+ def invoke(command)
6
+ Kernel.`(command)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,32 @@
1
+ class RMonitor
2
+ class Matcher
3
+ def initialize(options = {})
4
+ @capabilities = options[:capabilities] || Capabilities.new(options).parse
5
+ end
6
+
7
+ def invokable?(profile)
8
+ return false if profile.has_key?(:only_if) && !profile[:only_if].call
9
+ return false if profile.has_key?(:not_if) && profile[:not_if].call
10
+
11
+ profile[:devices].all? do |device|
12
+ has_desired_capability? device
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def has_desired_capability?(desire)
19
+ @capabilities.any? do |capability|
20
+ match_desire_capability?(desire, capability)
21
+ end
22
+ end
23
+
24
+ def match_desire_capability?(desire, capability)
25
+ return false if desire[:name] != capability[:name]
26
+ return false if desire[:mode] && desire[:mode] != capability[:mode]
27
+ return false if desire[:rate] && desire[:rate] != capability[:rate]
28
+
29
+ true
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,15 @@
1
+ require "rmonitor/profile/dsl"
2
+
3
+ class RMonitor
4
+ module Profile
5
+ class Builder
6
+ class << self
7
+ def define(name, options = {}, &block)
8
+ dsl = RMonitor::Profile::DSL.new
9
+ dsl.instance_eval &block
10
+ options.merge :name => name, :devices => dsl.devices
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ class RMonitor
2
+ module Profile
3
+ class DSL
4
+ attr_accessor :devices
5
+
6
+ def initialize
7
+ @devices = []
8
+ end
9
+
10
+ def device(name, options = {})
11
+ @devices << options.merge(:name => name)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ class RMonitor
2
+ class Selector
3
+ def initialize(options = {})
4
+ @profiles = options[:profiles] || Config.new.profiles
5
+ @matcher = options[:matcher] || Matcher.new(options)
6
+ end
7
+
8
+ def first_invokable
9
+ @profiles.find do |profile|
10
+ @matcher.invokable? profile
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ class RMonitor
2
+ module Strategies
3
+ class Base
4
+ def initialize(options = {})
5
+ @xrandr = options[:xrandr] || XRandR.new(options)
6
+ @transformer = options[:transformer] || Transformer.new
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ require "rmonitor/strategies/base"
2
+
3
+ class RMonitor
4
+ module Strategies
5
+ class Optimistic < Base
6
+ def execute(actions)
7
+ transformations = actions.map do |action|
8
+ @transformer.transform(action)
9
+ end
10
+
11
+ @xrandr.invoke(*transformations.flatten)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ require "rmonitor/strategies/base"
2
+
3
+ class RMonitor
4
+ module Strategies
5
+ class Pessimistic < Base
6
+ def execute(actions)
7
+ transformations = actions.map do |action|
8
+ @transformer.transform(action)
9
+ end
10
+
11
+ transformations.each do |transformation|
12
+ @xrandr.invoke(*transformation)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,38 @@
1
+ class RMonitor
2
+ class Transformer
3
+ def transform(action)
4
+ case action.delete(:action)
5
+ when :off
6
+ transform_off(action)
7
+ when :on
8
+ transform_on(action)
9
+ when :option
10
+ transforn_option(action)
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def transform_on(action)
17
+ args = ["--output", action.delete(:name)]
18
+
19
+ action.each do |key, value|
20
+ args << "--#{key.to_s.gsub("_", "-")}"
21
+
22
+ unless value.is_a?(TrueClass)
23
+ args << value.to_s
24
+ end
25
+ end
26
+
27
+ args
28
+ end
29
+
30
+ def transform_off(action)
31
+ ["--output", action.delete(:name), "--off"]
32
+ end
33
+
34
+ def transforn_option(action)
35
+ ["--#{action[:name].to_s.gsub("_", "-")}", action[:value].to_s]
36
+ end
37
+ end
38
+ end