ruco 0.0.43 → 0.0.44
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/Readme.md +6 -0
- data/VERSION +1 -1
- data/lib/ruco.rb +1 -0
- data/lib/ruco/application.rb +17 -8
- data/lib/ruco/core_ext/hash.rb +5 -1
- data/lib/ruco/editor_area.rb +1 -1
- data/lib/ruco/keyboard.rb +21 -23
- data/lib/ruco/option_accessor.rb +25 -0
- data/lib/ruco/text_area.rb +2 -2
- data/ruco.gemspec +7 -3
- data/spec/ruco/application_spec.rb +32 -14
- data/spec/ruco/editor_spec.rb +6 -0
- data/spec/ruco/option_accessor_spec.rb +26 -0
- metadata +11 -11
data/Readme.md
CHANGED
@@ -26,6 +26,11 @@ Customize
|
|
26
26
|
|
27
27
|
# ~/.ruco.rb
|
28
28
|
Ruco.configure do
|
29
|
+
# set options
|
30
|
+
options.window_line_scroll_offset = 5 # default 1
|
31
|
+
options.history_entries = 10 # default 100
|
32
|
+
...
|
33
|
+
|
29
34
|
# bind a key
|
30
35
|
# - you can use Integers and Symbols
|
31
36
|
# - use "ruco --debug-keys foo" to see which keys are possible
|
@@ -65,6 +70,7 @@ TIPS
|
|
65
70
|
|
66
71
|
TODO
|
67
72
|
=====
|
73
|
+
- align soft-tabs
|
68
74
|
- strip whitespace after content / whitespace only lines, without removing intentional whitespace e.g. from markdown
|
69
75
|
- handle \\r and \\r\\n nicely <-> breaks curses output
|
70
76
|
- highlight tabs (e.g. strange character or reverse/underline/color)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.44
|
data/lib/ruco.rb
CHANGED
data/lib/ruco/application.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
module Ruco
|
2
2
|
class Application
|
3
|
+
attr_reader :editor, :status, :command, :options
|
4
|
+
|
3
5
|
def initialize(file, options)
|
4
6
|
@file = file
|
5
|
-
@options = options
|
7
|
+
@options = OptionAccessor.new(options)
|
6
8
|
|
7
9
|
setup_actions
|
8
10
|
setup_keys
|
@@ -123,8 +125,6 @@ module Ruco
|
|
123
125
|
|
124
126
|
private
|
125
127
|
|
126
|
-
attr_reader :editor, :status, :command
|
127
|
-
|
128
128
|
def setup_actions
|
129
129
|
@actions = {}
|
130
130
|
|
@@ -228,22 +228,31 @@ module Ruco
|
|
228
228
|
|
229
229
|
def load_user_config
|
230
230
|
Ruco.application = self
|
231
|
-
config = File.expand_path("~/.ruco.rb")
|
231
|
+
config = File.expand_path(@options[:rc] || "~/.ruco.rb")
|
232
232
|
load config if File.exist?(config)
|
233
233
|
end
|
234
234
|
|
235
235
|
def create_components
|
236
236
|
@status_lines = 1
|
237
|
-
|
238
|
-
|
239
|
-
|
237
|
+
|
238
|
+
editor_options = @options.slice(
|
239
|
+
:columns, :convert_tabs, :convert_newlines
|
240
|
+
).merge(
|
241
|
+
:window => @options.nested(:window),
|
242
|
+
:history => @options.nested(:history),
|
243
|
+
:lines => editor_lines
|
244
|
+
).merge(@options.nested(:editor))
|
245
|
+
|
246
|
+
@editor ||= Ruco::Editor.new(@file, editor_options)
|
247
|
+
@status = Ruco::StatusBar.new(@editor, @options.nested(:status_bar).merge(:columns => options[:columns]))
|
248
|
+
@command = Ruco::CommandBar.new(@options.nested(:command_bar).merge(:columns => options[:columns]))
|
240
249
|
command.cursor_line = editor_lines
|
241
250
|
@focused = @editor
|
242
251
|
end
|
243
252
|
|
244
253
|
def editor_lines
|
245
254
|
command_lines = 1
|
246
|
-
|
255
|
+
@options[:lines] - @status_lines - command_lines
|
247
256
|
end
|
248
257
|
end
|
249
258
|
end
|
data/lib/ruco/core_ext/hash.rb
CHANGED
data/lib/ruco/editor_area.rb
CHANGED
@@ -4,7 +4,7 @@ module Ruco
|
|
4
4
|
class EditorArea < TextArea
|
5
5
|
def initialize(*args)
|
6
6
|
super(*args)
|
7
|
-
@history = History.new(:state => state, :track => [:content], :entries => 100, :timeout => 2)
|
7
|
+
@history = History.new((args.last[:history]||{}).reverse_merge(:state => state, :track => [:content], :entries => 100, :timeout => 2))
|
8
8
|
end
|
9
9
|
|
10
10
|
def undo
|
data/lib/ruco/keyboard.rb
CHANGED
@@ -38,16 +38,16 @@ class Keyboard
|
|
38
38
|
when Curses::Key::DOWN then :down
|
39
39
|
when Curses::Key::RIGHT then :right
|
40
40
|
when Curses::Key::LEFT then :left
|
41
|
-
when
|
42
|
-
when
|
43
|
-
when 555 then :"Ctrl+Shift+right"
|
44
|
-
when
|
45
|
-
when
|
46
|
-
when 540 then :"Ctrl+Shift+left"
|
47
|
-
when
|
48
|
-
when
|
49
|
-
when
|
50
|
-
when
|
41
|
+
when 402, '^[1;2C' then :"Shift+right"
|
42
|
+
when 554, '^[1;5C' then :"Ctrl+right"
|
43
|
+
when 555, '^[1;6C' then :"Ctrl+Shift+right"
|
44
|
+
when 393, '^[1;2D' then :"Shift+left"
|
45
|
+
when 539, '^[1;5D' then :"Ctrl+left"
|
46
|
+
when 540, '^[1;6D' then :"Ctrl+Shift+left"
|
47
|
+
when 337, '^[1;2A' then :"Shift+up"
|
48
|
+
when 560, '^[1;5A' then :"Ctrl+up"
|
49
|
+
when 336, '^[1;2B' then :"Shift+down"
|
50
|
+
when 519, '^[1;5B' then :"Ctrl+down"
|
51
51
|
when Curses::KEY_END then :end
|
52
52
|
when Curses::KEY_HOME then :home
|
53
53
|
when Curses::KEY_NPAGE then :page_down
|
@@ -68,7 +68,13 @@ class Keyboard
|
|
68
68
|
when ESCAPE then :escape
|
69
69
|
when Curses::KEY_RESIZE then :resize
|
70
70
|
else
|
71
|
-
key
|
71
|
+
if key.is_a? Fixnum
|
72
|
+
key > MAX_CHAR ? key : key.chr
|
73
|
+
elsif is_alt_key_code?(key)
|
74
|
+
:"Alt+#{key.slice(1,1)}"
|
75
|
+
else
|
76
|
+
key
|
77
|
+
end
|
72
78
|
end
|
73
79
|
end
|
74
80
|
|
@@ -133,7 +139,8 @@ class Keyboard
|
|
133
139
|
else
|
134
140
|
# when connected via ssh escape sequences are used
|
135
141
|
if escape_sequence?(sequence)
|
136
|
-
|
142
|
+
stringified = bytes_to_string(sequence).sub("\e",'^').sub('[[','[')
|
143
|
+
[translate_key_to_code(stringified)]
|
137
144
|
else
|
138
145
|
bytes_to_key_codes(sequence)
|
139
146
|
end
|
@@ -144,16 +151,7 @@ class Keyboard
|
|
144
151
|
sequence[0] == ESCAPE and sequence.size.between?(2,6) # Esc
|
145
152
|
end
|
146
153
|
|
147
|
-
def self.
|
148
|
-
|
149
|
-
when [ESCAPE, 91, 49, 59, 50, 65] then :"Shift+up"
|
150
|
-
when [ESCAPE, 91, 49, 59, 50, 66] then :"Shift+down"
|
151
|
-
else
|
152
|
-
if sequence.size == 2
|
153
|
-
:"Alt+#{sequence[1].chr}"
|
154
|
-
else
|
155
|
-
bytes_to_string(sequence)
|
156
|
-
end
|
157
|
-
end
|
154
|
+
def self.is_alt_key_code?(key)
|
155
|
+
key.slice(0,1) == "^" and key.size == 2
|
158
156
|
end
|
159
157
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Ruco
|
2
|
+
# Can be used like a hash, but also allows .key access
|
3
|
+
class OptionAccessor
|
4
|
+
attr_reader :wrapped
|
5
|
+
delegate :[], :[]=, :slice, :to => :wrapped
|
6
|
+
|
7
|
+
def initialize(wrapped={})
|
8
|
+
@wrapped = wrapped
|
9
|
+
end
|
10
|
+
|
11
|
+
def nested(key)
|
12
|
+
Hash[wrapped.map do |k,v|
|
13
|
+
if k.to_s =~ /^#{key}_(.*)$/
|
14
|
+
[$1.to_sym,v]
|
15
|
+
end
|
16
|
+
end.compact]
|
17
|
+
end
|
18
|
+
|
19
|
+
def method_missing(method, *args)
|
20
|
+
base = method.to_s.sub('=','').to_sym
|
21
|
+
raise if args.size != 1
|
22
|
+
@wrapped[base] = args.first
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/ruco/text_area.rb
CHANGED
@@ -7,7 +7,7 @@ module Ruco
|
|
7
7
|
@options = options.dup
|
8
8
|
@column = 0
|
9
9
|
@line = 0
|
10
|
-
@window = Window.new(@options.delete(:lines), @options.delete(:columns))
|
10
|
+
@window = Window.new(@options.delete(:lines), @options.delete(:columns), @options[:window]||{})
|
11
11
|
adjust_window
|
12
12
|
end
|
13
13
|
|
@@ -80,7 +80,7 @@ module Ruco
|
|
80
80
|
delete_content_in_selection if @selection
|
81
81
|
|
82
82
|
text.tabs_to_spaces!
|
83
|
-
if text == "\n" and @column >=
|
83
|
+
if text == "\n" and @column >= current_line.leading_whitespace.size
|
84
84
|
current_whitespace = current_line.leading_whitespace
|
85
85
|
next_whitespace = lines[line+1].to_s.leading_whitespace
|
86
86
|
text = text + [current_whitespace, next_whitespace].max
|
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.44"
|
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-02-
|
12
|
+
s.date = %q{2011-02-09}
|
13
13
|
s.default_executable = %q{ruco}
|
14
14
|
s.email = %q{michael@grosser.it}
|
15
15
|
s.executables = ["ruco"]
|
@@ -35,6 +35,7 @@ Gem::Specification.new do |s|
|
|
35
35
|
"lib/ruco/form.rb",
|
36
36
|
"lib/ruco/history.rb",
|
37
37
|
"lib/ruco/keyboard.rb",
|
38
|
+
"lib/ruco/option_accessor.rb",
|
38
39
|
"lib/ruco/position.rb",
|
39
40
|
"lib/ruco/status_bar.rb",
|
40
41
|
"lib/ruco/style_map.rb",
|
@@ -52,6 +53,7 @@ Gem::Specification.new do |s|
|
|
52
53
|
"spec/ruco/form_spec.rb",
|
53
54
|
"spec/ruco/history_spec.rb",
|
54
55
|
"spec/ruco/keyboard_spec.rb",
|
56
|
+
"spec/ruco/option_accessor_spec.rb",
|
55
57
|
"spec/ruco/status_bar_spec.rb",
|
56
58
|
"spec/ruco/style_map_spec.rb",
|
57
59
|
"spec/ruco/text_area_spec.rb",
|
@@ -61,7 +63,7 @@ Gem::Specification.new do |s|
|
|
61
63
|
]
|
62
64
|
s.homepage = %q{http://github.com/grosser/ruco}
|
63
65
|
s.require_paths = ["lib"]
|
64
|
-
s.rubygems_version = %q{1.
|
66
|
+
s.rubygems_version = %q{1.3.7}
|
65
67
|
s.summary = %q{Commandline editor written in ruby}
|
66
68
|
s.test_files = [
|
67
69
|
"spec/ruco/application_spec.rb",
|
@@ -73,6 +75,7 @@ Gem::Specification.new do |s|
|
|
73
75
|
"spec/ruco/form_spec.rb",
|
74
76
|
"spec/ruco/history_spec.rb",
|
75
77
|
"spec/ruco/keyboard_spec.rb",
|
78
|
+
"spec/ruco/option_accessor_spec.rb",
|
76
79
|
"spec/ruco/status_bar_spec.rb",
|
77
80
|
"spec/ruco/style_map_spec.rb",
|
78
81
|
"spec/ruco/text_area_spec.rb",
|
@@ -82,6 +85,7 @@ Gem::Specification.new do |s|
|
|
82
85
|
]
|
83
86
|
|
84
87
|
if s.respond_to? :specification_version then
|
88
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
85
89
|
s.specification_version = 3
|
86
90
|
|
87
91
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
@@ -4,10 +4,15 @@ require File.expand_path('spec/spec_helper')
|
|
4
4
|
describe Ruco::Application do
|
5
5
|
before do
|
6
6
|
`rm -rf ~/.ruco/sessions`
|
7
|
+
`rm #{rucorc} 2>&1`
|
7
8
|
@file = 'spec/temp.txt'
|
8
9
|
write('')
|
9
10
|
end
|
10
11
|
|
12
|
+
after do
|
13
|
+
`rm #{rucorc} 2>&1`
|
14
|
+
end
|
15
|
+
|
11
16
|
def write(content)
|
12
17
|
File.open(@file,'w'){|f| f.write(content) }
|
13
18
|
end
|
@@ -24,7 +29,8 @@ describe Ruco::Application do
|
|
24
29
|
keys.each{|k| app.key k }
|
25
30
|
end
|
26
31
|
|
27
|
-
let(:
|
32
|
+
let(:rucorc){ 'spec/.ruco.rb' }
|
33
|
+
let(:app){ Ruco::Application.new(@file, :lines => 5, :columns => 10, :rc => rucorc) }
|
28
34
|
let(:status){ "Ruco #{Ruco::VERSION} -- spec/temp.txt \n" }
|
29
35
|
let(:command){ "^W Exit" }
|
30
36
|
|
@@ -239,12 +245,16 @@ describe Ruco::Application do
|
|
239
245
|
editor_part(app.view).should == "a\n c\n b"
|
240
246
|
end
|
241
247
|
|
242
|
-
it "
|
248
|
+
it "indents when inside line and next line has more whitespace" do
|
243
249
|
write("ab\n b\n")
|
244
|
-
|
245
|
-
app.
|
246
|
-
|
247
|
-
|
250
|
+
type :right, :enter, 'c'
|
251
|
+
editor_part(app.view).should == "a\n cb\n b"
|
252
|
+
end
|
253
|
+
|
254
|
+
it "indents when inside indented line" do
|
255
|
+
write(" ab\nc\n")
|
256
|
+
type :right, :right, :right, :enter, 'd'
|
257
|
+
editor_part(app.view).should == " a\n db\nc"
|
248
258
|
end
|
249
259
|
|
250
260
|
it "indents when tabbing on selection" do
|
@@ -262,19 +272,27 @@ describe Ruco::Application do
|
|
262
272
|
end
|
263
273
|
|
264
274
|
describe '.ruco.rb' do
|
265
|
-
around do |block|
|
266
|
-
rucorc = File.expand_path('~/.ruco.rb')
|
267
|
-
`mv #{rucorc} #{rucorc}.backup 2>&1`
|
268
|
-
File.write(rucorc, "Ruco.configure{ bind(:'Ctrl+e'){ @editor.insert('TEST') } }")
|
269
|
-
block.call
|
270
|
-
`rm #{rucorc} && mv #{rucorc}.backup #{rucorc} 2>&1`
|
271
|
-
end
|
272
|
-
|
273
275
|
it "loads it and can use the bound keys" do
|
276
|
+
File.write(rucorc, "Ruco.configure{ bind(:'Ctrl+e'){ @editor.insert('TEST') } }")
|
274
277
|
app.view.should_not include('TEST')
|
275
278
|
app.key(:"Ctrl+e")
|
276
279
|
app.view.should include("TEST")
|
277
280
|
end
|
281
|
+
|
282
|
+
it "uses settings" do
|
283
|
+
File.write(rucorc, "Ruco.configure{ options.convert_tabs = true }")
|
284
|
+
app.options[:convert_tabs].should == true
|
285
|
+
end
|
286
|
+
|
287
|
+
it "passes settings to the window" do
|
288
|
+
File.write(rucorc, "Ruco.configure{ options.window_line_scroll_offset = 10 }")
|
289
|
+
app.send(:editor).send(:text_area).instance_eval{@window}.instance_eval{@options[:line_scroll_offset]}.should == 10
|
290
|
+
end
|
291
|
+
|
292
|
+
it "passes settings to history" do
|
293
|
+
File.write(rucorc, "Ruco.configure{ options.history_entries = 10 }")
|
294
|
+
app.send(:editor).send(:text_area).instance_eval{@history}.instance_eval{@options[:entries]}.should == 10
|
295
|
+
end
|
278
296
|
end
|
279
297
|
|
280
298
|
describe :save do
|
data/spec/ruco/editor_spec.rb
CHANGED
@@ -517,6 +517,12 @@ describe Ruco::Editor do
|
|
517
517
|
editor.view.should == " \n\n\n"
|
518
518
|
editor.cursor.should == [0,2]
|
519
519
|
end
|
520
|
+
|
521
|
+
it "keeps indentation" do
|
522
|
+
write("ab\n cd")
|
523
|
+
editor.move(:to, 1,2)
|
524
|
+
editor.insert("\n")
|
525
|
+
end
|
520
526
|
end
|
521
527
|
|
522
528
|
describe :indent do
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.expand_path('spec/spec_helper')
|
2
|
+
|
3
|
+
describe Ruco::OptionAccessor do
|
4
|
+
let(:options){ Ruco::OptionAccessor.new }
|
5
|
+
|
6
|
+
it "can be accessed like a hash" do
|
7
|
+
options[:xx].should == nil
|
8
|
+
options[:xx] = 1
|
9
|
+
options[:xx].should == 1
|
10
|
+
end
|
11
|
+
|
12
|
+
it "can be written" do
|
13
|
+
options.foo = true
|
14
|
+
options[:foo].should == true
|
15
|
+
end
|
16
|
+
|
17
|
+
it "can access nested keys" do
|
18
|
+
options.foo_bar = 1
|
19
|
+
options.history_size = 1
|
20
|
+
options.nested(:history).should == {:size => 1}
|
21
|
+
end
|
22
|
+
|
23
|
+
it "has empty hash for nested key" do
|
24
|
+
options.nested(:history).should == {}
|
25
|
+
end
|
26
|
+
end
|
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
|
+
- 44
|
9
|
+
version: 0.0.44
|
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-02-
|
17
|
+
date: 2011-02-09 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:
|
@@ -64,6 +62,7 @@ files:
|
|
64
62
|
- lib/ruco/form.rb
|
65
63
|
- lib/ruco/history.rb
|
66
64
|
- lib/ruco/keyboard.rb
|
65
|
+
- lib/ruco/option_accessor.rb
|
67
66
|
- lib/ruco/position.rb
|
68
67
|
- lib/ruco/status_bar.rb
|
69
68
|
- lib/ruco/style_map.rb
|
@@ -81,6 +80,7 @@ files:
|
|
81
80
|
- spec/ruco/form_spec.rb
|
82
81
|
- spec/ruco/history_spec.rb
|
83
82
|
- spec/ruco/keyboard_spec.rb
|
83
|
+
- spec/ruco/option_accessor_spec.rb
|
84
84
|
- spec/ruco/status_bar_spec.rb
|
85
85
|
- spec/ruco/style_map_spec.rb
|
86
86
|
- spec/ruco/text_area_spec.rb
|
@@ -101,7 +101,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
101
101
|
requirements:
|
102
102
|
- - ">="
|
103
103
|
- !ruby/object:Gem::Version
|
104
|
-
hash:
|
104
|
+
hash: -55157123
|
105
105
|
segments:
|
106
106
|
- 0
|
107
107
|
version: "0"
|
@@ -110,14 +110,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
110
|
requirements:
|
111
111
|
- - ">="
|
112
112
|
- !ruby/object:Gem::Version
|
113
|
-
hash: 3
|
114
113
|
segments:
|
115
114
|
- 0
|
116
115
|
version: "0"
|
117
116
|
requirements: []
|
118
117
|
|
119
118
|
rubyforge_project:
|
120
|
-
rubygems_version: 1.
|
119
|
+
rubygems_version: 1.3.7
|
121
120
|
signing_key:
|
122
121
|
specification_version: 3
|
123
122
|
summary: Commandline editor written in ruby
|
@@ -131,6 +130,7 @@ test_files:
|
|
131
130
|
- spec/ruco/form_spec.rb
|
132
131
|
- spec/ruco/history_spec.rb
|
133
132
|
- spec/ruco/keyboard_spec.rb
|
133
|
+
- spec/ruco/option_accessor_spec.rb
|
134
134
|
- spec/ruco/status_bar_spec.rb
|
135
135
|
- spec/ruco/style_map_spec.rb
|
136
136
|
- spec/ruco/text_area_spec.rb
|