ruco 0.0.25 → 0.0.26
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/ruco/editor.rb +13 -8
- data/lib/ruco/keyboard.rb +42 -29
- data/lib/ruco/text_area.rb +14 -17
- data/ruco.gemspec +4 -3
- data/spec/ruco/editor_spec.rb +10 -0
- metadata +8 -11
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.26
|
data/lib/ruco/editor.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
module Ruco
|
2
2
|
class Editor
|
3
3
|
attr_reader :file
|
4
|
-
|
4
|
+
attr_reader :text_area
|
5
|
+
private :text_area
|
6
|
+
delegate :view, :selection, :text_in_selection, :color_mask, :selecting, :move, :cursor, :resize, :to => :text_area
|
5
7
|
|
6
8
|
def initialize(file, options)
|
7
9
|
@file = file
|
@@ -11,15 +13,17 @@ module Ruco
|
|
11
13
|
end
|
12
14
|
|
13
15
|
def find(text)
|
14
|
-
|
15
|
-
|
16
|
+
return unless start = text_area.content.index(text, text_area.index_for_position+1)
|
17
|
+
finish = start + text.size
|
18
|
+
move(:to_index, finish)
|
19
|
+
selecting{ move(:to_index, start) }
|
16
20
|
end
|
17
21
|
|
18
22
|
def reset;end
|
19
23
|
|
20
24
|
def insert(text)
|
21
|
-
@modified = true
|
22
25
|
text_area.insert(text)
|
26
|
+
@modified = true
|
23
27
|
end
|
24
28
|
|
25
29
|
def delete(*args)
|
@@ -27,6 +31,11 @@ module Ruco
|
|
27
31
|
@modified = true
|
28
32
|
end
|
29
33
|
|
34
|
+
def delete_line(*args)
|
35
|
+
text_area.delete_line(*args)
|
36
|
+
@modified = true
|
37
|
+
end
|
38
|
+
|
30
39
|
def modified?
|
31
40
|
@modified
|
32
41
|
end
|
@@ -35,9 +44,5 @@ module Ruco
|
|
35
44
|
File.open(@file,'w'){|f| f.write(text_area.content) }
|
36
45
|
@modified = false
|
37
46
|
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
attr_reader :text_area
|
42
47
|
end
|
43
48
|
end
|
data/lib/ruco/keyboard.rb
CHANGED
@@ -13,28 +13,17 @@ class Keyboard
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.output
|
16
|
-
@sequence =
|
16
|
+
@sequence = []
|
17
17
|
@started = Time.now.to_f
|
18
18
|
|
19
19
|
loop do
|
20
20
|
key = fetch_user_input
|
21
21
|
if sequence_finished?
|
22
|
-
|
23
|
-
|
24
|
-
else
|
25
|
-
# weird stuff that happens when connected via ssh
|
26
|
-
if @sequence == [27, 91, 49, 59, 50, 65]
|
27
|
-
yield :"Shift+up"
|
28
|
-
elsif @sequence == [27, 91, 49, 59, 50, 66]
|
29
|
-
yield :"Shift+down"
|
30
|
-
else
|
31
|
-
bytes_to_key_codes(@sequence).each{|c| yield c }
|
32
|
-
end
|
33
|
-
end
|
34
|
-
@sequence = nil
|
22
|
+
sequence_to_keys(@sequence).each{|key| yield key }
|
23
|
+
@sequence = []
|
35
24
|
end
|
36
25
|
next unless key
|
37
|
-
|
26
|
+
append_to_sequence key
|
38
27
|
end
|
39
28
|
end
|
40
29
|
|
@@ -88,9 +77,8 @@ class Keyboard
|
|
88
77
|
key
|
89
78
|
end
|
90
79
|
|
91
|
-
def self.
|
80
|
+
def self.append_to_sequence(key)
|
92
81
|
@started = Time.now.to_f
|
93
|
-
@sequence ||= []
|
94
82
|
@sequence << key
|
95
83
|
end
|
96
84
|
|
@@ -101,26 +89,25 @@ class Keyboard
|
|
101
89
|
# split a text so fast-typers do not get bugs like ^B^C in output
|
102
90
|
def self.bytes_to_key_codes(bytes)
|
103
91
|
result = []
|
104
|
-
multi_byte =
|
92
|
+
multi_byte = []
|
93
|
+
|
94
|
+
append_multibyte = lambda{
|
95
|
+
unless multi_byte.empty?
|
96
|
+
result << bytes_to_string(multi_byte)
|
97
|
+
multi_byte = []
|
98
|
+
end
|
99
|
+
}
|
105
100
|
|
106
101
|
bytes.each do |byte|
|
107
102
|
if multi_byte_part?(byte)
|
108
|
-
multi_byte ||= []
|
109
103
|
multi_byte << byte
|
110
104
|
else
|
111
|
-
|
112
|
-
# finish multi-byte char
|
113
|
-
result << bytes_to_string(multi_byte)
|
114
|
-
multi_byte = nil
|
115
|
-
end
|
105
|
+
append_multibyte.call
|
116
106
|
result << translate_key_to_code(byte)
|
117
107
|
end
|
118
108
|
end
|
119
109
|
|
120
|
-
|
121
|
-
result << bytes_to_string(multi_byte)
|
122
|
-
end
|
123
|
-
|
110
|
+
append_multibyte.call
|
124
111
|
result
|
125
112
|
end
|
126
113
|
|
@@ -130,11 +117,37 @@ class Keyboard
|
|
130
117
|
end
|
131
118
|
|
132
119
|
def self.sequence_finished?
|
133
|
-
@sequence and (Time.now.to_f - @started) > SEQUENCE_TIMEOUT
|
120
|
+
@sequence.size != 0 and (Time.now.to_f - @started) > SEQUENCE_TIMEOUT
|
134
121
|
end
|
135
122
|
|
136
123
|
# paste of multiple \n or \n in text would cause weird indentation
|
137
124
|
def self.needs_paste_fix?(sequence)
|
138
125
|
sequence.size > 1 and sequence.include?(ENTER)
|
139
126
|
end
|
127
|
+
|
128
|
+
def self.sequence_to_keys(sequence)
|
129
|
+
if needs_paste_fix?(sequence)
|
130
|
+
[bytes_to_string(sequence)]
|
131
|
+
else
|
132
|
+
# weird stuff that happens when connected via ssh
|
133
|
+
if escape_sequence?(sequence)
|
134
|
+
[escape_sequence_to_key(sequence)]
|
135
|
+
else
|
136
|
+
bytes_to_key_codes(sequence)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def self.escape_sequence?(sequence)
|
142
|
+
sequence[0..1] == [27, 91] # Esc [
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.escape_sequence_to_key(sequence)
|
146
|
+
case sequence
|
147
|
+
when [27, 91, 49, 59, 50, 65] then :"Shift+up"
|
148
|
+
when [27, 91, 49, 59, 50, 66] then :"Shift+down"
|
149
|
+
else
|
150
|
+
bytes_to_string(sequence)
|
151
|
+
end
|
152
|
+
end
|
140
153
|
end
|
data/lib/ruco/text_area.rb
CHANGED
@@ -50,6 +50,7 @@ module Ruco
|
|
50
50
|
when :to_eol then move_to_eol(*args)
|
51
51
|
when :to_line then @line = args.first
|
52
52
|
when :to_column then @column = args.first
|
53
|
+
when :to_index then move(:to, *position_for_index(*args))
|
53
54
|
when :page_down then
|
54
55
|
shift = @options[:lines] - 1
|
55
56
|
@line += shift
|
@@ -111,7 +112,7 @@ module Ruco
|
|
111
112
|
current_line.slice!(@column, count)
|
112
113
|
else
|
113
114
|
with_lines_as_string do |content|
|
114
|
-
content.slice!(
|
115
|
+
content.slice!(index_for_position, count)
|
115
116
|
end
|
116
117
|
end
|
117
118
|
else
|
@@ -128,21 +129,12 @@ module Ruco
|
|
128
129
|
Cursor.new @cursor_line, @cursor_column
|
129
130
|
end
|
130
131
|
|
131
|
-
def
|
132
|
+
def index_for_position(line=@line, column=@column)
|
132
133
|
index = lines[0...line].join("\n").size + column
|
133
134
|
index += 1 if line > 0 # account for missing newline
|
134
135
|
index
|
135
136
|
end
|
136
137
|
|
137
|
-
def index_for_position(line, column)
|
138
|
-
cursor_index(line, column)
|
139
|
-
end
|
140
|
-
|
141
|
-
def position_for_index(index)
|
142
|
-
jump = content.slice(0, index).to_s.naive_split("\n")
|
143
|
-
[jump.size - 1, jump.last.size]
|
144
|
-
end
|
145
|
-
|
146
138
|
def content
|
147
139
|
(lines * "\n").freeze
|
148
140
|
end
|
@@ -154,6 +146,15 @@ module Ruco
|
|
154
146
|
|
155
147
|
protected
|
156
148
|
|
149
|
+
def position
|
150
|
+
Cursor.new(@line, @column)
|
151
|
+
end
|
152
|
+
|
153
|
+
def position_for_index(index)
|
154
|
+
jump = content.slice(0, index).to_s.naive_split("\n")
|
155
|
+
[jump.size - 1, jump.last.size]
|
156
|
+
end
|
157
|
+
|
157
158
|
def with_lines_as_string
|
158
159
|
string = @lines * "\n"
|
159
160
|
yield string
|
@@ -164,10 +165,6 @@ module Ruco
|
|
164
165
|
current_line.index(/\s*$/)
|
165
166
|
end
|
166
167
|
|
167
|
-
def position
|
168
|
-
[@line, @column]
|
169
|
-
end
|
170
|
-
|
171
168
|
def move_to_eol
|
172
169
|
after_last_whitespace = current_line.size
|
173
170
|
|
@@ -194,7 +191,7 @@ module Ruco
|
|
194
191
|
current_line.slice!(new_colum, count)
|
195
192
|
move :to_column, new_colum
|
196
193
|
else
|
197
|
-
start_index =
|
194
|
+
start_index = index_for_position - count
|
198
195
|
if start_index < 0
|
199
196
|
count += start_index
|
200
197
|
start_index = 0
|
@@ -253,7 +250,7 @@ module Ruco
|
|
253
250
|
def insert_into_content(text)
|
254
251
|
if text.include?("\n")
|
255
252
|
with_lines_as_string do |content|
|
256
|
-
content.insert(
|
253
|
+
content.insert(index_for_position, text)
|
257
254
|
end
|
258
255
|
else
|
259
256
|
# faster but complicated for newlines
|
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.26"
|
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-26}
|
13
13
|
s.default_executable = %q{ruco}
|
14
14
|
s.email = %q{michael@grosser.it}
|
15
15
|
s.executables = ["ruco"]
|
@@ -51,7 +51,7 @@ Gem::Specification.new do |s|
|
|
51
51
|
]
|
52
52
|
s.homepage = %q{http://github.com/grosser/ruco}
|
53
53
|
s.require_paths = ["lib"]
|
54
|
-
s.rubygems_version = %q{1.
|
54
|
+
s.rubygems_version = %q{1.3.7}
|
55
55
|
s.summary = %q{Commandline editor written in ruby}
|
56
56
|
s.test_files = [
|
57
57
|
"spec/ruco/application_spec.rb",
|
@@ -68,6 +68,7 @@ Gem::Specification.new do |s|
|
|
68
68
|
]
|
69
69
|
|
70
70
|
if s.respond_to? :specification_version then
|
71
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
71
72
|
s.specification_version = 3
|
72
73
|
|
73
74
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
data/spec/ruco/editor_spec.rb
CHANGED
@@ -536,6 +536,11 @@ describe Ruco::Editor do
|
|
536
536
|
editor.save
|
537
537
|
editor.modified?.should == false
|
538
538
|
end
|
539
|
+
|
540
|
+
it "is changed after delete_line" do
|
541
|
+
editor.delete_line
|
542
|
+
editor.modified?.should == true
|
543
|
+
end
|
539
544
|
end
|
540
545
|
|
541
546
|
describe :find do
|
@@ -559,6 +564,11 @@ describe Ruco::Editor do
|
|
559
564
|
editor.find('ab')
|
560
565
|
editor.cursor.should == [2,1]
|
561
566
|
end
|
567
|
+
|
568
|
+
it "selects the occurrence" do
|
569
|
+
editor.find('ab')
|
570
|
+
editor.selection.should == ([1, 1]..[1, 3])
|
571
|
+
end
|
562
572
|
end
|
563
573
|
|
564
574
|
describe :delete_line do
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruco
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
4
|
+
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 0
|
8
7
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
8
|
+
- 26
|
9
|
+
version: 0.0.26
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Michael Grosser
|
@@ -15,25 +14,24 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2011-01-
|
17
|
+
date: 2011-01-26 00:00:00 +01:00
|
19
18
|
default_executable: ruco
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
21
|
+
name: clipboard
|
22
22
|
requirement: &id001 !ruby/object:Gem::Requirement
|
23
23
|
none: false
|
24
24
|
requirements:
|
25
25
|
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
hash: 51
|
28
27
|
segments:
|
29
28
|
- 0
|
30
29
|
- 9
|
31
30
|
- 4
|
32
31
|
version: 0.9.4
|
32
|
+
type: :runtime
|
33
33
|
prerelease: false
|
34
34
|
version_requirements: *id001
|
35
|
-
type: :runtime
|
36
|
-
name: clipboard
|
37
35
|
description:
|
38
36
|
email: michael@grosser.it
|
39
37
|
executables:
|
@@ -91,7 +89,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
91
89
|
requirements:
|
92
90
|
- - ">="
|
93
91
|
- !ruby/object:Gem::Version
|
94
|
-
hash:
|
92
|
+
hash: -84268255
|
95
93
|
segments:
|
96
94
|
- 0
|
97
95
|
version: "0"
|
@@ -100,14 +98,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
98
|
requirements:
|
101
99
|
- - ">="
|
102
100
|
- !ruby/object:Gem::Version
|
103
|
-
hash: 3
|
104
101
|
segments:
|
105
102
|
- 0
|
106
103
|
version: "0"
|
107
104
|
requirements: []
|
108
105
|
|
109
106
|
rubyforge_project:
|
110
|
-
rubygems_version: 1.
|
107
|
+
rubygems_version: 1.3.7
|
111
108
|
signing_key:
|
112
109
|
specification_version: 3
|
113
110
|
summary: Commandline editor written in ruby
|