rmonitor 1.0.1 → 2.0.0
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.
- 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
|
[](https://travis-ci.org/badeball/rmonitor)
|
4
|
+
[](https://codeclimate.com/github/badeball/rmonitor)
|
5
|
+
[](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
|