rumai 2.0.2 → 2.1.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.
Files changed (167) hide show
  1. data/CREDITS +2 -0
  2. data/bin/rumai +20 -8
  3. data/doc/api/classes/IO.html +72 -0
  4. data/doc/api/classes/Integer.html +110 -0
  5. data/doc/api/classes/Object.html +60 -0
  6. data/doc/api/classes/Rumai.html +867 -0
  7. data/doc/api/classes/Rumai/Area.html +836 -0
  8. data/doc/api/classes/Rumai/Chain.html +197 -0
  9. data/doc/api/classes/Rumai/Client.html +865 -0
  10. data/doc/api/classes/Rumai/ClientContainer.html +191 -0
  11. data/doc/api/classes/Rumai/ExportInstanceMethods.html +69 -0
  12. data/doc/api/classes/Rumai/IXP.html +131 -0
  13. data/doc/api/classes/Rumai/IXP/Agent.html +836 -0
  14. data/doc/api/classes/Rumai/IXP/Agent/FidStream.html +456 -0
  15. data/doc/api/classes/Rumai/IXP/Agent/MODES.html +108 -0
  16. data/doc/api/classes/Rumai/IXP/Agent/RangedPool.html +241 -0
  17. data/doc/api/classes/Rumai/IXP/Error.html +67 -0
  18. data/doc/api/classes/Rumai/IXP/Fcall.html +323 -0
  19. data/doc/api/classes/Rumai/IXP/Qid.html +153 -0
  20. data/doc/api/classes/Rumai/IXP/Rattach.html +67 -0
  21. data/doc/api/classes/Rumai/IXP/Rauth.html +67 -0
  22. data/doc/api/classes/Rumai/IXP/Rclunk.html +67 -0
  23. data/doc/api/classes/Rumai/IXP/Rcreate.html +67 -0
  24. data/doc/api/classes/Rumai/IXP/Rerror.html +67 -0
  25. data/doc/api/classes/Rumai/IXP/Rflush.html +67 -0
  26. data/doc/api/classes/Rumai/IXP/Ropen.html +67 -0
  27. data/doc/api/classes/Rumai/IXP/Rread.html +67 -0
  28. data/doc/api/classes/Rumai/IXP/Rremove.html +67 -0
  29. data/doc/api/classes/Rumai/IXP/Rstat.html +67 -0
  30. data/doc/api/classes/Rumai/IXP/Rversion.html +67 -0
  31. data/doc/api/classes/Rumai/IXP/Rwalk.html +67 -0
  32. data/doc/api/classes/Rumai/IXP/Rwrite.html +67 -0
  33. data/doc/api/classes/Rumai/IXP/Rwstat.html +67 -0
  34. data/doc/api/classes/Rumai/IXP/Stat.html +252 -0
  35. data/doc/api/classes/Rumai/IXP/Stream.html +131 -0
  36. data/doc/api/classes/Rumai/IXP/Struct.html +315 -0
  37. data/doc/api/classes/Rumai/IXP/Struct/Field.html +415 -0
  38. data/doc/api/classes/Rumai/IXP/Struct/Field/CounteeField.html +153 -0
  39. data/doc/api/classes/Rumai/IXP/Struct/Field/CounterField.html +104 -0
  40. data/doc/api/classes/Rumai/IXP/Tattach.html +68 -0
  41. data/doc/api/classes/Rumai/IXP/Tauth.html +67 -0
  42. data/doc/api/classes/Rumai/IXP/Tclunk.html +67 -0
  43. data/doc/api/classes/Rumai/IXP/Tcreate.html +68 -0
  44. data/doc/api/classes/Rumai/IXP/Terror.html +110 -0
  45. data/doc/api/classes/Rumai/IXP/Tflush.html +67 -0
  46. data/doc/api/classes/Rumai/IXP/Topen.html +165 -0
  47. data/doc/api/classes/Rumai/IXP/Tread.html +67 -0
  48. data/doc/api/classes/Rumai/IXP/Tremove.html +67 -0
  49. data/doc/api/classes/Rumai/IXP/Tstat.html +67 -0
  50. data/doc/api/classes/Rumai/IXP/Tversion.html +86 -0
  51. data/doc/api/classes/Rumai/IXP/Twalk.html +68 -0
  52. data/doc/api/classes/Rumai/IXP/Twrite.html +68 -0
  53. data/doc/api/classes/Rumai/IXP/Twstat.html +67 -0
  54. data/doc/api/classes/Rumai/Node.html +817 -0
  55. data/doc/api/classes/Rumai/View.html +818 -0
  56. data/doc/api/classes/Rumai/WidgetImpl.html +65 -0
  57. data/doc/api/classes/Rumai/WidgetNode.html +68 -0
  58. data/doc/api/classes/String.html +163 -0
  59. data/doc/api/classes/StringIO.html +72 -0
  60. data/doc/api/classes/Time.html +156 -0
  61. data/doc/api/created.rid +1 -0
  62. data/doc/api/css/main.css +263 -0
  63. data/doc/api/css/panel.css +383 -0
  64. data/doc/api/css/reset.css +53 -0
  65. data/doc/api/files/CREDITS.html +64 -0
  66. data/doc/api/files/LICENSE.html +76 -0
  67. data/doc/api/files/lib/rumai/fs_rb.html +75 -0
  68. data/doc/api/files/lib/rumai/ixp/message_rb.html +91 -0
  69. data/doc/api/files/lib/rumai/ixp/transport_rb.html +75 -0
  70. data/doc/api/files/lib/rumai/ixp_rb.html +69 -0
  71. data/doc/api/files/lib/rumai/wm_rb.html +77 -0
  72. data/doc/api/files/lib/rumai_rb.html +65 -0
  73. data/doc/api/i/arrows.png +0 -0
  74. data/doc/api/i/results_bg.png +0 -0
  75. data/doc/api/i/tree_bg.png +0 -0
  76. data/doc/api/index.html +14 -18
  77. data/doc/api/js/jquery-1.3.2.min.js +19 -0
  78. data/doc/api/js/jquery-effect.js +593 -0
  79. data/doc/api/js/main.js +22 -0
  80. data/doc/api/js/searchdoc.js +605 -0
  81. data/doc/api/panel/index.html +63 -0
  82. data/doc/api/panel/search_index.js +1 -0
  83. data/doc/api/panel/tree.js +1 -0
  84. data/doc/history.erb +41 -16
  85. data/doc/index.erb +14 -11
  86. data/doc/index.xhtml +519 -846
  87. data/doc/intro.erb +33 -32
  88. data/doc/setup.erb +14 -13
  89. data/doc/usage.erb +69 -35
  90. data/lib/rumai.rb +13 -5
  91. data/lib/rumai/fs.rb +71 -27
  92. data/lib/rumai/ixp.rb +4 -0
  93. data/lib/rumai/ixp/message.rb +178 -81
  94. data/lib/rumai/ixp/transport.rb +144 -91
  95. data/lib/rumai/wm.rb +717 -593
  96. data/rakefile +14 -0
  97. data/test/rumai/ixp/message.rb +42 -54
  98. metadata +110 -89
  99. data/Rakefile +0 -8
  100. data/doc/api/IO.html +0 -53
  101. data/doc/api/Integer.html +0 -102
  102. data/doc/api/Object.html +0 -23
  103. data/doc/api/Rumai.html +0 -1218
  104. data/doc/api/Rumai/Area.html +0 -1088
  105. data/doc/api/Rumai/Chain.html +0 -230
  106. data/doc/api/Rumai/Client.html +0 -1264
  107. data/doc/api/Rumai/ClientContainer.html +0 -227
  108. data/doc/api/Rumai/ExportInstMethods.html +0 -115
  109. data/doc/api/Rumai/IXP.html +0 -23
  110. data/doc/api/Rumai/IXP/Agent.html +0 -1222
  111. data/doc/api/Rumai/IXP/Agent/FidStream.html +0 -602
  112. data/doc/api/Rumai/IXP/Agent/RangedPool.html +0 -263
  113. data/doc/api/Rumai/IXP/Error.html +0 -32
  114. data/doc/api/Rumai/IXP/Fcall.html +0 -398
  115. data/doc/api/Rumai/IXP/Qid.html +0 -99
  116. data/doc/api/Rumai/IXP/Rattach.html +0 -71
  117. data/doc/api/Rumai/IXP/Rauth.html +0 -71
  118. data/doc/api/Rumai/IXP/Rclunk.html +0 -71
  119. data/doc/api/Rumai/IXP/Rcreate.html +0 -71
  120. data/doc/api/Rumai/IXP/Rerror.html +0 -71
  121. data/doc/api/Rumai/IXP/Rflush.html +0 -71
  122. data/doc/api/Rumai/IXP/Ropen.html +0 -71
  123. data/doc/api/Rumai/IXP/Rread.html +0 -71
  124. data/doc/api/Rumai/IXP/Rremove.html +0 -71
  125. data/doc/api/Rumai/IXP/Rstat.html +0 -71
  126. data/doc/api/Rumai/IXP/Rversion.html +0 -71
  127. data/doc/api/Rumai/IXP/Rwalk.html +0 -71
  128. data/doc/api/Rumai/IXP/Rwrite.html +0 -71
  129. data/doc/api/Rumai/IXP/Rwstat.html +0 -71
  130. data/doc/api/Rumai/IXP/Stat.html +0 -188
  131. data/doc/api/Rumai/IXP/Stream.html +0 -112
  132. data/doc/api/Rumai/IXP/Struct.html +0 -348
  133. data/doc/api/Rumai/IXP/Struct/ClassField.html +0 -177
  134. data/doc/api/Rumai/IXP/Struct/Field.html +0 -549
  135. data/doc/api/Rumai/IXP/Struct/Field/CounteeField.html +0 -175
  136. data/doc/api/Rumai/IXP/Struct/Field/CounterField.html +0 -95
  137. data/doc/api/Rumai/IXP/Struct/Integer8Field.html +0 -181
  138. data/doc/api/Rumai/IXP/Struct/StringField.html +0 -128
  139. data/doc/api/Rumai/IXP/Tattach.html +0 -71
  140. data/doc/api/Rumai/IXP/Tauth.html +0 -71
  141. data/doc/api/Rumai/IXP/Tclunk.html +0 -71
  142. data/doc/api/Rumai/IXP/Tcreate.html +0 -71
  143. data/doc/api/Rumai/IXP/Terror.html +0 -156
  144. data/doc/api/Rumai/IXP/Tflush.html +0 -71
  145. data/doc/api/Rumai/IXP/Topen.html +0 -113
  146. data/doc/api/Rumai/IXP/Tread.html +0 -71
  147. data/doc/api/Rumai/IXP/Tremove.html +0 -71
  148. data/doc/api/Rumai/IXP/Tstat.html +0 -71
  149. data/doc/api/Rumai/IXP/Tversion.html +0 -83
  150. data/doc/api/Rumai/IXP/Twalk.html +0 -71
  151. data/doc/api/Rumai/IXP/Twrite.html +0 -71
  152. data/doc/api/Rumai/IXP/Twstat.html +0 -71
  153. data/doc/api/Rumai/Node.html +0 -1139
  154. data/doc/api/Rumai/View.html +0 -1280
  155. data/doc/api/Rumai/WidgetImpl.html +0 -196
  156. data/doc/api/Rumai/WidgetNode.html +0 -184
  157. data/doc/api/String.html +0 -180
  158. data/doc/api/StringIO.html +0 -53
  159. data/doc/api/Time.html +0 -175
  160. data/doc/api/all-methods.html +0 -1436
  161. data/doc/api/all-namespaces.html +0 -140
  162. data/doc/api/app.js +0 -18
  163. data/doc/api/jquery.js +0 -11
  164. data/doc/api/readme.html +0 -38
  165. data/doc/api/style.css +0 -68
  166. data/doc/api/syntax_highlight.css +0 -21
  167. data/doc/theory.erb +0 -3
