uh-wm 0.0.2.pre → 0.0.2

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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +15 -0
  5. data/Gemfile +5 -0
  6. data/Guardfile +12 -0
  7. data/LICENSE +30 -0
  8. data/README.md +68 -0
  9. data/Rakefile +40 -0
  10. data/bin/uhwm +5 -0
  11. data/config/cucumber.yaml +1 -0
  12. data/features/actions/execute.feature +9 -0
  13. data/features/actions/layout_delegation.feature +31 -0
  14. data/features/actions/quit.feature +9 -0
  15. data/features/cli/debug.feature +5 -0
  16. data/features/cli/layout.feature +15 -0
  17. data/features/cli/require.feature +5 -0
  18. data/features/cli/run_control.feature +9 -0
  19. data/features/cli/usage.feature +11 -0
  20. data/features/cli/verbose.feature +5 -0
  21. data/features/cli/version.feature +6 -0
  22. data/features/cli/worker.feature +9 -0
  23. data/features/layout/manage.feature +12 -0
  24. data/features/layout/protocol.feature +24 -0
  25. data/features/layout/unmanage.feature +10 -0
  26. data/features/manager/check_other_wm.feature +8 -0
  27. data/features/manager/input_events.feature +8 -0
  28. data/features/manager/manage.feature +14 -0
  29. data/features/manager/unmanage.feature +13 -0
  30. data/features/manager/x_errors.feature +17 -0
  31. data/features/run_control/evaluation.feature +18 -0
  32. data/features/run_control/key.feature +33 -0
  33. data/features/run_control/modifier.feature +10 -0
  34. data/features/run_control/worker.feature +9 -0
  35. data/features/session/connection.feature +5 -0
  36. data/features/session/termination.feature +13 -0
  37. data/features/steps/filesystem_steps.rb +3 -0
  38. data/features/steps/output_steps.rb +44 -0
  39. data/features/steps/run_control_steps.rb +3 -0
  40. data/features/steps/run_steps.rb +41 -0
  41. data/features/steps/x_steps.rb +53 -0
  42. data/features/support/env.rb +33 -0
  43. data/lib/uh/wm.rb +8 -0
  44. data/lib/uh/wm/actions_handler.rb +46 -0
  45. data/lib/uh/wm/cli.rb +20 -13
  46. data/lib/uh/wm/client.rb +64 -0
  47. data/lib/uh/wm/dispatcher.rb +3 -1
  48. data/lib/uh/wm/env.rb +15 -9
  49. data/lib/uh/wm/env_logging.rb +8 -0
  50. data/lib/uh/wm/logger_formatter.rb +16 -0
  51. data/lib/uh/wm/manager.rb +96 -14
  52. data/lib/uh/wm/run_control.rb +8 -3
  53. data/lib/uh/wm/runner.rb +82 -14
  54. data/lib/uh/wm/testing/acceptance_helpers.rb +140 -18
  55. data/lib/uh/wm/version.rb +1 -1
  56. data/lib/uh/wm/workers.rb +21 -0
  57. data/lib/uh/wm/workers/base.rb +27 -0
  58. data/lib/uh/wm/workers/blocking.rb +11 -0
  59. data/lib/uh/wm/workers/mux.rb +18 -0
  60. data/spec/spec_helper.rb +26 -0
  61. data/spec/support/exit_helpers.rb +6 -0
  62. data/spec/support/filesystem_helpers.rb +11 -0
  63. data/spec/uh/wm/actions_handler_spec.rb +30 -0
  64. data/spec/uh/wm/cli_spec.rb +214 -0
  65. data/spec/uh/wm/client_spec.rb +133 -0
  66. data/spec/uh/wm/dispatcher_spec.rb +76 -0
  67. data/spec/uh/wm/env_spec.rb +145 -0
  68. data/spec/uh/wm/manager_spec.rb +355 -0
  69. data/spec/uh/wm/run_control_spec.rb +102 -0
  70. data/spec/uh/wm/runner_spec.rb +186 -0
  71. data/uh-wm.gemspec +25 -0
  72. metadata +112 -9
