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.
- data/.yardopts +1 -0
- data/LICENSE +22 -0
- data/README.md +23 -0
- data/lib/tmux.rb +56 -0
- data/lib/tmux/buffer.rb +131 -0
- data/lib/tmux/client.rb +193 -0
- data/lib/tmux/exception.rb +5 -0
- data/lib/tmux/exception/basic_exception.rb +6 -0
- data/lib/tmux/exception/in_tmux.rb +9 -0
- data/lib/tmux/exception/index_in_use.rb +9 -0
- data/lib/tmux/exception/unknown_command.rb +9 -0
- data/lib/tmux/exception/unsupported_version.rb +15 -0
- data/lib/tmux/filterable_hash.rb +15 -0
- data/lib/tmux/options.rb +109 -0
- data/lib/tmux/options/attr_option.rb +10 -0
- data/lib/tmux/options/bell_action_option.rb +19 -0
- data/lib/tmux/options/boolean_option.rb +26 -0
- data/lib/tmux/options/char_array_option.rb +26 -0
- data/lib/tmux/options/clock_mode_style_option.rb +27 -0
- data/lib/tmux/options/color_option.rb +23 -0
- data/lib/tmux/options/justification_option.rb +19 -0
- data/lib/tmux/options/keymap_option.rb +19 -0
- data/lib/tmux/options/number_option.rb +26 -0
- data/lib/tmux/options/option.rb +38 -0
- data/lib/tmux/options/string_option.rb +26 -0
- data/lib/tmux/options/symbol_option.rb +26 -0
- data/lib/tmux/options/word_array_option.rb +26 -0
- data/lib/tmux/options_list.rb +150 -0
- data/lib/tmux/pane.rb +496 -0
- data/lib/tmux/server.rb +217 -0
- data/lib/tmux/session.rb +312 -0
- data/lib/tmux/status_bar.rb +134 -0
- data/lib/tmux/status_bar/field.rb +129 -0
- data/lib/tmux/version.rb +4 -0
- data/lib/tmux/widget.rb +35 -0
- data/lib/tmux/widgets/progress_bar.rb +107 -0
- data/lib/tmux/window.rb +697 -0
- data/lib/tmux/window/status.rb +21 -0
- data/lib/tmux/window/status/state.rb +87 -0
- 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
|
data/lib/tmux/version.rb
ADDED
data/lib/tmux/widget.rb
ADDED
@@ -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
|
+
# 
|
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
|
data/lib/tmux/window.rb
ADDED
@@ -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 >=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 >=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 >=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 >=1.3 for :tiled layout
|
538
|
+
# @tmuxver >=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 >=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 >=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 >=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
|