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
data/.rspec DELETED
@@ -1 +0,0 @@
1
- --require spec_helper
data/Gemfile DELETED
@@ -1,3 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec
@@ -1,24 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- rmonitor (1.0.1)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- diff-lcs (1.2.4)
10
- rspec (2.13.0)
11
- rspec-core (~> 2.13.0)
12
- rspec-expectations (~> 2.13.0)
13
- rspec-mocks (~> 2.13.0)
14
- rspec-core (2.13.1)
15
- rspec-expectations (2.13.0)
16
- diff-lcs (>= 1.1.3, < 2.0)
17
- rspec-mocks (2.13.1)
18
-
19
- PLATFORMS
20
- ruby
21
-
22
- DEPENDENCIES
23
- rmonitor!
24
- rspec
@@ -1,29 +0,0 @@
1
- require 'rmonitor/helpers/xrandr_read_helpers'
2
-
3
- class RMonitor
4
- class Devices
5
- extend XRandRReadHelpers
6
-
7
- def self.parse(devices_data)
8
- # Split the blocks of XRandR output
9
- blocks = split_blocks(devices_data)
10
-
11
- # Filter out blocks that are not devices
12
- devices = collect_devices(blocks)
13
-
14
- # Create a data structure for each block
15
- devices.map! do |device|
16
- {
17
- :name => extract_name(device),
18
- :pos => extract_pos(device),
19
- :connected => extract_connected(device),
20
- :enabled => extract_enabled(device),
21
- :configuration => extract_configuration(device),
22
- :configurations => extract_configurations(device),
23
- }
24
- end
25
-
26
- devices
27
- end
28
- end
29
- end
@@ -1,38 +0,0 @@
1
- class RMonitor
2
- module DSLHelpers
3
- class ProfileBuilder
4
- attr_accessor :profiles
5
-
6
- def initialize
7
- @profiles = []
8
- end
9
-
10
- def profile(name, options = {}, &block)
11
- device_builder = DeviceBuilder.new
12
- device_builder.instance_eval(&block)
13
-
14
- if options[:only_if]
15
- options[:only_if] = method(options[:only_if])
16
- elsif options[:not_if]
17
- options[:not_if] = method(options[:not_if])
18
- end
19
-
20
- @profiles << { :name => name,
21
- :options => options,
22
- :devices => device_builder.devices }
23
- end
24
- end
25
-
26
- class DeviceBuilder
27
- attr_accessor :devices
28
-
29
- def initialize
30
- @devices = []
31
- end
32
-
33
- def device(name, options = {})
34
- @devices << { :name => name }.merge(options)
35
- end
36
- end
37
- end
38
- end
@@ -1,48 +0,0 @@
1
- class RMonitor
2
- module ProfileHelpers
3
- def invokable?(devices, profile, verbose = false)
4
- necessary_devices_present = necessary_devices_present?(devices, profile)
5
- user_defined_rules_satisfied = user_defined_rules_satisfied?(profile)
6
-
7
- if necessary_devices_present && !user_defined_rules_satisfied && verbose
8
- method = (profile[:options][:not_if] || profile[:options][:only_if]).name
9
-
10
- puts "#{profile[:name].inspect} deemed not invokable due to #{method.inspect}."
11
- end
12
-
13
- necessary_devices_present && user_defined_rules_satisfied
14
- end
15
-
16
- def necessary_devices_present?(devices, profile)
17
- profile[:devices].all? do |wanted_device|
18
- device = devices.find { |d| d[:name] == wanted_device[:name] }
19
-
20
- device and
21
- has_matching_configuration(device,
22
- wanted_device[:mode],
23
- wanted_device[:rate])
24
- end
25
- end
26
-
27
- def user_defined_rules_satisfied?(profile)
28
- if profile[:options][:only_if]
29
- profile[:options][:only_if].call
30
- elsif profile[:options][:not_if]
31
- !profile[:options][:not_if].call
32
- else
33
- true
34
- end
35
- end
36
-
37
- def best_matching_configuration(device, mode, rate)
38
- device[:configurations].find do |configuration|
39
- (!mode or configuration[:mode] == mode) &&
40
- (!rate or configuration[:rate] == rate)
41
- end
42
- end
43
-
44
- def has_matching_configuration(device, mode, rate)
45
- !best_matching_configuration(device, mode, rate).nil?
46
- end
47
- end
48
- end
@@ -1,75 +0,0 @@
1
- class RMonitor
2
- module XRandRReadHelpers
3
- def split_blocks(devices_data)
4
- block = /
5
- ^[^\s] .+? \n (?=[^\s]|\Z)
6
- /mx
7
-
8
- devices_data.scan(block)
9
- end
10
-
11
- def collect_devices(blocks)
12
- blocks.reject do |block|
13
- block.match(/\AScreen/)
14
- end
15
- end
16
-
17
- def extract_name(block)
18
- block.split.first
19
- end
20
-
21
- def extract_pos(block)
22
- if /\+(?<x_pos>\d+)\+(?<y_pos>\d+)/ =~ block
23
- "#{x_pos}x#{y_pos}"
24
- end
25
- end
26
-
27
- def extract_enabled(block)
28
- block.match(/\d+x\d+\+\d+\+\d+/)
29
- end
30
-
31
- def extract_connected(block)
32
- block.match(/(?<!dis)connected/)
33
- end
34
-
35
- def extract_configuration(block)
36
- # Consider each line except the first
37
- block.split("\n")[1..-1].each do |configuration_line|
38
-
39
- # See if it contains any current configurations
40
- if /(?<rate>\d+\.\d+)\*/ =~ configuration_line
41
-
42
- # Extract the mode (resolution)
43
- /(?<mode>\d+x\d+)/ =~ configuration_line
44
- return {
45
- :mode => mode,
46
- :rate => rate,
47
- }
48
- end
49
- end
50
-
51
- nil
52
- end
53
-
54
- def extract_configurations(block)
55
- configurations = []
56
-
57
- # Consider each line except the first
58
- block.split("\n")[1..-1].each do |configuration_block|
59
-
60
- # Extract the mode (resolution)
61
- /(?<mode>\d+x\d+)/ =~ configuration_block
62
-
63
- # Extract each supported frame rate of that mode (resolution)
64
- configuration_block.scan(/\d+\.\d+/).each do |rate|
65
- configurations << {
66
- :mode => mode,
67
- :rate => rate,
68
- }
69
- end
70
- end
71
-
72
- configurations
73
- end
74
- end
75
- end
@@ -1,55 +0,0 @@
1
- class RMonitor
2
- module XRandRWriteHelpers
3
- def turn_off(device)
4
- "--output #{device} --off"
5
- end
6
-
7
- def turn_on(device, options)
8
- on = '--output %s --mode %s --rate %s' % [
9
- device,
10
- options[:mode],
11
- options[:rate],
12
- ]
13
-
14
- if options[:pos]
15
- on << ' --pos ' << options[:pos]
16
- elsif options[:left_of]
17
- on << ' --left-of ' << options[:left_of]
18
- elsif options[:right_of]
19
- on << ' --right-of ' << options[:right_of]
20
- elsif options[:above]
21
- on << ' --above ' << options[:above]
22
- elsif options[:below]
23
- on << ' --below ' << options[:below]
24
- elsif options[:same_as]
25
- on << ' --same-as ' << options[:same_as]
26
- end
27
-
28
- if options[:rotate]
29
- allowed_options = %w(normal inverted left right)
30
-
31
- if allowed_options.include?(options[:rotate])
32
- on << ' --rotate ' << options[:rotate]
33
- else
34
- raise XRandRArgumentError.new("Invalid argument for --rotate")
35
- end
36
- end
37
-
38
- if options[:reflect]
39
- allowed_options = %w(normal x y xy)
40
-
41
- if allowed_options.include?(options[:reflect])
42
- on << ' --reflect ' << options[:reflect]
43
- else
44
- raise XRandRArgumentError.new("Invalid argument for --reflect")
45
- end
46
- end
47
-
48
- if options[:primary]
49
- on << ' --primary'
50
- end
51
-
52
- on
53
- end
54
- end
55
- end
@@ -1,51 +0,0 @@
1
- require 'rmonitor/helpers/dsl_helpers'
2
- require 'rmonitor/helpers/profile_helpers'
3
- require 'rmonitor/helpers/xrandr_write_helpers'
4
-
5
- class RMonitor
6
- class Profiles
7
- include DSLHelpers
8
- extend ProfileHelpers
9
- extend XRandRWriteHelpers
10
-
11
- def self.parse(config_data)
12
- profile_builder = ProfileBuilder.new
13
- profile_builder.instance_eval(config_data)
14
- profile_builder.profiles
15
- end
16
-
17
- def self.to_xrandr(devices, profile)
18
- xrandr = 'xrandr'
19
-
20
- # Devices that are currently enabled, but not contained in the profile
21
- to_disable = devices.select { |d| d[:enabled ]}.map { |d| d[:name] } -
22
- profile[:devices].map { |d| d[:name] }
23
-
24
- unless to_disable.empty?
25
- to_disable.each do |name|
26
- xrandr << ' ' << turn_off(name)
27
- end
28
-
29
- xrandr << ' && xrandr'
30
- end
31
-
32
- if profile[:options] and profile[:options][:dpi]
33
- xrandr << ' --dpi ' << profile[:options][:dpi].to_s
34
- end
35
-
36
- # The devices contained in the profile are to be turned on and configured
37
- profile[:devices].each do |wanted_device|
38
- device = devices.find { |d| d[:name] == wanted_device[:name] }
39
-
40
- configuration = best_matching_configuration(device,
41
- wanted_device[:mode],
42
- wanted_device[:rate])
43
-
44
- xrandr << ' ' << turn_on(device[:name],
45
- configuration.merge(wanted_device))
46
- end
47
-
48
- xrandr
49
- end
50
- end
51
- end
@@ -1,44 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'lib', 'rmonitor', 'version')
2
-
3
- Gem::Specification.new do |s|
4
- s.name = 'rmonitor'
5
- s.version = RMonitor::VERSION
6
- s.license = 'MIT'
7
- s.date = '2014-08-14'
8
-
9
- s.summary = 'A tool for creating monitor profiles that are easily invoked.'
10
- s.description = 'RMonitor is a tool for creating monitor profiles that are easily invoked. This is useful when you often find yourself in situations with different monitor configurations.'
11
-
12
- s.authors = ['Jonas Amundsen']
13
- s.email = ['jonasba+gem@gmail.com']
14
- s.homepage = 'https://github.com/badeball/rmonitor'
15
-
16
- s.executables = 'rmonitor'
17
-
18
- s.files = %w[
19
- bin/rmonitor
20
- lib/rmonitor/helpers/dsl_helpers.rb
21
- lib/rmonitor/helpers/profile_helpers.rb
22
- lib/rmonitor/helpers/xrandr_read_helpers.rb
23
- lib/rmonitor/helpers/xrandr_write_helpers.rb
24
- lib/rmonitor/devices.rb
25
- lib/rmonitor/profiles.rb
26
- lib/rmonitor/version.rb
27
- lib/rmonitor.rb
28
- spec/lib/helpers/dsl_helper_spec.rb
29
- spec/lib/helpers/profile_helpers_spec.rb
30
- spec/lib/helpers/xrandr_read_helpers_spec.rb
31
- spec/lib/helpers/xrandr_write_helpers_spec.rb
32
- spec/support/device_helper.rb
33
- spec/support/profile_helper.rb
34
- spec/support/string_helpers.rb
35
- .rspec
36
- Gemfile
37
- Gemfile.lock
38
- LICENSE
39
- README.md
40
- rmonitor.gemspec
41
- ]
42
-
43
- s.add_development_dependency('rspec')
44
- end
@@ -1,29 +0,0 @@
1
- require 'rmonitor/helpers/dsl_helpers'
2
-
3
- describe RMonitor::DSLHelpers::ProfileBuilder do
4
- context "with :only_if being present" do
5
- it "should replace the symbol with the respective method proc" do
6
- profile_parser = RMonitor::DSLHelpers::ProfileBuilder.new
7
-
8
- profile_parser.define_singleton_method(:user_defined_rule) do
9
- # No operation
10
- end
11
-
12
- profile_parser.profile("dummy profile", :only_if => :user_defined_rule) do end
13
- profile_parser.profiles.first[:options][:only_if].is_a?(Method).should be_true
14
- end
15
- end
16
-
17
- context "with :not_if being present" do
18
- it "should replace the symbol with the respective method proc" do
19
- profile_parser = RMonitor::DSLHelpers::ProfileBuilder.new
20
-
21
- profile_parser.define_singleton_method(:user_defined_rule) do
22
- # No operation
23
- end
24
-
25
- profile_parser.profile("dummy profile", :not_if => :user_defined_rule) do end
26
- profile_parser.profiles.first[:options][:not_if].is_a?(Method).should be_true
27
- end
28
- end
29
- end
@@ -1,138 +0,0 @@
1
- require 'rmonitor/devices'
2
- require 'rmonitor/helpers/profile_helpers'
3
-
4
- describe RMonitor::ProfileHelpers do
5
- include RMonitor::ProfileHelpers
6
-
7
- describe :invokable? do
8
- after do
9
- rspec_reset
10
- end
11
-
12
- context "with necessary devices not being present" do
13
- it "should return false" do
14
- stub!(:necessary_devices_present?).and_return(false)
15
- stub!(:user_defined_rules_satisfied?).and_return(true)
16
-
17
- invokable?(nil, nil).should be_false
18
- end
19
- end
20
-
21
- context "with user defined rules not being satisfied" do
22
- it "should return false" do
23
- stub!(:necessary_devices_present?).and_return(true)
24
- stub!(:user_defined_rules_satisfied?).and_return(false)
25
-
26
- invokable?(nil, nil).should be_false
27
- end
28
- end
29
-
30
- context "with necessary devices being present and user defined rules being satisfied" do
31
- it "should return true" do
32
- stub!(:necessary_devices_present?).and_return(true)
33
- stub!(:user_defined_rules_satisfied?).and_return(true)
34
-
35
- invokable?(nil, nil).should be_true
36
- end
37
- end
38
- end
39
-
40
- describe :user_defined_rules_satisfied? do
41
- context "with :only_if being present" do
42
- it "should return what the user defined rule is returning" do
43
- profile = {
44
- :options => {
45
- :only_if => Proc.new { true }
46
- }
47
- }
48
-
49
- user_defined_rules_satisfied?(profile).should be_true
50
- end
51
- end
52
-
53
- context "with :not_if being present" do
54
- it "should return the opposite of what the user defined rule is returning" do
55
- profile = {
56
- :options => {
57
- :not_if => Proc.new { true }
58
- }
59
- }
60
-
61
- user_defined_rules_satisfied?(profile).should be_false
62
- end
63
- end
64
- end
65
-
66
- describe :best_matching_configuration do
67
- context "no matching configuration" do
68
- it "should return nil" do
69
- device = parse_device <<-D.strip_heredoc
70
- HDMI1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 477mm x 268mm
71
- 1920x1080 60.0*+
72
- 1280x1024 75.0 60.0
73
- 1152x864 75.0
74
- 1024x768 75.1 60.0
75
- 800x600 75.0 60.3
76
- 640x480 75.0 60.0
77
- 720x400 70.1
78
- D
79
-
80
- best_matching_configuration(device, "1280x768", nil).should == nil
81
- end
82
- end
83
-
84
- context "one matching configuration" do
85
- it "should return it" do
86
- device = parse_device <<-D.strip_heredoc
87
- HDMI1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 477mm x 268mm
88
- 1920x1080 60.0*+
89
- 1280x1024 75.0 60.0
90
- 1152x864 75.0
91
- 1024x768 75.1 60.0
92
- 800x600 75.0 60.3
93
- 640x480 75.0 60.0
94
- 720x400 70.1
95
- D
96
-
97
- best_matching_configuration(device, "1920x1080", nil).should == { :mode => "1920x1080",
98
- :rate => "60.0" }
99
- end
100
- end
101
-
102
- context "more matching configurations due to no rate specified" do
103
- it "should return the 'best' configuration" do
104
- device = parse_device <<-D.strip_heredoc
105
- HDMI1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 477mm x 268mm
106
- 1920x1080 60.0*+
107
- 1280x1024 75.0 60.0
108
- 1152x864 75.0
109
- 1024x768 75.1 60.0
110
- 800x600 75.0 60.3
111
- 640x480 75.0 60.0
112
- 720x400 70.1
113
- D
114
-
115
- best_matching_configuration(device, "1280x1024", nil).should == { :mode => "1280x1024",
116
- :rate => "75.0" }
117
- end
118
- end
119
-
120
- context "more matching configurations due to no mode specified" do
121
- it "should return the 'best' configuration" do
122
- device = parse_device <<-D.strip_heredoc
123
- HDMI1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 477mm x 268mm
124
- 1920x1080 60.0*+
125
- 1280x1024 75.0 60.0
126
- 1152x864 75.0
127
- 1024x768 75.1 60.0
128
- 800x600 75.0 60.3
129
- 640x480 75.0 60.0
130
- 720x400 70.1
131
- D
132
-
133
- best_matching_configuration(device, nil, "60.0").should == { :mode => "1920x1080",
134
- :rate => "60.0" }
135
- end
136
- end
137
- end
138
- end