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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/lib/uh/wm/actions_handler.rb +9 -0
  3. data/lib/uh/wm/cli.rb +1 -1
  4. data/lib/uh/wm/client.rb +14 -0
  5. data/lib/uh/wm/env.rb +3 -1
  6. data/lib/uh/wm/env_logging.rb +1 -1
  7. data/lib/uh/wm/launcher.rb +73 -0
  8. data/lib/uh/wm/run_control.rb +10 -0
  9. data/lib/uh/wm/runner.rb +26 -5
  10. data/lib/uh/wm/testing/acceptance_helpers.rb +36 -65
  11. data/lib/uh/wm/testing/x_client.rb +63 -0
  12. data/lib/uh/wm/version.rb +1 -1
  13. data/lib/uh/wm/workers/base.rb +1 -1
  14. data/lib/uh/wm/workers/mux.rb +3 -1
  15. data/lib/uh/wm.rb +5 -3
  16. metadata +9 -111
  17. data/.gitignore +0 -3
  18. data/.rspec +0 -1
  19. data/.travis.yml +0 -15
  20. data/Gemfile +0 -5
  21. data/Guardfile +0 -12
  22. data/LICENSE +0 -30
  23. data/Rakefile +0 -40
  24. data/config/cucumber.yaml +0 -1
  25. data/features/actions/execute.feature +0 -9
  26. data/features/actions/layout_delegation.feature +0 -31
  27. data/features/actions/quit.feature +0 -9
  28. data/features/cli/debug.feature +0 -5
  29. data/features/cli/layout.feature +0 -15
  30. data/features/cli/require.feature +0 -5
  31. data/features/cli/run_control.feature +0 -9
  32. data/features/cli/usage.feature +0 -11
  33. data/features/cli/verbose.feature +0 -5
  34. data/features/cli/version.feature +0 -6
  35. data/features/cli/worker.feature +0 -9
  36. data/features/layout/manage.feature +0 -12
  37. data/features/layout/protocol.feature +0 -56
  38. data/features/layout/unmanage.feature +0 -10
  39. data/features/manager/change.feature +0 -7
  40. data/features/manager/check_other_wm.feature +0 -8
  41. data/features/manager/expose.feature +0 -5
  42. data/features/manager/input_events.feature +0 -8
  43. data/features/manager/manage.feature +0 -14
  44. data/features/manager/unmanage.feature +0 -13
  45. data/features/manager/x_errors.feature +0 -17
  46. data/features/run_control/evaluation.feature +0 -18
  47. data/features/run_control/key.feature +0 -33
  48. data/features/run_control/layout.feature +0 -39
  49. data/features/run_control/modifier.feature +0 -10
  50. data/features/run_control/worker.feature +0 -9
  51. data/features/session/connection.feature +0 -5
  52. data/features/session/termination.feature +0 -12
  53. data/features/steps/filesystem_steps.rb +0 -3
  54. data/features/steps/output_steps.rb +0 -55
  55. data/features/steps/run_control_steps.rb +0 -3
  56. data/features/steps/run_steps.rb +0 -41
  57. data/features/steps/x_steps.rb +0 -58
  58. data/features/support/env.rb +0 -33
  59. data/features/workers/block.feature +0 -15
  60. data/features/workers/mux.feature +0 -15
  61. data/spec/spec_helper.rb +0 -30
  62. data/spec/support/exit_helpers.rb +0 -6
  63. data/spec/support/factories.rb +0 -27
  64. data/spec/support/filesystem_helpers.rb +0 -11
  65. data/spec/uh/wm/actions_handler_spec.rb +0 -35
  66. data/spec/uh/wm/cli_spec.rb +0 -214
  67. data/spec/uh/wm/client_spec.rb +0 -148
  68. data/spec/uh/wm/dispatcher_spec.rb +0 -76
  69. data/spec/uh/wm/env_spec.rb +0 -154
  70. data/spec/uh/wm/manager_spec.rb +0 -386
  71. data/spec/uh/wm/run_control_spec.rb +0 -126
  72. data/spec/uh/wm/runner_spec.rb +0 -196
  73. data/uh-wm.gemspec +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f36b28780f56841b401c23d062a1a46bb420ad91
4
- data.tar.gz: d42c2d7864fd8211115c0f975436f6aa57184a0e
3
+ metadata.gz: a3607acc6f3a156a4fe6ecfdd4c960daecdde3bc
4
+ data.tar.gz: 9aac8a32b1d1619e055e0c5af14e28d8033dfe9f
5
5
  SHA512:
6
- metadata.gz: 789e6b27ddb37be96a2d766843139256334fb7891967b3ab8a9a051fe0163e09315a7ea216ec5158028d1c0e9ea7fc55889d688c0ef2df3886023fb466d39c52
7
- data.tar.gz: 7d3d6b8fdbd28b553a474777a1fa5316fbfa8c73521f9e4efbeb2eebc438754c4374e98124e60562699ea681ebf51571995a2aac83df389fc1eb98b97a4c97ba
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
@@ -35,7 +35,7 @@ module Uh
35
35
  def parse_arguments!
36
36
  option_parser.parse! @arguments
37
37
  rescue OptionParser::InvalidOption => e
38
- fail ArgumentError, option_parser
38
+ raise ArgumentError, option_parser
39
39
  end
40
40
 
41
41
  def run
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?
@@ -2,7 +2,7 @@ module Uh
2
2
  module WM
3
3
  module EnvLogging
4
4
  extend Forwardable
5
- def_delegators :@env, :log, :log_error, :log_debug
5
+ def_delegators :@env, :log, :log_fatal, :log_error, :log_debug
6
6
  end
7
7
  end
8
8
  end
@@ -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
@@ -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 "Terminating..."
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 "Disconnected from X server" }
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) { |*error| XEventLogger.new(env).log_xerror *error }
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
- fail <<-eoh
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 x_socket_check pid
93
- case RbConfig::CONFIG['host_os']
94
- when /linux/
95
- `netstat -xp 2> /dev/null`.lines.grep /\s+#{pid}\/ruby/
96
- else
97
- `sockstat -u`.lines.grep /\s+ruby.+\s+#{pid}/
98
- end.any?
99
- end
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
- fail TimeoutError.new(message % timeout, timeout)
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
@@ -1,5 +1,5 @@
1
1
  module Uh
2
2
  module WM
3
- VERSION = '0.0.6'
3
+ VERSION = '0.0.7'
4
4
  end
5
5
  end
@@ -9,7 +9,7 @@ module Uh
9
9
  end
10
10
 
11
11
  def watch io
12
- @ios << io
12
+ @ios << io.to_io
13
13
  end
14
14
 
15
15
  CALLBACKS.each do |m|
@@ -2,7 +2,9 @@ module Uh
2
2
  module WM
3
3
  module Workers
4
4
  class Mux < Base
5
- def initialize timeout: 1
5
+ TIMEOUT_DEFAULT = 1
6
+
7
+ def initialize timeout: TIMEOUT_DEFAULT
6
8
  super
7
9
  @timeout = timeout
8
10
  end
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 = Class.new(StandardError)
25
- RuntimeError = Class.new(RuntimeError)
26
- ArgumentError = Class.new(Error)
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