ruco 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme.md +1 -2
- data/VERSION +1 -1
- data/bin/ruco +9 -7
- data/lib/ruco.rb +2 -1
- data/lib/ruco/command_bar.rb +11 -9
- data/lib/ruco/cursor.rb +10 -0
- data/lib/ruco/editor.rb +25 -171
- data/lib/ruco/form.rb +4 -3
- data/lib/ruco/text_area.rb +181 -0
- data/lib/ruco/text_field.rb +4 -29
- data/ruco.gemspec +4 -3
- data/spec/ruco/command_bar_spec.rb +16 -9
- data/spec/ruco/editor_spec.rb +162 -114
- data/spec/ruco/form_spec.rb +8 -8
- metadata +6 -5
- data/lib/ruco/focusable.rb +0 -11
data/Readme.md
CHANGED
@@ -11,6 +11,7 @@ Finished:
|
|
11
11
|
- writeable indicator
|
12
12
|
- backspace / delete
|
13
13
|
- find / go to line
|
14
|
+
- delete line
|
14
15
|
|
15
16
|
Install
|
16
17
|
=======
|
@@ -22,8 +23,6 @@ Usage
|
|
22
23
|
|
23
24
|
TODO
|
24
25
|
=====
|
25
|
-
- delete line
|
26
|
-
- scrolling inside text field
|
27
26
|
- smart staying at end of line/column when changing line
|
28
27
|
- indentation + paste support
|
29
28
|
- warnings / messages
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.6
|
data/bin/ruco
CHANGED
@@ -76,19 +76,19 @@ init_screen do
|
|
76
76
|
display editor, status_lines, Curses::A_NORMAL
|
77
77
|
display command, status_lines + editor_lines, Curses::A_REVERSE
|
78
78
|
|
79
|
-
Curses.setpos(focused.
|
79
|
+
Curses.setpos(focused.cursor.line + status_lines, focused.cursor.column)
|
80
80
|
|
81
81
|
key = Curses.getch
|
82
82
|
|
83
83
|
case key
|
84
84
|
|
85
85
|
# move
|
86
|
-
when Curses::Key::UP then focused.move(-1,0)
|
87
|
-
when Curses::Key::DOWN then focused.move(1,0)
|
88
|
-
when Curses::Key::RIGHT then focused.move(0,1)
|
89
|
-
when Curses::Key::LEFT then focused.move(0,-1)
|
90
|
-
when Curses::KEY_END then focused.
|
91
|
-
when Curses::KEY_HOME then focused.
|
86
|
+
when Curses::Key::UP then focused.move(:relative, -1,0)
|
87
|
+
when Curses::Key::DOWN then focused.move(:relative, 1,0)
|
88
|
+
when Curses::Key::RIGHT then focused.move(:relative, 0,1)
|
89
|
+
when Curses::Key::LEFT then focused.move(:relative, 0,-1)
|
90
|
+
when Curses::KEY_END then focused.move :to_eol
|
91
|
+
when Curses::KEY_HOME then focused.move :to_bol
|
92
92
|
|
93
93
|
# modify
|
94
94
|
when 9 then focused.insert(key.chr) # tab
|
@@ -103,6 +103,8 @@ init_screen do
|
|
103
103
|
when Curses::KEY_DC then focused.delete(1) # delete
|
104
104
|
|
105
105
|
# misc
|
106
|
+
when ?\C-d then
|
107
|
+
editor.delete_line
|
106
108
|
when ?\C-f then
|
107
109
|
focused = command
|
108
110
|
command.find
|
data/lib/ruco.rb
CHANGED
@@ -2,7 +2,7 @@ require 'ruco/core_ext/object'
|
|
2
2
|
require 'ruco/core_ext/string'
|
3
3
|
require 'ruco/core_ext/array'
|
4
4
|
|
5
|
-
require 'ruco/
|
5
|
+
require 'ruco/cursor'
|
6
6
|
require 'ruco/command'
|
7
7
|
|
8
8
|
require 'ruco/editor'
|
@@ -10,6 +10,7 @@ require 'ruco/status_bar'
|
|
10
10
|
require 'ruco/command_bar'
|
11
11
|
|
12
12
|
require 'ruco/form'
|
13
|
+
require 'ruco/text_area'
|
13
14
|
require 'ruco/text_field'
|
14
15
|
|
15
16
|
module Ruco
|
data/lib/ruco/command_bar.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
module Ruco
|
2
2
|
class CommandBar
|
3
|
-
include Focusable
|
4
|
-
|
5
3
|
attr_accessor :cursor_line, :form
|
6
4
|
delegate :move, :delete, :insert, :to => :form
|
7
5
|
|
@@ -13,8 +11,6 @@ module Ruco
|
|
13
11
|
'^G Go to line'
|
14
12
|
]
|
15
13
|
|
16
|
-
SEARCH_PREFIX = "Find: "
|
17
|
-
|
18
14
|
def initialize(options)
|
19
15
|
@options = options
|
20
16
|
@forms_cache = {}
|
@@ -30,11 +26,17 @@ module Ruco
|
|
30
26
|
end
|
31
27
|
|
32
28
|
def find
|
33
|
-
@
|
29
|
+
@forms_cache[:find] ||= Form.new('Find: ', :columns => @options[:columns]) do |value|
|
30
|
+
Command.new(:find, value)
|
31
|
+
end
|
32
|
+
@form = @forms_cache[:find]
|
34
33
|
end
|
35
34
|
|
36
35
|
def move_to_line
|
37
|
-
@form = Form.new('Go to Line: ', :columns => @options[:columns], :
|
36
|
+
@form = Form.new('Go to Line: ', :columns => @options[:columns], :type => :integer) do |value|
|
37
|
+
reset
|
38
|
+
Command.new(:move, :to_line, value.to_i)
|
39
|
+
end
|
38
40
|
end
|
39
41
|
|
40
42
|
def reset
|
@@ -42,11 +44,11 @@ module Ruco
|
|
42
44
|
@form = nil
|
43
45
|
end
|
44
46
|
|
45
|
-
def
|
47
|
+
def cursor
|
46
48
|
if @form
|
47
|
-
@form.cursor
|
49
|
+
Cursor.new cursor_line, @form.cursor.column
|
48
50
|
else
|
49
|
-
0
|
51
|
+
Cursor.new cursor_line, 0
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
data/lib/ruco/cursor.rb
ADDED
data/lib/ruco/editor.rb
CHANGED
@@ -1,202 +1,56 @@
|
|
1
1
|
module Ruco
|
2
2
|
class Editor
|
3
|
-
|
4
|
-
|
5
|
-
SCROLLING_OFFSET = 20
|
6
|
-
|
7
|
-
attr_reader :cursor_line, :cursor_column, :file
|
3
|
+
attr_reader :file
|
4
|
+
delegate :view, :move, :cursor, :to => :text_area
|
8
5
|
|
9
6
|
def initialize(file, options)
|
10
7
|
@file = file
|
11
8
|
@options = options
|
12
|
-
|
13
|
-
@
|
14
|
-
@column = 0
|
15
|
-
@cursor_line = 0
|
16
|
-
@cursor_column = 0
|
17
|
-
@scrolled_lines = 0
|
18
|
-
@scrolled_columns = 0
|
9
|
+
content = (File.exist?(@file) ? File.read(@file) : '')
|
10
|
+
@text_area = TextArea.new(content, @options)
|
19
11
|
@modified = false
|
20
|
-
@options[:line_scrolling_offset] ||= @options[:lines] / 2
|
21
|
-
@options[:column_scrolling_offset] ||= @options[:columns] / 2
|
22
|
-
end
|
23
|
-
|
24
|
-
def view
|
25
|
-
Array.new(@options[:lines]).map_with_index do |_,i|
|
26
|
-
(lines[i + @scrolled_lines] || "").slice(@scrolled_columns, @options[:columns])
|
27
|
-
end * "\n" + "\n"
|
28
|
-
end
|
29
|
-
|
30
|
-
def move(line, column)
|
31
|
-
@line += line
|
32
|
-
@column += column
|
33
|
-
adjust_view
|
34
|
-
end
|
35
|
-
|
36
|
-
def move_to(line, column)
|
37
|
-
@line = line
|
38
|
-
@column = column
|
39
|
-
adjust_view
|
40
|
-
end
|
41
|
-
|
42
|
-
def move_to_line(line)
|
43
|
-
move_to(line, @column)
|
44
|
-
end
|
45
|
-
|
46
|
-
def move_to_column(column)
|
47
|
-
move_to(@line, column)
|
48
|
-
end
|
49
|
-
|
50
|
-
def move_to_eol
|
51
|
-
after_last_word = current_line.index(/\s*$/)
|
52
|
-
after_last_whitespace = current_line.size
|
53
|
-
|
54
|
-
if @column == after_last_whitespace or @column < after_last_word
|
55
|
-
move_to_column after_last_word
|
56
|
-
else
|
57
|
-
move_to_column after_last_whitespace
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def move_to_bol
|
62
|
-
before_first_word = current_line.index(/[^\s]/) || 0
|
63
|
-
if @column == 0 or @column > before_first_word
|
64
|
-
move_to_column before_first_word
|
65
|
-
else
|
66
|
-
move_to_column 0
|
67
|
-
end
|
68
12
|
end
|
69
13
|
|
70
14
|
def find(text)
|
71
|
-
index =
|
72
|
-
|
15
|
+
index = text_area.content.index(text, text_area.cursor_index+1) || text_area.cursor_index
|
16
|
+
move :to, *text_area.cursor_for_index(index)
|
73
17
|
end
|
74
18
|
|
19
|
+
def reset;end
|
20
|
+
|
75
21
|
def insert(text)
|
76
|
-
text = tabs_to_spaces(text)
|
77
|
-
insert_into_content cursor_index, text
|
78
|
-
move_according_to_insert(text)
|
79
22
|
@modified = true
|
23
|
+
text_area.insert(text)
|
80
24
|
end
|
81
25
|
|
82
|
-
def delete(
|
83
|
-
|
84
|
-
@content.slice!(cursor_index, count)
|
85
|
-
else
|
86
|
-
backspace(count.abs)
|
87
|
-
end
|
26
|
+
def delete(*args)
|
27
|
+
text_area.delete(*args)
|
88
28
|
@modified = true
|
89
29
|
end
|
90
30
|
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
31
|
+
def delete_line
|
32
|
+
old_cursor = cursor
|
33
|
+
move :to, cursor.line, 0
|
34
|
+
delete text_area.line_length
|
35
|
+
if cursor == [0,0]
|
36
|
+
delete(1)
|
37
|
+
else
|
38
|
+
delete(-1)
|
96
39
|
end
|
97
|
-
|
98
|
-
@content.slice!(start_index, count)
|
99
|
-
move_to *cursor_for_index(start_index)
|
100
|
-
@modified = true
|
101
|
-
end
|
102
|
-
|
103
|
-
def save
|
104
|
-
File.open(@file,'w'){|f| f.write(@content) }
|
105
|
-
@modified = false
|
106
|
-
end
|
107
|
-
|
108
|
-
def cursor
|
109
|
-
[cursor_line, cursor_column]
|
40
|
+
move :to, *old_cursor
|
110
41
|
end
|
111
42
|
|
112
43
|
def modified?
|
113
44
|
@modified
|
114
45
|
end
|
115
46
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
@content.naive_split("\n")
|
120
|
-
end
|
121
|
-
|
122
|
-
def adjust_view
|
123
|
-
@line = [[@line, 0].max, lines.size - 1].min
|
124
|
-
@column = [[@column, 0].max, (lines[@line]||'').size].min
|
125
|
-
reposition_cursor
|
126
|
-
scroll_column_into_view
|
127
|
-
scroll_line_into_view
|
128
|
-
reposition_cursor
|
129
|
-
end
|
130
|
-
|
131
|
-
def scroll_column_into_view
|
132
|
-
offset = [@options[:column_scrolling_offset], @options[:columns]].min
|
133
|
-
|
134
|
-
if @cursor_column >= @options[:columns]
|
135
|
-
@scrolled_columns = @column - @options[:columns] + offset
|
136
|
-
end
|
137
|
-
|
138
|
-
if @cursor_column < 0
|
139
|
-
@scrolled_columns = @column - offset
|
140
|
-
end
|
141
|
-
|
142
|
-
@scrolled_columns = [[@scrolled_columns, 0].max, @column].min
|
143
|
-
end
|
144
|
-
|
145
|
-
def scroll_line_into_view
|
146
|
-
offset = [@options[:line_scrolling_offset], @options[:lines]].min
|
147
|
-
|
148
|
-
if @cursor_line >= @options[:lines]
|
149
|
-
@scrolled_lines = @line - @options[:lines] + offset
|
150
|
-
end
|
151
|
-
|
152
|
-
if @cursor_line < 0
|
153
|
-
@scrolled_lines = @line - offset
|
154
|
-
end
|
155
|
-
|
156
|
-
@scrolled_lines = [[@scrolled_lines, 0].max, @line].min
|
157
|
-
end
|
158
|
-
|
159
|
-
def reposition_cursor
|
160
|
-
@cursor_column = @column - @scrolled_columns
|
161
|
-
@cursor_line = @line - @scrolled_lines
|
162
|
-
end
|
163
|
-
|
164
|
-
def insert_into_content(index, text)
|
165
|
-
# expand with newlines when inserting after maximum position
|
166
|
-
if index > @content.size
|
167
|
-
@content << "\n" * (index - @content.size)
|
168
|
-
end
|
169
|
-
@content.insert(index, text)
|
170
|
-
end
|
171
|
-
|
172
|
-
def current_line
|
173
|
-
lines[@line] || ''
|
174
|
-
end
|
175
|
-
|
176
|
-
def cursor_index
|
177
|
-
index = lines[0...@line].join("\n").size + @column
|
178
|
-
index += 1 if @line > 0 # account for missing newline
|
179
|
-
index
|
180
|
-
end
|
181
|
-
|
182
|
-
def cursor_for_index(index)
|
183
|
-
jump = @content.slice(0, index).to_s.naive_split("\n")
|
184
|
-
[jump.size - 1, jump.last.size]
|
47
|
+
def save
|
48
|
+
File.open(@file,'w'){|f| f.write(text_area.content) }
|
49
|
+
@modified = false
|
185
50
|
end
|
186
51
|
|
187
|
-
|
188
|
-
inserted_lines = text.naive_split("\n")
|
189
|
-
if inserted_lines.size > 1
|
190
|
-
# column position does not add up when hitting return
|
191
|
-
@column = inserted_lines.last.size
|
192
|
-
move(inserted_lines.size - 1, 0)
|
193
|
-
else
|
194
|
-
move(inserted_lines.size - 1, inserted_lines.last.size)
|
195
|
-
end
|
196
|
-
end
|
52
|
+
private
|
197
53
|
|
198
|
-
|
199
|
-
text.gsub("\t",' ' * Ruco::TAB_SIZE)
|
200
|
-
end
|
54
|
+
attr_reader :text_area
|
201
55
|
end
|
202
56
|
end
|
data/lib/ruco/form.rb
CHANGED
@@ -2,9 +2,10 @@ module Ruco
|
|
2
2
|
class Form
|
3
3
|
delegate :move, :delete, :to => :text_field
|
4
4
|
|
5
|
-
def initialize(label, options)
|
5
|
+
def initialize(label, options, &submit)
|
6
6
|
@options = options
|
7
7
|
@label = label.strip + ' '
|
8
|
+
@submit = submit
|
8
9
|
reset
|
9
10
|
end
|
10
11
|
|
@@ -17,12 +18,12 @@ module Ruco
|
|
17
18
|
if text.include?("\n")
|
18
19
|
result = @text_field.value
|
19
20
|
result = result.to_i if @options[:type] == :integer
|
20
|
-
|
21
|
+
@submit.call(result)
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
24
25
|
def cursor
|
25
|
-
|
26
|
+
Cursor.new 0, @label.size + @text_field.cursor.column
|
26
27
|
end
|
27
28
|
|
28
29
|
def reset
|
@@ -0,0 +1,181 @@
|
|
1
|
+
module Ruco
|
2
|
+
class TextArea
|
3
|
+
attr_reader :content
|
4
|
+
|
5
|
+
def initialize(content, options)
|
6
|
+
@content = tabs_to_spaces(content)
|
7
|
+
@options = options
|
8
|
+
@line = 0
|
9
|
+
@column = 0
|
10
|
+
@cursor_line = 0
|
11
|
+
@cursor_column = 0
|
12
|
+
@scrolled_lines = 0
|
13
|
+
@scrolled_columns = 0
|
14
|
+
@options[:line_scrolling_offset] ||= @options[:lines] / 2
|
15
|
+
@options[:column_scrolling_offset] ||= @options[:columns] / 2
|
16
|
+
end
|
17
|
+
|
18
|
+
def view
|
19
|
+
Array.new(@options[:lines]).map_with_index do |_,i|
|
20
|
+
(lines[i + @scrolled_lines] || "").slice(@scrolled_columns, @options[:columns])
|
21
|
+
end * "\n" + "\n"
|
22
|
+
end
|
23
|
+
|
24
|
+
def move(where, *args)
|
25
|
+
case where
|
26
|
+
when :relative then
|
27
|
+
@line += args.first
|
28
|
+
@column += args.last
|
29
|
+
when :to then
|
30
|
+
@line, @column = args
|
31
|
+
when :to_bol then move_to_bol(*args)
|
32
|
+
when :to_eol then move_to_eol(*args)
|
33
|
+
when :to_line then @line = args.first
|
34
|
+
when :to_column then @column = args.first
|
35
|
+
else
|
36
|
+
raise "Unknown move type #{where} with #{args.inspect}"
|
37
|
+
end
|
38
|
+
adjust_view
|
39
|
+
end
|
40
|
+
|
41
|
+
def insert(text)
|
42
|
+
text = tabs_to_spaces(text)
|
43
|
+
insert_into_content cursor_index, text
|
44
|
+
move_according_to_insert(text)
|
45
|
+
end
|
46
|
+
|
47
|
+
def delete(count)
|
48
|
+
if count > 0
|
49
|
+
@content.slice!(cursor_index, count)
|
50
|
+
else
|
51
|
+
backspace(count.abs)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def cursor
|
56
|
+
Cursor.new @cursor_line, @cursor_column
|
57
|
+
end
|
58
|
+
|
59
|
+
def cursor_index
|
60
|
+
index = lines[0...@line].join("\n").size + @column
|
61
|
+
index += 1 if @line > 0 # account for missing newline
|
62
|
+
index
|
63
|
+
end
|
64
|
+
|
65
|
+
def cursor_for_index(index)
|
66
|
+
jump = @content.slice(0, index).to_s.naive_split("\n")
|
67
|
+
[jump.size - 1, jump.last.size]
|
68
|
+
end
|
69
|
+
|
70
|
+
def line_length
|
71
|
+
lines[@line].size
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def move_to_eol
|
77
|
+
after_last_word = current_line.index(/\s*$/)
|
78
|
+
after_last_whitespace = current_line.size
|
79
|
+
|
80
|
+
if @column == after_last_whitespace or @column < after_last_word
|
81
|
+
move :to_column, after_last_word
|
82
|
+
else
|
83
|
+
move :to_column, after_last_whitespace
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def move_to_bol
|
88
|
+
before_first_word = current_line.index(/[^\s]/) || 0
|
89
|
+
column = if @column == 0 or @column > before_first_word
|
90
|
+
before_first_word
|
91
|
+
else
|
92
|
+
0
|
93
|
+
end
|
94
|
+
move :to_column, column
|
95
|
+
end
|
96
|
+
|
97
|
+
def backspace(count)
|
98
|
+
start_index = cursor_index - count
|
99
|
+
if start_index < 0
|
100
|
+
count += start_index
|
101
|
+
start_index = 0
|
102
|
+
end
|
103
|
+
|
104
|
+
@content.slice!(start_index, count)
|
105
|
+
move :to, *cursor_for_index(start_index)
|
106
|
+
end
|
107
|
+
|
108
|
+
def lines
|
109
|
+
@content.naive_split("\n")
|
110
|
+
end
|
111
|
+
|
112
|
+
def adjust_view
|
113
|
+
@line = [[@line, 0].max, lines.size - 1].min
|
114
|
+
@column = [[@column, 0].max, (lines[@line]||'').size].min
|
115
|
+
reposition_cursor
|
116
|
+
scroll_column_into_view
|
117
|
+
scroll_line_into_view
|
118
|
+
reposition_cursor
|
119
|
+
end
|
120
|
+
|
121
|
+
def scroll_column_into_view
|
122
|
+
offset = [@options[:column_scrolling_offset], @options[:columns]].min
|
123
|
+
|
124
|
+
if @cursor_column >= @options[:columns]
|
125
|
+
@scrolled_columns = @column - @options[:columns] + offset
|
126
|
+
end
|
127
|
+
|
128
|
+
if @cursor_column < 0
|
129
|
+
@scrolled_columns = @column - offset
|
130
|
+
end
|
131
|
+
|
132
|
+
@scrolled_columns = [[@scrolled_columns, 0].max, @column].min
|
133
|
+
end
|
134
|
+
|
135
|
+
def scroll_line_into_view
|
136
|
+
offset = [@options[:line_scrolling_offset], @options[:lines]].min
|
137
|
+
|
138
|
+
if @cursor_line >= @options[:lines]
|
139
|
+
@scrolled_lines = @line - @options[:lines] + offset
|
140
|
+
end
|
141
|
+
|
142
|
+
if @cursor_line < 0
|
143
|
+
@scrolled_lines = @line - offset
|
144
|
+
end
|
145
|
+
|
146
|
+
@scrolled_lines = [[@scrolled_lines, 0].max, @line].min
|
147
|
+
end
|
148
|
+
|
149
|
+
def reposition_cursor
|
150
|
+
@cursor_column = @column - @scrolled_columns
|
151
|
+
@cursor_line = @line - @scrolled_lines
|
152
|
+
end
|
153
|
+
|
154
|
+
def insert_into_content(index, text)
|
155
|
+
# expand with newlines when inserting after maximum position
|
156
|
+
if index > @content.size
|
157
|
+
@content << "\n" * (index - @content.size)
|
158
|
+
end
|
159
|
+
@content.insert(index, text)
|
160
|
+
end
|
161
|
+
|
162
|
+
def current_line
|
163
|
+
lines[@line] || ''
|
164
|
+
end
|
165
|
+
|
166
|
+
def move_according_to_insert(text)
|
167
|
+
inserted_lines = text.naive_split("\n")
|
168
|
+
if inserted_lines.size > 1
|
169
|
+
# column position does not add up when hitting return
|
170
|
+
@column = inserted_lines.last.size
|
171
|
+
move(:relative, inserted_lines.size - 1, 0)
|
172
|
+
else
|
173
|
+
move(:relative, inserted_lines.size - 1, inserted_lines.last.size)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def tabs_to_spaces(text)
|
178
|
+
text.gsub("\t",' ' * Ruco::TAB_SIZE)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
data/lib/ruco/text_field.rb
CHANGED
@@ -1,40 +1,15 @@
|
|
1
1
|
module Ruco
|
2
|
-
class TextField
|
2
|
+
class TextField < TextArea
|
3
3
|
def initialize(options)
|
4
|
-
|
5
|
-
@content = ''
|
6
|
-
@column = 0
|
7
|
-
end
|
8
|
-
|
9
|
-
def insert(text)
|
10
|
-
@content += text
|
11
|
-
move(0, text.size)
|
12
|
-
end
|
13
|
-
|
14
|
-
def delete(count)
|
15
|
-
if count > 0
|
16
|
-
@content.slice!(@column, count)
|
17
|
-
else
|
18
|
-
delete_start = [@column - count.abs, 0].max
|
19
|
-
@content[delete_start...@column] = ''
|
20
|
-
@column = delete_start
|
21
|
-
end
|
4
|
+
super('', options.merge(:lines => 1))
|
22
5
|
end
|
23
6
|
|
24
7
|
def view
|
25
|
-
|
8
|
+
super.gsub("\n",'')
|
26
9
|
end
|
27
10
|
|
28
11
|
def value
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
def move(line, column)
|
33
|
-
@column = [[@column + column, 0].max, @content.size].min
|
34
|
-
end
|
35
|
-
|
36
|
-
def cursor
|
37
|
-
[0, @column]
|
12
|
+
content.gsub("\n",'')
|
38
13
|
end
|
39
14
|
end
|
40
15
|
end
|
data/ruco.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ruco}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Michael Grosser"]
|
12
|
-
s.date = %q{2011-01-
|
12
|
+
s.date = %q{2011-01-11}
|
13
13
|
s.default_executable = %q{ruco}
|
14
14
|
s.email = %q{michael@grosser.it}
|
15
15
|
s.executables = ["ruco"]
|
@@ -26,10 +26,11 @@ Gem::Specification.new do |s|
|
|
26
26
|
"lib/ruco/core_ext/array.rb",
|
27
27
|
"lib/ruco/core_ext/object.rb",
|
28
28
|
"lib/ruco/core_ext/string.rb",
|
29
|
+
"lib/ruco/cursor.rb",
|
29
30
|
"lib/ruco/editor.rb",
|
30
|
-
"lib/ruco/focusable.rb",
|
31
31
|
"lib/ruco/form.rb",
|
32
32
|
"lib/ruco/status_bar.rb",
|
33
|
+
"lib/ruco/text_area.rb",
|
33
34
|
"lib/ruco/text_field.rb",
|
34
35
|
"ruco.gemspec",
|
35
36
|
"spec/ruco/command_bar_spec.rb",
|
@@ -1,15 +1,16 @@
|
|
1
1
|
require File.expand_path('spec/spec_helper')
|
2
2
|
|
3
3
|
describe Ruco::CommandBar do
|
4
|
+
let(:default_view){ "^W Exit ^S Save ^F Find" }
|
4
5
|
let(:bar){ Ruco::CommandBar.new(:columns => 30) }
|
5
6
|
|
6
7
|
it "shows shortcuts by default" do
|
7
|
-
bar.view.should ==
|
8
|
+
bar.view.should == default_view
|
8
9
|
end
|
9
10
|
|
10
11
|
it "shows less shortcuts when space is low" do
|
11
12
|
bar = Ruco::CommandBar.new(:columns => 29)
|
12
|
-
bar.view.should ==
|
13
|
+
bar.view.should == default_view
|
13
14
|
bar = Ruco::CommandBar.new(:columns => 28)
|
14
15
|
bar.view.should == "^W Exit ^S Save"
|
15
16
|
end
|
@@ -18,14 +19,14 @@ describe Ruco::CommandBar do
|
|
18
19
|
it "sets command bar into search mode" do
|
19
20
|
bar.find
|
20
21
|
bar.view.should == "Find: "
|
21
|
-
bar.
|
22
|
+
bar.cursor.column.should == 6
|
22
23
|
end
|
23
24
|
|
24
25
|
it "can enter stuff" do
|
25
26
|
bar.find
|
26
27
|
bar.insert('abc')
|
27
28
|
bar.view.should == "Find: abc"
|
28
|
-
bar.
|
29
|
+
bar.cursor.column.should == 9
|
29
30
|
end
|
30
31
|
|
31
32
|
it "keeps entered stuff" do
|
@@ -33,7 +34,7 @@ describe Ruco::CommandBar do
|
|
33
34
|
bar.insert('abc')
|
34
35
|
bar.find
|
35
36
|
bar.view.should == "Find: abc"
|
36
|
-
bar.
|
37
|
+
bar.cursor.column.should == 9
|
37
38
|
end
|
38
39
|
|
39
40
|
it "can reset the search" do
|
@@ -42,7 +43,7 @@ describe Ruco::CommandBar do
|
|
42
43
|
bar.insert("\n")
|
43
44
|
bar.reset
|
44
45
|
|
45
|
-
bar.view.should
|
46
|
+
bar.view.should == default_view
|
46
47
|
bar.find
|
47
48
|
bar.view.should == "Find: " # term removed
|
48
49
|
end
|
@@ -73,23 +74,29 @@ describe Ruco::CommandBar do
|
|
73
74
|
bar.move_to_line
|
74
75
|
bar.insert('123')
|
75
76
|
result = bar.insert("\n")
|
76
|
-
result.should == Ruco::Command.new(:
|
77
|
+
result.should == Ruco::Command.new(:move, :to_line, 123)
|
77
78
|
end
|
78
79
|
|
79
|
-
it "gets reset" do
|
80
|
+
it "gets reset when starting a new go to line" do
|
80
81
|
bar.move_to_line
|
81
82
|
bar.insert('123')
|
82
83
|
bar.move_to_line
|
83
84
|
bar.view.should == "Go to Line: "
|
84
85
|
end
|
85
86
|
|
87
|
+
it "gets reset when submitting" do
|
88
|
+
bar.move_to_line
|
89
|
+
bar.insert("123\n")
|
90
|
+
bar.view.should == default_view
|
91
|
+
end
|
92
|
+
|
86
93
|
it "does not reset search when resetting" do
|
87
94
|
bar.find
|
88
95
|
bar.insert('abc')
|
89
96
|
bar.move_to_line
|
90
97
|
bar.reset
|
91
98
|
|
92
|
-
bar.view.should
|
99
|
+
bar.view.should == default_view
|
93
100
|
bar.find
|
94
101
|
bar.view.should == "Find: abc"
|
95
102
|
end
|
data/spec/ruco/editor_spec.rb
CHANGED
@@ -26,62 +26,62 @@ describe Ruco::Editor do
|
|
26
26
|
end
|
27
27
|
|
28
28
|
it "can move" do
|
29
|
-
editor.move(1,2)
|
29
|
+
editor.move(:relative, 1,2)
|
30
30
|
editor.cursor.should == [1,2]
|
31
|
-
editor.move(1,1)
|
31
|
+
editor.move(:relative, 1,1)
|
32
32
|
editor.cursor.should == [2,3]
|
33
33
|
end
|
34
34
|
|
35
35
|
it "can move in empty file" do
|
36
36
|
write("\n\n\n")
|
37
|
-
editor.move(2,0)
|
37
|
+
editor.move(:relative, 2,0)
|
38
38
|
editor.cursor.should == [2,0]
|
39
39
|
end
|
40
40
|
|
41
41
|
it "cannot move left/top off screen" do
|
42
|
-
editor.move(-1,-1)
|
42
|
+
editor.move(:relative, -1,-1)
|
43
43
|
editor.cursor.should == [0,0]
|
44
44
|
end
|
45
45
|
|
46
46
|
it "cannot move right of characters" do
|
47
|
-
editor.move(2,6)
|
47
|
+
editor.move(:relative, 2,6)
|
48
48
|
editor.cursor.should == [2,4]
|
49
49
|
end
|
50
50
|
|
51
51
|
it "stays in last line when moving past lines" do
|
52
52
|
write(" ")
|
53
|
-
editor.move(6,3)
|
53
|
+
editor.move(:relative, 6,3)
|
54
54
|
editor.cursor.should == [0,3]
|
55
55
|
end
|
56
56
|
|
57
57
|
describe 'column scrolling' do
|
58
58
|
it "can scroll columns" do
|
59
59
|
write("123456789\n123")
|
60
|
-
editor.move(0,4)
|
60
|
+
editor.move(:relative, 0,4)
|
61
61
|
editor.view.should == "12345\n123\n\n"
|
62
|
-
editor.
|
62
|
+
editor.cursor.column.should == 4
|
63
63
|
|
64
|
-
editor.move(0,1)
|
64
|
+
editor.move(:relative, 0,1)
|
65
65
|
editor.view.should == "6789\n\n\n"
|
66
|
-
editor.
|
66
|
+
editor.cursor.column.should == 0
|
67
67
|
end
|
68
68
|
|
69
69
|
it "cannot scroll past the screen" do
|
70
70
|
write('123456789')
|
71
|
-
editor.move(0,4)
|
72
|
-
6.times{ editor.move(0,1) }
|
71
|
+
editor.move(:relative, 0,4)
|
72
|
+
6.times{ editor.move(:relative, 0,1) }
|
73
73
|
editor.view.should == "6789\n\n\n"
|
74
|
-
editor.
|
74
|
+
editor.cursor.column.should == 4
|
75
75
|
end
|
76
76
|
|
77
77
|
it "can scroll columns backwards" do
|
78
78
|
write('123456789')
|
79
|
-
editor.move(0,5)
|
79
|
+
editor.move(:relative, 0,5)
|
80
80
|
editor.view.should == "6789\n\n\n"
|
81
81
|
|
82
|
-
editor.move(0,-1)
|
82
|
+
editor.move(:relative, 0,-1)
|
83
83
|
editor.view.should == "12345\n\n\n"
|
84
|
-
editor.
|
84
|
+
editor.cursor.column.should == 4
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
@@ -91,119 +91,96 @@ describe Ruco::Editor do
|
|
91
91
|
end
|
92
92
|
|
93
93
|
it "can scroll lines down (at maximum of screen size)" do
|
94
|
-
editor.move(2,0)
|
94
|
+
editor.move(:relative, 2,0)
|
95
95
|
editor.view.should == "1\n2\n3\n"
|
96
96
|
|
97
|
-
editor.move(1,0)
|
97
|
+
editor.move(:relative, 1,0)
|
98
98
|
editor.view.should == "4\n5\n6\n"
|
99
|
-
editor.
|
99
|
+
editor.cursor.line.should == 0
|
100
100
|
end
|
101
101
|
|
102
102
|
it "can scroll till end of file" do
|
103
|
-
editor.move(15,0)
|
103
|
+
editor.move(:relative, 15,0)
|
104
104
|
editor.view.should == "9\n\n\n"
|
105
|
-
editor.
|
105
|
+
editor.cursor.line.should == 0
|
106
106
|
end
|
107
107
|
end
|
108
|
-
end
|
109
|
-
|
110
|
-
describe :move_to do
|
111
|
-
it "cannot move outside of text (bottom/right)" do
|
112
|
-
write("123\n456")
|
113
|
-
editor.move_to(10,10)
|
114
|
-
editor.cursor.should == [1,3]
|
115
|
-
end
|
116
|
-
|
117
|
-
it "cannot move outside of text (top/left)" do
|
118
|
-
write("123\n456")
|
119
|
-
editor.move(1,1)
|
120
|
-
editor.move_to(-10,-10)
|
121
|
-
editor.cursor.should == [0,0]
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
describe :move_to_eol do
|
126
|
-
before do
|
127
|
-
write("\n aa \n ")
|
128
|
-
end
|
129
108
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
109
|
+
describe :to do
|
110
|
+
it "cannot move outside of text (bottom/right)" do
|
111
|
+
write("123\n456")
|
112
|
+
editor.move(:to, 10,10)
|
113
|
+
editor.cursor.should == [1,3]
|
114
|
+
end
|
134
115
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
116
|
+
it "cannot move outside of text (top/left)" do
|
117
|
+
write("123\n456")
|
118
|
+
editor.move(:relative, 1,1)
|
119
|
+
editor.move(:to, -10,-10)
|
120
|
+
editor.cursor.should == [0,0]
|
121
|
+
end
|
139
122
|
end
|
140
123
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
end
|
124
|
+
describe :to_eol do
|
125
|
+
before do
|
126
|
+
write("\n aa \n ")
|
127
|
+
end
|
146
128
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
end
|
152
|
-
end
|
129
|
+
it 'stays at start when line is empty' do
|
130
|
+
editor.move :to_eol
|
131
|
+
editor.cursor.should == [0,0]
|
132
|
+
end
|
153
133
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
134
|
+
it 'moves after last word if cursor was before it' do
|
135
|
+
editor.move(:relative, 1,1)
|
136
|
+
editor.move :to_eol
|
137
|
+
editor.cursor.should == [1,3]
|
138
|
+
end
|
158
139
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
140
|
+
it 'moves after last whitespace if cursor was after last word' do
|
141
|
+
editor.move(:relative, 1,3)
|
142
|
+
editor.move :to_eol
|
143
|
+
editor.cursor.should == [1,4]
|
144
|
+
end
|
163
145
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
146
|
+
it 'moves after last work if cursor was after last whitespace' do
|
147
|
+
editor.move(:relative, 1,4)
|
148
|
+
editor.move :to_eol
|
149
|
+
editor.cursor.should == [1,3]
|
150
|
+
end
|
168
151
|
end
|
169
152
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
editor.move(0,2)
|
176
|
-
editor.move_to_bol
|
177
|
-
editor.cursor.should == [1,0]
|
178
|
-
end
|
153
|
+
describe :to_bol do
|
154
|
+
before do
|
155
|
+
write("\n aa \n ")
|
156
|
+
end
|
179
157
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
end
|
185
|
-
end
|
158
|
+
it 'stays at start when line is empty' do
|
159
|
+
editor.move :to_bol
|
160
|
+
editor.cursor.should == [0,0]
|
161
|
+
end
|
186
162
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
163
|
+
it 'moves before first work if at start of line' do
|
164
|
+
editor.move(:relative, 1,0)
|
165
|
+
editor.move :to_bol
|
166
|
+
editor.cursor.should == [1,2]
|
167
|
+
end
|
191
168
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
169
|
+
it 'moves to start of line if before first word' do
|
170
|
+
editor.move(:relative, 1,1)
|
171
|
+
editor.move :to_bol
|
172
|
+
editor.cursor.should == [1,0]
|
196
173
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
end
|
174
|
+
editor.move(:relative, 0,2)
|
175
|
+
editor.move :to_bol
|
176
|
+
editor.cursor.should == [1,0]
|
177
|
+
end
|
202
178
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
179
|
+
it 'moves before first word if inside line' do
|
180
|
+
editor.move(:relative, 1,5)
|
181
|
+
editor.move :to_bol
|
182
|
+
editor.cursor.should == [1,2]
|
183
|
+
end
|
207
184
|
end
|
208
185
|
end
|
209
186
|
|
@@ -239,7 +216,7 @@ describe Ruco::Editor do
|
|
239
216
|
|
240
217
|
it "can insert new chars" do
|
241
218
|
write('123')
|
242
|
-
editor.move(0,1)
|
219
|
+
editor.move(:relative, 0,1)
|
243
220
|
editor.insert('ab')
|
244
221
|
editor.view.should == "1ab23\n\n\n"
|
245
222
|
editor.cursor.should == [0,3]
|
@@ -253,7 +230,7 @@ describe Ruco::Editor do
|
|
253
230
|
|
254
231
|
it "jumps to correct column when inserting newline" do
|
255
232
|
write("abc\ndefg")
|
256
|
-
editor.move(1,2)
|
233
|
+
editor.move(:relative, 1,2)
|
257
234
|
editor.insert("1\n23")
|
258
235
|
editor.view.should == "abc\nde1\n23fg\n"
|
259
236
|
editor.cursor.should == [2,2]
|
@@ -261,7 +238,7 @@ describe Ruco::Editor do
|
|
261
238
|
|
262
239
|
it "jumps to correct column when inserting 1 newline" do
|
263
240
|
write("abc\ndefg")
|
264
|
-
editor.move(1,2)
|
241
|
+
editor.move(:relative, 1,2)
|
265
242
|
editor.insert("\n")
|
266
243
|
editor.view.should == "abc\nde\nfg\n"
|
267
244
|
editor.cursor.should == [2,0]
|
@@ -276,7 +253,7 @@ describe Ruco::Editor do
|
|
276
253
|
|
277
254
|
it "can add newlines to the moveable end" do
|
278
255
|
write('abc')
|
279
|
-
editor.move(0,3)
|
256
|
+
editor.move(:relative, 0,3)
|
280
257
|
editor.insert("\n")
|
281
258
|
editor.insert("\n")
|
282
259
|
editor.cursor.should == [2,0]
|
@@ -315,7 +292,7 @@ describe Ruco::Editor do
|
|
315
292
|
|
316
293
|
it 'removes a line' do
|
317
294
|
write("123\n45")
|
318
|
-
editor.move(0,3)
|
295
|
+
editor.move(:relative, 0,3)
|
319
296
|
editor.delete(1)
|
320
297
|
editor.view.should == "12345\n\n\n"
|
321
298
|
editor.cursor.should == [0,3]
|
@@ -323,7 +300,7 @@ describe Ruco::Editor do
|
|
323
300
|
|
324
301
|
it "cannot backspace over 0,0" do
|
325
302
|
write("aa")
|
326
|
-
editor.move(0,1)
|
303
|
+
editor.move(:relative, 0,1)
|
327
304
|
editor.delete(-3)
|
328
305
|
editor.view.should == "a\n\n\n"
|
329
306
|
editor.cursor.should == [0,0]
|
@@ -331,7 +308,7 @@ describe Ruco::Editor do
|
|
331
308
|
|
332
309
|
it 'backspaces a char' do
|
333
310
|
write('123')
|
334
|
-
editor.move(0,3)
|
311
|
+
editor.move(:relative, 0,3)
|
335
312
|
editor.delete(-1)
|
336
313
|
editor.view.should == "12\n\n\n"
|
337
314
|
editor.cursor.should == [0,2]
|
@@ -339,7 +316,7 @@ describe Ruco::Editor do
|
|
339
316
|
|
340
317
|
it 'backspaces a newline' do
|
341
318
|
write("1\n234")
|
342
|
-
editor.move(1,0)
|
319
|
+
editor.move(:relative, 1,0)
|
343
320
|
editor.delete(-1)
|
344
321
|
editor.view.should == "1234\n\n\n"
|
345
322
|
editor.cursor.should == [0,1]
|
@@ -362,7 +339,7 @@ describe Ruco::Editor do
|
|
362
339
|
end
|
363
340
|
|
364
341
|
it "is not changed after move" do
|
365
|
-
editor.move(1,1)
|
342
|
+
editor.move(:relative, 1,1)
|
366
343
|
editor.modified?.should == false
|
367
344
|
end
|
368
345
|
|
@@ -372,4 +349,75 @@ describe Ruco::Editor do
|
|
372
349
|
editor.modified?.should == false
|
373
350
|
end
|
374
351
|
end
|
352
|
+
|
353
|
+
describe :find do
|
354
|
+
before do
|
355
|
+
write("\n ab\n ab")
|
356
|
+
end
|
357
|
+
|
358
|
+
it "moves to first occurrence" do
|
359
|
+
editor.find('ab')
|
360
|
+
editor.cursor.should == [1,1]
|
361
|
+
end
|
362
|
+
|
363
|
+
it "moves to next occurrence" do
|
364
|
+
editor.move(:relative, 1,1)
|
365
|
+
editor.find('ab')
|
366
|
+
editor.cursor.should == [2,1]
|
367
|
+
end
|
368
|
+
|
369
|
+
it "stays in place when nothing was found" do
|
370
|
+
editor.move(:relative, 2,1)
|
371
|
+
editor.find('ab')
|
372
|
+
editor.cursor.should == [2,1]
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
describe :delete_line do
|
377
|
+
before do
|
378
|
+
write("1\nlonger_than_columns\n56789")
|
379
|
+
end
|
380
|
+
|
381
|
+
it "removes the current line from first char" do
|
382
|
+
editor.move(:to, 1, 0)
|
383
|
+
editor.delete_line
|
384
|
+
editor.view.should == "1\n56789\n\n"
|
385
|
+
editor.cursor.should == [1, 0]
|
386
|
+
end
|
387
|
+
|
388
|
+
it "removes the current line from last char" do
|
389
|
+
editor.move(:to, 1, 3)
|
390
|
+
editor.delete_line
|
391
|
+
editor.view.should == "1\n56789\n\n"
|
392
|
+
editor.cursor.should == [1, 3]
|
393
|
+
end
|
394
|
+
|
395
|
+
it "can remove the first line" do
|
396
|
+
editor.delete_line
|
397
|
+
editor.view.should == "longe\n56789\n\n"
|
398
|
+
editor.cursor.should == [0, 0]
|
399
|
+
end
|
400
|
+
|
401
|
+
it "can remove the last line" do
|
402
|
+
write("aaa")
|
403
|
+
editor.delete_line
|
404
|
+
editor.view.should == "\n\n\n"
|
405
|
+
editor.cursor.should == [0, 0]
|
406
|
+
end
|
407
|
+
|
408
|
+
it "can remove the last line with lines remaining" do
|
409
|
+
write("aaa\nbbb")
|
410
|
+
editor.move(:to, 1,1)
|
411
|
+
editor.delete_line
|
412
|
+
editor.view.should == "aaa\n\n\n"
|
413
|
+
editor.cursor.should == [0, 1]
|
414
|
+
end
|
415
|
+
|
416
|
+
it "jumps to end of next lines end when put of space" do
|
417
|
+
write("1\n234\n5")
|
418
|
+
editor.move(:to, 1, 3)
|
419
|
+
editor.delete_line
|
420
|
+
editor.cursor.should == [1, 1]
|
421
|
+
end
|
422
|
+
end
|
375
423
|
end
|
data/spec/ruco/form_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.expand_path('spec/spec_helper')
|
2
2
|
|
3
3
|
describe Ruco::Form do
|
4
|
-
let(:form){ Ruco::Form.new('Test', :columns => 30
|
4
|
+
let(:form){ Ruco::Form.new('Test', :columns => 30){|value| Ruco::Command.new(:find, value) } }
|
5
5
|
|
6
6
|
it "positions cursor in text field" do
|
7
7
|
form.cursor.should == [0, 5]
|
@@ -26,20 +26,20 @@ describe Ruco::Form do
|
|
26
26
|
describe :move do
|
27
27
|
it "moves in text-field" do
|
28
28
|
form.insert('abc')
|
29
|
-
form.move(0, -1)
|
29
|
+
form.move(:relative, 0, -1)
|
30
30
|
form.cursor.should == [0,7]
|
31
31
|
end
|
32
32
|
|
33
33
|
it "cannot move out of left side" do
|
34
|
-
form.move(0, -3)
|
34
|
+
form.move(:relative, 0, -3)
|
35
35
|
form.cursor.should == [0,5]
|
36
36
|
end
|
37
37
|
|
38
38
|
it "cannot move out of right side" do
|
39
|
-
form.move(0, 4)
|
39
|
+
form.move(:relative, 0, 4)
|
40
40
|
form.cursor.should == [0,5]
|
41
41
|
form.insert('abc')
|
42
|
-
form.move(0, 4)
|
42
|
+
form.move(:relative, 0, 4)
|
43
43
|
form.cursor.should == [0,8]
|
44
44
|
end
|
45
45
|
end
|
@@ -47,21 +47,21 @@ describe Ruco::Form do
|
|
47
47
|
describe :delete do
|
48
48
|
it "removes characters forward" do
|
49
49
|
form.insert('abc')
|
50
|
-
form.move(0, -2)
|
50
|
+
form.move(:relative, 0, -2)
|
51
51
|
form.delete(1)
|
52
52
|
form.view.should == 'Test ac'
|
53
53
|
end
|
54
54
|
|
55
55
|
it "removes characters backward" do
|
56
56
|
form.insert('abc')
|
57
|
-
form.move(0, -1)
|
57
|
+
form.move(:relative, 0, -1)
|
58
58
|
form.delete(-1)
|
59
59
|
form.view.should == 'Test ac'
|
60
60
|
end
|
61
61
|
|
62
62
|
it "moves the cursor backward" do
|
63
63
|
form.insert('abc')
|
64
|
-
form.move(0, -1)
|
64
|
+
form.move(:relative, 0, -1)
|
65
65
|
form.delete(-1)
|
66
66
|
form.cursor.should == [0,6]
|
67
67
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruco
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 6
|
10
|
+
version: 0.0.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Michael Grosser
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-01-
|
18
|
+
date: 2011-01-11 00:00:00 +01:00
|
19
19
|
default_executable: ruco
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -40,10 +40,11 @@ files:
|
|
40
40
|
- lib/ruco/core_ext/array.rb
|
41
41
|
- lib/ruco/core_ext/object.rb
|
42
42
|
- lib/ruco/core_ext/string.rb
|
43
|
+
- lib/ruco/cursor.rb
|
43
44
|
- lib/ruco/editor.rb
|
44
|
-
- lib/ruco/focusable.rb
|
45
45
|
- lib/ruco/form.rb
|
46
46
|
- lib/ruco/status_bar.rb
|
47
|
+
- lib/ruco/text_area.rb
|
47
48
|
- lib/ruco/text_field.rb
|
48
49
|
- ruco.gemspec
|
49
50
|
- spec/ruco/command_bar_spec.rb
|