rawline 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,130 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ #
4
+ # history_buffer.rb
5
+ #
6
+ # Created by Fabio Cevasco on 2008-03-01.
7
+ # Copyright (c) 2008 Fabio Cevasco. All rights reserved.
8
+ #
9
+ # This is Free Software. See LICENSE for details.
10
+ #
11
+ #
12
+ #
13
+ module RawLine
14
+
15
+ #
16
+ # The HistoryBuffer class is used to hold the editor and line histories, as well
17
+ # as word completion matches.
18
+ #
19
+ class HistoryBuffer < Array
20
+
21
+ attr_reader :position, :size
22
+ attr_accessor :duplicates, :exclude, :cycle
23
+
24
+ undef <<
25
+
26
+ #
27
+ # Create an instance of RawLine::HistoryBuffer.
28
+ # This method takes an optional block used to override the
29
+ # following instance attributes:
30
+ # * <tt>@duplicates</tt> - whether or not duplicate items will be stored in the
31
+ # buffer.
32
+ # * <tt>@exclude</tt> - a Proc object defining exclusion rules to prevent items
33
+ # from being added to the buffer.
34
+ # * <tt>@cycle</tt> - Whether or not the buffer is cyclic.
35
+ #
36
+ def initialize(size)
37
+ @duplicates = true
38
+ @exclude = lambda { nil }
39
+ @cycle = false
40
+ yield self if block_given?
41
+ @size = size
42
+ @position = nil
43
+ end
44
+
45
+ #
46
+ # Resize the buffer, resetting <tt>@position</tt> to nil.
47
+ #
48
+ def resize(new_size)
49
+ if new_size < @size
50
+ @size-new_size.times { pop }
51
+ end
52
+ @size = new_size
53
+ @position = nil
54
+ end
55
+
56
+ #
57
+ # Clear the content of the buffer and reset <tt>@position</tt> to nil.
58
+ #
59
+ def empty
60
+ @position = nil
61
+ clear
62
+ end
63
+
64
+ #
65
+ # Retrieve the element at <tt>@position</tt>.
66
+ #
67
+ def get
68
+ return nil unless length > 0
69
+ @position = length-1 unless @position
70
+ at @position
71
+ end
72
+
73
+ #
74
+ # Return true if <tt>@position</tt> is at the end of the buffer.
75
+ #
76
+ def end?
77
+ @position == length-1
78
+ end
79
+
80
+ #
81
+ # Return true if <tt>@position</tt> is at the start of the buffer.
82
+ #
83
+ def start?
84
+ @position == 0
85
+ end
86
+
87
+ #
88
+ # Decrement <tt>@position</tt>.
89
+ #
90
+ def back
91
+ return nil unless length > 0
92
+ case @position
93
+ when nil: @position = length-1
94
+ when 0: @position = length-1 if @cycle
95
+ else @position -= 1
96
+ end
97
+ end
98
+
99
+ #
100
+ # Increment <tt>@position</tt>.
101
+ #
102
+ def forward
103
+ return nil unless length > 0
104
+ case @position
105
+ when nil: @position = length-1
106
+ when length-1: @position = 0 if @cycle
107
+ else @position += 1
108
+ end
109
+ end
110
+
111
+ #
112
+ # Add a new item to the buffer.
113
+ #
114
+ def <<(item)
115
+ delete(item) unless @duplicates
116
+ unless @exclude.call(item)
117
+ # Remove the oldest element if size is exceeded
118
+ if @size <= length
119
+ reverse!.pop
120
+ reverse!
121
+ end
122
+ # Add the new item and reset the position
123
+ push(item)
124
+ @position = nil
125
+ end
126
+ end
127
+
128
+ end
129
+
130
+ end
@@ -0,0 +1,158 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ #
4
+ # line.rb
5
+ #
6
+ # Created by Fabio Cevasco on 2008-03-01.
7
+ # Copyright (c) 2008 Fabio Cevasco. All rights reserved.
8
+ #
9
+ # This is Free Software. See LICENSE for details.
10
+ #
11
+
12
+ module RawLine
13
+
14
+ #
15
+ # The Line class is used to represent the current line being processed and edited
16
+ # by RawLine::Editor. It keeps track of the characters typed, the cursor position,
17
+ # the current word and maintains an internal history to allow undos and redos.
18
+ #
19
+ class Line
20
+
21
+ attr_accessor :text, :position, :history, :prompt, :history_size, :word_separator
22
+ attr_reader :offset
23
+
24
+ include HighLine::SystemExtensions
25
+
26
+ #
27
+ # Create an instance of RawLine::Line.
28
+ # This method takes an optional block used to override the
29
+ # following instance attributes:
30
+ # * <tt>@text</tt> - the line text.
31
+ # * <tt>@history_size</tt> - the size of the line history buffer.
32
+ # * <tt>@position</tt> - the current cursor position within the line.
33
+ # * <tt>@prompt</tt> - a prompt to prepend to the line text.
34
+ #
35
+ def initialize(history_size)
36
+ @text = ""
37
+ @history_size = history_size
38
+ @position = 0
39
+ @prompt = ""
40
+ @word_separator = ' '
41
+ yield self if block_given?
42
+ @words = []
43
+ @history = RawLine::HistoryBuffer.new(@history_size)
44
+ @history << "" # Add empty line for complete undo...
45
+ @offset = @prompt.length
46
+ end
47
+
48
+ #
49
+ # Return the maximum line length. By default, it corresponds to the terminal's
50
+ # width minus the length of the line prompt.
51
+ #
52
+ def max_length
53
+ terminal_size[0]-@offset
54
+ end
55
+
56
+ #
57
+ # Return information about the current word, as a Hash composed by the following
58
+ # elements:
59
+ # * <tt>:start</tt>: The position in the line corresponding to the word start
60
+ # * <tt>:end</tt>: The position in the line corresponding to the word end
61
+ # * <tt>:text</tt>: The word text.
62
+ def word
63
+ last = @text.index(@word_separator, @position)
64
+ first = @text.rindex(@word_separator, @position)
65
+ # Trim word separators and handle EOL and BOL
66
+ if first: first +=1
67
+ else first = bol
68
+ end
69
+ if last: last -=1
70
+ else last = eol+1 unless last
71
+ end
72
+ # Swap if overlapping
73
+ last, first = first, last if last < first
74
+ text = @text[first..last]
75
+ # Repeat the search if within word separator
76
+ if text.match @word_separator then
77
+ last = first
78
+ first = @text.rindex(@word_separator, first)
79
+ if first then first+=1
80
+ else first = bol
81
+ end
82
+ text = @text[first..last]
83
+ end
84
+ {:start => first, :end => last, :text => text}
85
+ end
86
+
87
+ #
88
+ # Return the position corresponding to the beginning of the line.
89
+ #
90
+ def bol
91
+ 0
92
+ end
93
+
94
+ #
95
+ # Return true if the cursor is at the beginning of the line.
96
+ #
97
+ def bol?
98
+ @position<=bol
99
+ end
100
+
101
+ #
102
+ # Return the position corresponding to the end of the line.
103
+ #
104
+ def eol
105
+ @text.length-1
106
+ end
107
+
108
+ #
109
+ # Return true if the cursor is at the end of the line.
110
+ #
111
+ def eol?
112
+ @position>=eol
113
+ end
114
+
115
+ #
116
+ # Decrement the line position by <tt>offset</tt>
117
+ #
118
+ def left(offset=1)
119
+ @position = (@position-offset <= 0) ? 0 : @position-offset
120
+ end
121
+
122
+ #
123
+ # Increment the line position by <tt>offset</tt>
124
+ #
125
+ def right(offset=1)
126
+ @position = (@position+offset >= max_length) ? max_length : @position+offset
127
+ end
128
+
129
+ #
130
+ # Add a character (expressed as a character code) to the line text.
131
+ #
132
+ def <<(char)
133
+ @text << char.chr
134
+ end
135
+
136
+ #
137
+ # Access the line text at <tt>@index</tt>
138
+ #
139
+ def [](index)
140
+ @text[index]
141
+ end
142
+
143
+ #
144
+ # Modify the character(s) in the line text at <tt>@index</tt>
145
+ #
146
+ def []=(index, chars)
147
+ @text[index] = chars
148
+ end
149
+
150
+ #
151
+ # Return the length of the line text.
152
+ #
153
+ def length
154
+ @text.length
155
+ end
156
+
157
+ end
158
+ end
@@ -0,0 +1,66 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ #
4
+ # vt220_terminal.rb
5
+ #
6
+ # Created by Fabio Cevasco on 2008-03-01.
7
+ # Copyright (c) 2008 Fabio Cevasco. All rights reserved.
8
+ #
9
+ # This is Free Software. See LICENSE for details.
10
+ #
11
+
12
+ module RawLine
13
+
14
+ #
15
+ # This class is used to define all the most common character codes and
16
+ # escape sequences used on *nix systems.
17
+ #
18
+ class VT220Terminal < Terminal
19
+
20
+ def initialize
21
+ super
22
+ @escape_codes = [?\e]
23
+ @keys.merge!(
24
+ {
25
+ :up_arrow => [?\e, ?[, ?A],
26
+ :down_arrow => [?\e, ?[, ?B],
27
+ :right_arrow => [?\e, ?[, ?C],
28
+ :left_arrow => [?\e, ?[, ?D],
29
+ :insert => [?\e, ?[, ?2, ?~],
30
+ :delete => [?\e, ?[, ?3, ?~],
31
+ :backspace => [?\C-?],
32
+ :enter => [?\n],
33
+
34
+ :ctrl_alt_a => [?\e, ?\C-a],
35
+ :ctrl_alt_b => [?\e, ?\C-b],
36
+ :ctrl_alt_c => [?\e, ?\C-c],
37
+ :ctrl_alt_d => [?\e, ?\C-d],
38
+ :ctrl_alt_e => [?\e, ?\C-e],
39
+ :ctrl_alt_f => [?\e, ?\C-f],
40
+ :ctrl_alt_g => [?\e, ?\C-g],
41
+ :ctrl_alt_h => [?\e, ?\C-h],
42
+ :ctrl_alt_i => [?\e, ?\C-i],
43
+ :ctrl_alt_j => [?\e, ?\C-j],
44
+ :ctrl_alt_k => [?\e, ?\C-k],
45
+ :ctrl_alt_l => [?\e, ?\C-l],
46
+ :ctrl_alt_m => [?\e, ?\C-m],
47
+ :ctrl_alt_n => [?\e, ?\C-n],
48
+ :ctrl_alt_o => [?\e, ?\C-o],
49
+ :ctrl_alt_p => [?\e, ?\C-p],
50
+ :ctrl_alt_q => [?\e, ?\C-q],
51
+ :ctrl_alt_r => [?\e, ?\C-r],
52
+ :ctrl_alt_s => [?\e, ?\C-s],
53
+ :ctrl_alt_t => [?\e, ?\C-t],
54
+ :ctrl_alt_u => [?\e, ?\C-u],
55
+ :ctrl_alt_v => [?\e, ?\C-v],
56
+ :ctrl_alt_w => [?\e, ?\C-w],
57
+ :ctrl_alt_x => [?\e, ?\C-x],
58
+ :ctrl_alt_y => [?\e, ?\C-y],
59
+ :ctrl_alt_z => [?\e, ?\C-z]
60
+ })
61
+ end
62
+
63
+ end
64
+
65
+
66
+ end
@@ -0,0 +1,66 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ #
4
+ # windows_terminal.rb
5
+ #
6
+ # Created by Fabio Cevasco on 2008-03-01.
7
+ # Copyright (c) 2008 Fabio Cevasco. All rights reserved.
8
+ #
9
+ # This is Free Software. See LICENSE for details.
10
+ #
11
+
12
+ module RawLine
13
+
14
+ #
15
+ # This class is used to define all the most common character codes and
16
+ # escape sequences used on Windows systems.
17
+ #
18
+ class WindowsTerminal < Terminal
19
+
20
+ def initialize
21
+ super
22
+ @escape_codes = [0, 27, 224]
23
+ @keys.merge!(
24
+ {
25
+ :left_arrow => [224, 75],
26
+ :right_arrow => [224, 77],
27
+ :up_arrow => [224, 72],
28
+ :down_arrow => [224, 80],
29
+ :insert => [224, 82],
30
+ :delete => [224, 83],
31
+ :backspace => [8],
32
+ :enter => [13],
33
+
34
+ :ctrl_alt_a => [0, 30],
35
+ :ctrl_alt_b => [0, 48],
36
+ :ctrl_alt_c => [0, 46],
37
+ :ctrl_alt_d => [0, 32],
38
+ :ctrl_alt_e => [0, 63],
39
+ :ctrl_alt_f => [0, 33],
40
+ :ctrl_alt_g => [0, 34],
41
+ :ctrl_alt_h => [0, 35],
42
+ :ctrl_alt_i => [0, 23],
43
+ :ctrl_alt_j => [0, 36],
44
+ :ctrl_alt_k => [0, 37],
45
+ :ctrl_alt_l => [0, 26],
46
+ :ctrl_alt_m => [0, 32],
47
+ :ctrl_alt_n => [0, 31],
48
+ :ctrl_alt_o => [0, 24],
49
+ :ctrl_alt_p => [0, 25],
50
+ :ctrl_alt_q => [0, 16],
51
+ :ctrl_alt_r => [0, 19],
52
+ :ctrl_alt_s => [0, 31],
53
+ :ctrl_alt_t => [0, 20],
54
+ :ctrl_alt_u => [0, 22],
55
+ :ctrl_alt_v => [0, 47],
56
+ :ctrl_alt_w => [0, 17],
57
+ :ctrl_alt_x => [0, 45],
58
+ :ctrl_alt_y => [0, 21],
59
+ :ctrl_alt_z => [0, 44]
60
+ })
61
+ end
62
+
63
+ end
64
+
65
+
66
+ end
@@ -0,0 +1,87 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ #
4
+ # terminal.rb
5
+ #
6
+ # Created by Fabio Cevasco on 2008-03-01.
7
+ # Copyright (c) 2008 Fabio Cevasco. All rights reserved.
8
+ #
9
+ # This is Free Software. See LICENSE for details.
10
+ #
11
+ #
12
+ #
13
+ module RawLine
14
+
15
+ #
16
+ # The Terminal class defines character codes and code sequences which can be
17
+ # bound to actions by editors.
18
+ # An OS-dependent subclass of RawLine::Terminal is automatically instantiated by
19
+ # RawLine::Editor.
20
+ #
21
+ class Terminal
22
+
23
+ include HighLine::SystemExtensions
24
+
25
+ attr_accessor :escape_codes
26
+ attr_reader :keys, :escape_sequences
27
+
28
+ #
29
+ # Create an instance of RawLine::Terminal.
30
+ #
31
+ def initialize
32
+ @keys =
33
+ {
34
+ :tab => [?\t],
35
+ :return => [?\r],
36
+ :newline => [?\n],
37
+ :escape => [?\e],
38
+
39
+ :ctrl_a => [?\C-a],
40
+ :ctrl_b => [?\C-b],
41
+ :ctrl_c => [?\C-c],
42
+ :ctrl_d => [?\C-d],
43
+ :ctrl_e => [?\C-e],
44
+ :ctrl_f => [?\C-f],
45
+ :ctrl_g => [?\C-g],
46
+ :ctrl_h => [?\C-h],
47
+ :ctrl_i => [?\C-i],
48
+ :ctrl_j => [?\C-j],
49
+ :ctrl_k => [?\C-k],
50
+ :ctrl_l => [?\C-l],
51
+ :ctrl_m => [?\C-m],
52
+ :ctrl_n => [?\C-n],
53
+ :ctrl_o => [?\C-o],
54
+ :ctrl_p => [?\C-p],
55
+ :ctrl_q => [?\C-q],
56
+ :ctrl_r => [?\C-r],
57
+ :ctrl_s => [?\C-s],
58
+ :ctrl_t => [?\C-t],
59
+ :ctrl_u => [?\C-u],
60
+ :ctrl_v => [?\C-v],
61
+ :ctrl_w => [?\C-w],
62
+ :ctrl_x => [?\C-x],
63
+ :ctrl_y => [?\C-y],
64
+ :ctrl_z => [?\C-z]
65
+ }
66
+ @escape_codes = []
67
+ @escape_sequences = []
68
+ update
69
+ end
70
+
71
+ #
72
+ # Update the terminal escape sequences. This method is called automatically
73
+ # by RawLine::Editor#bind().
74
+ #
75
+ def update
76
+ @keys.each_value do |k|
77
+ l = k.length
78
+ if l > 1 then
79
+ @escape_sequences << k unless @escape_sequences.include? k
80
+ end
81
+ end
82
+ end
83
+
84
+ end
85
+
86
+
87
+ end
data/lib/rawline.rb ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ #
4
+ # RawLine.rb
5
+ #
6
+ # Created by Fabio Cevasco on 2008-03-01.
7
+ # Copyright (c) 2008 Fabio Cevasco. All rights reserved.
8
+ #
9
+ # This is Free Software. See LICENSE for details.
10
+ #
11
+
12
+ module RawLine
13
+ HOME = File.dirname(File.expand_path(__FILE__))
14
+ class BindingException < Exception; end
15
+ begin
16
+ WIN32CONSOLE = require "win32console" if PLATFORM.match(/win32/i)
17
+ ANSI = true
18
+ rescue
19
+ ANSI = false
20
+ end
21
+ end
22
+
23
+ require "rubygems"
24
+ require "highline"
25
+ require "#{RawLine::HOME}/RawLine/terminal"
26
+ require "#{RawLine::HOME}/RawLine/terminal/windows_terminal"
27
+ require "#{RawLine::HOME}/RawLine/terminal/vt220_terminal"
28
+ require "#{RawLine::HOME}/RawLine/history_buffer"
29
+ require "#{RawLine::HOME}/RawLine/line"
30
+ require "#{RawLine::HOME}/RawLine/editor"
31
+
32
+
data/test/test_all.rb ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ module RawLine
4
+ TEST_HOME = File.dirname(File.expand_path(__FILE__))+'/..' unless const_defined?(:TEST_HOME)
5
+ end
6
+
7
+ require "test_history_buffer"
8
+ require "test_line"
9
+ require "test_editor"
@@ -0,0 +1,169 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ module RawLine
4
+ TEST_HOME = File.dirname(File.expand_path(__FILE__))+'/..' unless const_defined?(:TEST_HOME)
5
+ end
6
+
7
+ require 'highline/system_extensions'
8
+
9
+ module HighLine::SystemExtensions
10
+ # Override Windows' character reading so it's not tied to STDIN.
11
+ def get_character( input = STDIN )
12
+ input.getc
13
+ end
14
+ end
15
+
16
+ require 'stringio'
17
+ require "#{RawLine::TEST_HOME}/lib/RawLine"
18
+
19
+ describe RawLine::Editor do
20
+
21
+ before :each do
22
+ @output = StringIO.new
23
+ @input = StringIO.new
24
+ @editor = RawLine::Editor.new(@input, @output)
25
+ end
26
+
27
+ it "reads raw characters from @input" do
28
+ @input << "test #1"
29
+ @input.rewind
30
+ @editor.read
31
+ @editor.line.text.should == "test #1"
32
+ @output.string.should == "test #1"
33
+ end
34
+
35
+ it "can bind keys to code blocks" do
36
+ @editor.bind(:ctrl_w) { @editor.write "test #2a" }
37
+ @editor.bind(?\C-q) { "test #2b" }
38
+ @editor.bind(21) { "test #2c" }
39
+ @editor.bind([22]) { "test #2d" }
40
+ @editor.terminal.escape_codes = [] # remove any existing escape codes
41
+ lambda {@editor.bind({:test => [?\e, ?t, ?e, ?s, ?t]}) { "test #2e" }}.should raise_error(RawLine::BindingException)
42
+ @editor.terminal.escape_codes << ?\e
43
+ lambda {@editor.bind({:test => "\etest"}) { "test #2e" }}.should_not raise_error(RawLine::BindingException)
44
+ lambda {@editor.bind("\etest2") { "test #2f" }}.should_not raise_error(RawLine::BindingException)
45
+ @input << ?\C-w.chr
46
+ @input.rewind
47
+ @editor.read
48
+ @editor.line.text.should == "test #2a"
49
+ @editor.char = [?\C-q]
50
+ @editor.press_key.should == "test #2b"
51
+ @editor.char = [?\C-u]
52
+ @editor.press_key.should == "test #2c"
53
+ @editor.char = [?\C-v]
54
+ @editor.press_key.should == "test #2d"
55
+ @editor.char = [?\e, ?t, ?e, ?s, ?t]
56
+ @editor.press_key.should == "test #2e"
57
+ @editor.char = [?\e, ?t, ?e, ?s, ?t, ?2]
58
+ @editor.press_key.should == "test #2f"
59
+ end
60
+
61
+ it "keeps track of the cursor position" do
62
+ @input << "test #4"
63
+ @input.rewind
64
+ @editor.read
65
+ @editor.line.position.should == 7
66
+ 3.times { @editor.move_left }
67
+ @editor.line.position.should == 4
68
+ 2.times { @editor.move_right }
69
+ @editor.line.position.should == 6
70
+ end
71
+
72
+ it "can delete characters" do
73
+ @input << "test #5"
74
+ @input.rewind
75
+ @editor.read
76
+ 3.times { @editor.move_left }
77
+ 4.times { @editor.delete_left_character }
78
+ 3.times { @editor.delete_character }
79
+ @editor.line.text.should == ""
80
+ @editor.line.position.should == 0
81
+ end
82
+
83
+ it "can clear the whole line" do
84
+ @input << "test #5"
85
+ @input.rewind
86
+ @editor.read
87
+ @editor.clear_line
88
+ @editor.line.text.should == ""
89
+ @editor.line.position.should == 0
90
+ end
91
+
92
+ it "supports undo and redo" do
93
+ @input << "test #6"
94
+ @input.rewind
95
+ @editor.read
96
+ 3.times { @editor.delete_left_character }
97
+ 2.times { @editor.undo }
98
+ @editor.line.text.should == "test #"
99
+ 2.times { @editor.redo }
100
+ @editor.line.text.should == "test"
101
+ end
102
+
103
+ it "supports history" do
104
+ @input << "test #7a"
105
+ @input.rewind
106
+ @editor.read
107
+ @editor.newline
108
+ @input << "test #7b"
109
+ @input.pos = 8
110
+ @editor.read
111
+ @editor.newline
112
+ @input << "test #7c"
113
+ @input.pos = 16
114
+ @editor.read
115
+ @editor.newline
116
+ @input << "test #7d"
117
+ @input.pos = 24
118
+ @editor.read
119
+ @editor.newline
120
+ @editor.history_back
121
+ @editor.line.text.should == "test #7c"
122
+ 10.times { @editor.history_back }
123
+ @editor.line.text.should == "test #7a"
124
+ 2.times { @editor.history_forward }
125
+ @editor.line.text.should == "test #7c"
126
+ end
127
+
128
+ it "can overwrite lines" do
129
+ @input << "test #8a"
130
+ @input.rewind
131
+ @editor.read
132
+ @editor.overwrite_line("test #8b", 2)
133
+ @editor.line.text.should == "test #8b"
134
+ @editor.line.position.should == 2
135
+ end
136
+
137
+ it "can complete words" do
138
+ @editor.completion_append_string = "\t"
139
+ @editor.bind(:tab) { @editor.complete }
140
+ @editor.completion_proc = lambda do |word|
141
+ if word
142
+ ['select', 'update', 'delete', 'debug', 'destroy'].find_all { |e| e.match(/^#{Regexp.escape(word)}/) }
143
+ end
144
+ end
145
+ @input << "test #9 de" << ?\t.chr << ?\t.chr
146
+ @input.rewind
147
+ @editor.read
148
+ @editor.line.text.should == "test #9 delete\t"
149
+ end
150
+
151
+ it "supports INSERT and REPLACE modes" do
152
+ @input << "test 0"
153
+ @editor.terminal.keys[:left_arrow].each { |k| @input << k.chr }
154
+ @input << "#1"
155
+ @input.rewind
156
+ @editor.read
157
+ @editor.line.text.should == "test #10"
158
+ @editor.toggle_mode
159
+ @input << "test 0"
160
+ @editor.terminal.keys[:left_arrow].each { |k| @input << k.chr }
161
+ @input << "#1"
162
+ @input.pos = 10
163
+ @editor.read
164
+ @editor.line.text.should == "test #1"
165
+ end
166
+
167
+
168
+ end
169
+