sup 0.11 → 0.12
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sup might be problematic. Click here for more details.
- data/CONTRIBUTORS +16 -5
- data/History.txt +9 -0
- data/ReleaseNotes +9 -0
- data/bin/sup +9 -24
- data/bin/sup-add +3 -3
- data/bin/sup-config +1 -1
- data/bin/sup-dump +22 -9
- data/bin/sup-recover-sources +1 -11
- data/bin/sup-sync +65 -130
- data/bin/sup-sync-back +6 -5
- data/bin/sup-tweak-labels +5 -6
- data/lib/sup.rb +89 -71
- data/lib/sup/account.rb +3 -2
- data/lib/sup/buffer.rb +28 -16
- data/lib/sup/client.rb +92 -0
- data/lib/sup/crypto.rb +91 -49
- data/lib/sup/draft.rb +14 -17
- data/lib/sup/hook.rb +10 -5
- data/lib/sup/index.rb +72 -28
- data/lib/sup/logger.rb +1 -1
- data/lib/sup/maildir.rb +55 -112
- data/lib/sup/mbox.rb +151 -6
- data/lib/sup/message-chunks.rb +20 -4
- data/lib/sup/message.rb +183 -76
- data/lib/sup/modes/compose-mode.rb +2 -1
- data/lib/sup/modes/console-mode.rb +4 -1
- data/lib/sup/modes/edit-message-mode.rb +50 -5
- data/lib/sup/modes/line-cursor-mode.rb +1 -0
- data/lib/sup/modes/reply-mode.rb +17 -11
- data/lib/sup/modes/thread-index-mode.rb +10 -9
- data/lib/sup/modes/thread-view-mode.rb +48 -2
- data/lib/sup/poll.rb +56 -60
- data/lib/sup/protocol.rb +161 -0
- data/lib/sup/sent.rb +8 -11
- data/lib/sup/server.rb +116 -0
- data/lib/sup/source.rb +15 -33
- data/lib/sup/thread.rb +6 -0
- data/lib/sup/util.rb +44 -39
- metadata +126 -88
- data/lib/sup/connection.rb +0 -63
- data/lib/sup/imap.rb +0 -349
- data/lib/sup/mbox/loader.rb +0 -180
- data/lib/sup/mbox/ssh-file.rb +0 -254
- data/lib/sup/mbox/ssh-loader.rb +0 -74
data/bin/sup-sync-back
CHANGED
@@ -4,8 +4,9 @@ require 'rubygems'
|
|
4
4
|
require 'uri'
|
5
5
|
require 'tempfile'
|
6
6
|
require 'trollop'
|
7
|
-
require
|
8
|
-
|
7
|
+
require "sup"; Redwood::check_library_version_against "0.12"
|
8
|
+
|
9
|
+
fail "not working yet"
|
9
10
|
|
10
11
|
## save a message 'm' to an open file pointer 'fp'
|
11
12
|
def save m, fp
|
@@ -17,7 +18,7 @@ def die msg
|
|
17
18
|
end
|
18
19
|
def has_any_from_source_with_label? index, source, label
|
19
20
|
query = { :source_id => source.id, :label => label, :limit => 1, :load_spam => true, :load_deleted => true, :load_killed => true }
|
20
|
-
|
21
|
+
index.num_results_for(query) != 0
|
21
22
|
end
|
22
23
|
|
23
24
|
opts = Trollop::options do
|
@@ -81,12 +82,12 @@ begin
|
|
81
82
|
|
82
83
|
sources = ARGV.map do |uri|
|
83
84
|
s = Redwood::SourceManager.source_for(uri) or die "unknown source: #{uri}. Did you add it with sup-add first?"
|
84
|
-
s.is_a?(Redwood::MBox
|
85
|
+
s.is_a?(Redwood::MBox) or die "#{uri} is not an mbox source."
|
85
86
|
s
|
86
87
|
end
|
87
88
|
|
88
89
|
if sources.empty?
|
89
|
-
sources = Redwood::SourceManager.usual_sources.select { |s| s.is_a? Redwood::MBox
|
90
|
+
sources = Redwood::SourceManager.usual_sources.select { |s| s.is_a? Redwood::MBox }
|
90
91
|
end
|
91
92
|
|
92
93
|
unless sources.all? { |s| s.file_path.nil? } || File.executable?(dotlockfile) || opts[:dont_use_dotlockfile]
|
data/bin/sup-tweak-labels
CHANGED
@@ -2,8 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'trollop'
|
5
|
-
require
|
6
|
-
require "sup"; Redwood::check_library_version_against "0.11"
|
5
|
+
require "sup"; Redwood::check_library_version_against "0.12"
|
7
6
|
|
8
7
|
class Float
|
9
8
|
def to_s; sprintf '%.2f', self; end
|
@@ -74,18 +73,18 @@ begin
|
|
74
73
|
end.map { |s| s.id }
|
75
74
|
Trollop::die "nothing to do: no sources" if source_ids.empty?
|
76
75
|
|
77
|
-
query = "
|
76
|
+
query = "(" + source_ids.map { |id| "source_id:#{id}" }.join(" OR ") + ")"
|
78
77
|
if add_labels.empty?
|
79
78
|
## if all we're doing is removing labels, we can further restrict the
|
80
79
|
## query to only messages with those labels
|
81
|
-
query += "
|
80
|
+
query += " (" + remove_labels.map { |l| "label:#{l}" }.join(" OR ") + ")"
|
82
81
|
end
|
83
82
|
query += ' ' + opts[:query] if opts[:query]
|
84
83
|
|
85
84
|
parsed_query = index.parse_query query
|
86
85
|
parsed_query.merge! :load_spam => true, :load_deleted => true, :load_killed => true
|
87
|
-
ids =
|
88
|
-
num_total =
|
86
|
+
ids = Enumerator.new(index, :each_id, parsed_query)
|
87
|
+
num_total = index.num_results_for parsed_query
|
89
88
|
|
90
89
|
$stderr.puts "Found #{num_total} documents across #{source_ids.length} sources. Scanning..."
|
91
90
|
|
data/lib/sup.rb
CHANGED
@@ -5,6 +5,7 @@ require 'thread'
|
|
5
5
|
require 'fileutils'
|
6
6
|
require 'gettext'
|
7
7
|
require 'curses'
|
8
|
+
require 'rmail'
|
8
9
|
begin
|
9
10
|
require 'fastthread'
|
10
11
|
rescue LoadError
|
@@ -37,7 +38,7 @@ class Module
|
|
37
38
|
end
|
38
39
|
|
39
40
|
module Redwood
|
40
|
-
VERSION = "0.
|
41
|
+
VERSION = "0.12"
|
41
42
|
|
42
43
|
BASE_DIR = ENV["SUP_BASE"] || File.join(ENV["HOME"], ".sup")
|
43
44
|
CONFIG_FN = File.join(BASE_DIR, "config.yaml")
|
@@ -51,6 +52,7 @@ module Redwood
|
|
51
52
|
SUICIDE_FN = File.join(BASE_DIR, "please-kill-yourself")
|
52
53
|
HOOK_DIR = File.join(BASE_DIR, "hooks")
|
53
54
|
SEARCH_FN = File.join(BASE_DIR, "searches.txt")
|
55
|
+
LOG_FN = File.join(BASE_DIR, "log")
|
54
56
|
|
55
57
|
YAML_DOMAIN = "masanjin.net"
|
56
58
|
YAML_DATE = "2006-10-01"
|
@@ -119,26 +121,41 @@ module Redwood
|
|
119
121
|
o
|
120
122
|
end
|
121
123
|
|
124
|
+
def managers
|
125
|
+
%w(HookManager SentManager ContactManager LabelManager AccountManager
|
126
|
+
DraftManager UpdateManager PollManager CryptoManager UndoManager
|
127
|
+
SourceManager SearchManager IdleManager).map { |x| Redwood.const_get x.to_sym }
|
128
|
+
end
|
129
|
+
|
122
130
|
def start
|
131
|
+
managers.each { |x| fail "#{x} already instantiated" if x.instantiated? }
|
132
|
+
|
133
|
+
FileUtils.mkdir_p Redwood::BASE_DIR
|
134
|
+
$config = load_config Redwood::CONFIG_FN
|
135
|
+
@log_io = File.open(Redwood::LOG_FN, 'a')
|
136
|
+
Redwood::Logger.add_sink @log_io
|
137
|
+
Redwood::HookManager.init Redwood::HOOK_DIR
|
123
138
|
Redwood::SentManager.init $config[:sent_source] || 'sup://sent'
|
124
139
|
Redwood::ContactManager.init Redwood::CONTACT_FN
|
125
140
|
Redwood::LabelManager.init Redwood::LABEL_FN
|
126
141
|
Redwood::AccountManager.init $config[:accounts]
|
127
142
|
Redwood::DraftManager.init Redwood::DRAFT_DIR
|
128
|
-
Redwood::UpdateManager.init
|
129
|
-
Redwood::PollManager.init
|
130
|
-
Redwood::CryptoManager.init
|
131
|
-
Redwood::UndoManager.init
|
132
|
-
Redwood::SourceManager.init
|
133
143
|
Redwood::SearchManager.init Redwood::SEARCH_FN
|
134
|
-
|
144
|
+
|
145
|
+
managers.each { |x| x.init unless x.instantiated? }
|
135
146
|
end
|
136
147
|
|
137
148
|
def finish
|
138
149
|
Redwood::LabelManager.save if Redwood::LabelManager.instantiated?
|
139
150
|
Redwood::ContactManager.save if Redwood::ContactManager.instantiated?
|
140
|
-
Redwood::BufferManager.deinstantiate! if Redwood::BufferManager.instantiated?
|
141
151
|
Redwood::SearchManager.save if Redwood::SearchManager.instantiated?
|
152
|
+
Redwood::Logger.remove_sink @log_io
|
153
|
+
|
154
|
+
managers.each { |x| x.deinstantiate! if x.instantiated? }
|
155
|
+
|
156
|
+
@log_io.close
|
157
|
+
@log_io = nil
|
158
|
+
$config = nil
|
142
159
|
end
|
143
160
|
|
144
161
|
## not really a good place for this, so I'll just dump it here.
|
@@ -220,81 +237,84 @@ EOS
|
|
220
237
|
end
|
221
238
|
end
|
222
239
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
Socket.gethostname
|
241
|
-
end
|
240
|
+
## set up default configuration file
|
241
|
+
def load_config filename
|
242
|
+
if File.exists? filename
|
243
|
+
config = Redwood::load_yaml_obj filename
|
244
|
+
abort "#{filename} is not a valid configuration file (it's a #{config.class}, not a hash)" unless config.is_a?(Hash)
|
245
|
+
config
|
246
|
+
else
|
247
|
+
require 'etc'
|
248
|
+
require 'socket'
|
249
|
+
name = Etc.getpwnam(ENV["USER"]).gecos.split(/,/).first rescue nil
|
250
|
+
name ||= ENV["USER"]
|
251
|
+
email = ENV["USER"] + "@" +
|
252
|
+
begin
|
253
|
+
Socket.gethostbyname(Socket.gethostname).first
|
254
|
+
rescue SocketError
|
255
|
+
Socket.gethostname
|
256
|
+
end
|
242
257
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
258
|
+
config = {
|
259
|
+
:accounts => {
|
260
|
+
:default => {
|
261
|
+
:name => name,
|
262
|
+
:email => email,
|
263
|
+
:alternates => [],
|
264
|
+
:sendmail => "/usr/sbin/sendmail -oem -ti",
|
265
|
+
:signature => File.join(ENV["HOME"], ".signature"),
|
266
|
+
:gpgkey => ""
|
267
|
+
}
|
268
|
+
},
|
269
|
+
:editor => ENV["EDITOR"] || "/usr/bin/vim -f -c 'setlocal spell spelllang=en_us' -c 'set filetype=mail'",
|
270
|
+
:thread_by_subject => false,
|
271
|
+
:edit_signature => false,
|
272
|
+
:ask_for_from => false,
|
273
|
+
:ask_for_to => true,
|
274
|
+
:ask_for_cc => true,
|
275
|
+
:ask_for_bcc => false,
|
276
|
+
:ask_for_subject => true,
|
277
|
+
:confirm_no_attachments => true,
|
278
|
+
:confirm_top_posting => true,
|
279
|
+
:jump_to_open_message => true,
|
280
|
+
:discard_snippets_from_encrypted_messages => false,
|
281
|
+
:default_attachment_save_dir => "",
|
282
|
+
:sent_source => "sup://sent",
|
283
|
+
:poll_interval => 300,
|
284
|
+
:wrap_width => 0,
|
285
|
+
:slip_rows => 0
|
251
286
|
}
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
:ask_for_subject => true,
|
260
|
-
:confirm_no_attachments => true,
|
261
|
-
:confirm_top_posting => true,
|
262
|
-
:jump_to_open_message => true,
|
263
|
-
:discard_snippets_from_encrypted_messages => false,
|
264
|
-
:default_attachment_save_dir => "",
|
265
|
-
:sent_source => "sup://sent",
|
266
|
-
:poll_interval => 300,
|
267
|
-
:wrap_width => 0
|
268
|
-
}
|
269
|
-
begin
|
270
|
-
FileUtils.mkdir_p Redwood::BASE_DIR
|
271
|
-
Redwood::save_yaml_obj $config, Redwood::CONFIG_FN
|
272
|
-
rescue StandardError => e
|
273
|
-
$stderr.puts "warning: #{e.message}"
|
287
|
+
begin
|
288
|
+
Redwood::save_yaml_obj config, filename
|
289
|
+
rescue StandardError => e
|
290
|
+
$stderr.puts "warning: #{e.message}"
|
291
|
+
end
|
292
|
+
config
|
293
|
+
end
|
274
294
|
end
|
295
|
+
|
296
|
+
module_function :save_yaml_obj, :load_yaml_obj, :start, :finish,
|
297
|
+
:report_broken_sources, :check_library_version_against,
|
298
|
+
:load_config, :managers
|
275
299
|
end
|
276
300
|
|
277
301
|
require "sup/util"
|
278
302
|
require "sup/hook"
|
279
303
|
|
280
|
-
## we have to initialize this guy first, because other classes must
|
281
|
-
## reference it in order to register hooks, and they do that at parse
|
282
|
-
## time.
|
283
|
-
Redwood::HookManager.init Redwood::HOOK_DIR
|
284
|
-
|
285
304
|
## everything we need to get logging working
|
286
305
|
require "sup/logger"
|
287
306
|
Redwood::Logger.init.add_sink $stderr
|
288
307
|
include Redwood::LogsStuff
|
289
308
|
|
290
309
|
## determine encoding and character set
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
310
|
+
$encoding = Locale.current.charset
|
311
|
+
$encoding = "UTF-8" if $encoding == "utf8"
|
312
|
+
if $encoding
|
313
|
+
debug "using character set encoding #{$encoding.inspect}"
|
314
|
+
else
|
315
|
+
warn "can't find character set by using locale, defaulting to utf-8"
|
316
|
+
$encoding = "UTF-8"
|
317
|
+
end
|
298
318
|
|
299
319
|
require "sup/buffer"
|
300
320
|
require "sup/keymap"
|
@@ -308,7 +328,6 @@ require "sup/message"
|
|
308
328
|
require "sup/source"
|
309
329
|
require "sup/mbox"
|
310
330
|
require "sup/maildir"
|
311
|
-
require "sup/imap"
|
312
331
|
require "sup/person"
|
313
332
|
require "sup/account"
|
314
333
|
require "sup/thread"
|
@@ -348,7 +367,6 @@ require "sup/sent"
|
|
348
367
|
require "sup/search"
|
349
368
|
require "sup/modes/search-list-mode"
|
350
369
|
require "sup/idle"
|
351
|
-
require "sup/connection"
|
352
370
|
|
353
371
|
$:.each do |base|
|
354
372
|
d = File.join base, "sup/share/modes/"
|
data/lib/sup/account.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Redwood
|
2
2
|
|
3
3
|
class Account < Person
|
4
|
-
attr_accessor :sendmail, :signature
|
4
|
+
attr_accessor :sendmail, :signature, :gpgkey
|
5
5
|
|
6
6
|
def initialize h
|
7
7
|
raise ArgumentError, "no name for account" unless h[:name]
|
@@ -9,6 +9,7 @@ class Account < Person
|
|
9
9
|
super h[:name], h[:email]
|
10
10
|
@sendmail = h[:sendmail]
|
11
11
|
@signature = h[:signature]
|
12
|
+
@gpgkey = h[:gpgkey]
|
12
13
|
end
|
13
14
|
|
14
15
|
# Default sendmail command for bouncing mail,
|
@@ -46,7 +47,7 @@ class AccountManager
|
|
46
47
|
def add_account hash, default=false
|
47
48
|
raise ArgumentError, "no email specified for account" unless hash[:email]
|
48
49
|
unless default
|
49
|
-
[:name, :sendmail, :signature].each { |k| hash[k] ||= @default_account.send(k) }
|
50
|
+
[:name, :sendmail, :signature, :gpgkey].each { |k| hash[k] ||= @default_account.send(k) }
|
50
51
|
end
|
51
52
|
hash[:alternates] ||= []
|
52
53
|
|
data/lib/sup/buffer.rb
CHANGED
@@ -100,7 +100,7 @@ class Buffer
|
|
100
100
|
|
101
101
|
def redraw status
|
102
102
|
if @dirty
|
103
|
-
draw status
|
103
|
+
draw status
|
104
104
|
else
|
105
105
|
draw_status status
|
106
106
|
end
|
@@ -130,15 +130,13 @@ class Buffer
|
|
130
130
|
s ||= ""
|
131
131
|
maxl = @width - x # maximum display width width
|
132
132
|
stringl = maxl # string "length"
|
133
|
+
|
134
|
+
# fill up the line with blanks to overwrite old screen contents
|
135
|
+
@w.mvaddstr y, x, " " * maxl unless opts[:no_fill]
|
136
|
+
|
133
137
|
## the next horribleness is thanks to ruby's lack of widechar support
|
134
138
|
stringl += 1 while stringl < s.length && s[0 ... stringl].display_length < maxl
|
135
139
|
@w.mvaddstr y, x, s[0 ... stringl]
|
136
|
-
unless opts[:no_fill]
|
137
|
-
l = s.display_length
|
138
|
-
unless l >= maxl
|
139
|
-
@w.mvaddstr(y, x + l, " " * (maxl - l))
|
140
|
-
end
|
141
|
-
end
|
142
140
|
end
|
143
141
|
|
144
142
|
def clear
|
@@ -228,7 +226,7 @@ EOS
|
|
228
226
|
|
229
227
|
def focus_on buf
|
230
228
|
return unless @buffers.member? buf
|
231
|
-
return if buf == @focus_buf
|
229
|
+
return if buf == @focus_buf
|
232
230
|
@focus_buf.blur if @focus_buf
|
233
231
|
@focus_buf = buf
|
234
232
|
@focus_buf.focus
|
@@ -354,7 +352,7 @@ EOS
|
|
354
352
|
## creates a new buffer. returns two things: the buffer, and a boolean
|
355
353
|
## indicating whether it's a new buffer or not.
|
356
354
|
def spawn_unless_exists title, opts={}
|
357
|
-
new =
|
355
|
+
new =
|
358
356
|
if @name_map.member? title
|
359
357
|
raise_to_front @name_map[title] unless opts[:hidden]
|
360
358
|
false
|
@@ -455,13 +453,14 @@ EOS
|
|
455
453
|
|
456
454
|
def ask_with_completions domain, question, completions, default=nil
|
457
455
|
ask domain, question, default do |s|
|
458
|
-
|
456
|
+
s.force_encoding 'UTF-8' if s.methods.include?(:encoding)
|
457
|
+
completions.select { |x| x =~ /^#{Regexp::escape s}/iu }.map { |x| [x, x] }
|
459
458
|
end
|
460
459
|
end
|
461
460
|
|
462
461
|
def ask_many_with_completions domain, question, completions, default=nil
|
463
462
|
ask domain, question, default do |partial|
|
464
|
-
prefix, target =
|
463
|
+
prefix, target =
|
465
464
|
case partial
|
466
465
|
when /^\s*$/
|
467
466
|
["", ""]
|
@@ -471,6 +470,8 @@ EOS
|
|
471
470
|
raise "william screwed up completion: #{partial.inspect}"
|
472
471
|
end
|
473
472
|
|
473
|
+
prefix.force_encoding 'UTF-8' if prefix.methods.include?(:encoding)
|
474
|
+
target.force_encoding 'UTF-8' if target.methods.include?(:encoding)
|
474
475
|
completions.select { |x| x =~ /^#{Regexp::escape target}/i }.map { |x| [prefix + x, x] }
|
475
476
|
end
|
476
477
|
end
|
@@ -479,7 +480,11 @@ EOS
|
|
479
480
|
ask domain, question, default do |partial|
|
480
481
|
prefix, target = partial.split_on_commas_with_remainder
|
481
482
|
target ||= prefix.pop || ""
|
483
|
+
target.force_encoding 'UTF-8' if target.methods.include?(:encoding)
|
484
|
+
|
482
485
|
prefix = prefix.join(", ") + (prefix.empty? ? "" : ", ")
|
486
|
+
prefix.force_encoding 'UTF-8' if prefix.methods.include?(:encoding)
|
487
|
+
|
483
488
|
completions.select { |x| x =~ /^#{Regexp::escape target}/i }.sort_by { |c| [ContactManager.contact_for(c) ? 0 : 1, c] }.map { |x| [prefix + x, x] }
|
484
489
|
end
|
485
490
|
end
|
@@ -559,6 +564,13 @@ EOS
|
|
559
564
|
end
|
560
565
|
end
|
561
566
|
|
567
|
+
def ask_for_account domain, question
|
568
|
+
completions = AccountManager.user_emails
|
569
|
+
answer = BufferManager.ask_many_emails_with_completions domain, question, completions, ""
|
570
|
+
answer = AccountManager.default_account.email if answer == ""
|
571
|
+
AccountManager.account_for Person.from_address(answer).email if answer
|
572
|
+
end
|
573
|
+
|
562
574
|
## for simplicitly, we always place the question at the very bottom of the
|
563
575
|
## screen
|
564
576
|
def ask domain, question, default=nil, &block
|
@@ -586,7 +598,7 @@ EOS
|
|
586
598
|
|
587
599
|
if tf.new_completions?
|
588
600
|
kill_buffer completion_buf if completion_buf
|
589
|
-
|
601
|
+
|
590
602
|
shorts = tf.completions.map { |full, short| short }
|
591
603
|
prefix_len = shorts.shared_prefix.length
|
592
604
|
|
@@ -603,7 +615,7 @@ EOS
|
|
603
615
|
|
604
616
|
Ncurses.sync { Ncurses.refresh }
|
605
617
|
end
|
606
|
-
|
618
|
+
|
607
619
|
kill_buffer completion_buf if completion_buf
|
608
620
|
|
609
621
|
@dirty = true
|
@@ -684,12 +696,12 @@ EOS
|
|
684
696
|
|
685
697
|
def minibuf_lines
|
686
698
|
@minibuf_mutex.synchronize do
|
687
|
-
[(@flash ? 1 : 0) +
|
699
|
+
[(@flash ? 1 : 0) +
|
688
700
|
(@asking ? 1 : 0) +
|
689
701
|
@minibuf_stack.compact.size, 1].max
|
690
702
|
end
|
691
703
|
end
|
692
|
-
|
704
|
+
|
693
705
|
def draw_minibuf opts={}
|
694
706
|
m = nil
|
695
707
|
@minibuf_mutex.synchronize do
|
@@ -791,7 +803,7 @@ private
|
|
791
803
|
|
792
804
|
statusbar_text = HookManager.run("status-bar-text", opts) || default_status_bar(buf)
|
793
805
|
term_title_text = HookManager.run("terminal-title-text", opts) || default_terminal_title(buf)
|
794
|
-
|
806
|
+
|
795
807
|
[statusbar_text, term_title_text]
|
796
808
|
end
|
797
809
|
|