@@ -1,770 +1,894 @@
1
1
  # Abstractions for the window manager.
2
+ #--
3
+ # Copyright 2006 Suraj N. Kurapati
4
+ # See the LICENSE file for details.
5
+ #++
2
6
 
3
7
  require 'rumai/fs'
4
8
  require 'enumerator'
5
9
 
6
- class Object
7
- # prevent these deprecated properties from clashing with our usage below
8
- undef id if respond_to? :id
10
+ class Object #:nodoc:
11
+ # prevent these deprecated properties
12
+ # from clashing with our usage below
13
+ undef id if respond_to? :id
9
14
  undef type if respond_to? :type
10
15
  end
11
16
 
12
17
  module Rumai
13
- ##
14
- #
15
18
  # access to global WM state
16
- #
17
- ##
18
-
19
- ROOT = Node.new '/'
20
-
21
- # Returns the root of IXP file system hierarchy.
22
- def fs
23
- ROOT
24
- end
25
-
26
- # Returns the current set of tags.
27
- def tags
28
- fs.tag.entries.sort - %w[sel]
29
- end
30
-
31
- # Returns the current set of views.
32
- def views
33
- tags.map! {|t| View.new t}
34
- end
35
-
36
- module ClientContainer
37
- # see definition below!
38
- end
39
-
40
- include ClientContainer
41
- # Returns the IDs of the current set of clients.
42
- def client_ids
43
- fs.client.entries - %w[sel]
44
- end
45
-
46
- # Returns the name of the currently focused tag.
47
- def curr_tag
48
- curr_view.id
49
- end
50
-
51
- # Returns the name of the next tag.
52
- def next_tag
53
- next_view.id
54
- end
55
-
56
- # Returns the name of the previous tag.
57
- def prev_tag
58
- prev_view.id
59
- end
60
-
61
-
62
- ##
63
- #
64
- # multiple client grouping: allows you to group a set of clients
65
- # together and perform operations on all of them simultaneously.
66
- #
67
- ##
68
19
 
