tmux-ruby 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 (40) hide show
  1. data/.yardopts +1 -0
  2. data/LICENSE +22 -0
  3. data/README.md +23 -0
  4. data/lib/tmux.rb +56 -0
  5. data/lib/tmux/buffer.rb +131 -0
  6. data/lib/tmux/client.rb +193 -0
  7. data/lib/tmux/exception.rb +5 -0
  8. data/lib/tmux/exception/basic_exception.rb +6 -0
  9. data/lib/tmux/exception/in_tmux.rb +9 -0
  10. data/lib/tmux/exception/index_in_use.rb +9 -0
  11. data/lib/tmux/exception/unknown_command.rb +9 -0
  12. data/lib/tmux/exception/unsupported_version.rb +15 -0
  13. data/lib/tmux/filterable_hash.rb +15 -0
  14. data/lib/tmux/options.rb +109 -0
  15. data/lib/tmux/options/attr_option.rb +10 -0
  16. data/lib/tmux/options/bell_action_option.rb +19 -0
  17. data/lib/tmux/options/boolean_option.rb +26 -0
  18. data/lib/tmux/options/char_array_option.rb +26 -0
  19. data/lib/tmux/options/clock_mode_style_option.rb +27 -0
  20. data/lib/tmux/options/color_option.rb +23 -0
  21. data/lib/tmux/options/justification_option.rb +19 -0
  22. data/lib/tmux/options/keymap_option.rb +19 -0
  23. data/lib/tmux/options/number_option.rb +26 -0
  24. data/lib/tmux/options/option.rb +38 -0
  25. data/lib/tmux/options/string_option.rb +26 -0
  26. data/lib/tmux/options/symbol_option.rb +26 -0
  27. data/lib/tmux/options/word_array_option.rb +26 -0
  28. data/lib/tmux/options_list.rb +150 -0
  29. data/lib/tmux/pane.rb +496 -0
  30. data/lib/tmux/server.rb +217 -0
  31. data/lib/tmux/session.rb +312 -0
  32. data/lib/tmux/status_bar.rb +134 -0
  33. data/lib/tmux/status_bar/field.rb +129 -0
  34. data/lib/tmux/version.rb +4 -0
  35. data/lib/tmux/widget.rb +35 -0
  36. data/lib/tmux/widgets/progress_bar.rb +107 -0
  37. data/lib/tmux/window.rb +697 -0
  38. data/lib/tmux/window/status.rb +21 -0
  39. data/lib/tmux/window/status/state.rb +87 -0
  40. metadata +96 -0