@@ -0,0 +1,17 @@
1
+ Feature: X errors logging
2
+
3
+ Scenario: logs error details
4
+ Given a file named layout.rb with:
5
+ """
6
+ class Layout
7
+ def register _; end
8
+
9
+ # Focusing a client before mapping will force an error
10
+ def << client
11
+ client.focus
12
+ end
13
+ end
14
+ """
15
+ And uhwm is running with options -v -r./layout -l Layout
16
+ When a window requests to be mapped
17
+ Then the output must match /x.*error.+x_setinputfocus.+/i
@@ -0,0 +1,18 @@
1
+ Feature: run control file evaluation
2
+
3
+ Scenario: evaluates the default run control file when present
4
+ Given a run control file with:
5
+ """
6
+ puts 'run control evaluation'
7
+ """
8
+ When I start uhwm
9
+ Then the output must contain "run control evaluation"
10
+
11
+ Scenario: reports run control code in backtrace on errors
12
+ Given a run control file with:
13
+ """
14
+ 'no error on first line'
15
+ fail 'fails on second line'
16
+ """
17
+ When I start uhwm
18
+ Then the output must match /\.uhwmrc\.rb:2:.+fails on second line/
@@ -0,0 +1,33 @@
1
+ Feature: `key' run control keyword
2
+
3
+ Scenario: defines code to run when given key is pressed
4
+ Given uhwm is running with this run control file:
5
+ """
6
+ key(:f) { puts 'trigger f key code' }
7
+ """
8
+ When I press the alt+f keys
9
+ Then the output must contain "trigger f key code"
10
+
11
+ Scenario: defines code to run when given keys are pressed
12
+ Given uhwm is running with this run control file:
13
+ """
14
+ key(:f, :shift) { puts 'trigger f key code' }
15
+ """
16
+ When I press the alt+shift+f keys
17
+ Then the output must contain "trigger f key code"
18
+
19
+ Scenario: translates common key names to their X equivalent
20
+ Given uhwm is running with this run control file:
21
+ """
22
+ key(:enter) { puts 'trigger return key code' }
23
+ """
24
+ When I press the alt+Return keys
25
+ Then the output must contain "trigger return key code"
26
+
27
+ Scenario: translates upcased key names to combination with shift key
28
+ Given uhwm is running with this run control file:
29
+ """
30
+ key(:F) { puts 'trigger shift+f key code' }
31
+ """
32
+ When I press the alt+shift+f keys
33
+ Then the output must contain "trigger shift+f key code"
@@ -0,0 +1,10 @@
1
+ Feature: `modifier' run control keyword
2
+
3
+ Scenario: configures the modifier key
4
+ Given a run control file with:
5
+ """
6
+ modifier :ctrl
7
+ """
8
+ And uhwm is running
9
+ When I press the ctrl+shift+q keys
10
+ Then uhwm must terminate successfully
@@ -0,0 +1,9 @@
1
+ Feature: `worker' run control keyword
2
+
3
+ Scenario: configures the modifier key
4
+ Given a run control file with:
5
+ """
6
+ worker :mux
7
+ """
8
+ And I start uhwm
9
+ Then the output must match /work.+event.+mux/i
@@ -0,0 +1,5 @@
1
+ Feature: connection to X server
2
+
3
+ Scenario: connects to X server
4
+ When I start uhwm
5
+ Then it must connect to X display
@@ -0,0 +1,13 @@
1
+ Feature: program termination
2
+
3
+ Background:
4
+ Given uhwm is running
5
+
6
+ Scenario: terminates on quit request
7
+ When I tell uhwm to quit
8
+ Then uhwm must terminate successfully
9
+
10
+ Scenario: logs about termination
11
+ When I tell uhwm to quit
12
+ Then uhwm must terminate successfully
13
+ And the output must match /terminat/i
@@ -0,0 +1,3 @@
1
+ Given /^a file named ([^ ]+) with:$/ do |path, content|
2
+ write_file path, content
3
+ end
@@ -0,0 +1,44 @@
1
+ Then /^the output must contain exactly the usage$/ do
2
+ assert_exact_output <<-eoh, all_output
3
+ Usage: uhwm [options]
4
+
5
+ options:
6
+ -v, --verbose enable verbose mode
7
+ -d, --debug enable debug mode
8
+ -f, --run-control PATH specify alternate run control file
9
+ -r, --require PATH require ruby feature
10
+ -l, --layout LAYOUT specify layout
11
+ -w, --worker WORKER specify worker
12
+
13
+ -h, --help print this message
14
+ -V, --version print version
15
+ eoh
16
+ end
17
+
18
+ Then /^the output must contain exactly the version$/ do
19
+ assert_exact_output "%s\n" % Uh::WM::VERSION, all_output
20
+ end
21
+
22
+ Then /^the output must match \/([^\/]+)\/([a-z]*)$/ do |pattern, options|
23
+ uhwm_wait_output Regexp.new(pattern, options)
24
+ end
25
+
26
+ Then /^the output must not match \/([^\/]+)\/([a-z]*)$/ do |pattern, options|
27
+ expect(all_output).not_to match Regexp.new(pattern, options)
28
+ end
29
+
30
+ Then /^the output must contain:$/ do |content|
31
+ uhwm_wait_output content.to_s
32
+ end
33
+
34
+ Then /^the output must contain "([^"]+)"$/ do |content|
35
+ uhwm_wait_output content.to_s
36
+ end
37
+
38
+ Then /^the output must contain current display$/ do
39
+ uhwm_wait_output ENV['DISPLAY']
40
+ end
41
+
42
+ Then /^the output must contain the window name$/ do
43
+ uhwm_wait_output x_window_name
44
+ end
@@ -0,0 +1,3 @@
1
+ Given /^a run control file with:$/ do |content|
2
+ write_file '.uhwmrc.rb', content
3
+ end
@@ -0,0 +1,41 @@
1
+ Given /^another window manager is running$/ do
2
+ expect(other_wm).to be_alive
3
+ end
4
+
5
+ Given /^uhwm is running$/ do
6
+ uhwm_run_wait_ready
7
+ end
8
+
9
+ Given /^uhwm is running with options? (-.+)$/ do |options|
10
+ uhwm_run_wait_ready options
11
+ end
12
+
13
+ Given /^uhwm is running with this run control file:$/ do |rc|
14
+ write_file '.uhwmrc.rb', rc
15
+ uhwm_run_wait_ready
16
+ end
17
+
18
+ When /^I start uhwm$/ do
19
+ uhwm_run
20
+ end
21
+
22
+ When /^I run uhwm with options? (-.+)$/ do |options|
23
+ uhwm_run options
24
+ end
25
+
26
+ When /^I tell uhwm to quit$/ do
27
+ x_key 'alt+shift+q'
28
+ end
29
+
30
+ When /^I quit uhwm$/ do
31
+ x_key 'alt+shift+q'
32
+ assert_exit_status 0
33
+ end
34
+
35
+ Then /^the exit status must be (\d+)$/ do |exit_status|
36
+ assert_exit_status exit_status.to_i
37
+ end
38
+
39
+ Then /^uhwm must terminate successfully$/ do
40
+ assert_exit_status 0
41
+ end
@@ -0,0 +1,53 @@
1
+ Given /^a (\w+) window is mapped$/ do |ident|
2
+ x_window_map ident: ident
3
+ end
4
+
5
+ Given /^a window is managed$/ do
6
+ x_window_map
7
+ uhwm_wait_output /manag.+#{x_window_name}/i
8
+ end
9
+
10
+ When /^I press the ([^ ]+) keys?$/ do |keys|
11
+ x_key keys
12
+ end
13
+
14
+ When /^a window requests to be mapped$/ do
15
+ x_window_map
16
+ end
17
+
18
+ When /^the window requests to be unmapped$/ do
19
+ x_window_unmap
20
+ end
21
+
22
+ When /^the (\w+) window requests to be unmapped$/ do |ident|
23
+ x_window_unmap ident: ident
24
+ end
25
+
26
+ When /^a window requests to be mapped (\d+) times$/ do |times|
27
+ x_window_map times: times.to_i
28
+ end
29
+
30
+ When /^the window is destroyed$/ do
31
+ x_window_destroy
32
+ end
33
+
34
+ Then /^it must connect to X display$/ do
35
+ uhwm_wait_output 'Connected to'
36
+ expect(x_socket_check uhwm_pid).to be true
37
+ end
38
+
39
+ Then /^the window must be mapped$/ do
40
+ expect(x_window_map_state).to eq 'IsViewable'
41
+ end
42
+
43
+ Then /^the (\w+) window must be mapped$/ do |ident|
44
+ expect(x_window_map_state ident: ident).to eq 'IsViewable'
45
+ end
46
+
47
+ Then /^the window must be focused$/ do
48
+ expect(x_focused_window_id).to eq x_window_id
49
+ end
50
+
51
+ Then /^the input event mask must include (.+)$/ do |mask|
52
+ expect(x_input_event_masks).to include mask
53
+ end
@@ -0,0 +1,33 @@
1
+ require 'aruba/cucumber'
2
+ require 'headless'
3
+
4
+ require 'uh/wm/testing/acceptance_helpers'
5
+
6
+ module Aruba
7
+ class SpawnProcess
8
+ def pid
9
+ @process.pid
10
+ end
11
+ end
12
+ end
13
+
14
+ World(Uh::WM::Testing::AcceptanceHelpers)
15
+
16
+ Headless.new.start
17
+
18
+ Before do
19
+ set_env 'HOME', File.expand_path(current_dir)
20
+ end
21
+
22
+ After do
23
+ uhwm_ensure_stop
24
+ x_clients_ensure_stop
25
+ end
26
+
27
+ Around '@other_wm_running' do |_, block|
28
+ with_other_wm { block.call }
29
+ end
30
+
31
+ if ENV.key? 'TRAVIS'
32
+ ENV['UHWMTEST_TIMEOUT'] = 8.to_s
33
+ end
data/lib/uh/wm.rb CHANGED
@@ -3,13 +3,21 @@ require 'logger'
3
3
  require 'optparse'
4
4
  require 'uh'
5
5
 
6
+ require 'uh/wm/env_logging'
7
+
6
8
  require 'uh/wm/actions_handler'
7
9
  require 'uh/wm/cli'
10
+ require 'uh/wm/client'
8
11
  require 'uh/wm/dispatcher'
9
12
  require 'uh/wm/env'
13
+ require 'uh/wm/logger_formatter'
10
14
  require 'uh/wm/manager'
11
15
  require 'uh/wm/run_control'
12
16
  require 'uh/wm/runner'
17
+ require 'uh/wm/workers'
18
+ require 'uh/wm/workers/base'
19
+ require 'uh/wm/workers/blocking'
20
+ require 'uh/wm/workers/mux'
13
21
 
14
22
  module Uh
15
23
  module WM
@@ -1,6 +1,11 @@
1
1
  module Uh
2
2
  module WM
3
3
  class ActionsHandler
4
+ include EnvLogging
5
+
6
+ extend Forwardable
7
+ def_delegator :@env, :layout
8
+
4
9
  def initialize env, events
5
10
  @env, @events = env, events
6
11
  end
@@ -10,8 +15,49 @@ module Uh
10
15
  end
11
16
 
12
17
  def quit
18
+ log 'Quit requested'
13
19
  @events.emit :quit
14
20
  end
21
+
22
+ def execute command
23
+ log "Execute: #{command}"
24
+ pid = fork do
25
+ fork do
26
+ Process.setsid
27
+ begin
28
+ exec command
29
+ rescue Errno::ENOENT => e
30
+ log_error "ExecuteError: #{e}"
31
+ end
32
+ end
33
+ end
34
+ Process.waitpid pid
35
+ end
36
+
37
+ def method_missing(m, *args, &block)
38
+ if respond_to? m
39
+ meth = layout_method m
40
+ log "#{layout.class.name}##{meth} #{args.inspect}"
41
+ begin
42
+ layout.send(meth, *args)
43
+ rescue NoMethodError
44
+ log_error "Layout does not implement `#{meth}'"
45
+ end
46
+ else
47
+ super
48
+ end
49
+ end
50
+
51
+ def respond_to_missing?(m, *)
52
+ m.to_s =~ /\Alayout_/ || super
53
+ end
54
+
55
+
56
+ private
57
+
58
+ def layout_method(m)
59
+ m.to_s.gsub(/\Alayout_/, 'handle_').to_sym
60
+ end
15
61
  end