69
- GROUPING_TAG = '@'
20
+ ROOT = Node.new '/'
70
21
 
71
- # Returns a list of all grouped clients in
72
- # the currently focused view. If there are
73
- # no grouped clients, then the currently
74
- # focused client is returned in the list.
75
- def grouping
76
- list = curr_view.clients.select {|c| c.group? }
77
- list << curr_client if list.empty? and curr_client.exist?
78
- list
79
- end
80
-
81
-
82
- ##
83
- #
84
- # abstraction of WM components
85
- #
86
- ##
87
-
88
- # NOTE: Inheritors must override the 'chain' method.
89
- module Chain
90
- # Returns an array of objects related to this one.
91
- def chain
92
- [self]
22
+ # Returns the root of IXP file system hierarchy.
23
+ def fs
24
+ ROOT
93
25
  end
94
26
 
95
- # Returns the object after this one in the chain.
96
- def next
97
- sibling(+1)
27
+ # Returns the current set of tags.
28
+ def tags
29
+ fs.tag.entries.sort - %w[sel]
98
30
  end
99
31
 
100
- # Returns the object before this one in the chain.
101
- def prev
102
- sibling(-1)
32
+ # Returns the current set of views.
33
+ def views
34
+ tags.map! {|t| View.new t }
103
35
  end
104
36
 
105
- private
37
+ module ClientContainer
38
+ # see definition below!
39
+ end
106
40
 
107
- def sibling aOffset
108
- arr = chain
41
+ include ClientContainer
109
42
 
110
- if pos = arr.index(self)
111
- arr[(pos + aOffset) % arr.length]
43
+ # Returns the IDs of the current set of clients.
44
+ def client_ids
45
+ fs.client.entries - %w[sel]
112
46
  end
113
- end
114
- end
115
-
116
- # The basic building block of the WM hierarchy.
117
- #
118
- # NOTE: Inheritors must have a 'current' class method.
119
- # NOTE: Inheritors must override the 'focus' method.
120
- #
121
- module WidgetImpl #:nodoc:
122
- attr_reader :id
123
-
124
- def == aOther
125
- @id == aOther.id
47
+
48
+ # Returns the name of the currently focused tag.
49
+ def curr_tag
50
+ curr_view.id
126
51
  end
127
52
 
128
- # Checks if this widget currently has focus.
129
- def current?
130
- self == self.class.curr
53
+ # Returns the name of the next tag.
54
+ def next_tag
55
+ next_view.id
131
56
  end
132
57
 
133
- alias focus? current?
134
- end
58
+ # Returns the name of the previous tag.
59
+ def prev_tag
60
+ prev_view.id
61
+ end
135
62
 
136
- # A widget that has a corresponding representation in the IXP file system.
137
- class WidgetNode < Node #:nodoc:
138
- include WidgetImpl
139
63
 
140
- def initialize aId, aPathPrefix
141
- super "#{aPathPrefix}/#{aId}"
64
+ # multiple client grouping: allows you to group a set of clients
65
+ # together and perform operations on all of them simultaneously.
142
66
 
143
- if aId.to_s == 'sel' and ctl.exist?
144
- @id = ctl.read.split.first
145
- @path = File.join(File.dirname(@path), @id)
146
- else
147
- @id = File.basename(@path)
148
- end
149
- end
150
- end
67
+ GROUPING_TAG = '@'
151
68
 
152
- # A graphical program that is running in your current X Windows session.
153
- class Client < WidgetNode
154
- def initialize aClientId
155
- super aClientId, '/client'
69
+ # Returns a list of all grouped clients in
70
+ # the currently focused view. If there are
71
+ # no grouped clients, then the currently
72
+ # focused client is returned in the list.
73
+ def grouping
74
+ list = curr_view.clients.select {|c| c.group? }
75
+ list << curr_client if list.empty? and curr_client.exist?
76
+ list
156
77
  end
157
78
 
158
- # Returns the currently focused client.
159
- def self.curr
160
- new :sel
161
- end
162
79
 
163
- include Chain
164
- # Returns a list of clients in the current view.
165
- def chain
166
- View.curr.clients
167
- end
80
+ # abstraction of WM components
168
81
 
169
82
  ##
83
+ # NOTE: Inheritors must override the 'chain' method.
170
84
  #
171
- # WM operations
172
- #
173
- ##
85
+ module Chain
86
+ ##
87
+ # Returns an array of objects related to this one.
88
+ #
89
+ def chain
90
+ [self]
91
+ end
174
92
 
175
- # Focuses this client within the given view.
176
- def focus aView = nil
177
- if exist? and not focus?
178
- (aView ? [aView] : self.views).each do |v|
179
- if a = self.area(v) and a.exist?
180
- v.focus
181
- a.focus
93
+ ##
94
+ # Returns the object after this one in the chain.
95
+ #
96
+ def next
97
+ sibling(+1)
98
+ end
182
99
 
183
- # slide focus from the current client onto this client
184
- arr = a.client_ids
185
- src = arr.index Client.curr.id
186
- dst = arr.index @id
100
+ ##
101
+ # Returns the object before this one in the chain.
102
+ #
103
+ def prev
104
+ sibling(-1)
105
+ end
187
106
 
188
- distance = (src - dst).abs
189
- direction = src < dst ? :down : :up
107
+ private
190
108
 
191
- distance.times do
192
- v.ctl.write "select #{direction}"
193
- end
109
+ def sibling offset
110
+ arr = chain
194
111
 
195
- break
196
- end
112
+ if pos = arr.index(self)
113
+ arr[(pos + offset) % arr.length]
197
114
  end
198
115
  end
199
116
  end
200
117
 