@@ -0,0 +1,134 @@
1
+ require "tmux/status_bar/field"
2
+
3
+ module Tmux
4
+ # Every {Session session} has a status bar. This is where various
5
+ # information as well as a list of {Window windows} will be
6
+ # displayed. For this purpose, the status bar is divided into three
7
+ # parts: the left, center and right part. While the center part
8
+ # displays the window list, the left and right part can be set to
9
+ # display any text.
10
+ #
11
+ # This class allows accessing various attributes (e.g. the
12
+ # {#background_color background color} of the bar) and the
13
+ # editable parts ({#left left} and {#right right}).
14
+ #
15
+ # Note: You will not have to instantiate this class. Use
16
+ # {Session#status_bar} instead.
17
+ class StatusBar
18
+ # @return [Session]
19
+ attr_reader :session
20
+ # The left {Field field} which may display custom {Field#text
21
+ # text} and {Widget widgets}.
22
+ #
23
+ # @return [Field]
24
+ attr_reader :left
25
+
26
+ # The right {Field field} which may display custom {Field#text
27
+ # text} and {Widget widgets}.
28
+ #
29
+ # @return [Field]
30
+ attr_reader :right
31
+ # @param [Session] session
32
+ def initialize(session)
33
+ @session = session
34
+ @left = Field.new(self, :left)
35
+ @right = Field.new(self, :right)
36
+ end
37
+
38
+ # Hides the status bar.
39
+ #
40
+ # @return [void]
41
+ def hide
42
+ @session.options.status = false
43
+ end
44
+
45
+ # Shows the status bar.
46
+ #
47
+ # @return [void]
48
+ def show
49
+ @session.options.status = true
50
+ end
51
+
52
+ # @return [Symbol]
53
+ attr_accessor :background_color
54
+ undef_method "background_color"
55
+ undef_method "background_color="
56
+ def background_color
57
+ @session.options.status_bg
58
+ end
59
+
60
+ def background_color=(color)
61
+ @session.options.status_bg = color
62
+ end
63
+
64
+ # @return [Symbol]
65
+ attr_accessor :foreground_color
66
+ undef_method "foreground_color"
67
+ undef_method "foreground_color="
68
+ def foreground_color
69
+ @session.options.status_fg
70
+ end
71
+
72
+ def foreground_color=(color)
73
+ @session.options.status_fg = color
74
+ end
75
+
76
+ # @return [Number] The interval in which the status bar will be
77
+ # updated.
78
+ attr_accessor :interval
79
+ undef_method "interval"
80
+ undef_method "interval="
81
+ def interval
82
+ @session.options.status_interval
83
+ end
84
+
85
+ def interval=(value)
86
+ @session.options.status_interval = value
87
+ end
88
+
89
+ # Sets the justification of the window list component of the status
90
+ # line.
91
+ #
92
+ # @return [Symbol<:left, :right, :centre>]
93
+ attr_accessor :justification
94
+ undef_method "justification"
95
+ undef_method "justification="
96
+ def justification
97
+ @session.options.status_justify
98
+ end
99
+
100
+ def justification=(val)
101
+ @session.options.status_justify = val
102
+ end
103
+
104
+ # @return [Symbol<:emacs, :vi>]
105
+ attr_accessor :keymap
106
+ undef_method "keymap"
107
+ undef_method "keymap="
108
+ def keymap
109
+ # TODO keymap class?
110
+ @session.options.status_keys
111
+ end
112
+
113
+ def keymap=(val)
114
+ @session.options.status_keys = val
115
+ end
116
+
117
+ # Instruct tmux to treat top-bit-set characters in
118
+ # {StatusBar::Field#text} as UTF-8. Notably, this is important for
119
+ # wide characters. This option defaults to false.
120
+ #
121
+ # @return [Boolean]
122
+ attr_accessor :utf8
123
+ undef_method "utf8"
124
+ undef_method "utf8="
125
+ def utf8
126
+ @session.options.status_utf8
127
+ end
128
+ alias_method :utf8?, :utf8
129
+
130
+ def utf8=(bool)
131
+ @session.options.status_utf8 = bool
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,129 @@
1
+ module Tmux
2
+ class StatusBar
3
+ # This class represents a field in a {StatusBar status bar}. Every
4
+ # {StatusBar status bar} has two fields, one on the left side and
5
+ # one on the right side.
6
+ #
7
+ # A field can either display a simple {#text text}, or display a
8
+ # {Widget widget}. While only one {Widget widget} can be displayed
9
+ # at a time per field, a field will keep a stack of widgets, to
10
+ # and from which new {Widget widgets} can be {#push_widget pushed}
11
+ # and {#pop_widget popped}. This is useful for example when
12
+ # temporarily displaying a {Widgets::ProgressBar progress bar}.
13
+ class Field
14
+ def initialize(status_bar, side)
15
+ @status_bar = status_bar
16
+ @side = side
17
+ @widgets = []
18
+ @backups = []
19
+ end
20
+
21
+ # Pushes a widget to the stack, making it the currently visible
22
+ # one.
23
+ #
24
+ # @param [Widget] widget the widget to push to the stack
25
+ # @return [void]
26
+ def push_widget(widget)
27
+ @backups << self.text
28
+ @widgets << widget
29
+ widget.field = self
30
+ end
31
+ alias_method :add_widget, :push_widget
32
+
33
+ # Removes the current {Widget widget} from the stack.
34
+ #
35
+ # @param [Widget] pop If not nil, try to remove the specified
36
+ # widget instead of popping off the topmost one.
37
+ # @return [Widget, nil] the {Widget widget} which has been popped
38
+ def pop_widget(pop = nil)
39
+ widget = pop || @widgets.first
40
+ pos = @widgets.index(widget)
41
+ @widgets.delete_at(pos)
42
+ backup = @backups.delete_at(pos)
43
+
44
+ self.text = backup if backup and pos == 0
45
+ widget
46
+ end
47
+ alias_method :remove_widget, :pop_widget
48
+
49
+ # @overload widget
50
+ # @return [Widget] The currently displayed {Widget widget},
51
+ # that is the one on top of the stack.
52
+ # @overload widget=(widget)
53
+ # Overwrites the stack of {Widget widgets} and makes `widget` the only
54
+ # {Widget widget}.
55
+ #
56
+ # @return [Widget]
57
+ # @return [Widget] The currently displayed {Widget widget},
58
+ # that is the one on top of the stack.
59
+ attr_accessor :widget
60
+ undef_method "widget"
61
+ undef_method "widget="
62
+ def widget
63
+ @widgets.last
64
+ end
65
+
66
+ def widget=(widget)
67
+ restore
68
+ push_widget(widget)
69
+ end
70
+
71
+ # Removes all {Widget widgets} from the stack, restoring the
72
+ # {StatusBar status bar's} original state.
73
+ #
74
+ # @return [void]
75
+ def restore
76
+ while pop_widget; end
77
+ end
78
+
79
+ # @return [String]
80
+ attr_accessor :text
81
+ undef_method "text"
82
+ undef_method "text="
83
+ def text
84
+ @status_bar.session.options.get "status-#@side"
85
+ end
86
+
87
+ def text=(val)
88
+ meth = "status_#@side="
89
+ @status_bar.session.options.set "status-#@side", val
90
+ end
91
+
92
+ # @return [Symbol]
93
+ attr_accessor :background_color
94
+ undef_method "background_color"
95
+ undef_method "background_color="
96
+ def background_color
97
+ @status_bar.session.options.get "status-#@side-bg"
98
+ end
99
+
100
+ def background_color=(color)
101
+ @status_bar.session.options.set "status-#@side-bg", color
102
+ end
103
+
104
+ # @return [Symbol]
105
+ attr_accessor :foreground_color
106
+ undef_method "foreground_color"
107
+ undef_method "foreground_color="
108
+ def foreground_color
109
+ @status_bar.session.options.get "status-#@side-fg"
110
+ end
111
+
112
+ def foreground_color=(color)
113
+ @status_bar.session.options.set "status-#@side-fg", color
114
+ end
115
+
116
+ # @return [Number]
117
+ attr_accessor :max_length
118
+ undef_method "max_length"
119
+ undef_method "max_length="
120
+ def max_length
121
+ @status_bar.session.options.get "status-#@side-length"
122
+ end
123
+
124
+ def max_length=(num)
125
+ @status_bar.session.options.set "status-#@side-length", num
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,4 @@
1
+ module Tmux
2
+ # The version of this library
3
+ VERSION = "0.0.2".freeze
4
+ end
@@ -0,0 +1,35 @@
1
+ module Tmux
2
+ # @abstract Subclass this class, provide a meaningful #display
3
+ # method and make sure it is being called.
4
+ class Widget
5
+ # @return [Field]
6
+ attr_accessor :field
7
+ undef_method "field="
8
+
9
+ def field=(new_field)
10
+ @field = new_field
11
+ if new_field
12
+ @max_length = new_field.max_length # Cache this to avoid constantly pulling the option
13
+ else
14
+ @max_length = 0
15
+ end
16
+ end
17
+
18
+ def initialize
19
+ @max_length = 0
20
+ @field = nil
21
+ end
22
+
23
+ # Displays the widget if `@field` is not `nil`.
24
+ #
25
+ # @api abstract
26
+ # @return [void]
27
+ def display
28
+ end
29
+
30
+ # @return [Boolean] True if `@field` is not `nil` and `@max_length` is > 0
31
+ def can_display?
32
+ true if @field && @max_length > 0
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,107 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Tmux
3
+ module Widgets
4
+ # # Description
5
+ #
6
+ # Tmux::Widgets::ProgressBar offers an easy way of displaying progress
7
+ # bars in the {Tmux::StatusBar status bar}.
8
+ #
9
+ # Thanks to the widget and stack system of tmux-ruby, a progress
10
+ # bar can be temporarily displayed without destroying previous
11
+ # contents of the {Tmux::StatusBar status bar}, offering an
12
+ # unobtrusive way of displaying the progress of a long running
13
+ # system. As soon as the progress bar is not needed anymore, it
14
+ # can be removed from the stack, revealing any previous content of
15
+ # the {Tmux::StatusBar status bar}.
16
+ #
17
+ #
18
+ # # Features
19
+ #
20
+ # - a freely definable maximum value
21
+ # - automatic conversion of absolute values to their respective
22
+ # percentage
23
+ # - automatic scaling of the progress bar, adapting to the available width in the status bar
24
+ # - labels
25
+ #
26
+ #
27
+ # # Example
28
+ # require "tmux"
29
+ # require "tmux/widgets/progress_bar" # widgets won't be required by default
30
+ #
31
+ # server = Tmux::Server.new
32
+ # session = server.session # returns the first available session. Actual applications can determine the appropriate session.
33
+ #
34
+ # pbar = Tmux::Widgets::ProgressBar.new("Download") # initialize a new progress bar with the label "Download"
35
+ # session.status_bar.right.add_widget(pbar) # add the progress bar to the right part of the status bar and display it
36
+ #
37
+ # num_files = 24 # in a real application, we would dynamically determine the amount of files/mails/… to download
38
+ # pbar.total = num_files
39
+ #
40
+ # num_files.times do
41
+ # # in a real application, we would be downloading something here
42
+ # pbar.value += 1
43
+ # sleep 0.1
44
+ # end
45
+ #
46
+ # sleep 1 # give the user a chance to see that the process has finished
47
+ #
48
+ # # Remove the progress bar again, restoring any old content of the status bar.
49
+ # # Note: by passing the progress bar to #pop_widget, we avoid breaking the stack
50
+ # # if another application decided to display its own widget on top of ours.
51
+ # session.status_bar.right.pop_widget(pbar)
52
+ #
53
+ #
54
+ # # Screenshot
55
+ # ![Screenshot of ProgressBar](http://doc.fork-bomb.org/tmux/screenshots/progress_bar.png)
56
+
57
+ class ProgressBar < Widget
58
+ # @overload value
59
+ # @return [Number]
60
+ # @overload value=(new_value)
61
+ # Sets an absolute value. It will be automatically
62
+ # converted to a percentage when rendered.
63
+ #
64
+ # @return [Number]
65
+ # @return [Number]
66
+ attr_accessor :value
67
+ undef_method "value="
68
+
69
+ def value=(new_value)
70
+ @value = new_value
71
+ display
72
+ end
73
+
74
+ # @return [String]
75
+ attr_accessor :label
76
+ # @return [Number]
77
+ attr_accessor :total
78
+
79
+ # @param [String] label Label for the progress bar
80
+ # @param [Number] total The maximal value of the progress bar
81
+ # @param field (see Widget#initialize)
82
+ def initialize(label = "Progress", total = 100)
83
+ super()
84
+ @label = label
85
+ @total = total
86
+ @value = 0
87
+ end
88
+
89
+ # Display the progress bar. {#value=} automatically calls this
90
+ # method to update the widget.
91
+ #
92
+ # @return [void]
93
+ def display
94
+ return unless can_display?
95
+ s = "#{@label}: "
96
+ remaining_chars = @max_length - s.size - 3 # 3 = "|" + "|" + ">"
97
+ return if remaining_chars <= 0
98
+
99
+ bar = "=" * (((@value / @total.to_f) * remaining_chars).ceil - 1) + ">"
100
+ bar << " " * (remaining_chars - bar.size) unless (remaining_chars - bar.size) < 0
101
+ s << "|#{bar}|"
102
+
103
+ @field.text = s
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,697 @@
1
+ # -*- coding: utf-8 -*-
2
+ require "tmux/window/status"
3
+
4
+ module Tmux
5
+ # A {Window window} occupies the entire
6
+ # screen and may be split into rectangular {Pane panes}, each of
7
+ # which is a separate pseudo terminal (the pty(4) manual page
8
+ # documents the technical details of pseudo terminals).
9
+ #
10
+ # @todo Figure out better names for some attributes, e.g. mode_mouse
11
+ class Window
12
+ include Comparable
13
+
14
+ class << self
15
+ # @return [OptionsList]
16
+ attr_reader :options
17
+ undef_method "options"
18
+ def options(server)
19
+ OptionsList.new(:window, server, true)
20
+ end
21
+ end
22
+
23
+ # @overload number
24
+ # @return [Number]
25
+ # @overload number=(new_number)
26
+ # @return [Number]
27
+ # @raise [Exception::IndexInUse]
28
+ # @see #move
29
+ # @return [Number]
30
+ attr_accessor :number
31
+ undef_method "number="
32
+
33
+ # @overload session
34
+ # @return [Session]
35
+ # @overload session=(new_session)
36
+ # Moves the window to another {Session session}. First it tries
37
+ # to reuse the current number of the window. If that number is
38
+ # already used in the new {Session session}, the first free
39
+ # number will be used instead.
40
+ #
41
+ # @return [Session]
42
+ # @raise [Exception::IndexInUse]
43
+ # @see #move
44
+ # @todo use base-index
45
+ # @return [Session]
46
+ attr_accessor :session
47
+ undef_method "session="
48
+ # @return [OptionsList]
49
+ attr_reader :options
50
+ # @return [Status]
51
+ attr_reader :status
52
+ def initialize(session, number)
53
+ @session, @number = session, number
54
+ @options = OptionsList.new(:window, self, false)
55
+ @status = Status.new(self)
56
+ end
57
+
58
+ def session=(new_session)
59
+ i = -1
60
+ first_try = true
61
+ begin
62
+ num = (first_try ? @number : (i += 1))
63
+ move(new_session, num)
64
+ rescue IndexInUse
65
+ first_try = false
66
+ retry
67
+ end
68
+ end
69
+
70
+ def number=(new_number)
71
+ move(@session, new_number)
72
+ end
73
+
74
+ # Moves the window to either a different session, a different
75
+ # position or both.
76
+ #
77
+ # @param [Session] new_session
78
+ # @param [Number] new_number
79
+ #
80
+ # @return [void]
81
+ # @raise [Exception::IndexInUse]
82
+ # @see #number=
83
+ # @see #session=
84
+ #
85
+ # @tmux move-window
86
+ def move(new_session, new_number)
87
+ return if @session == new_session && @number == new_number
88
+ target = "%s:%s" % [new_session.identifier, new_number]
89
+
90
+ res = server.invoke_command("move-window -s #{identifier} -t #{target}")
91
+ if res =~ /^can't move window: index in use: \d+/
92
+ raise IndexInUse, [new_session, new_number]
93
+ end
94
+ @session = new_session
95
+ @number = new_number
96
+ end
97
+
98
+ def <=>(other)
99
+ return nil unless other.is_a?(Window)
100
+ [@session, @number] <=> [other.session, other.number]
101
+ end
102
+
103
+ # @return [Boolean]
104
+ def ==(other)
105
+ self.class == other.class && @session == other.session && @number == other.number
106
+ end
107
+
108
+ # @return [Number]
109
+ def hash
110
+ [@session.hash, @number].hash
111
+ end
112
+
113
+ # @return [Boolean]
114
+ def eql?(other)
115
+ self == other
116
+ end
117
+
118
+ # @return [Server]
119
+ attr_reader :server
120
+ undef_method "server"
121
+ def server
122
+ @session.server
123
+ end
124
+
125
+ # @return [String]
126
+ # @tmuxver &gt;=1.1
127
+ # @tmux rename-window
128
+ attr_accessor :name
129
+ undef_method "name"
130
+ undef_method "name="
131
+ def name
132
+ server.check_for_version!("1.1")
133
+
134
+ @session.windows_information[@number][:name]
135
+ end
136
+
137
+ def name=(value)
138
+ # TODO escape name?
139
+ server.invoke_command "rename-window -t #{identifier} '#{value}'"
140
+ end
141
+
142
+ # @return [Integer]
143
+ # @tmuxver &gt;=1.1
144
+ attr_reader :width
145
+ undef_method "width"
146
+ def width
147
+ server.check_for_version!("1.1")
148
+
149
+ @session.windows_information[@number][:width]
150
+ end
151
+
152
+ # @return [Integer]
153
+ # @tmuxver &gt;=1.1
154
+ attr_reader :height
155
+ undef_method "height"
156
+ def height
157
+ server.check_for_version!("1.1")
158
+
159
+ @session.windows_information[@number][:height]
160
+ end
161
+
162
+ # @return [String]
163
+ attr_reader :identifier
164
+ undef_method "identifier"
165
+ def identifier
166
+ "%s:%s" % [@session.identifier, @number]
167
+ end
168
+
169
+ # Aggressively resize the window. This means that tmux will resize
170
+ # the window to the size of the smallest {Session session} for
171
+ # which it is the current window, rather than the smallest
172
+ # {Session session} to which it is attached. The window may resize
173
+ # when the current window is changed on another {Session session};
174
+ # this option is good for full-screen programs which support
175
+ # SIGWINCH and poor for interactive programs such as shells.
176
+ #
177
+ # @return [Boolean]
178
+ attr_accessor :aggressive_resize
179
+ undef_method "aggressive_resize"
180
+ undef_method "aggressive_resize="
181
+ def aggressive_resize
182
+ @options.aggressive_resize
183
+ end
184
+ alias_method :aggressive_resize?, :aggressive_resize
185
+
186
+ def aggressive_resize=(bool)
187
+ @options.aggressive_resize = bool
188
+ end
189
+
190
+ # Control automatic window renaming. When this setting is enabled,
191
+ # tmux will attempt – on supported platforms – to rename the
192
+ # window to reflect the command currently running in it. This flag
193
+ # is automatically disabled for an individual window when a name
194
+ # is specified at creation with {Session#create_window} or
195
+ # {Server#create_session}, or later with {#name=}.
196
+ #
197
+ # @return [Boolean]
198
+ attr_accessor :automatic_rename
199
+ undef_method "automatic_rename"
200
+ undef_method "automatic_rename="
201
+ def automatic_rename
202
+ @options.automatic_rename
203
+ end
204
+ alias_method :automatic_rename?, :automatic_rename
205
+
206
+ def automatic_rename=(bool)
207
+ @options.automatic_rename = bool
208
+ end
209
+
210
+ # Duplicate input to any {Pane pane} to all other {Pane panes} in
211
+ # the same window (only for {Pane panes} that are not in any
212
+ # special mode)
213
+ #
214
+ # @return [Boolean]
215
+ attr_accessor :synchronize_panes
216
+ undef_method "synchronize_panes"
217
+ undef_method "synchronize_panes="
218
+ def synchronize_panes
219
+ @options.synchronize_panes
220
+ end
221
+ alias_method :synchronize_panes?, :synchronize_panes
222
+
223
+ def synchronize_panes=(bool)
224
+ @options.synchronize_panes = bool
225
+ end
226
+
227
+ # A window with this flag set is not destroyed when the program
228
+ # running in it exits. The window may be reactivated with
229
+ # {#respawn}.
230
+ #
231
+ # @return [Boolean]
232
+ attr_accessor :remain_on_exit
233
+ undef_method "remain_on_exit"
234
+ undef_method "remain_on_exit="
235
+ def remain_on_exit
236
+ @options.remain_on_exit
237
+ end
238
+ alias_method :remain_on_exit?, :remain_on_exit
239
+
240
+ def remain_on_exit=(bool)
241
+ @options.remain_on_exit = bool
242
+ end
243
+
244
+ # Instructs tmux to expect UTF-8 sequences to appear in this
245
+ # window.
246
+ #
247
+ # @return [Boolean]
248
+ attr_accessor :utf8
249
+ undef_method "utf8"
250
+ undef_method "utf8="
251
+ def utf8
252
+ @options.utf8
253
+ end
254
+ alias_method :utf8?, :utf8
255
+
256
+ def utf8=(bool)
257
+ @options.utf8 = bool
258
+ end
259
+
260
+ # Monitor for activity in the window. Windows with activity are
261
+ # highlighted in the {StatusBar status line}.
262
+ #
263
+ # @return [Boolean]
264
+ attr_accessor :monitor_activity
265
+ undef_method "monitor_activity"
266
+ undef_method "monitor_activity="
267
+ def monitor_activity
268
+ @options.monitor_activity
269
+ end
270
+ alias_method :monitor_activity?, :monitor_activity
271
+
272
+ def monitor_activity=(bool)
273
+ @options.monitor_activity = bool
274
+ end
275
+
276
+ # Monitor content in the window. When the
277
+ # {http://linux.die.net/man/3/fnmatch fnmatch(3)} pattern appears
278
+ # in the window, it is highlighted in the {StatusBar status line}.
279
+ #
280
+ # @return [String]
281
+ attr_accessor :monitor_content
282
+ undef_method "monitor_content"
283
+ undef_method "monitor_content="
284
+ def monitor_content
285
+ @options.monitor_content
286
+ end
287
+
288
+ def monitor_content=(pattern)
289
+ @options.monitor_content = pattern
290
+ end
291
+
292
+ # Prevent tmux from resizing the window to greater than
293
+ # `max_width`. A value of zero restores the default unlimited
294
+ # setting.
295
+ #
296
+ # @return [Number]
297
+ attr_accessor :max_width
298
+ undef_method "max_width"
299
+ undef_method "max_width="
300
+ def max_width
301
+ @options.force_width
302
+ end
303
+
304
+ def max_width=(value)
305
+ @options.force_width = value
306
+ end
307
+ alias_method :force_width, :max_width
308
+ alias_method :force_width=, "max_width="
309
+
310
+ # Prevent tmux from resizing the window to greater than
311
+ # `max_height`. A value of zero restores the default unlimited
312
+ # setting.
313
+ #
314
+ # @return [Number]
315
+ attr_accessor :max_height
316
+ undef_method "max_height"
317
+ undef_method "max_height="
318
+ def max_height
319
+ @options.force_height
320
+ end
321
+
322
+ def max_height=(value)
323
+ @options.force_height = value
324
+ end
325
+ alias_method :force_height, :max_height
326
+ alias_method :force_height=, "max_height="
327
+
328
+ # If this option is set to true, tmux will generate
329
+ # {http://linux.die.net/man/1/xterm xterm(1)}-style function key
330
+ # sequences. These have a number included to indicate modifiers
331
+ # such as Shift, Alt or Ctrl. The default is false.
332
+ #
333
+ # @return [Boolean]
334
+ attr_accessor :xterm_keys
335
+ undef_method "xterm_keys"
336
+ undef_method "xterm_keys="
337
+ def xterm_keys
338
+ @options.xterm_keys
339
+ end
340
+ alias_method :xterm_keys?, :xterm_keys
341
+
342
+ def xterm_keys=(bool)
343
+ @options.xterm_keys = bool
344
+ end
345
+
346
+ # Sets the window's conception of what characters are considered
347
+ # word separators, for the purposes of the next and previous word
348
+ # commands in {Pane#copy_mode copy mode}. The default is `[" ",
349
+ # "-", "_", "@"]`.
350
+ #
351
+ # @return [Array<String>]
352
+ attr_accessor :word_separators
353
+ undef_method "word_separators"
354
+ undef_method "word_separators="
355
+ def word_separators
356
+ @options.word_separators
357
+ end
358
+
359
+ def word_separators=(value)
360
+ @options.word_separators = value
361
+ end
362
+
363
+ # This option configures whether programs running inside tmux may
364
+ # use the terminal alternate screen feature, which allows the
365
+ # smcup and rmcup {http://linux.die.net/man/5/terminfo
366
+ # terminfo(5)} capabilities to be issued to preserve the existing
367
+ # window content on start and restore it on exit.
368
+ #
369
+ # @return [Boolean]
370
+ attr_accessor :alternate_screen
371
+ undef_method "alternate_screen"
372
+ undef_method "alternate_screen="
373
+ def alternate_screen
374
+ @options.alternate_screen
375
+ end
376
+ alias_method :alternate_screen?, :alternate_screen
377
+
378
+ def alternate_screen=(bool)
379
+ @options.alternate_screen = bool
380
+ end
381
+
382
+ # Mouse state in modes. If true, the mouse may be used to copy a
383
+ # selection by dragging in {Pane#copy_mode copy mode}, or to
384
+ # select an option in choice mode.
385
+ #
386
+ # @return [Boolean]
387
+ attr_accessor :mode_mouse
388
+ undef_method "mode_mouse"
389
+ undef_method "mode_mouse="
390
+ def mode_mouse
391
+ @options.mode_mouse
392
+ end
393
+ alias_method :mode_mouse?, :mode_mouse
394
+
395
+ def mode_mouse=(bool)
396
+ @options.mode_mouse = bool
397
+ end
398
+
399
+ # Clock color.
400
+ #
401
+ # @return [Symbol]
402
+ attr_accessor :clock_mode_color
403
+ undef_method "clock_mode_color"
404
+ undef_method "clock_mode_color="
405
+ def clock_mode_color
406
+ @options.clock_mode_colour
407
+ end
408
+ alias_method :clock_mode_colour, :clock_mode_color
409
+
410
+ def clock_mode_color=(color)
411
+ @options.clock_mode_colour = color
412
+ end
413
+ alias_method :clock_mode_colour=, "clock_mode_color="
414
+
415
+ # Clock hour format.
416
+ #
417
+ # @return [Symbol<:twelve, :twenty_four>]
418
+ attr_accessor :clock_mode_style
419
+ undef_method "clock_mode_style"
420
+ undef_method "clock_mode_style="
421
+
422
+ def clock_mode_style
423
+ @options.clock_mode_style
424
+ end
425
+
426
+ def clock_mode_style=(style)
427
+ @options.clock_mode_style = style
428
+ end
429
+
430
+ # Set the height of the main (left or top) pane in the
431
+ # main-horizontal or main-vertical {#layout= layouts}.
432
+ #
433
+ # @return [Number]
434
+ # @see #layout=
435
+ attr_accessor :main_pane_height
436
+ undef_method "main_pane_height"
437
+ undef_method "main_pane_height="
438
+ def main_pane_height
439
+ @options.main_pane_height
440
+ end
441
+
442
+ def main_pane_height=(height)
443
+ @options.main_pane_height = height
444
+ end
445
+
446
+ # Set the width of the main (left or top) pane in the
447
+ # main-horizontal or main-vertical {#layout= layouts}.
448
+ #
449
+ # @return [Number]
450
+ # @see #layout=
451
+ attr_accessor :main_pane_width
452
+ undef_method "main_pane_width"
453
+ undef_method "main_pane_width="
454
+ def main_pane_width
455
+ @options.main_pane_width
456
+ end
457
+
458
+ def main_pane_width=(width)
459
+ @options.main_pane_width = width
460
+ end
461
+
462
+ # @return [Symbol]
463
+ attr_accessor :mode_attr
464
+ undef_method "mode_attr"
465
+ undef_method "mode_attr="
466
+ def mode_attr
467
+ @options.mode_attr
468
+ end
469
+
470
+ def mode_attr=(attr)
471
+ @options.mode_attr = attr
472
+ end
473
+
474
+ # @return [Symbol]
475
+ attr_accessor :mode_bg
476
+ undef_method "mode_bg"
477
+ undef_method "mode_bg="
478
+ def mode_bg
479
+ @options.mode_bg
480
+ end
481
+
482
+ def mode_bg=(bg)
483
+ @options.mode_bg = bg
484
+ end
485
+
486
+ # @return [Symbol]
487
+ attr_accessor :mode_fg
488
+ undef_method "mode_fg"
489
+ undef_method "mode_fg="
490
+ def mode_fg
491
+ @options.mode_fg
492
+ end
493
+
494
+ def mode_fg=(fg)
495
+ @options.mode_fg = fg
496
+ end
497
+
498
+ # @return [Symbol]
499
+ attr_accessor :mode_keys
500
+ undef_method "mode_keys"
501
+ undef_method "mode_keys="
502
+ def mode_keys
503
+ @options.mode_keys
504
+ end
505
+
506
+ def mode_keys=(keymap)
507
+ @options.mode_keys = keymap
508
+ end
509
+
510
+ # Kills the window.
511
+ # @tmux kill-window
512
+ # @return [void]
513
+ def kill
514
+ server.invoke_command "kill-window -t #{identifier}"
515
+ end
516
+
517
+ # Rotates the positions of the {Pane panes} within a window.
518
+ #
519
+ # @tmux rotate-window
520
+ # @return [void]
521
+ def rotate(direction = :upward)
522
+ flag = case direction
523
+ when :upward
524
+ "U"
525
+ when :downward
526
+ "D"
527
+ else
528
+ raise ArgumentError
529
+ end
530
+ server.invoke_command "rotate-window -#{flag} -t #{identifier}"
531
+ end
532
+
533
+ # @todo attr_reader
534
+ # @param [Symbol<:even_horizontal, :even_vertical, :main_horizontal, :main_vertical] The layout to apply to the window
535
+ # @return [Symbol]
536
+ # @tmux select-layout
537
+ # @tmuxver &gt;=1.3 for :tiled layout
538
+ # @tmuxver &gt;=1.0 for all other layouts
539
+ attr_writer :layout
540
+ undef_method "layout="
541
+ def layout=(layout)
542
+ server.check_for_version!("1.0")
543
+ raise Exception::UnsupportedVersion, "1.3" if layout == :tiled && server.version < "1.3"
544
+
545
+ valid_layouts = [:even_horizontal, :even_vertical, :main_horizontal, :main_vertical, :tiled]
546
+ raise ArgumentError unless valid_layouts.include?(layout)
547
+ layout = layout.to_s.tr("_", "-")
548
+ server.invoke_command "select-layout -t #{identifier} #{layout}"
549
+ end
550
+
551
+ # @param [Hash] search Filters the resulting hash using {FilterableHash#filter}
552
+ # @return [Hash] A hash with information for all panes
553
+ # @tmux list-panes
554
+ # @tmuxver &gt;=1.1
555
+ def panes_information(search={})
556
+ server.check_for_version!("1.1")
557
+
558
+ hash = {}
559
+ output = server.invoke_command "list-panes -t #{identifier}"
560
+ output.each_line do |pane|
561
+ params = pane.match(/^(?<num>\d+): \[(?<width>\d+)x(?<height>\d+)\] \[history (?<cur_history>\d+)\/(?<max_history>\d+), (?<memory>\d+) bytes\](?<active> \(active\))?$/)
562
+ num = params[:num].to_i
563
+ width = params[:width].to_i
564
+ height = params[:height].to_i
565
+ cur_history = params[:cur_history].to_i
566
+ max_history = params[:max_history].to_i
567
+ memory = Filesize.new(params[:memory].to_i)
568
+
569
+ # this flag requires tmux >=1.4
570
+ active = !params[:active].nil?
571
+
572
+ hash[num] = {
573
+ :num => num,
574
+ :width => width,
575
+ :height => height,
576
+ :cur_history => cur_history,
577
+ :max_history => max_history,
578
+ :memory => memory,
579
+ :active => active,
580
+ }
581
+ end
582
+ hash.extend FilterableHash
583
+ hash.filter(search)
584
+ end
585
+
586
+ # @return [Array<Pane>] All {Pane panes}
587
+ # @tmuxver &gt;=1.1
588
+ attr_reader :panes
589
+ undef_method "panes"
590
+ def panes
591
+ server.check_for_version!("1.1")
592
+
593
+ panes_information.map do |num, information|
594
+ Pane.new(self, num)
595
+ end
596
+ end
597
+
598
+ # Pastes a {Buffer buffer} into the window.
599
+ #
600
+ # @param [Buffer] buffer The {Buffer buffer} to paste
601
+ # @param pop (see Buffer#paste)
602
+ # @param translate (see Buffer#paste)
603
+ # @param separator (see Buffer#paste)
604
+ # @return [void]
605
+ # @tmux paste-buffer
606
+ # @see Buffer#paste
607
+ # @see Pane#paste
608
+ def paste(buffer, pop = false, translate = true, separator = nil)
609
+ buffer.paste(self, pop, translate, separator)
610
+ end
611
+
612
+ # Select the window.
613
+ #
614
+ # @return [void]
615
+ # @tmux select-window
616
+ def select
617
+ server.invoke_command "select-window -t #{identifier}"
618
+ end
619
+
620
+ # Swap the window with another one.
621
+ #
622
+ # @param [Window] window The window to swap with
623
+ # @return [void]
624
+ # @tmux swap-window
625
+ def swap_with(window)
626
+ server.invoke_command "swap-window -s #{identifier} -t #{window.identifier}"
627
+ end
628
+
629
+ # @param [Symbol<:never, :if_same_window, :always>] return_if When
630
+ # to return the current pane.
631
+ #
632
+ # Note: In tmux versions prior to 1.4, :always can lead to flickering
633
+ # Note: Since tmux version 1.4, :always is forced
634
+ # @return [Pane, nil] The current pane
635
+ attr_reader :current_pane
636
+ undef_method "current_pane"
637
+ def current_pane(return_if = :always)
638
+ if server.version >= "1.4"
639
+ self.panes.find(&:active?)
640
+ else
641
+ # In tmux <1.4, we can only determine the selected pane of the
642
+ # current window.
643
+ #
644
+ # If the user specified return_if = :always, we select this
645
+ # window (if it is not already selected), determine the
646
+ # current pane and select the lastly selected window again.
647
+ cur_window = self.session.any_client.current_window
648
+ same_window = cur_window == self
649
+ return_if_b = ((return_if == :if_same_window && same_window) || (return_if == :always))
650
+
651
+ self.select if return_if_b && !same_window
652
+
653
+ new_pane = nil
654
+ if return_if_b
655
+ num = server.invoke_command("display -p -t #{self.session.any_client.identifier} '#P'").chomp
656
+ new_pane = Pane.new(self, num)
657
+ end
658
+
659
+ if return_if == :always && !same_window
660
+ self.session.select_previous_window
661
+ end
662
+
663
+ return new_pane if new_pane
664
+ end
665
+ end
666
+
667
+ # Select the previously selected pane.
668
+ #
669
+ # @param return_if (see Window#current_pane)
670
+ # @return (see Window#current_pane)
671
+ # @tmux last-pane
672
+ # @tmuxver &gt;=1.4
673
+ def select_last_pane(return_if = :always)
674
+ server.invoke_command("last-pane -t #{identifier}")
675
+ current_pane(return_if)
676
+ end
677
+
678
+ # Reactivates a window in which the command has exited.
679
+ #
680
+ # @param [String, nil] command The command to use to respawn the
681
+ # window. If nil, the command used when the window was created is
682
+ # executed.
683
+ # @param [Boolean] kill Unless `kill` is true, only inactive windows can be respawned
684
+ # @return [void]
685
+ # @tmux respawn-window
686
+ # @see #remain_on_exit
687
+ # @todo escape command
688
+ def respawn(command = nil, kill = false)
689
+ flags = []
690
+ flags << "-k" if kill
691
+ flags << "-t #{identifier}"
692
+ flags << "\"#{command}\"" if command
693
+
694
+ server.invoke_command "respawn-window #{flags.join(" ")}"
695
+ end
696
+ end
697
+ end