16
62
  end
17
63
  end
data/lib/uh/wm/cli.rb CHANGED
@@ -3,6 +3,8 @@ module Uh
3
3
  class CLI
4
4
  ArgumentError = Class.new(ArgumentError)
5
5
 
6
+ include EnvLogging
7
+
6
8
  USAGE = "Usage: #{File.basename $0} [options]".freeze
7
9
 
8
10
  EX_USAGE = 64
@@ -49,33 +51,38 @@ module Uh
49
51
  opts.separator ''
50
52
  opts.separator 'options:'
51
53
 
52
- opts.on '-h', '--help', 'print this message' do
53
- @env.print opts
54
- exit
55
- end
56
-
57
- opts.on '-v', '--version', 'enable verbose mode' do
54
+ opts.on '-v', '--verbose', 'enable verbose mode' do
58
55
  @env.verbose = true
59
56
  @env.log_logger_level
60
57
  end
61
-
62
58
  opts.on '-d', '--debug', 'enable debug mode' do
63
59
  @env.debug = true
64
60
  @env.log_logger_level
65
61
  end
66
-
67
62
  opts.on '-f', '--run-control PATH',
68
- 'specify alternate run control file' do |e|
63
+ 'specify alternate run control file' do |e|
69
64
  @env.rc_path = e
70
65
  end
71
-
72
66
  opts.on '-r', '--require PATH', 'require ruby feature' do |feature|
73
67
  require feature
74
- @env.log "Loaded `#{feature}' ruby feature"
68
+ log "Loaded `#{feature}' ruby feature"
75
69
  end
76
-
77
70
  opts.on '-l', '--layout LAYOUT', 'specify layout' do |layout|
78
- @env.layout_class = self.class.const_get layout.to_sym
71
+ @env.layout_class = Object.const_get layout.to_sym
72
+ end
73
+ opts.on '-w', Workers.types, '--worker WORKER',
74
+ 'specify worker' do |worker|
75
+ @env.worker = worker.to_sym
76
+ end
77
+
78
+ opts.separator ''
79
+ opts.on_tail '-h', '--help', 'print this message' do
80
+ @env.print opts
81
+ exit
82
+ end
83
+ opts.on_tail '-V', '--version', 'print version' do
84
+ @env.puts VERSION
85
+ exit
79
86
  end
80
87
  end
81
88
  end