uh-wm 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|