textbringer 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.editorconfig +3 -0
- data/.travis.yml +6 -6
- data/CHANGES.md +4 -0
- data/exe/tbclient +34 -0
- data/lib/textbringer.rb +1 -0
- data/lib/textbringer/buffer.rb +53 -6
- data/lib/textbringer/commands/buffers.rb +4 -5
- data/lib/textbringer/commands/files.rb +1 -1
- data/lib/textbringer/commands/fill.rb +1 -1
- data/lib/textbringer/commands/isearch.rb +2 -2
- data/lib/textbringer/commands/register.rb +2 -2
- data/lib/textbringer/commands/server.rb +63 -0
- data/lib/textbringer/keymap.rb +2 -1
- data/lib/textbringer/mode.rb +2 -2
- data/lib/textbringer/modes/c_mode.rb +2 -2
- data/lib/textbringer/modes/ruby_mode.rb +2 -2
- data/lib/textbringer/utils.rb +9 -5
- data/lib/textbringer/version.rb +1 -1
- data/lib/textbringer/window.rb +1 -1
- data/textbringer.gemspec +1 -1
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 501a7f57f239b45890a30564482e20d2f80d20b5b21719268f97d0f787600c77
|
4
|
+
data.tar.gz: 56ec3be0a84a84663542072d76d0bfd868e42144cab77d51439d3ba317fe6302
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc8752782f2b63601fc382a88689b79d874d3deef1a829ef2efaa969ccfc43175b7d6f8ca2757dd345a88bb997cbc0e3b0aafaf4bcabafad478234e6e4ecd3af
|
7
|
+
data.tar.gz: 3d7ec2385be73f6d739e5fd0b547c28dc24001e58827d2d4ae15753d03d8d71e257a8f0efd50a9630ea169d3d2c58ade94104be772d9e0d91dfce08ea0b5f957
|
data/.editorconfig
CHANGED
data/.travis.yml
CHANGED
@@ -4,28 +4,28 @@ matrix:
|
|
4
4
|
- os: linux
|
5
5
|
dist: trusty
|
6
6
|
sudo: false
|
7
|
-
rvm: 2.
|
7
|
+
rvm: 2.4.5
|
8
8
|
- os: linux
|
9
9
|
dist: trusty
|
10
10
|
sudo: false
|
11
|
-
rvm: 2.
|
11
|
+
rvm: 2.5.2
|
12
12
|
- os: linux
|
13
13
|
dist: trusty
|
14
14
|
sudo: false
|
15
|
-
rvm: 2.
|
15
|
+
rvm: 2.6.0
|
16
16
|
- os: linux
|
17
17
|
dist: trusty
|
18
18
|
sudo: false
|
19
19
|
rvm: ruby-head
|
20
20
|
- os: osx
|
21
21
|
osx_image: xcode8.2
|
22
|
-
rvm: 2.
|
22
|
+
rvm: 2.4.5
|
23
23
|
- os: osx
|
24
24
|
osx_image: xcode8.2
|
25
|
-
rvm: 2.
|
25
|
+
rvm: 2.5.2
|
26
26
|
- os: osx
|
27
27
|
osx_image: xcode8.2
|
28
|
-
rvm: 2.
|
28
|
+
rvm: 2.6.0
|
29
29
|
- os: osx
|
30
30
|
osx_image: xcode8.2
|
31
31
|
rvm: ruby-head
|
data/CHANGES.md
CHANGED
data/exe/tbclient
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "drb"
|
4
|
+
require "optparse"
|
5
|
+
|
6
|
+
eval = false
|
7
|
+
wait = true
|
8
|
+
uri = "drbunix:" + File.expand_path("server.sock", "~/.textbringer")
|
9
|
+
|
10
|
+
opt = OptionParser.new
|
11
|
+
opt.banner = "Usage: tbclient [OPTIONS] FILE"
|
12
|
+
opt.on("--uri URI", "Specify the URI of the server") do |val|
|
13
|
+
uri = val
|
14
|
+
end
|
15
|
+
opt.on("-e", "--eval", "Evaluate FILE as a Ruby expression") do
|
16
|
+
eval = true
|
17
|
+
end
|
18
|
+
opt.on("-n", "--no-wait", "Don't wait for the server") do
|
19
|
+
wait = false
|
20
|
+
end
|
21
|
+
args = ARGV.dup
|
22
|
+
opt.parse!(args)
|
23
|
+
if args.empty?
|
24
|
+
STDERR.puts(opt.help)
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
arg = args.first
|
28
|
+
tb = DRbObject.new_with_uri(uri)
|
29
|
+
if eval
|
30
|
+
puts tb.eval(arg)
|
31
|
+
else
|
32
|
+
tb.visit_file(File.expand_path(arg), wait: wait)
|
33
|
+
end
|
34
|
+
|
data/lib/textbringer.rb
CHANGED
@@ -23,6 +23,7 @@ require_relative "textbringer/commands/clipboard"
|
|
23
23
|
require_relative "textbringer/commands/register"
|
24
24
|
require_relative "textbringer/commands/keyboard_macro"
|
25
25
|
require_relative "textbringer/commands/fill"
|
26
|
+
require_relative "textbringer/commands/server"
|
26
27
|
require_relative "textbringer/commands/help"
|
27
28
|
require_relative "textbringer/mode"
|
28
29
|
require_relative "textbringer/modes/fundamental_mode"
|
data/lib/textbringer/buffer.rb
CHANGED
@@ -4,6 +4,7 @@ require "nkf"
|
|
4
4
|
require "unicode/display_width"
|
5
5
|
require "json"
|
6
6
|
require "fileutils"
|
7
|
+
require "editorconfig"
|
7
8
|
|
8
9
|
module Textbringer
|
9
10
|
class Buffer
|
@@ -398,6 +399,13 @@ module Textbringer
|
|
398
399
|
raise EditorError, "File name is not set"
|
399
400
|
end
|
400
401
|
file_name = File.expand_path(file_name)
|
402
|
+
config = EditorConfig.load_file(file_name)
|
403
|
+
if config["trim_trailing_whitespace"]
|
404
|
+
trim_trailing_whitespace
|
405
|
+
end
|
406
|
+
if config["insert_final_newline"]
|
407
|
+
insert_final_newline
|
408
|
+
end
|
401
409
|
begin
|
402
410
|
File.open(file_name, "w",
|
403
411
|
external_encoding: @file_encoding, binmode: true) do |f|
|
@@ -666,7 +674,7 @@ module Textbringer
|
|
666
674
|
end
|
667
675
|
end
|
668
676
|
end
|
669
|
-
|
677
|
+
|
670
678
|
def forward_line(n = 1)
|
671
679
|
if n > 0
|
672
680
|
n.times do
|
@@ -683,7 +691,7 @@ module Textbringer
|
|
683
691
|
end
|
684
692
|
end
|
685
693
|
end
|
686
|
-
|
694
|
+
|
687
695
|
def backward_line(n = 1)
|
688
696
|
forward_line(-n)
|
689
697
|
end
|
@@ -941,7 +949,7 @@ module Textbringer
|
|
941
949
|
m.location = s
|
942
950
|
end
|
943
951
|
end
|
944
|
-
push_undo(DeleteAction.new(self, old_pos, s, str))
|
952
|
+
push_undo(DeleteAction.new(self, old_pos, s, str))
|
945
953
|
self.modified = true
|
946
954
|
end
|
947
955
|
end
|
@@ -1328,7 +1336,15 @@ module Textbringer
|
|
1328
1336
|
end
|
1329
1337
|
|
1330
1338
|
def gsub(*args, &block)
|
1331
|
-
|
1339
|
+
if block
|
1340
|
+
s = to_s.gsub(*args) { |*params|
|
1341
|
+
set_block_backref(block, $~)
|
1342
|
+
block.call(*params)
|
1343
|
+
}
|
1344
|
+
else
|
1345
|
+
s = to_s.gsub(*args)
|
1346
|
+
end
|
1347
|
+
|
1332
1348
|
composite_edit do
|
1333
1349
|
delete_region(point_min, point_max)
|
1334
1350
|
insert(s)
|
@@ -1336,6 +1352,26 @@ module Textbringer
|
|
1336
1352
|
self
|
1337
1353
|
end
|
1338
1354
|
|
1355
|
+
def trim_trailing_whitespace
|
1356
|
+
save_excursion do
|
1357
|
+
beginning_of_buffer
|
1358
|
+
composite_edit do
|
1359
|
+
while re_search_forward(/[ \t]+$/, raise_error: false)
|
1360
|
+
replace_match("")
|
1361
|
+
end
|
1362
|
+
end
|
1363
|
+
end
|
1364
|
+
end
|
1365
|
+
|
1366
|
+
def insert_final_newline
|
1367
|
+
save_excursion do
|
1368
|
+
end_of_buffer
|
1369
|
+
if char_before != "\n"
|
1370
|
+
insert("\n")
|
1371
|
+
end
|
1372
|
+
end
|
1373
|
+
end
|
1374
|
+
|
1339
1375
|
private
|
1340
1376
|
|
1341
1377
|
def set_contents(s, enc)
|
@@ -1348,7 +1384,7 @@ module Textbringer
|
|
1348
1384
|
@contents.force_encoding(Encoding::ASCII_8BIT)
|
1349
1385
|
self.file_encoding = enc
|
1350
1386
|
case @contents
|
1351
|
-
when /(?<!\r)\n/
|
1387
|
+
when /(?<!\r)\n/
|
1352
1388
|
@file_format = :unix
|
1353
1389
|
when /\r(?!\n)/
|
1354
1390
|
@file_format = :mac
|
@@ -1391,7 +1427,7 @@ module Textbringer
|
|
1391
1427
|
if pos <= @gap_start
|
1392
1428
|
pos
|
1393
1429
|
else
|
1394
|
-
gap_size + pos
|
1430
|
+
gap_size + pos
|
1395
1431
|
end
|
1396
1432
|
end
|
1397
1433
|
|
@@ -1540,6 +1576,17 @@ module Textbringer
|
|
1540
1576
|
callback.call(self)
|
1541
1577
|
end
|
1542
1578
|
end
|
1579
|
+
|
1580
|
+
def set_block_backref(block, backref)
|
1581
|
+
Thread.current[:__textbringer_backref] = backref
|
1582
|
+
begin
|
1583
|
+
block.binding.eval(<<-EOC)
|
1584
|
+
$~ = Thread.current[:__textbringer_backref]
|
1585
|
+
EOC
|
1586
|
+
ensure
|
1587
|
+
Thread.current[:__textbringer_backref] = nil
|
1588
|
+
end
|
1589
|
+
end
|
1543
1590
|
end
|
1544
1591
|
|
1545
1592
|
class Mark
|
@@ -7,7 +7,7 @@ module Textbringer
|
|
7
7
|
|n = number_prefix_arg|
|
8
8
|
Buffer.current.forward_char(n)
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
define_command(:backward_char,
|
12
12
|
doc: "Move point n characters backward.") do
|
13
13
|
|n = number_prefix_arg|
|
@@ -25,26 +25,25 @@ module Textbringer
|
|
25
25
|
|n = number_prefix_arg|
|
26
26
|
Buffer.current.backward_word(n)
|
27
27
|
end
|
28
|
-
|
29
28
|
|
30
29
|
define_command(:next_line,
|
31
30
|
doc: "Move point n lines forward.") do
|
32
31
|
|n = number_prefix_arg|
|
33
32
|
Buffer.current.next_line(n)
|
34
33
|
end
|
35
|
-
|
34
|
+
|
36
35
|
define_command(:previous_line,
|
37
36
|
doc: "Move point n lines backward.") do
|
38
37
|
|n = number_prefix_arg|
|
39
38
|
Buffer.current.previous_line(n)
|
40
39
|
end
|
41
|
-
|
40
|
+
|
42
41
|
define_command(:delete_char,
|
43
42
|
doc: "Delete n characters forward.") do
|
44
43
|
|n = number_prefix_arg|
|
45
44
|
Buffer.current.delete_char(n)
|
46
45
|
end
|
47
|
-
|
46
|
+
|
48
47
|
define_command(:backward_delete_char,
|
49
48
|
doc: "Delete n characters backward.") do
|
50
49
|
|n = number_prefix_arg|
|
@@ -122,7 +122,7 @@ module Textbringer
|
|
122
122
|
|
123
123
|
define_command(:chdir, doc: "Change the current working directory.") do
|
124
124
|
|dir_name = read_file_name("Change directory: ",
|
125
|
-
default: Buffer.current.file_name &&
|
125
|
+
default: Buffer.current.file_name &&
|
126
126
|
File.dirname(Buffer.current.file_name))|
|
127
127
|
Dir.chdir(dir_name)
|
128
128
|
end
|
@@ -8,7 +8,7 @@ module Textbringer
|
|
8
8
|
end
|
9
9
|
ISEARCH_MODE_MAP.define_key(?\t, :isearch_printing_char)
|
10
10
|
ISEARCH_MODE_MAP.handle_undefined_key do |key|
|
11
|
-
if key.is_a?(String) && /[\0-\x7f]/ !~ key
|
11
|
+
if key.is_a?(String) && /[\0-\x7f]/ !~ key
|
12
12
|
:isearch_printing_char
|
13
13
|
else
|
14
14
|
nil
|
@@ -21,7 +21,7 @@ module Textbringer
|
|
21
21
|
ISEARCH_MODE_MAP.define_key(?\C-w, :isearch_yank_word_or_char)
|
22
22
|
ISEARCH_MODE_MAP.define_key(?\C-m, :isearch_exit)
|
23
23
|
ISEARCH_MODE_MAP.define_key(?\C-g, :isearch_abort)
|
24
|
-
|
24
|
+
|
25
25
|
ISEARCH_STATUS = {
|
26
26
|
forward: true,
|
27
27
|
string: "",
|
@@ -4,7 +4,7 @@ module Textbringer
|
|
4
4
|
module Commands
|
5
5
|
class BufferPosition
|
6
6
|
attr_reader :buffer, :mark
|
7
|
-
|
7
|
+
|
8
8
|
def initialize(buffer, mark)
|
9
9
|
@buffer = buffer
|
10
10
|
@mark = mark
|
@@ -118,7 +118,7 @@ module Textbringer
|
|
118
118
|
when Integer
|
119
119
|
REGISTERS[register] = i + prefix_numeric_value(n)
|
120
120
|
when String
|
121
|
-
append_to_register(register,
|
121
|
+
append_to_register(register,
|
122
122
|
Buffer.current.mark, Buffer.current.point, n)
|
123
123
|
else
|
124
124
|
raise ArgumentError, "Register doesn't contain a number or text"
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "drb"
|
4
|
+
|
5
|
+
module Textbringer
|
6
|
+
module Commands
|
7
|
+
define_command(:server_start,
|
8
|
+
doc: "Start Textbringer server.") do
|
9
|
+
uri = CONFIG[:server_uri] ||
|
10
|
+
"drbunix:" + File.expand_path("server.sock", "~/.textbringer")
|
11
|
+
options = CONFIG[:server_options] || { UNIXFileMode: 0600 }
|
12
|
+
DRb.start_service(uri, Server.new, options)
|
13
|
+
end
|
14
|
+
|
15
|
+
define_command(:server_kill,
|
16
|
+
doc: "Kill Textbringer server.") do
|
17
|
+
DRb.stop_service
|
18
|
+
end
|
19
|
+
|
20
|
+
define_command(:server_edit_done,
|
21
|
+
doc: "Finish server edit.") do
|
22
|
+
queue = Buffer.current[:client_wait_queue]
|
23
|
+
if queue.nil?
|
24
|
+
raise EditorError, "No waiting clients"
|
25
|
+
end
|
26
|
+
if Buffer.current.modified? &&
|
27
|
+
y_or_n?("Save file #{Buffer.current.file_name}?")
|
28
|
+
save_buffer
|
29
|
+
end
|
30
|
+
kill_buffer(Buffer.current, force: true)
|
31
|
+
queue.push(:done)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Server
|
36
|
+
def eval(s)
|
37
|
+
redisplay do
|
38
|
+
Controller.current.instance_eval(s).inspect
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def visit_file(filename, wait: true)
|
43
|
+
queue = Queue.new if wait
|
44
|
+
redisplay do
|
45
|
+
find_file(filename)
|
46
|
+
Buffer.current[:client_wait_queue] = queue if wait
|
47
|
+
end
|
48
|
+
queue.deq if wait
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def redisplay
|
54
|
+
foreground! do
|
55
|
+
begin
|
56
|
+
yield
|
57
|
+
ensure
|
58
|
+
Window.redisplay
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/textbringer/keymap.rb
CHANGED
@@ -191,8 +191,9 @@ module Textbringer
|
|
191
191
|
GLOBAL_MAP.define_key([:f1, "b"], :describe_bindings)
|
192
192
|
GLOBAL_MAP.define_key([:f1, "f"], :describe_command)
|
193
193
|
GLOBAL_MAP.define_key([:f1, "k"], :describe_key)
|
194
|
+
GLOBAL_MAP.define_key("\C-x#", :server_edit_done)
|
194
195
|
GLOBAL_MAP.handle_undefined_key do |key|
|
195
|
-
if key.is_a?(String) && /[\0-\x7f]/ !~ key
|
196
|
+
if key.is_a?(String) && /[\0-\x7f]/ !~ key
|
196
197
|
:self_insert
|
197
198
|
else
|
198
199
|
nil
|
data/lib/textbringer/mode.rb
CHANGED
@@ -35,7 +35,7 @@ module Textbringer
|
|
35
35
|
(?: " (?: [^\\"] | \\ (?:.|\n) )* " ) |
|
36
36
|
(?: ' (?: [^\\'] | \\ (?:.|\n) )* ' )
|
37
37
|
/x
|
38
|
-
|
38
|
+
|
39
39
|
def initialize(buffer)
|
40
40
|
super(buffer)
|
41
41
|
@buffer[:indent_level] = CONFIG[:c_indent_level]
|
@@ -68,7 +68,7 @@ module Textbringer
|
|
68
68
|
:partial_comment,
|
69
69
|
:unknown
|
70
70
|
]
|
71
|
-
|
71
|
+
|
72
72
|
TOKEN_REGEXP = /\G(?:
|
73
73
|
(?<preprocessing_directive>
|
74
74
|
^[ \t\f\v]*(?:\#|%:).*(?:\\\n.*)*[^\\]\n
|
@@ -259,7 +259,7 @@ module Textbringer
|
|
259
259
|
indentation
|
260
260
|
end
|
261
261
|
end
|
262
|
-
|
262
|
+
|
263
263
|
BLOCK_END = {
|
264
264
|
"{" => "}",
|
265
265
|
"(" => ")",
|
@@ -334,7 +334,7 @@ module Textbringer
|
|
334
334
|
end
|
335
335
|
nil
|
336
336
|
end
|
337
|
-
|
337
|
+
|
338
338
|
class PartialLiteralAnalyzer < Ripper
|
339
339
|
def self.in_literal?(src)
|
340
340
|
new(src).in_literal?
|
data/lib/textbringer/utils.rb
CHANGED
@@ -54,20 +54,22 @@ module Textbringer
|
|
54
54
|
begin
|
55
55
|
yield
|
56
56
|
rescue Exception => e
|
57
|
-
|
57
|
+
foreground do
|
58
58
|
raise e
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
def
|
64
|
+
def foreground(&block)
|
65
65
|
Controller.current.next_tick(&block)
|
66
66
|
end
|
67
67
|
|
68
|
-
|
68
|
+
alias next_tick foreground
|
69
|
+
|
70
|
+
def foreground!
|
69
71
|
q = Queue.new
|
70
|
-
|
72
|
+
foreground do
|
71
73
|
begin
|
72
74
|
result = yield
|
73
75
|
q.push([:ok, result])
|
@@ -77,12 +79,14 @@ module Textbringer
|
|
77
79
|
end
|
78
80
|
status, value = q.pop
|
79
81
|
if status == :error
|
80
|
-
raise value
|
82
|
+
raise value
|
81
83
|
else
|
82
84
|
value
|
83
85
|
end
|
84
86
|
end
|
85
87
|
|
88
|
+
alias next_tick! foreground!
|
89
|
+
|
86
90
|
def read_event
|
87
91
|
Controller.current.read_event
|
88
92
|
end
|
data/lib/textbringer/version.rb
CHANGED
data/lib/textbringer/window.rb
CHANGED
data/textbringer.gemspec
CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
|
|
21
21
|
|
22
22
|
spec.required_ruby_version = '>= 2.3'
|
23
23
|
|
24
|
-
spec.add_runtime_dependency "curses", ">= 1.2.
|
24
|
+
spec.add_runtime_dependency "curses", ">= 1.2.6"
|
25
25
|
spec.add_runtime_dependency "unicode-display_width", "~> 1.1"
|
26
26
|
spec.add_runtime_dependency "clipboard", "~> 1.1"
|
27
27
|
spec.add_runtime_dependency "fiddley", ">= 0.0.5"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: textbringer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shugo Maeda
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: curses
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.2.
|
19
|
+
version: 1.2.6
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.2.
|
26
|
+
version: 1.2.6
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: unicode-display_width
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -183,6 +183,7 @@ description: Textbringer is a member of a demon race that takes on the form of a
|
|
183
183
|
email:
|
184
184
|
- shugo@ruby-lang.org
|
185
185
|
executables:
|
186
|
+
- tbclient
|
186
187
|
- tbtags
|
187
188
|
- textbringer
|
188
189
|
extensions: []
|
@@ -198,6 +199,7 @@ files:
|
|
198
199
|
- Rakefile
|
199
200
|
- appveyor.yml
|
200
201
|
- bin/console
|
202
|
+
- exe/tbclient
|
201
203
|
- exe/tbtags
|
202
204
|
- exe/textbringer
|
203
205
|
- lib/textbringer.rb
|
@@ -216,6 +218,7 @@ files:
|
|
216
218
|
- lib/textbringer/commands/misc.rb
|
217
219
|
- lib/textbringer/commands/register.rb
|
218
220
|
- lib/textbringer/commands/replace.rb
|
221
|
+
- lib/textbringer/commands/server.rb
|
219
222
|
- lib/textbringer/commands/windows.rb
|
220
223
|
- lib/textbringer/config.rb
|
221
224
|
- lib/textbringer/controller.rb
|