201
- # Sends this client to the given destination within the given view.
202
- def send aAreaOrId, aView = View.curr
203
- dst = area_to_id(aAreaOrId)
204
- aView.ctl.write "send #{@id} #{dst}"
205
- end
118
+ ##
119
+ # The basic building block of the WM hierarchy.
120
+ #
121
+ # NOTE: Inheritors must have a 'current' class method.
122
+ # NOTE: Inheritors must override the 'focus' method.
123
+ #
124
+ module WidgetImpl #:nodoc:
125
+ attr_reader :id
206
126
 
207
- # Swaps this client with the given destination within the given view.
208
- def swap aAreaOrId, aView = View.curr
209
- dst = area_to_id(aAreaOrId)
210
- aView.ctl.write "swap #{@id} #{dst}"
211
- end
127
+ def == other
128
+ @id == other.id
129
+ end
130
+
131
+ ##
132
+ # Checks if this widget currently has focus.
133
+ #
134
+ def current?
135
+ self == self.class.curr
136
+ end
212
137
 
213
- # Terminates this client nicely (requests this window to be closed).
214
- def kill
215
- ctl.write :kill
138
+ alias focus? current?
216
139
  end
217
140
 
218
141
  ##
142
+ # A widget that has a corresponding representation in the IXP file system.
219
143
  #
220
- # WM hierarchy
221
- #
222
- ##
144
+ class WidgetNode < Node #:nodoc:
145
+ include WidgetImpl
223
146
 
224
- # Returns the area that contains this client within the given view.
225
- def area aView = View.curr
226
- aView.area_of_client self
227
- end
147
+ def initialize id, path_prefix
148
+ super "#{path_prefix}/#{id}"
228
149
 
229
- # Returns the views that contain this client.
230
- def views
231
- tags.map! {|t| View.new t}
150
+ if id.to_s == 'sel' and ctl.exist?
151
+ @id = ctl.read.split.first
152
+ @path = File.join(File.dirname(@path), @id)
153
+ else
154
+ @id = File.basename(@path)
155
+ end
156
+ end
232
157
  end
233
158
 
234
159
  ##
160
+ # A graphical program that is running in your current X Windows session.
235
161
  #
236
- # tag manipulations
237
- #
238
- ##
162
+ class Client < WidgetNode
163
+ def initialize client_id
164
+ super client_id, '/client'
165
+ end
239
166
 
240
- TAG_DELIMITER = '+'.freeze
167
+ ##
168
+ # Returns the currently focused client.
169
+ #
170
+ def self.curr
171
+ new :sel
172
+ end
241
173
 
242
- # Returns the tags associated with this client.
243
- def tags
244
- self[:tags].read.split TAG_DELIMITER
245
- end
174
+ include Chain
246
175
 
247
- # Modifies the tags associated with this client.
248
- def tags= *aTags
249
- arr = aTags.flatten.compact.uniq
250
- self[:tags].write arr.join(TAG_DELIMITER)
251
- end
176
+ ##
177
+ # Returns a list of all clients in the current view.
178
+ #
179
+ def chain
180
+ View.curr.clients
181
+ end
252
182
 
253
- # Evaluates the given block within the
254
- # context of this client's list of tags.
255
- def with_tags &aBlock
256
- arr = self.tags
257
- arr.instance_eval(&aBlock)
258
- self.tags = arr
259
- end
183
+ # WM operations
260
184
 
261
- # Adds the given tags to this client.
262
- def tag *aTags
263
- with_tags do
264
- concat aTags
265
- end
266
- end
185
+ ##
186
+ # Focuses this client within the given view.
187
+ #
188
+ def focus view = nil
189
+ if exist? and not focus?
190
+ Array(view || self.views).each do |v|
191
+ if a = self.area(v) and a.exist?
192
+ v.focus
193
+ a.focus
267
194
 
268
- # Removes the given tags from this client.
269
- def untag *aTags
270
- with_tags do
271
- aTags.flatten.each do |tag|
272
- delete tag.to_s
195
+ # slide focus from the current client onto this client
196
+ arr = a.client_ids
197
+ src = arr.index Client.curr.id
198
+ dst = arr.index @id
199
+
200
+ distance = (src - dst).abs
201
+ direction = src < dst ? :down : :up
202
+
203
+ distance.times do
204
+ v.ctl.write "select #{direction}"
205
+ end
206
+
207
+ break
208
+ end
209
+ end
210
+ end
273
211
  end
274
- end
275
- end
276
212
 
277
- ##
278
- #
279
- # multiple client grouping
280
- #
281
- ##
213
+ ##
214
+ # Sends this client to the given destination within the given view.
215
+ #
216
+ def send area_or_id, view = View.curr
217
+ dst = area_to_id(area_or_id)
218
+ view.ctl.write "send #{@id} #{dst}"
219
+ end
282
220
 
283
- # Checks if this client is included in the current grouping.
284
- def group?
285
- tags.include? GROUPING_TAG
286
- end
221
+ ##
222
+ # Swaps this client with the given destination within the given view.
223
+ #
224
+ def swap area_or_id, view = View.curr
225
+ dst = area_to_id(area_or_id)
226
+ view.ctl.write "swap #{@id} #{dst}"
227
+ end
287
228
 
288
- # Adds this client to the current grouping.
289
- def group
290
- with_tags do
291
- push GROUPING_TAG
292
- end
293
- end
229
+ ##
230
+ # Terminates this client nicely (requests this window to be closed).
231
+ #
232
+ def kill
233
+ ctl.write :kill
234
+ end
294
235
 
295
- # Removes this client to the current grouping.
296
- def ungroup
297
- untag GROUPING_TAG
298
- end
236
+ # WM hierarchy
299
237
 
300
- # Toggles the presence of this client in the current grouping.
301
- def toggle_group
302
- if group?
303
- ungroup
304
- else
305
- group
306
- end
307
- end
238
+ ##
239
+ # Returns the area that contains this client within the given view.
240
+ #
241
+ def area view = View.curr
242
+ view.area_of_client self
243
+ end
308
244
 
309
- private
245
+ ##
246
+ # Returns the views that contain this client.
247
+ #
248
+ def views
249
+ tags.map! {|t| View.new t }
250
+ end
310
251
 
311
- def area_to_id aAreaOrId
312
- if aAreaOrId.respond_to? :id
313
- id = aAreaOrId.id
314
- id == '~' ? :toggle : id
315
- else
316
- aAreaOrId
317
- end
318
- end
319
- end
252
+ # tag manipulations
320
253
 
321
- # NOTE: Inheritors should override the 'client_ids' method.
322
- module ClientContainer
323
- # Returns the IDs of the clients in this container.
324
- def client_ids
325
- []
326
- end
254
+ TAG_DELIMITER = '+'.freeze
327
255
 
