rmonitor 1.0.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +49 -40
- data/bin/rmonitor +38 -100
- data/lib/rmonitor.rb +17 -20
- data/lib/rmonitor/actions.rb +30 -0
- data/lib/rmonitor/actions/builder.rb +15 -0
- data/lib/rmonitor/actions/dsl.rb +23 -0
- data/lib/rmonitor/cache.rb +12 -0
- data/lib/rmonitor/capabilities.rb +38 -0
- data/lib/rmonitor/capabilities/builder.rb +15 -0
- data/lib/rmonitor/capabilities/dsl.rb +15 -0
- data/lib/rmonitor/commands/cl/base.rb +13 -0
- data/lib/rmonitor/commands/cl/invoke.rb +22 -0
- data/lib/rmonitor/commands/cl/list.rb +43 -0
- data/lib/rmonitor/commands/cl/update.rb +20 -0
- data/lib/rmonitor/commands/invoke.rb +23 -0
- data/lib/rmonitor/commands/list.rb +13 -0
- data/lib/rmonitor/commands/update.rb +18 -0
- data/lib/rmonitor/config.rb +27 -0
- data/lib/rmonitor/config/builder.rb +21 -0
- data/lib/rmonitor/config/dsl.rb +25 -0
- data/lib/rmonitor/invoker.rb +9 -0
- data/lib/rmonitor/matcher.rb +32 -0
- data/lib/rmonitor/profile/builder.rb +15 -0
- data/lib/rmonitor/profile/dsl.rb +15 -0
- data/lib/rmonitor/selector.rb +14 -0
- data/lib/rmonitor/strategies/base.rb +10 -0
- data/lib/rmonitor/strategies/optimistic.rb +15 -0
- data/lib/rmonitor/strategies/pessimistic.rb +17 -0
- data/lib/rmonitor/transformer.rb +38 -0
- data/lib/rmonitor/version.rb +1 -1
- data/lib/rmonitor/xrandr.rb +16 -0
- data/test/actions/builder_test.rb +27 -0
- data/test/actions_test.rb +60 -0
- data/test/cache_test.rb +30 -0
- data/test/capabilities/builder_test.rb +23 -0
- data/test/capabilities_test.rb +114 -0
- data/test/commands/cl/invoke_test.rb +38 -0
- data/test/commands/cl/list_test.rb +36 -0
- data/test/commands/cl/update_test.rb +24 -0
- data/test/commands/invoke_test.rb +86 -0
- data/test/commands/list_test.rb +50 -0
- data/test/commands/update_test.rb +67 -0
- data/test/config/builder_test.rb +51 -0
- data/test/config_test.rb +68 -0
- data/test/matcher_test.rb +90 -0
- data/test/profile/builder_test.rb +26 -0
- data/test/selector_test.rb +30 -0
- data/test/strategies/optimistic_test.rb +24 -0
- data/test/strategies/pessimistic_test.rb +26 -0
- data/test/test_helper.rb +19 -0
- data/test/transformer_test.rb +159 -0
- data/test/xrandr_test.rb +76 -0
- metadata +178 -28
- data/.rspec +0 -1
- data/Gemfile +0 -3
- data/Gemfile.lock +0 -24
- data/lib/rmonitor/devices.rb +0 -29
- data/lib/rmonitor/helpers/dsl_helpers.rb +0 -38
- data/lib/rmonitor/helpers/profile_helpers.rb +0 -48
- data/lib/rmonitor/helpers/xrandr_read_helpers.rb +0 -75
- data/lib/rmonitor/helpers/xrandr_write_helpers.rb +0 -55
- data/lib/rmonitor/profiles.rb +0 -51
- data/rmonitor.gemspec +0 -44
- data/spec/lib/helpers/dsl_helper_spec.rb +0 -29
- data/spec/lib/helpers/profile_helpers_spec.rb +0 -138
- data/spec/lib/helpers/xrandr_read_helpers_spec.rb +0 -259
- data/spec/lib/helpers/xrandr_write_helpers_spec.rb +0 -158
- data/spec/support/device_helper.rb +0 -3
- data/spec/support/profile_helper.rb +0 -3
- data/spec/support/string_helpers.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39988281a286deee26d615bb35fb4023b5bca9e0
|
4
|
+
data.tar.gz: 1b09ddd2c01ad30a7f31c75bcd2baf06624b1a90
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 249da323f0ac72f0e52fee4f39cc55cb6d8702e7d098625362874a947dab993d71b2f299e85fbf15f732d6acc67543695de4868ab614e45f5623afeb225d2b68
|
7
|
+
data.tar.gz: a96ea8f0a0f87f286e882e1ea186b60600b9df3cfc3fee2bdf9a93004ff71f48373c48b5979d5d96ac8d8b88eedf00a1c0e8affa92e37d17804fcdc8f612600a
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
## RMonitor
|
2
2
|
|
3
3
|
[![Build Status](https://travis-ci.org/badeball/rmonitor.png)](https://travis-ci.org/badeball/rmonitor)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/badeball/rmonitor/badges/gpa.svg)](https://codeclimate.com/github/badeball/rmonitor)
|
5
|
+
[![Test Coverage](https://codeclimate.com/github/badeball/rmonitor/badges/coverage.svg)](https://codeclimate.com/github/badeball/rmonitor/coverage)
|
4
6
|
|
5
|
-
RMonitor is a tool for
|
6
|
-
|
7
|
-
configurations.
|
8
|
-
|
9
|
-
representing three different monitor setups.
|
7
|
+
RMonitor is a tool for defining monitor profiles that can be invoked. This is
|
8
|
+
useful when you often find yourself in situations with different monitor
|
9
|
+
configurations. The following example shows a configuration containing monitor
|
10
|
+
profiles representing three different setups.
|
10
11
|
|
11
12
|
```ruby
|
12
13
|
profile "docked" do
|
@@ -24,66 +25,59 @@ profile "default" do
|
|
24
25
|
end
|
25
26
|
```
|
26
27
|
|
27
|
-
|
28
|
+
A configuration is parsed and considered from top to bottom. The first profile
|
29
|
+
that is currently invokable (ie. the requested devices with modes and rates are
|
30
|
+
available) is preferred. Profiles can also be invoked by name. `xrandr` is used
|
31
|
+
behind the scenes to read devices and perform changes.
|
28
32
|
|
29
|
-
|
30
|
-
Usage: rmonitor [option]
|
31
|
-
-c, --create [NAME] Create and output a profile with an optional name
|
32
|
-
-i, --invoke NAME Invoke a profile with a given name
|
33
|
-
-u, --update Invoke the most preferable profile
|
34
|
-
-v, --verbose Verbose output
|
35
|
-
-d, --dry-run Do everything except actually update
|
36
|
-
--config-path PATH Specify the path to the configuration file (defaults to ~/.config/rmonitor/config.rb
|
37
|
-
-h, --help Show this message
|
38
|
-
--version Print the version number of rmonitor
|
39
|
-
```
|
40
|
-
|
41
|
-
### --create [NAME]
|
33
|
+
## Installation
|
42
34
|
|
43
|
-
|
35
|
+
The utility can be installed using `gem`.
|
44
36
|
|
45
37
|
```
|
46
|
-
$
|
47
|
-
profile "docked" do
|
48
|
-
device "HDMI1", :mode => "1920x1080", :rate => "60.0", :pos => "0x0"
|
49
|
-
device "HDMI2", :mode => "1920x1080", :rate => "60.0", :pos => "1920x0"
|
50
|
-
end
|
38
|
+
$ gem install rmonitor
|
51
39
|
```
|
52
40
|
|
53
|
-
|
41
|
+
It can be installed system-wide using the following options.
|
54
42
|
|
55
|
-
|
43
|
+
```
|
44
|
+
$ gem install --no-user-install -i "$(ruby -e'puts Gem.default_dir')" -n /usr/local/bin rmonitor
|
45
|
+
```
|
56
46
|
|
57
|
-
|
47
|
+
It is also packaged for Arch Linux.
|
58
48
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
configure your screens upon startup.
|
49
|
+
```
|
50
|
+
$ yaourt -S ruby-rmonitor
|
51
|
+
```
|
63
52
|
|
64
|
-
##
|
53
|
+
## Usage
|
65
54
|
|
66
|
-
The
|
55
|
+
The executable contains three sub-commands. `invoke` will invoke a monitor
|
56
|
+
profile by name.
|
67
57
|
|
68
58
|
```
|
69
|
-
$
|
59
|
+
$ rmonitor invoke --name "docked"
|
70
60
|
```
|
71
61
|
|
72
|
-
|
62
|
+
The `update` command will invoke the most preferred monitor profile. This
|
63
|
+
command can be mapped to XF86Display to achieve the functionality that one can
|
64
|
+
see in eg, windows or apple machines.
|
73
65
|
|
74
66
|
```
|
75
|
-
$
|
67
|
+
$ rmonitor update
|
76
68
|
```
|
77
69
|
|
78
|
-
|
70
|
+
Lastly there is `list` which just list all defined monitor profiles.
|
79
71
|
|
80
72
|
```
|
81
|
-
$
|
73
|
+
$ rmonitor list
|
82
74
|
```
|
83
75
|
|
84
76
|
## Configurable options
|
85
77
|
|
86
|
-
The following examples shows how RMonitor can be configured.
|
78
|
+
The following examples shows how RMonitor can be configured. The default
|
79
|
+
configuration path is `~/.config/rmonitor/config.rb`, but can be configured
|
80
|
+
using the `--config-path` argument.
|
87
81
|
|
88
82
|
```ruby
|
89
83
|
# Specify device location with position
|
@@ -136,6 +130,21 @@ end
|
|
136
130
|
|
137
131
|
## Changelog
|
138
132
|
|
133
|
+
### 2.0.0
|
134
|
+
|
135
|
+
* Re-implementing the --config-path option.
|
136
|
+
* Re-implementing the :dpi profile option.
|
137
|
+
|
138
|
+
### 2.0.0.rc2
|
139
|
+
|
140
|
+
* Relaxing the regular expression for matching device names. Previously it
|
141
|
+
would not match eg. `DP1-1`, but now it does.
|
142
|
+
|
143
|
+
### 2.0.0.rc1
|
144
|
+
|
145
|
+
* Complete revamp of the codebase. Test coverage is wastly better. The code is
|
146
|
+
more maintainable and ready for change.
|
147
|
+
|
139
148
|
### 1.0.0
|
140
149
|
|
141
150
|
* The -a option is removed.
|
data/bin/rmonitor
CHANGED
@@ -1,112 +1,50 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
require "commander/import"
|
4
|
+
require "rmonitor"
|
5
|
+
require "rmonitor/version"
|
6
|
+
|
7
|
+
program :name, "rmonitor"
|
8
|
+
program :version, RMonitor::VERSION
|
9
|
+
program :description, "A tool for creating monitor profiles that are easily invoked."
|
10
|
+
|
11
|
+
global_option "-c", "--config-path PATH", <<DESC.strip do |path|
|
12
|
+
Specify the path to the configuration file (defaults to ~/.config/rmonitor/config.rb)
|
13
|
+
DESC
|
14
|
+
RMonitor::Config.config_path = path
|
11
15
|
end
|
12
16
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
options[:action] = :invoke
|
25
|
-
options[:name] = name
|
26
|
-
end
|
27
|
-
|
28
|
-
opts.on("-u", "--update", "Invoke the most preferable profile") do
|
29
|
-
options[:action] = :update
|
30
|
-
end
|
31
|
-
|
32
|
-
opts.on("-v", "--verbose", "Verbose output") do
|
33
|
-
options[:verbose] = true
|
34
|
-
end
|
35
|
-
|
36
|
-
opts.on("-d", "--dry-run", "Do everything except actually update (implies -v)") do
|
37
|
-
options[:dry_run] = true
|
38
|
-
options[:verbose] = true
|
39
|
-
end
|
40
|
-
|
41
|
-
opts.on("--config-path PATH", String, "Specify the path to the configuration file (defaults to ~/.config/rmonitor/config.rb") do |config_path|
|
42
|
-
RMonitor.config_path = config_path
|
17
|
+
command :invoke do |c|
|
18
|
+
c.syntax = "invoke [options]"
|
19
|
+
c.description = "invoke a profile by name"
|
20
|
+
c.option "-n", "--name NAME", String
|
21
|
+
c.option "--dry-run", "don't run any destructive commands"
|
22
|
+
c.option "--verbose", "print every command ran"
|
23
|
+
c.action do |_, options|
|
24
|
+
RMonitor::Commands::CL::Invoke.new(
|
25
|
+
:verbose => options.verbose,
|
26
|
+
:dry_run => options.dry_run
|
27
|
+
).execute(options.name)
|
43
28
|
end
|
44
|
-
|
45
|
-
opts.on_tail("-h", "--help", "Show this message") do
|
46
|
-
puts opts
|
47
|
-
exit
|
48
|
-
end
|
49
|
-
|
50
|
-
opts.on_tail("--version", "Print the version number of rmonitor") do
|
51
|
-
puts "rmonitor #{RMonitor::VERSION}"
|
52
|
-
exit
|
53
|
-
end
|
54
|
-
end.parse!
|
55
|
-
|
56
|
-
def v_puts(content)
|
57
|
-
if options[:verbose]
|
58
|
-
puts content
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def exit_with(content)
|
63
|
-
$stderr.puts content
|
64
|
-
exit! 1
|
65
29
|
end
|
66
30
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
RMonitor::Profiles.invokable?(rm.devices, profile)
|
73
|
-
end
|
74
|
-
|
75
|
-
if profile
|
76
|
-
v_puts "Found #{profile[:name].inspect} that is invokable."
|
77
|
-
options[:name] = profile[:name]
|
78
|
-
options[:action] = :invoke
|
79
|
-
else
|
80
|
-
exit_with 'no invokable profile exists'
|
31
|
+
command :list do |c|
|
32
|
+
c.syntax = "list"
|
33
|
+
c.description = "lists all available profiles"
|
34
|
+
c.action do
|
35
|
+
RMonitor::Commands::CL::List.new.execute
|
81
36
|
end
|
82
37
|
end
|
83
38
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
end
|
95
|
-
else
|
96
|
-
exit_with 'no profile with that name exists'
|
97
|
-
end
|
98
|
-
|
99
|
-
elsif options[:action] == :create
|
100
|
-
puts "profile #{(options[:name] || 'My profile').inspect} do"
|
101
|
-
rm.devices.each do |device|
|
102
|
-
if device[:enabled]
|
103
|
-
puts ' device %s, :mode => %s, :rate => %s, :pos => %s' % [
|
104
|
-
device[:name].inspect,
|
105
|
-
device[:configuration][:mode].inspect,
|
106
|
-
device[:configuration][:rate].inspect,
|
107
|
-
device[:pos].inspect,
|
108
|
-
]
|
109
|
-
end
|
39
|
+
command :update do |c|
|
40
|
+
c.syntax = "update"
|
41
|
+
c.description = "invokes the most preferred profile"
|
42
|
+
c.option "--dry-run", "don't run any destructive commands"
|
43
|
+
c.option "--verbose", "print every command ran"
|
44
|
+
c.action do |_, options|
|
45
|
+
RMonitor::Commands::CL::Update.new(
|
46
|
+
:verbose => options.verbose,
|
47
|
+
:dry_run => options.dry_run
|
48
|
+
).execute
|
110
49
|
end
|
111
|
-
puts 'end'
|
112
50
|
end
|
data/lib/rmonitor.rb
CHANGED
@@ -1,23 +1,20 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "rmonitor/commands/cl/invoke"
|
2
|
+
require "rmonitor/commands/cl/list"
|
3
|
+
require "rmonitor/commands/cl/update"
|
4
|
+
require "rmonitor/strategies/optimistic"
|
5
|
+
require "rmonitor/strategies/pessimistic"
|
6
|
+
require "rmonitor/actions"
|
7
|
+
require "rmonitor/cache"
|
8
|
+
require "rmonitor/capabilities"
|
9
|
+
require "rmonitor/config"
|
10
|
+
require "rmonitor/invoker"
|
11
|
+
require "rmonitor/matcher"
|
12
|
+
require "rmonitor/selector"
|
13
|
+
require "rmonitor/transformer"
|
14
|
+
require "rmonitor/xrandr"
|
5
15
|
|
6
16
|
class RMonitor
|
7
|
-
class
|
8
|
-
|
9
|
-
class
|
10
|
-
attr_accessor :config_path
|
11
|
-
end
|
12
|
-
|
13
|
-
attr_accessor :devices, :profiles
|
14
|
-
|
15
|
-
def initialize(raw_devices_data, raw_profiles_data)
|
16
|
-
@devices = Devices.parse(raw_devices_data)
|
17
|
-
@profiles = Profiles.parse(raw_profiles_data)
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.load
|
21
|
-
self.new(`xrandr -q`, File.new(config_path).read)
|
22
|
-
end
|
17
|
+
class UnknownProfileError < StandardError; end
|
18
|
+
class UninvokableProfileError < StandardError; end
|
19
|
+
class NoInvokableProfileError < StandardError; end
|
23
20
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "rmonitor/actions/builder"
|
2
|
+
|
3
|
+
class RMonitor
|
4
|
+
class Actions
|
5
|
+
def initialize(options = {})
|
6
|
+
@capabilities = options[:capabilities] || Capabilities.new(options).parse
|
7
|
+
end
|
8
|
+
|
9
|
+
def create(profile)
|
10
|
+
actions = []
|
11
|
+
|
12
|
+
@avaialble_devices = @capabilities.map { |capability| capability[:name] }.uniq
|
13
|
+
@desired_devices = profile[:devices].map { |device| device[:name] }
|
14
|
+
|
15
|
+
(@avaialble_devices - @desired_devices).each do |device|
|
16
|
+
actions << {:action => :off, :name => device}
|
17
|
+
end
|
18
|
+
|
19
|
+
if profile[:dpi]
|
20
|
+
actions << {:action => :option, :name => :dpi, :value => profile[:dpi]}
|
21
|
+
end
|
22
|
+
|
23
|
+
profile[:devices].each do |device|
|
24
|
+
actions << device.merge(:action => :on)
|
25
|
+
end
|
26
|
+
|
27
|
+
actions
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class RMonitor
|
2
|
+
class Actions
|
3
|
+
class DSL
|
4
|
+
attr_accessor :actions
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@actions = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def off(name)
|
11
|
+
@actions << {:action => :off, :name => name}
|
12
|
+
end
|
13
|
+
|
14
|
+
def on(name, options = {})
|
15
|
+
@actions << options.merge(:action => :on, :name => name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def dpi(value)
|
19
|
+
@actions << {:action => :option, :name => :dpi, :value => value}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "rmonitor/capabilities/builder"
|
2
|
+
|
3
|
+
class RMonitor
|
4
|
+
class Capabilities
|
5
|
+
def initialize(options = {})
|
6
|
+
@xrandr = options[:xrandr] || XRandR.new(options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def parse(input = @xrandr.invoke)
|
10
|
+
capabilities = []
|
11
|
+
current_name = nil
|
12
|
+
|
13
|
+
input = input.split("\n").tap(&:shift).map(&:strip)
|
14
|
+
|
15
|
+
input.each do |line|
|
16
|
+
if /(?<name>[\w\d-]+) (dis)?connected/ =~ line
|
17
|
+
current_name = name
|
18
|
+
end
|
19
|
+
|
20
|
+
if /(?<mode>\d+x\d+)/ =~ line
|
21
|
+
line.scan(/\s(\d+(?:\.\d+)?)(?:( |\*)( |\+)?)?/) do |rate, native, current|
|
22
|
+
capabilities << {:name => current_name, :mode => mode, :rate => rate}
|
23
|
+
|
24
|
+
if native == "*"
|
25
|
+
capabilities.last[:native] = true
|
26
|
+
end
|
27
|
+
|
28
|
+
if current == "+"
|
29
|
+
capabilities.last[:current] = true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
capabilities
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|