uh-wm 0.0.6 → 0.0.7
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/lib/uh/wm/actions_handler.rb +9 -0
- data/lib/uh/wm/cli.rb +1 -1
- data/lib/uh/wm/client.rb +14 -0
- data/lib/uh/wm/env.rb +3 -1
- data/lib/uh/wm/env_logging.rb +1 -1
- data/lib/uh/wm/launcher.rb +73 -0
- data/lib/uh/wm/run_control.rb +10 -0
- data/lib/uh/wm/runner.rb +26 -5
- data/lib/uh/wm/testing/acceptance_helpers.rb +36 -65
- data/lib/uh/wm/testing/x_client.rb +63 -0
- data/lib/uh/wm/version.rb +1 -1
- data/lib/uh/wm/workers/base.rb +1 -1
- data/lib/uh/wm/workers/mux.rb +3 -1
- data/lib/uh/wm.rb +5 -3
- metadata +9 -111
- data/.gitignore +0 -3
- data/.rspec +0 -1
- data/.travis.yml +0 -15
- data/Gemfile +0 -5
- data/Guardfile +0 -12
- data/LICENSE +0 -30
- data/Rakefile +0 -40
- data/config/cucumber.yaml +0 -1
- data/features/actions/execute.feature +0 -9
- data/features/actions/layout_delegation.feature +0 -31
- data/features/actions/quit.feature +0 -9
- data/features/cli/debug.feature +0 -5
- data/features/cli/layout.feature +0 -15
- data/features/cli/require.feature +0 -5
- data/features/cli/run_control.feature +0 -9
- data/features/cli/usage.feature +0 -11
- data/features/cli/verbose.feature +0 -5
- data/features/cli/version.feature +0 -6
- data/features/cli/worker.feature +0 -9
- data/features/layout/manage.feature +0 -12
- data/features/layout/protocol.feature +0 -56
- data/features/layout/unmanage.feature +0 -10
- data/features/manager/change.feature +0 -7
- data/features/manager/check_other_wm.feature +0 -8
- data/features/manager/expose.feature +0 -5
- data/features/manager/input_events.feature +0 -8
- data/features/manager/manage.feature +0 -14
- data/features/manager/unmanage.feature +0 -13
- data/features/manager/x_errors.feature +0 -17
- data/features/run_control/evaluation.feature +0 -18
- data/features/run_control/key.feature +0 -33
- data/features/run_control/layout.feature +0 -39
- data/features/run_control/modifier.feature +0 -10
- data/features/run_control/worker.feature +0 -9
- data/features/session/connection.feature +0 -5
- data/features/session/termination.feature +0 -12
- data/features/steps/filesystem_steps.rb +0 -3
- data/features/steps/output_steps.rb +0 -55
- data/features/steps/run_control_steps.rb +0 -3
- data/features/steps/run_steps.rb +0 -41
- data/features/steps/x_steps.rb +0 -58
- data/features/support/env.rb +0 -33
- data/features/workers/block.feature +0 -15
- data/features/workers/mux.feature +0 -15
- data/spec/spec_helper.rb +0 -30
- data/spec/support/exit_helpers.rb +0 -6
- data/spec/support/factories.rb +0 -27
- data/spec/support/filesystem_helpers.rb +0 -11
- data/spec/uh/wm/actions_handler_spec.rb +0 -35
- data/spec/uh/wm/cli_spec.rb +0 -214
- data/spec/uh/wm/client_spec.rb +0 -148
- data/spec/uh/wm/dispatcher_spec.rb +0 -76
- data/spec/uh/wm/env_spec.rb +0 -154
- data/spec/uh/wm/manager_spec.rb +0 -386
- data/spec/uh/wm/run_control_spec.rb +0 -126
- data/spec/uh/wm/runner_spec.rb +0 -196
- data/uh-wm.gemspec +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3607acc6f3a156a4fe6ecfdd4c960daecdde3bc
|
4
|
+
data.tar.gz: 9aac8a32b1d1619e055e0c5af14e28d8033dfe9f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f332e7a7d0b81b91d356f7e6345f073eb551d0ea6cabe361285df90c62a14b3cecb29c32f339b5fb032d47c343135b7bb676fb026111ef66463bd38f548a504e
|
7
|
+
data.tar.gz: 2e0fbe32e68ef89136a64045f55180fcf3211bd9dc1a4b6dfba461356e3a8076be7d64dcbb989fcacd07d4058dd756c6748315a484c0376d1cacbf304b134a98
|
@@ -38,6 +38,15 @@ module Uh
|
|
38
38
|
Process.waitpid pid
|
39
39
|
end
|
40
40
|
|
41
|
+
def kill_current
|
42
|
+
return unless layout.current_client
|
43
|
+
layout.current_client.kill
|
44
|
+
end
|
45
|
+
|
46
|
+
def log_separator
|
47
|
+
log '- ' * 24
|
48
|
+
end
|
49
|
+
|
41
50
|
def method_missing(m, *args, &block)
|
42
51
|
if respond_to? m
|
43
52
|
meth = layout_method m
|
data/lib/uh/wm/cli.rb
CHANGED
data/lib/uh/wm/client.rb
CHANGED
@@ -66,6 +66,20 @@ module Uh
|
|
66
66
|
@window.focus
|
67
67
|
self
|
68
68
|
end
|
69
|
+
|
70
|
+
def kill
|
71
|
+
if @window.icccm_wm_protocols.include? :WM_DELETE_WINDOW
|
72
|
+
@window.icccm_wm_delete
|
73
|
+
else
|
74
|
+
@window.kill
|
75
|
+
end
|
76
|
+
self
|
77
|
+
end
|
78
|
+
|
79
|
+
def kill!
|
80
|
+
window.kill
|
81
|
+
self
|
82
|
+
end
|
69
83
|
end
|
70
84
|
end
|
71
85
|
end
|
data/lib/uh/wm/env.rb
CHANGED
@@ -16,13 +16,14 @@ module Uh
|
|
16
16
|
|
17
17
|
extend Forwardable
|
18
18
|
def_delegator :logger, :info, :log
|
19
|
+
def_delegator :logger, :fatal, :log_fatal
|
19
20
|
def_delegator :logger, :error, :log_error
|
20
21
|
def_delegator :logger, :debug, :log_debug
|
21
22
|
def_delegators :@output, :print, :puts
|
22
23
|
|
23
24
|
attr_reader :output, :keybinds
|
24
25
|
attr_accessor :verbose, :debug, :rc_path, :modifier, :worker,
|
25
|
-
:layout, :layout_class
|
26
|
+
:layout, :layout_class, :rules, :launch
|
26
27
|
|
27
28
|
def initialize output
|
28
29
|
@output = output
|
@@ -30,6 +31,7 @@ module Uh
|
|
30
31
|
@modifier = MODIFIER
|
31
32
|
@keybinds = KEYBINDS.dup
|
32
33
|
@worker = :block
|
34
|
+
@rules = {}
|
33
35
|
end
|
34
36
|
|
35
37
|
def verbose?
|
data/lib/uh/wm/env_logging.rb
CHANGED
@@ -0,0 +1,73 @@
|
|
1
|
+
module Uh
|
2
|
+
module WM
|
3
|
+
class Launcher
|
4
|
+
class << self
|
5
|
+
def launch runner, instructions
|
6
|
+
new(runner.actions, runner.rules, runner.method(:run_until))
|
7
|
+
.launch instructions
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize actions, rules, run_until
|
12
|
+
@actions = actions
|
13
|
+
@rules = rules
|
14
|
+
@run_until = run_until
|
15
|
+
end
|
16
|
+
|
17
|
+
def launch instructions
|
18
|
+
with_clean_rules do
|
19
|
+
rules = @rules
|
20
|
+
DSL.new(@actions).evaluate(instructions).each do |m, args, block|
|
21
|
+
if m == :execute!
|
22
|
+
@rules[//] = -> { rules.clear }
|
23
|
+
@actions.execute *args, &block
|
24
|
+
@run_until.call { @rules.empty? }
|
25
|
+
else
|
26
|
+
@actions.send m, *args, &block
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def with_clean_rules
|
36
|
+
original_rules = @rules.dup
|
37
|
+
@rules.clear
|
38
|
+
yield
|
39
|
+
@rules.clear
|
40
|
+
@rules.merge! original_rules
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
class DSL
|
45
|
+
def initialize actions
|
46
|
+
@actions = actions
|
47
|
+
@messages = []
|
48
|
+
end
|
49
|
+
|
50
|
+
def evaluate instructions
|
51
|
+
instance_eval &instructions
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def each
|
56
|
+
@messages.each { |m| yield *m }
|
57
|
+
end
|
58
|
+
|
59
|
+
def method_missing m, *args, &block
|
60
|
+
if respond_to? m
|
61
|
+
@messages << [m, args, block]
|
62
|
+
else
|
63
|
+
super
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def respond_to_missing? m, _
|
68
|
+
m == :execute! || @actions.respond_to?(m) || super
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/uh/wm/run_control.rb
CHANGED
@@ -22,6 +22,8 @@ module Uh
|
|
22
22
|
|
23
23
|
def evaluate code, path
|
24
24
|
instance_eval code, path
|
25
|
+
rescue ::StandardError, ::ScriptError => e
|
26
|
+
raise RunControlEvaluationError, e.message, e.backtrace
|
25
27
|
end
|
26
28
|
|
27
29
|
def modifier mod
|
@@ -48,6 +50,14 @@ module Uh
|
|
48
50
|
@env.worker = [type, options]
|
49
51
|
end
|
50
52
|
|
53
|
+
def rule selectors = '', &block
|
54
|
+
[*selectors].each { |selector| @env.rules[/\A#{selector}/i] = block }
|
55
|
+
end
|
56
|
+
|
57
|
+
def launch &block
|
58
|
+
@env.launch = block
|
59
|
+
end
|
60
|
+
|
51
61
|
|
52
62
|
private
|
53
63
|
|
data/lib/uh/wm/runner.rb
CHANGED
@@ -17,7 +17,7 @@ module Uh
|
|
17
17
|
extend Forwardable
|
18
18
|
def_delegator :@env, :layout
|
19
19
|
|
20
|
-
attr_reader :env, :events, :actions
|
20
|
+
attr_reader :env, :events, :actions, :rules
|
21
21
|
|
22
22
|
def initialize env, manager: nil, stopped: false
|
23
23
|
@env = env
|
@@ -25,6 +25,7 @@ module Uh
|
|
25
25
|
@manager = manager
|
26
26
|
@actions = ActionsHandler.new(@env, @events)
|
27
27
|
@stopped = stopped
|
28
|
+
@rules = @env.rules
|
28
29
|
end
|
29
30
|
|
30
31
|
def stopped?
|
@@ -44,7 +45,7 @@ module Uh
|
|
44
45
|
end
|
45
46
|
|
46
47
|
def register_event_hooks
|
47
|
-
%w[runner manager layout keybinds]
|
48
|
+
%w[runner manager layout keybinds rules launcher]
|
48
49
|
.map { |e| "register_#{e}_hooks".to_sym }
|
49
50
|
.each { |e| send e }
|
50
51
|
end
|
@@ -74,7 +75,7 @@ module Uh
|
|
74
75
|
end
|
75
76
|
|
76
77
|
def terminate
|
77
|
-
log
|
78
|
+
log 'Terminating...'
|
78
79
|
manager.disconnect
|
79
80
|
end
|
80
81
|
|
@@ -92,9 +93,15 @@ module Uh
|
|
92
93
|
@events.on :connected do |display|
|
93
94
|
log "Connected to X server on `#{display}'"
|
94
95
|
end
|
95
|
-
@events.on(:disconnected) { log
|
96
|
+
@events.on(:disconnected) { log 'Disconnected from X server' }
|
96
97
|
@events.on(:xevent) { |event| XEventLogger.new(env).log_event event }
|
97
|
-
@events.on(:xerror)
|
98
|
+
@events.on(:xerror) do |*error|
|
99
|
+
if error.none?
|
100
|
+
log_fatal 'Fatal X IO Error received'
|
101
|
+
else
|
102
|
+
XEventLogger.new(env).log_xerror *error
|
103
|
+
end
|
104
|
+
end
|
98
105
|
end
|
99
106
|
|
100
107
|
def register_layout_hooks
|
@@ -130,6 +137,20 @@ module Uh
|
|
130
137
|
end
|
131
138
|
end
|
132
139
|
|
140
|
+
def register_rules_hooks
|
141
|
+
@events.on :manage do |client|
|
142
|
+
@rules.each do |selector, code|
|
143
|
+
@actions.evaluate code if client.wclass =~ selector
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def register_launcher_hooks
|
149
|
+
@events.on :connected do
|
150
|
+
Launcher.launch(self, @env.launch) if @env.launch
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
133
154
|
|
134
155
|
class XEventLogger
|
135
156
|
include EnvLogging
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'uh'
|
2
|
+
require 'uh/wm/testing/x_client'
|
2
3
|
|
3
4
|
module Uh
|
4
5
|
module WM
|
@@ -8,6 +9,29 @@ module Uh
|
|
8
9
|
QUIT_KEYBINDING = 'alt+shift+q'.freeze
|
9
10
|
LOG_READY = 'Working events'.freeze
|
10
11
|
|
12
|
+
def build_regexp pattern, options
|
13
|
+
Regexp.new(pattern, options.each_char.inject(0) do |m, e|
|
14
|
+
m | case e
|
15
|
+
when ?i then Regexp::IGNORECASE
|
16
|
+
when ?m then Regexp::MULTILINE
|
17
|
+
when ?x then Regexp::EXTENDED
|
18
|
+
end
|
19
|
+
end)
|
20
|
+
end
|
21
|
+
|
22
|
+
def icccm_window_start
|
23
|
+
@icccm_window = ChildProcess.build(*%w[xmessage window])
|
24
|
+
@icccm_window.start
|
25
|
+
end
|
26
|
+
|
27
|
+
def icccm_window_ensure_stop
|
28
|
+
@icccm_window.stop
|
29
|
+
end
|
30
|
+
|
31
|
+
def icccm_window_name
|
32
|
+
'xmessage'
|
33
|
+
end
|
34
|
+
|
11
35
|
def uhwm_run options = '-v'
|
12
36
|
command = %w[uhwm]
|
13
37
|
command << options if options
|
@@ -39,7 +63,7 @@ module Uh
|
|
39
63
|
end
|
40
64
|
value
|
41
65
|
rescue TimeoutError => e
|
42
|
-
|
66
|
+
raise <<-eoh
|
43
67
|
expected `#{message}' (#{times}) not seen after #{e.timeout} seconds in:
|
44
68
|
```\n#{output.call.lines.map { |e| " #{e}" }.join} ```
|
45
69
|
eoh
|
@@ -85,21 +109,19 @@ expected `#{message}' (#{times}) not seen after #{e.timeout} seconds in:
|
|
85
109
|
.grep /Mask\z/
|
86
110
|
end
|
87
111
|
|
88
|
-
def x_key k
|
112
|
+
def x_key *k, delay: 12
|
113
|
+
k = k.join " key --delay #{delay} "
|
89
114
|
fail "cannot simulate X key `#{k}'" unless system "xdotool key #{k}"
|
90
115
|
end
|
91
116
|
|
92
|
-
def
|
93
|
-
case
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
end
|
99
|
-
|
100
|
-
|
101
|
-
def x_window_map_state window_id
|
102
|
-
`xwininfo -id #{window_id}`[/Map State: (\w+)/, 1]
|
117
|
+
def x_window_map_state window_selector
|
118
|
+
select_args = case window_selector
|
119
|
+
when Integer then "-id #{window_selector}"
|
120
|
+
when String then "-name #{window_selector}"
|
121
|
+
else fail ArgumentError,
|
122
|
+
"not an Integer nor a String: `#{window_selector.inspect}'"
|
123
|
+
end
|
124
|
+
`xwininfo #{select_args} 2> /dev/null`[/Map State: (\w+)/, 1]
|
103
125
|
end
|
104
126
|
|
105
127
|
|
@@ -116,7 +138,7 @@ expected `#{message}' (#{times}) not seen after #{e.timeout} seconds in:
|
|
116
138
|
end
|
117
139
|
end
|
118
140
|
rescue Timeout::Error
|
119
|
-
|
141
|
+
raise TimeoutError.new(message % timeout, timeout)
|
120
142
|
end
|
121
143
|
|
122
144
|
|
@@ -128,57 +150,6 @@ expected `#{message}' (#{times}) not seen after #{e.timeout} seconds in:
|
|
128
150
|
@timeout = timeout
|
129
151
|
end
|
130
152
|
end
|
131
|
-
|
132
|
-
class XClient
|
133
|
-
attr_reader :name
|
134
|
-
|
135
|
-
def initialize name = object_id
|
136
|
-
@name = "#{self.class.name.split('::').last}/#{name}"
|
137
|
-
@geo = Geo.new(0, 0, 640, 480)
|
138
|
-
@display = Display.new.tap { |o| o.open }
|
139
|
-
end
|
140
|
-
|
141
|
-
def terminate
|
142
|
-
@display.close
|
143
|
-
end
|
144
|
-
|
145
|
-
def sync
|
146
|
-
@display.sync false
|
147
|
-
end
|
148
|
-
|
149
|
-
def window
|
150
|
-
@window ||= @display.create_window(@geo).tap { |o| o.name = @name }
|
151
|
-
end
|
152
|
-
|
153
|
-
def window_id
|
154
|
-
@window.id
|
155
|
-
end
|
156
|
-
|
157
|
-
def window_name
|
158
|
-
@name
|
159
|
-
end
|
160
|
-
|
161
|
-
def window_name= name
|
162
|
-
@name = @window.name = name
|
163
|
-
window.name
|
164
|
-
end
|
165
|
-
|
166
|
-
def map times: 1
|
167
|
-
times.times { window.map }
|
168
|
-
window.map
|
169
|
-
self
|
170
|
-
end
|
171
|
-
|
172
|
-
def unmap
|
173
|
-
window.unmap
|
174
|
-
self
|
175
|
-
end
|
176
|
-
|
177
|
-
def destroy
|
178
|
-
window.destroy
|
179
|
-
self
|
180
|
-
end
|
181
|
-
end
|
182
153
|
end
|
183
154
|
end
|
184
155
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'uh'
|
2
|
+
|
3
|
+
module Uh
|
4
|
+
module WM
|
5
|
+
module Testing
|
6
|
+
class XClient
|
7
|
+
attr_reader :name
|
8
|
+
|
9
|
+
def initialize name = object_id
|
10
|
+
@name = "#{self.class.name.split('::').last}/#{name}"
|
11
|
+
@geo = Geo.new(0, 0, 640, 480)
|
12
|
+
@display = Display.new.tap &:open
|
13
|
+
end
|
14
|
+
|
15
|
+
def terminate
|
16
|
+
@display.close
|
17
|
+
end
|
18
|
+
|
19
|
+
def sync
|
20
|
+
@display.sync false
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def window
|
25
|
+
@window ||= @display.create_window(@geo).tap { |o| o.name = @name }
|
26
|
+
end
|
27
|
+
|
28
|
+
def window_id
|
29
|
+
@window.id
|
30
|
+
end
|
31
|
+
|
32
|
+
def window_name
|
33
|
+
@name
|
34
|
+
end
|
35
|
+
|
36
|
+
def window_name= name
|
37
|
+
@name = window.name = name
|
38
|
+
window.name
|
39
|
+
end
|
40
|
+
|
41
|
+
def window_class= wclass
|
42
|
+
window.wclass = [wclass] * 2
|
43
|
+
end
|
44
|
+
|
45
|
+
def map times: 1
|
46
|
+
times.times { window.map }
|
47
|
+
window.map
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def unmap
|
52
|
+
window.unmap
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
def destroy
|
57
|
+
window.destroy
|
58
|
+
self
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/uh/wm/version.rb
CHANGED
data/lib/uh/wm/workers/base.rb
CHANGED
data/lib/uh/wm/workers/mux.rb
CHANGED
data/lib/uh/wm.rb
CHANGED
@@ -10,6 +10,7 @@ require 'uh/wm/cli'
|
|
10
10
|
require 'uh/wm/client'
|
11
11
|
require 'uh/wm/dispatcher'
|
12
12
|
require 'uh/wm/env'
|
13
|
+
require 'uh/wm/launcher'
|
13
14
|
require 'uh/wm/logger_formatter'
|
14
15
|
require 'uh/wm/manager'
|
15
16
|
require 'uh/wm/run_control'
|
@@ -21,9 +22,10 @@ require 'uh/wm/workers/mux'
|
|
21
22
|
|
22
23
|
module Uh
|
23
24
|
module WM
|
24
|
-
Error
|
25
|
-
RuntimeError
|
26
|
-
ArgumentError
|
25
|
+
Error = Class.new(StandardError)
|
26
|
+
RuntimeError = Class.new(RuntimeError)
|
27
|
+
ArgumentError = Class.new(Error)
|
28
|
+
RunControlEvaluationError = Class.new(RuntimeError)
|
27
29
|
|
28
30
|
class OtherWMRunningError < RuntimeError
|
29
31
|
def message
|