328
- # Returns the clients contained in this container.
329
- def clients
330
- client_ids.map! {|i| Client.new i}
331
- end
256
+ ##
257
+ # Returns the tags associated with this client.
258
+ #
259
+ def tags
260
+ self[:tags].read.split TAG_DELIMITER
261
+ end
332
262
 
333
- # multiple client grouping
334
- %w[group ungroup toggle_group].each do |meth|
335
- define_method meth do
336
- clients.each do |c|
337
- c.__send__ meth
263
+ ##
264
+ # Modifies the tags associated with this client.
265
+ #
266
+ def tags= *tags
267
+ arr = tags.flatten.compact.uniq
268
+ self[:tags].write arr.join(TAG_DELIMITER)
338
269
  end
339
- end
340
- end
341
270
 
342
- # Returns all grouped clients in this container.
343
- def grouping
344
- clients.select {|c| c.group? }
345
- end
346
- end
271
+ ##
272
+ # Evaluates the given block within the
273
+ # context of this client's list of tags.
274
+ #
275
+ def with_tags &block
276
+ arr = self.tags
277
+ arr.instance_eval(&block)
278
+ self.tags = arr
279
+ end
347
280
 
348
- # A region that contains clients. This can be either
349
- # the floating area or a column in the managed area.
350
- class Area
351
- attr_reader :view
281
+ ##
282
+ # Adds the given tags to this client.
283
+ #
284
+ def tag *tags
285
+ with_tags do
286
+ concat tags
287
+ end
288
+ end
352
289
 
353
- # aView:: the view which contains this area.
354
- def initialize aAreaId, aView = View.curr
355
- @id = Integer(aAreaId) rescue aAreaId
356
- @view = aView
357
- end
290
+ ##
291
+ # Removes the given tags from this client.
292
+ #
293
+ def untag *tags
294
+ with_tags do
295
+ tags.flatten.each do |tag|
296
+ delete tag.to_s
297
+ end
298
+ end
299
+ end
358
300
 
359
- # Checks if this area is the floating area.
360
- def float?
361
- @id == '~'
362
- end
301
+ # multiple client grouping
363
302
 
364
- # Checks if this area is a column in the managed area.
365
- def column?
366
- not float?
367
- end
303
+ ##
304
+ # Checks if this client is included in the current grouping.
305
+ #
306
+ def group?
307
+ tags.include? GROUPING_TAG
308
+ end
368
309
 
369
- include WidgetImpl
370
- # Returns the currently focused area.
371
- def self.curr
372
- View.curr.area_of_client Client.curr
373
- end
310
+ ##
311
+ # Adds this client to the current grouping.
312
+ #
313
+ def group
314
+ with_tags do
315
+ push GROUPING_TAG
316
+ end
317
+ end
374
318
 
375
- include Chain
376
- def chain
377
- @view.areas
378
- end
319
+ ##
320
+ # Removes this client to the current grouping.
321
+ #
322
+ def ungroup
323
+ untag GROUPING_TAG
324
+ end
379
325
 
380
- # Checks if this object exists in the chain.
381
- def exist?
382
- chain.include? self
383
- end
326
+ ##
327
+ # Toggles the presence of this client in the current grouping.
328
+ #
329
+ def toggle_group
330
+ if group?
331
+ ungroup
332
+ else
333
+ group
334
+ end
335
+ end
384
336
 
385
- include ClientContainer
386
- # Returns the IDs of the clients in this area.
387
- def client_ids
388
- @view.client_ids @id
389
- end
337
+ private
390
338
 
391
- include Enumerable
392
- # Iterates through each client in this container.
393
- def each &aBlock
394
- clients.each(&aBlock)
339
+ def area_to_id area_or_id
340
+ if area_or_id.respond_to? :id
341
+ id = area_or_id.id
342
+ id == '~' ? :toggle : id
343
+ else
344
+ area_or_id
345
+ end
395
346
  end
396
-
397
- # Sets the layout of clients in this column.
398
- def layout= aMode
399
- @view.ctl.write "colmode #{@id} #{aMode}"
400
347
  end
401
348
 
402
349
  ##
350
+ # NOTE: Inheritors should override the 'client_ids' method.
403
351
  #
404
- # WM operations
405
- #
406
- ##
352
+ module ClientContainer
353
+ ##
354
+ # Returns the IDs of the clients in this container.
355
+ #
356
+ def client_ids
357
+ []
358
+ end
359
+
360
+ ##
361
+ # Returns the clients contained in this container.
362
+ #
363
+ def clients
364
+ client_ids.map! {|i| Client.new i }
365
+ end
366
+
367
+ # multiple client grouping
368
+ %w[group ungroup toggle_group].each do |meth|
369
+ define_method meth do
370
+ clients.each do |c|
371
+ c.__send__ meth
372
+ end
373
+ end
374
+ end
407
375
 
408
- # Puts focus on this area.
409
- def focus
410
- @view.ctl.write "select #{@id}"
376
+ ##
377
+ # Returns all grouped clients in this container.
378
+ #
379
+ def grouping
380
+ clients.select {|c| c.group? }
381
+ end
411
382
  end
412
383
 
413
384
  ##
385
+ # A region that contains clients. This can be either
386
+ # the floating area or a column in the managed area.
414
387
  #
415
- # array abstraction: area is an array of clients
416
- #
417
- ##
388
+ class Area
389
+ attr_reader :view
418
390
 
419
- # Returns the number of clients in this area.
420
- def length
421
- client_ids.length
422
- end
391
+ ##
392
+ # [view] the view object which contains this area
393
+ #
394
+ def initialize area_id, view = View.curr
395
+ @id = Integer(area_id) rescue area_id
396
+ @view = view
397
+ end
423
398
 
424
- # Inserts the given clients at the bottom of this area.
425
- def push *aClients
426
- if target = clients.last
427
- target.focus
399
+ ##
400
+ # Checks if this area is the floating area.
401
+ #
402
+ def float?
403
+ @id == '~'
428
404
  end
429
405
 
430
- insert aClients
431
- end
406
+ ##
407
+ # Checks if this is a managed area (a column).
408
+ #
409
+ def column?
410
+ not float?
411
+ end
432
412
 
433
- alias << push
413
+ include WidgetImpl
434
414
 
435
- # Inserts the given clients after the currently focused client in this area.
436
- def insert *aClients
437
- aClients.flatten!
438
- return if aClients.empty?
415
+ ##
416
+ # Returns the currently focused area.
417
+ #
418
+ def self.curr
419
+ View.curr.area_of_client Client.curr
420
+ end
439
421
 
440
- aClients.each do |c|
441
- import_client c
442
- end
443
- end
422
+ include Chain
444
423
 
