ruco 0.0.25 → 0.0.26
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.
- 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
|