445
- # Inserts the given clients at the top of this area.
446
- def unshift *aClients
447
- aClients.flatten!
448
- return if aClients.empty?
424
+ ##
425
+ # Returns a list of all areas in the current view.
426
+ #
427
+ def chain
428
+ @view.areas
429
+ end
449
430
 
450
- if target = clients.first
451
- target.focus
452
- end
431
+ ##
432
+ # Checks if this object exists in the chain.
433
+ #
434
+ def exist?
435
+ chain.include? self
436
+ end
453
437
 
454
- aClients.each do |c|
455
- import_client c
456
- c.send :up if target
457
- end
458
- end
438
+ include ClientContainer
459
439
 
460
- # Concatenates the given area to the bottom of this area.
461
- def concat aArea
462
- push aArea.clients
463
- end
440
+ ##
441
+ # Returns the IDs of the clients in this area.
442
+ #
443
+ def client_ids
444
+ @view.client_ids @id
445
+ end
464
446
 
465
- # Ensures that this area has at most the given number of clients.
466
- # Areas to the right of this one serve as a buffer into which excess
467
- # clients are evicted and from which deficit clients are imported.
468
- def length= aMaxClients
469
- return unless aMaxClients > 0
470
- len, out = length, fringe
447
+ include Enumerable
471
448
 
472
- if len > aMaxClients
473
- out.unshift clients[aMaxClients..-1].reverse
449
+ ##
450
+ # Iterates through each client in this container.
451
+ #
452
+ def each &block
453
+ clients.each(&block)
454
+ end
455
+
456
+ ##
457
+ # Sets the layout of clients in this column.
458
+ #
459
+ def layout= mode
460
+ @view.ctl.write "colmode #{@id} #{mode}"
461
+ end
474
462
 
475
- elsif len < aMaxClients
476
- until (diff = aMaxClients - length) == 0
477
- immigrants = out.clients.first(diff)
478
- break if immigrants.empty?
463
+ # WM operations
479
464
 
480
- push immigrants
465
+ ##
466
+ # Puts focus on this area.
467
+ #
468
+ def focus
469
+ @view.ctl.write "select #{@id}"
481
470
  end
482
- end
483
- end
484
471
 
485
- private
472
+ # array abstraction: area is an array of clients
486
473
 
487
- # Moves the given client into this area.
488
- def import_client c
489
- if exist?
490
- c.send self
474
+ ##
475
+ # Returns the number of clients in this area.
476
+ #
477
+ def length
478
+ client_ids.length
479
+ end
491
480
 
492
- else
493
- # move the client to the nearest existing column
494
- src = c.area
495
- dst = chain.last
481
+ ##
482
+ # Inserts the given clients at the bottom of this area.
483
+ #
484
+ def push *clients
485
+ clients.flatten!
486
+ return if clients.empty?
496
487
 
497
- c.send dst unless src == dst
488
+ insert clients
498
489
 
499
- # slide the client over to this column
500
- c.send :right
501
- @id = dst.id.next
490
+ # adjust the order of clients in this
491
+ # area to reflect the tail-wise insertion
492
+ clients.each_with_index do |c, i|
493
+ until c.id == self.client_ids[-i.succ]
494
+ c.swap :down
495
+ end
496
+ end
497
+ end
502
498
 
503
- raise 'column should exist now' unless exist?
504
- end
505
- end
499
+ alias << push
506
500
 
507
- # Returns the next area, which may or may not exist.
508
- def fringe
509
- Area.new @id.next, @view
510
- end
511
- end
501
+ ##
502
+ # Inserts the given clients after the
503
+ # currently focused client in this area.
504
+ #
505
+ def insert *clients
506
+ clients.flatten!
507
+ return if clients.empty?
512
508
 
513
- # The visualization of a tag.
514
- class View < WidgetNode
515
- include WidgetImpl
516
- # Returns the currently focused view.
517
- def self.curr
518
- new :sel
519
- end
509
+ clients.each do |c|
510
+ import_client c
511
+ end
512
+ end
520
513
 
521
- # Focuses this view.
522
- def focus
523
- Rumai.fs.ctl.write "view #{@id}"
524
- end
514
+ ##
515
+ # Inserts the given clients at the top of this area.
516
+ #
517
+ def unshift *clients
518
+ clients.flatten!
519
+ return if clients.empty?
525
520
 
526
- include Chain
527
- def chain
528
- Rumai.views
529
- end
521
+ insert clients
530
522
 
531
- include ClientContainer
532
- # Returns the IDs of the clients contained
533
- # in the given area within this view.
534
- def client_ids aAreaId = '\S+'
535
- manifest.scan(/^#{aAreaId} (0x\S+)/).flatten
536
- end
523
+ # adjust the order of clients in this
524
+ # area to reflect the head-wise insertion
525
+ clients.each_with_index do |c, i|
526
+ until c.id == self.client_ids[i]
527
+ c.swap :up
528
+ end
529
+ end
530
+ end
537
531
 
538
- include Enumerable
539
- # Iterates through each area in this view.
540
- def each &aBlock
541
- areas.each(&aBlock)
542
- end
532
+ ##
533
+ # Concatenates the given area to the bottom of this area.
534
+ #
535
+ def concat area
536
+ push area.clients
537
+ end
543
538
 
544
- def initialize aViewId
545
- super aViewId, '/tag'
546
- end
539
+ ##
540
+ # Ensures that this area has at most the given number of clients.
541
+ #
542
+ # Areas to the right of this one serve as a buffer into which excess
543
+ # clients are evicted and from which deficit clients are imported.
544
+ #
545
+ def length= max_clients
546
+ return unless max_clients > 0
547
+ len, out = length, fringe
548
+
549
+ if len > max_clients
550
+ out.unshift clients[max_clients..-1]
551
+
552
+ elsif len < max_clients
553
+ until (diff = max_clients - length) == 0
554
+ importable = out.clients[0, diff]
555
+ break if importable.empty?
556
+
557
+ push importable
558
+ end
559
+ end
560
+ end
547
561
 
548
- # Returns the manifest of all areas and clients in this view.
549
- def manifest
550
- index.read || ''
551
- end
562
+ private
552
563
 
553
- ##
554
- #
555
- # WM hierarchy
556
- #
557
- ##
564
+ ##
565
+ # Moves the given client into this area.
566
+ #
567
+ def import_client c
568
+ if exist?
569
+ c.send self
558
570
 
559
- # Returns the area which contains the given client in this view.
560
- def area_of_client aClientOrId
561
- arg =
562
- if aClientOrId.respond_to? :id
563
- aClientOrId.id
564
571
  else
565
- aClientOrId
572
+ # move the client to the nearest existing column
573
+ src = c.area
574
+ dst = chain.last
575
+
576
+ c.send dst unless src == dst
577
+
578
+ # slide the client over to this column
579
+ c.send :right
580
+ @id = dst.id.next
581
+
582
+ raise 'column should exist now' unless exist?
566
583
  end
584
+ end
567
585
 
568
- manifest =~ /^(\S+) #{arg}/
569
- if areaId = $1
570
- Area.new areaId, self
586
+ ##
587
+ # Returns the next area, which may or may not exist.
588
+ #
589
+ def fringe
590
+ Area.new @id.next, @view
571
591
  end
572
592
  end
573
593
 
574
- # Returns the IDs of all areas in this view.
575
- def area_ids
576
- ids = manifest.scan(/^# (\d+)/).flatten
577
- ids.unshift '~' # always exists in output
578
- ids
579
- end
594
+ ##
595
+ # The visualization of a tag.
596
+ #
597
+ class View < WidgetNode
598
+ include WidgetImpl
599
+
600
+ ##
601
+ # Returns the currently focused view.
602
+ #
603
+ def self.curr
604
+ new :sel
605
+ end
580
606
 
581
- # Returns all areas in this view.
582
- def areas
583
- area_ids.map! {|i| Area.new i, self}
584
- end
607
+ ##
608
+ # Focuses this view.
609
+ #
610
+ def focus
611
+ Rumai.fs.ctl.write "view #{@id}"
612
+ end
585
613
 
586
- # Returns the floating area of this view.
587
- def floater
588
- areas.first
589
- end
614
+ include Chain
590
615
 
591
- # Returns all columns (managed areas) in this view.
592
- def columns
593
- areas[1..-1]
594
- end
616
+ ##
617
+ # Returns a list of all views.
618
+ #
619
+ def chain
620
+ Rumai.views
621
+ end
595
622
 
596
- # Resiliently iterates through possibly destructive changes to
597
- # each column. That is, if the given block creates new
598
- # columns, then those will also be processed in the iteration.
599
- def each_column aStartingColumnId = 1
600
- i = aStartingColumnId
601
- loop do
602
- a = Area.new i, self
623
+ include ClientContainer
603
624
 
604
- if a.exist?
605
- yield a
606
- else
607
- break
625
+ ##
626
+ # Returns the IDs of the clients contained
627
+ # in the given area within this view.
628
+ #
629
+ def client_ids area_id = '\S+'
630
+ manifest.scan(/^#{area_id} (0x\S+)/).flatten
631
+ end
632
+
633
+ include Enumerable
634
+
635
+ ##
636
+ # Iterates through each area in this view.
637
+ #
638
+ def each &block
639
+ areas.each(&block)
608
640
  end
609
641
 
610
- i += 1
642
+ def initialize view_id
643
+ super view_id, '/tag'
611
644
  end
612
- end
613
645
 
614
- ##
615
- #
616
- # visual arrangement of clients
617
- #
618
- ##
646
+ ##
647
+ # Returns the manifest of all areas and clients in this view.
648
+ #
649
+ def manifest
650
+ index.read || ''
651
+ end
619
652
 
620
- # Arranges the clients in this view, while maintaining
621
- # their relative order, in the tiling fashion of
622
- # LarsWM. Only the first client in the primary column
623
- # is kept; all others are evicted to the *top* of the
624
- # secondary column. Any subsequent columns are
625
- # squeezed into the *bottom* of the secondary column.
626
- def arrange_as_larswm
627
- float, main, *extra = areas
628
- main.length = 1
629
- squeeze extra
630
- end
653
+ # WM hierarchy
631
654
 
632
- # Arranges the clients in this view, while maintaining
633
- # their relative order, in a (at best) square grid.
634
- def arrange_in_grid aMaxClientsPerColumn = nil
635
- # compute client distribution
636
- unless aMaxClientsPerColumn
637
- numClients = num_managed_clients
638
- return unless numClients > 0
655
+ ##
656
+ # Returns the area which contains the given client in this view.
657
+ #
658
+ def area_of_client client_or_id
659
+ arg =
660
+ if client_or_id.respond_to? :id
661
+ client_or_id.id
662
+ else
663
+ client_or_id
664
+ end
639
665
 
640
- numColumns = Math.sqrt(numClients)
641
- aMaxClientsPerColumn = (numClients / numColumns).round
642
- end
666
+ manifest =~ /^(\S+) #{arg}/
667
+ if area_id = $1
668
+ Area.new area_id, self
669
+ end
670
+ end
643
671
 
644
- return unless aMaxClientsPerColumn > 1
672
+ ##
673
+ # Returns the IDs of all areas in this view.
674
+ #
675
+ def area_ids
676
+ ids = manifest.scan(/^# (\d+)/).flatten
677
+ ids.unshift '~' # the floating area
678
+ ids
679
+ end
645
680
 
646
- # apply the distribution
647
- each_column do |a|
648
- a.length = aMaxClientsPerColumn
649
- a.layout = :default
650
- end
651
- end
681
+ ##
682
+ # Returns all areas in this view.
683
+ #
684
+ def areas
685
+ area_ids.map! {|i| Area.new i, self }
686
+ end
652
687
 
653
- # Arranges the clients in this view, while maintaining their relative order,
654
- # in a (at best) equilateral triangle. However, the resulting arrangement
655
- # appears like a diamond because wmii does not waste screen space.
656
- def arrange_in_diamond
657
- numClients = num_managed_clients
658
- return unless numClients > 1
688
+ ##
689
+ # Returns the floating area of this view.
690
+ #
691
+ def floater
692
+ areas.first
693
+ end
659
694
 
660
- # determine dimensions of the rising sub-triangle
661
- rise = numClients / 2
695
+ ##
696
+ # Returns all columns (managed areas) in this view.
697
+ #
698
+ def columns
699
+ areas[1..-1]
700
+ end
662
701
 
663
- span = sum = 0
664
- 1.upto rise do |h|
665
- if sum + h > rise
666
- break
667
- else
668
- sum += h
669
- span += 1
702
+ ##
703
+ # Resiliently iterates through possibly destructive changes to
704
+ # each column. That is, if the given block creates new
705
+ # columns, then those will also be processed in the iteration.
706
+ #
707
+ def each_column starting_column_id = 1
708
+ i = starting_column_id
709
+ loop do
710
+ a = Area.new i, self
711
+
712
+ if a.exist?
713
+ yield a
714
+ else
715
+ break
716
+ end
717
+
718
+ i += 1
719
+ end
670
720
  end
671
- end
672
721
 
673
- peak = numClients - (sum * 2)
722
+ # visual arrangement of clients
723
+
724
+ ##
725
+ # Arranges the clients in this view, while maintaining
726
+ # their relative order, in the tiling fashion of LarsWM.
727
+ #
728
+ # Only the first client in the primary column is kept; all others
729
+ # are evicted to the *top* of the secondary column. Any subsequent
730
+ # columns are squeezed into the *bottom* of the secondary column.
731
+ #
732
+ def arrange_as_larswm
733
+ maintain_focus do
734
+ float, main, *extra = areas
735
+
736
+ # keep only one client in the primary column
737
+ main.length = 1
738
+
739
+ if extra.length > 1
740
+ # collapse remaining areas into secondary column
741
+ extra.reverse.each_cons(2) do |src, dst|
742
+ dst.concat src
743
+ end
744
+ end
745
+ end
746
+ end
747
+
748
+ ##
749
+ # Arranges the clients in this view, while maintaining
750
+ # their relative order, in a (at best) square grid.
751
+ #
752
+ def arrange_in_grid max_clients_per_column = nil
753
+ # compute client distribution
754
+ unless max_clients_per_column
755
+ num_clients = num_managed_clients
756
+ return unless num_clients > 0
757
+
758
+ num_columns = Math.sqrt(num_clients)
759
+ max_clients_per_column = (num_clients / num_columns).round
760
+ end
761
+
762
+ return if max_clients_per_column < 1
763
+
764
+ # apply the distribution
765
+ maintain_focus do
766
+ each_column do |a|
767
+ a.length = max_clients_per_column
768
+ a.layout = :default
769
+ end
770
+ end
771
+ end
772
+
773
+ ##
774
+ # Arranges the clients in this view, while
775
+ # maintaining their relative order, in a (at
776
+ # best) equilateral triangle. However, the
777
+ # resulting arrangement appears like a diamond
778
+ # because wmii does not waste screen space.
779
+ #
780
+ def arrange_in_diamond
781
+ num_clients = num_managed_clients
782
+ return unless num_clients > 1
783
+
784
+ # determine dimensions of the rising sub-triangle
785
+ rise = num_clients / 2
786
+
787
+ span = sum = 0
788
+ 1.upto rise do |h|
789
+ if sum + h > rise
790
+ break
791
+ else
792
+ sum += h
793
+ span += 1
794
+ end
795
+ end
796
+
797
+ peak = num_clients - (sum * 2)
674
798
 
675
- # describe the overall triangle as a sequence of heights
676
- riseSeq = (1..span).to_a
677
- fallSeq = riseSeq.reverse
799
+ # describe the overall triangle as a sequence of heights
800
+ rise_seq = (1..span).to_a
801
+ fall_seq = rise_seq.reverse
678
802
 
679
- heights = riseSeq
680
- heights << peak if peak > 0
681
- heights.concat fallSeq
803
+ heights = rise_seq
804
+ heights << peak if peak > 0
805
+ heights.concat fall_seq
682
806
 
683
- # apply the heights
684
- each_column do |col|
685
- if h = heights.shift
686
- col.length = h
687
- col.layout = :default
807
+ # apply the heights
808
+ maintain_focus do
809
+ each_column do |col|
810
+ if h = heights.shift
811
+ col.length = h
812
+ col.layout = :default
813
+ end
814
+ end
815
+ end
688
816
  end
689
- end
690
- end
691
817
 
692
- private
818
+ private
693
819
 
694
- # Returns the number of clients in the non-floating areas of this view.
695
- def num_managed_clients
696
- manifest.scan(/^\d+ 0x/).length
697
- end
820
+ ##
821
+ # Executes the given block and restores
822
+ # focus to the client that had focus
823
+ # before the given block was executed.
824
+ #
825
+ def maintain_focus
826
+ c = Rumai.curr_client
827
+ yield
828
+ c.focus
829
+ end
698
830
 
699
- # Smashes the given list of areas into the first one.
700
- # The relative ordering of clients is preserved.
701
- def squeeze aAreas
702
- aAreas.reverse.each_cons(2) do |src, dst|
703
- dst.concat src
831
+ ##
832
+ # Returns the number of clients in the non-floating areas of this view.
833
+ #
834
+ def num_managed_clients
835
+ manifest.scan(/^\d+ 0x/).length
704
836
  end
705
837
  end
706
- end
707
-
708
838
 
709
- ##
710
- #
711
839
  # shortcuts for interactive WM manipulation (via IRB)
712
- #
713
- ##
714
840
 
715
- # provide easy access to container state information
716
- [Client, Area, View].each do |c|
717
- c.extend ExportInstMethods
718
- end
841
+ # provide easy access to container state information
842
+ [Client, Area, View].each {|c| c.extend ExportInstanceMethods }
719
843
 
720
- def curr_client
721
- Client.curr
722
- end
844
+ def curr_client
845
+ Client.curr
846
+ end
723
847
 
724
- def next_client
725
- curr_client.next
726
- end
848
+ def next_client
849
+ curr_client.next
850
+ end
727
851
 
728
- def prev_client
729
- curr_client.prev
730
- end
852
+ def prev_client
853
+ curr_client.prev
854
+ end
731
855
 
732
- def curr_area
733
- Area.curr
734
- end
856
+ def curr_area
857
+ Area.curr
858
+ end
735
859
 
736
- def next_area
737
- curr_area.next
738
- end
860
+ def next_area
861
+ curr_area.next
862
+ end
739
863
 
740
- def prev_area
741
- curr_area.prev
742
- end
864
+ def prev_area
865
+ curr_area.prev
866
+ end
743
867
 
744
- def curr_view
745
- View.curr
746
- end
868
+ def curr_view
869
+ View.curr
870
+ end
747
871
 
748
- def next_view
749
- curr_view.next
750
- end
872
+ def next_view
873
+ curr_view.next
874
+ end
751
875
 
752
- def prev_view
753
- curr_view.prev
754
- end
876
+ def prev_view
877
+ curr_view.prev
878
+ end
755
879
 
756
- def focus_client aId
757
- Client.focus(aId)
758
- end
880
+ def focus_client id
881
+ Client.focus id
882
+ end
759
883
 
760
- def focus_area aId
761
- Area.focus(aId)
762
- end
884
+ def focus_area id
885
+ Area.focus id
886
+ end
763
887
 
764
- def focus_view aId
765
- View.focus(aId)
766
- end
888
+ def focus_view id
889
+ View.focus id
890
+ end
767
891
 
768
- # provide easy access to this module's instance methods
769
- module_function(*instance_methods)
892
+ # provide easy access to this module's instance methods
893
+ module_function(*instance_methods)
770
894
  end