vice-editor 0.0.1
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.
- checksums.yaml +7 -0
- data/README.md +10 -0
- data/Rakefile +24 -0
- data/bin/vice +6 -0
- data/lib/vice.rb +82 -0
- data/lib/vice/blitter.rb +133 -0
- data/lib/vice/buffer.rb +154 -0
- data/lib/vice/cursor.rb +8 -0
- data/lib/vice/movement.rb +54 -0
- data/lib/vice/parser.rb +188 -0
- data/lib/vice/prompt.rb +32 -0
- data/lib/vice/version.rb +3 -0
- data/test/vice.rb +37 -0
- data/test/vice/buffer.rb +82 -0
- data/test/vice/movement.rb +41 -0
- data/test/vice/parser.rb +81 -0
- metadata +86 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: d298389b60730b766f83fd18d71e7102437370fd
|
|
4
|
+
data.tar.gz: 46b702832f8a6a80c84f1a73782c227dde7528ac
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 0c77bab922bb385e70adae409916f475dfac1f30fe607bd92a8245b16eec1bb2f3156cdf812d1f8dc2a3bd3a77a0919df8c235279e7c25905592054f230f319d
|
|
7
|
+
data.tar.gz: c39f48642fd406ac1edd9816bf07d87b931c3c7a96301400108b5f7b44c07c7fbf625173848155bbbe7f81ba91d960a8654a1a2a6fff4f58ba40071b1d93536a
|
data/README.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# vice
|
|
2
|
+
[](https://travis-ci.org/knarka/vice)
|
|
3
|
+
|
|
4
|
+
vice (**vi**sual **c**ode **e**ditor) is a small vi-like editor. It is currently still a work in progress.
|
|
5
|
+
|
|
6
|
+
## Running
|
|
7
|
+
Execute `rake`.
|
|
8
|
+
|
|
9
|
+
## Running the tests
|
|
10
|
+
Execute `rake test`.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
task default: %w[run]
|
|
2
|
+
|
|
3
|
+
task :run do
|
|
4
|
+
require_relative 'lib/vice'
|
|
5
|
+
Vice::Vice.new(nil).start
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
task :test do
|
|
9
|
+
Dir.foreach('test/vice') do |test|
|
|
10
|
+
next if ['.', '..'].include? test
|
|
11
|
+
ruby 'test/vice/' + test
|
|
12
|
+
end
|
|
13
|
+
ruby 'test/vice.rb'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
task :style do
|
|
17
|
+
sh 'rubocop -c .rubocop.yml lib/ test/ Gemfile Rakefile'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
task :clean do
|
|
21
|
+
Dir.glob('.').select{ |f| /.*\.gem$/.match f }.each do |file|
|
|
22
|
+
File.delete file
|
|
23
|
+
end
|
|
24
|
+
end
|
data/bin/vice
ADDED
data/lib/vice.rb
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'curses'
|
|
2
|
+
|
|
3
|
+
module Vice
|
|
4
|
+
TAB_WIDTH = 4
|
|
5
|
+
|
|
6
|
+
class Vice
|
|
7
|
+
attr_accessor :buffers
|
|
8
|
+
attr_accessor :current_buffer
|
|
9
|
+
attr_accessor :cursor
|
|
10
|
+
attr_accessor :mode
|
|
11
|
+
attr_accessor :prompt
|
|
12
|
+
|
|
13
|
+
attr_reader :msg
|
|
14
|
+
|
|
15
|
+
def initialize(filenames)
|
|
16
|
+
@mode = :command
|
|
17
|
+
@buffers = []
|
|
18
|
+
@parser = Parser.new
|
|
19
|
+
@prompt = ''
|
|
20
|
+
|
|
21
|
+
@current_buffer = 0
|
|
22
|
+
if filenames.nil? || filenames.empty?
|
|
23
|
+
@buffers.push Buffer.new nil
|
|
24
|
+
else
|
|
25
|
+
filenames.each do |f|
|
|
26
|
+
@buffers.push Buffer.new(f)
|
|
27
|
+
next_buffer
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def start
|
|
33
|
+
Curses.init_screen
|
|
34
|
+
Curses.noecho
|
|
35
|
+
Curses.start_color
|
|
36
|
+
Curses.use_default_colors
|
|
37
|
+
window = Curses.stdscr
|
|
38
|
+
|
|
39
|
+
blitter = Blitter.new window
|
|
40
|
+
|
|
41
|
+
alert "welcome to vice #{VERSION} - https://github.com/knarka/vice"
|
|
42
|
+
|
|
43
|
+
loop do
|
|
44
|
+
blitter.drawbuffer self, window
|
|
45
|
+
key = window.getch
|
|
46
|
+
@parser.parsekeypress self, @current_buffer, key
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
Curses.close_screen
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def alert(msg)
|
|
53
|
+
@msg = msg
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def error(msg)
|
|
57
|
+
@msg = 'error: ' + msg
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def reset_alert
|
|
61
|
+
@msg = nil
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def next_buffer
|
|
65
|
+
@current_buffer += 1
|
|
66
|
+
@current_buffer = 0 if @current_buffer >= @buffers.length
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def prev_buffer
|
|
70
|
+
@current_buffer -= 1
|
|
71
|
+
@current_buffer = @buffers.length - 1 if @current_buffer < 0
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
require_relative 'vice/version'
|
|
77
|
+
require_relative 'vice/buffer'
|
|
78
|
+
require_relative 'vice/cursor'
|
|
79
|
+
require_relative 'vice/parser'
|
|
80
|
+
require_relative 'vice/blitter'
|
|
81
|
+
require_relative 'vice/movement'
|
|
82
|
+
require_relative 'vice/prompt'
|
data/lib/vice/blitter.rb
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
class Vice::Blitter
|
|
2
|
+
def initialize(window)
|
|
3
|
+
Curses.init_pair 1, Curses::COLOR_BLACK, Curses::COLOR_WHITE
|
|
4
|
+
window.attrset Curses.color_pair(0)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def drawtabs(vice, buffer, window)
|
|
8
|
+
window.attrset Curses.color_pair(1)
|
|
9
|
+
window.setpos 0, 0
|
|
10
|
+
window.addstr ' ' * Curses.cols
|
|
11
|
+
window.setpos 0, 2
|
|
12
|
+
vice.buffers.each do |b|
|
|
13
|
+
window.attrset(Curses.color_pair(0) | Curses::A_BOLD) if b == buffer
|
|
14
|
+
|
|
15
|
+
name = b.filename || '[no name]'
|
|
16
|
+
name = b.modified ? '+ ' + name : name
|
|
17
|
+
|
|
18
|
+
window.addstr ' ' + name + ' '
|
|
19
|
+
|
|
20
|
+
window.attrset Curses.color_pair(1) if b == buffer
|
|
21
|
+
end
|
|
22
|
+
window.attrset Curses.color_pair(0)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def drawalert(vice, window)
|
|
26
|
+
window.setpos Curses.lines - 1, 0
|
|
27
|
+
window.addstr ' ' * Curses.cols
|
|
28
|
+
|
|
29
|
+
return if vice.msg.nil?
|
|
30
|
+
|
|
31
|
+
window.setpos Curses.lines - 1, 0
|
|
32
|
+
window.addstr ' ' + vice.msg
|
|
33
|
+
|
|
34
|
+
vice.reset_alert
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def drawstatus(mode, window, buffer, prompt)
|
|
38
|
+
window.attrset Curses.color_pair(1)
|
|
39
|
+
|
|
40
|
+
# clear
|
|
41
|
+
window.setpos Curses.lines - 2, 0
|
|
42
|
+
window.addstr ' ' * Curses.cols
|
|
43
|
+
|
|
44
|
+
# draw mode
|
|
45
|
+
window.setpos Curses.lines - 2, 0
|
|
46
|
+
modestring = if mode == :insert
|
|
47
|
+
' -- insert --'
|
|
48
|
+
elsif mode == :prompt
|
|
49
|
+
' :' + prompt
|
|
50
|
+
end
|
|
51
|
+
window.addstr modestring
|
|
52
|
+
|
|
53
|
+
# draw cursor position
|
|
54
|
+
location = buffer.cursor.line.to_s + ',' + buffer.cursor.col.to_s
|
|
55
|
+
window.setpos Curses.lines - 2, Curses.cols - location.length - 1
|
|
56
|
+
window.addstr location
|
|
57
|
+
|
|
58
|
+
window.attrset Curses.color_pair(0)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def formatnumber(number)
|
|
62
|
+
delta = if number == '~'
|
|
63
|
+
@linenumwidth - 1
|
|
64
|
+
else
|
|
65
|
+
@linenumwidth - number.to_s.length
|
|
66
|
+
end
|
|
67
|
+
delta.times do
|
|
68
|
+
number = ' ' + number.to_s
|
|
69
|
+
end
|
|
70
|
+
number += ' '
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def pad(string)
|
|
74
|
+
delta = Curses.cols - string.length
|
|
75
|
+
delta.times { string += ' ' } if delta > 0
|
|
76
|
+
string
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def drawbuffer(vice, window)
|
|
80
|
+
buffer = vice.buffers[vice.current_buffer]
|
|
81
|
+
visual_cursor = Vice::Cursor.new buffer.cursor.line, 0
|
|
82
|
+
|
|
83
|
+
(0..buffer.cursor.col - 1).each do |i|
|
|
84
|
+
visual_cursor.col += if buffer.currentline[i] == "\t"
|
|
85
|
+
Vice::TAB_WIDTH
|
|
86
|
+
else
|
|
87
|
+
1
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
drawtabs vice, buffer, window
|
|
92
|
+
|
|
93
|
+
@linenumwidth = buffer.lines.to_s.length + 1
|
|
94
|
+
|
|
95
|
+
visual_cursor.line += 1 # space for tabs above buffer
|
|
96
|
+
visual_cursor.line -= buffer.v_scroll
|
|
97
|
+
visual_cursor.col += @linenumwidth + 1 # leave space for line numbers
|
|
98
|
+
|
|
99
|
+
while visual_cursor.line >= Curses.lines - 2
|
|
100
|
+
buffer.v_scroll += 1
|
|
101
|
+
visual_cursor.line -= 1
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
while visual_cursor.line < 1
|
|
105
|
+
buffer.v_scroll -= 1
|
|
106
|
+
visual_cursor.line += 1
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
(1..Curses.lines - 2).each do |r|
|
|
110
|
+
# r: on-screen line
|
|
111
|
+
# i: in-buffer line
|
|
112
|
+
i = r - 1 + buffer.v_scroll
|
|
113
|
+
window.setpos r, 0
|
|
114
|
+
if i < buffer.lines
|
|
115
|
+
line = pad buffer.getline(i).gsub(/(\t)/, ' ' * Vice::TAB_WIDTH)
|
|
116
|
+
window.addstr formatnumber(i + 1) + line
|
|
117
|
+
else
|
|
118
|
+
window.addstr pad(formatnumber('~'))
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
drawstatus vice.mode, window, buffer, vice.prompt
|
|
123
|
+
|
|
124
|
+
drawalert vice, window
|
|
125
|
+
|
|
126
|
+
if vice.mode == :prompt
|
|
127
|
+
window.setpos Curses.lines - 2, vice.prompt.length + 2
|
|
128
|
+
else
|
|
129
|
+
window.setpos visual_cursor.line, visual_cursor.col
|
|
130
|
+
end
|
|
131
|
+
window.refresh
|
|
132
|
+
end
|
|
133
|
+
end
|
data/lib/vice/buffer.rb
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
class Vice::Buffer
|
|
2
|
+
attr_reader :buffer
|
|
3
|
+
attr_reader :filename
|
|
4
|
+
attr_reader :modified
|
|
5
|
+
attr_accessor :cursor
|
|
6
|
+
attr_accessor :v_scroll
|
|
7
|
+
|
|
8
|
+
def initialize(filename)
|
|
9
|
+
@buffer = []
|
|
10
|
+
@marks = {}
|
|
11
|
+
if filename
|
|
12
|
+
@filename = filename
|
|
13
|
+
File.open(filename, 'r') do |f| # TODO: don't assume file exists
|
|
14
|
+
f.each_line { |line| @buffer.push line.chomp }
|
|
15
|
+
end
|
|
16
|
+
else
|
|
17
|
+
@buffer.push ''
|
|
18
|
+
end
|
|
19
|
+
@cursor = Vice::Cursor.new
|
|
20
|
+
@modified = false
|
|
21
|
+
@v_scroll = 0
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def writef(filename)
|
|
25
|
+
@modified = false
|
|
26
|
+
|
|
27
|
+
File.open(filename, 'w') do |f|
|
|
28
|
+
f.write @buffer.join "\n"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def write
|
|
33
|
+
writef @filename
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def cursor_end_of_line
|
|
37
|
+
# if we're out of bounds, move the cursor to the end of the line
|
|
38
|
+
@cursor.col = @buffer[@cursor.line].length - 1 if @cursor.col >= @buffer[@cursor.line].length
|
|
39
|
+
@cursor.col = 0 if @cursor.col < 0
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def cursor_up
|
|
43
|
+
@cursor.line -= 1 if @cursor.line > 0
|
|
44
|
+
cursor_end_of_line
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def cursor_down
|
|
48
|
+
@cursor.line += 1 if @cursor.line < @buffer.length - 1
|
|
49
|
+
cursor_end_of_line
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def cursor_left
|
|
53
|
+
@cursor.col -= 1 if @cursor.col > 0
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def cursor_right
|
|
57
|
+
@cursor.col += 1 if @cursor.col < @buffer[@cursor.line].length - 1
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def newline(index)
|
|
61
|
+
raise 'negative line index' unless index >= 0
|
|
62
|
+
|
|
63
|
+
@modified = true
|
|
64
|
+
|
|
65
|
+
# silently append to the end when index out of bounds
|
|
66
|
+
index = @buffer.length if index > @buffer.length
|
|
67
|
+
|
|
68
|
+
@buffer.insert index, ''
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def rmlinef(index)
|
|
72
|
+
raise 'negative line index' unless index >= 0
|
|
73
|
+
raise 'line index out of bounds' unless index < @buffer.length
|
|
74
|
+
|
|
75
|
+
@modified = true
|
|
76
|
+
|
|
77
|
+
@buffer.delete_at index
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def rmline
|
|
81
|
+
rmlinef @cursor.line
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def insertf(index, column, text)
|
|
85
|
+
raise 'negative line index' unless index >= 0
|
|
86
|
+
raise 'line index out of bounds' unless index < @buffer.length
|
|
87
|
+
raise 'negative column index' unless column >= 0
|
|
88
|
+
raise 'column index out of bounds' unless column <= @buffer[index].length
|
|
89
|
+
|
|
90
|
+
@modified = true
|
|
91
|
+
|
|
92
|
+
@buffer[index].insert column, text
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def insert(text)
|
|
96
|
+
insertf @cursor.line, @cursor.col, text
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def rmcharf(index, column)
|
|
100
|
+
raise 'negative line index' unless index >= 0
|
|
101
|
+
raise 'line index out of bounds' unless index < @buffer.length
|
|
102
|
+
raise 'negative column index' unless column >= 0
|
|
103
|
+
raise 'column index out of bounds' unless column <= @buffer[index].length
|
|
104
|
+
|
|
105
|
+
@modified = true
|
|
106
|
+
|
|
107
|
+
@buffer[index].slice! column
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def rmchar
|
|
111
|
+
rmcharf @cursor.line, @cursor.col
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def setline(index, text)
|
|
115
|
+
raise 'negative line index' unless index >= 0
|
|
116
|
+
raise 'line index out of bounds' unless index < @buffer.length
|
|
117
|
+
|
|
118
|
+
@modified = true
|
|
119
|
+
|
|
120
|
+
@buffer[index] = text
|
|
121
|
+
cursor_end_of_line
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def getline(index)
|
|
125
|
+
raise 'negative line index' unless index >= 0
|
|
126
|
+
raise 'line index out of bounds' unless index < @buffer.length
|
|
127
|
+
|
|
128
|
+
@buffer[index]
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def currentline
|
|
132
|
+
getline @cursor.line
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def lines
|
|
136
|
+
@buffer.length
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def cols
|
|
140
|
+
@buffer[@cursor.line].length
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def addmark(mark)
|
|
144
|
+
@marks[mark] = @cursor.clone
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def gotomark(mark)
|
|
148
|
+
return false unless @marks[mark]
|
|
149
|
+
@cursor = @marks[mark].clone
|
|
150
|
+
@cursor.line = @buffer.length - 1 if @cursor.line >= @buffer.length
|
|
151
|
+
cursor_end_of_line
|
|
152
|
+
true
|
|
153
|
+
end
|
|
154
|
+
end
|
data/lib/vice/cursor.rb
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
class Vice::Movement
|
|
2
|
+
def self.whitespace(char, harsh)
|
|
3
|
+
if harsh # only real whitespace
|
|
4
|
+
(char == ' ' || char == "\t" || char == "\n")
|
|
5
|
+
else # anything that's not alphanumeric
|
|
6
|
+
char !~ /\A\p{Alnum}+\z/
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.w_real(line, start, harsh)
|
|
11
|
+
return start if start == line.length - 1
|
|
12
|
+
return start + 1 if whitespace(line[start], harsh) && !whitespace(line[start + 1], harsh)
|
|
13
|
+
w_real(line, start + 1, harsh)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.w(line, start)
|
|
17
|
+
w_real(line, start, false)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.w_large(line, start)
|
|
21
|
+
w_real(line, start, true)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.b_internal(line, start, harsh)
|
|
25
|
+
return start if start.zero?
|
|
26
|
+
|
|
27
|
+
return start if !whitespace(line[start], harsh) && whitespace(line[start - 1], harsh)
|
|
28
|
+
|
|
29
|
+
b_internal(line, start - 1, harsh)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.b_real(line, start, harsh)
|
|
33
|
+
# if we're already on the beginning of a word, we jump to the previous one
|
|
34
|
+
start -= 1 if start > 0 && !whitespace(line[start], harsh) && whitespace(line[start - 1], harsh)
|
|
35
|
+
|
|
36
|
+
b_internal(line, start, harsh)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.b(line, start)
|
|
40
|
+
b_real(line, start, false)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.b_large(line, start)
|
|
44
|
+
b_real(line, start, true)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.dollar(line)
|
|
48
|
+
line.length - 1
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.zero
|
|
52
|
+
0
|
|
53
|
+
end
|
|
54
|
+
end
|
data/lib/vice/parser.rb
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
class Vice::Parser
|
|
2
|
+
def initialize
|
|
3
|
+
resettrail
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def resettrail
|
|
7
|
+
@trail = []
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def parsekeypress(vice, buffer, char)
|
|
11
|
+
if vice.mode == :command
|
|
12
|
+
parsechar_command vice, buffer, char
|
|
13
|
+
elsif vice.mode == :insert
|
|
14
|
+
parsechar_insert vice, buffer, char
|
|
15
|
+
elsif vice.mode == :prompt
|
|
16
|
+
parsechar_prompt vice, buffer, char
|
|
17
|
+
else
|
|
18
|
+
raise 'parsekeypress called with unknown mode'
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def parsechar_prompt(vice, current_buffer, char)
|
|
23
|
+
case char
|
|
24
|
+
when 10
|
|
25
|
+
Vice::Prompt.parse vice, vice.prompt, vice.buffers[current_buffer]
|
|
26
|
+
vice.prompt = ''
|
|
27
|
+
vice.mode = :command
|
|
28
|
+
when 27
|
|
29
|
+
vice.prompt = ''
|
|
30
|
+
vice.mode = :command
|
|
31
|
+
when Integer
|
|
32
|
+
vice.prompt += char if char >= 0 && char <= 10
|
|
33
|
+
else
|
|
34
|
+
vice.prompt += char
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def parsechar_command(vice, current_buffer, char)
|
|
39
|
+
buffer = vice.buffers[current_buffer]
|
|
40
|
+
raise 'parsechar called from command mode' unless vice.mode == :command
|
|
41
|
+
|
|
42
|
+
if @trail == ['m']
|
|
43
|
+
buffer.addmark char
|
|
44
|
+
vice.alert "added mark '" + char + "'"
|
|
45
|
+
@trail = []
|
|
46
|
+
return
|
|
47
|
+
elsif @trail == ["'"]
|
|
48
|
+
vice.alert 'mark not set' unless buffer.gotomark char
|
|
49
|
+
@trail = []
|
|
50
|
+
return
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
case char
|
|
54
|
+
# movement
|
|
55
|
+
when 'j'
|
|
56
|
+
buffer.cursor_down
|
|
57
|
+
when 'k'
|
|
58
|
+
buffer.cursor_up
|
|
59
|
+
when 'l'
|
|
60
|
+
buffer.cursor_right
|
|
61
|
+
when 'h'
|
|
62
|
+
buffer.cursor_left
|
|
63
|
+
when 'w'
|
|
64
|
+
if !@trail.empty?
|
|
65
|
+
if (@trail[0] == 'd' || @trail[0] == 'c') && buffer.currentline != ''
|
|
66
|
+
line_edited = buffer.currentline
|
|
67
|
+
slice_start = buffer.cursor.col
|
|
68
|
+
slice_end = Vice::Movement.w(buffer.currentline, buffer.cursor.col)
|
|
69
|
+
amount = slice_end - buffer.cursor.col
|
|
70
|
+
amount += 1 if slice_end == buffer.currentline.length - 1
|
|
71
|
+
line_edited.slice! slice_start, amount
|
|
72
|
+
|
|
73
|
+
buffer.setline buffer.cursor.line, line_edited
|
|
74
|
+
end
|
|
75
|
+
vice.mode = :insert if @trail[0] == 'c'
|
|
76
|
+
@trail = []
|
|
77
|
+
else
|
|
78
|
+
buffer.cursor.col = Vice::Movement.w(buffer.currentline, buffer.cursor.col)
|
|
79
|
+
end
|
|
80
|
+
when 'W'
|
|
81
|
+
buffer.cursor.col = Vice::Movement.W(buffer.currentline, buffer.cursor.col)
|
|
82
|
+
when 'b'
|
|
83
|
+
buffer.cursor.col = Vice::Movement.b(buffer.currentline, buffer.cursor.col)
|
|
84
|
+
when 'B'
|
|
85
|
+
buffer.cursor.col = Vice::Movement.B(buffer.currentline, buffer.cursor.col)
|
|
86
|
+
when '$'
|
|
87
|
+
buffer.cursor.col = Vice::Movement.dollar buffer.currentline
|
|
88
|
+
when '0'
|
|
89
|
+
buffer.cursor.col = Vice::Movement.zero
|
|
90
|
+
|
|
91
|
+
# entering insert mode
|
|
92
|
+
when 'I'
|
|
93
|
+
buffer.cursor.col = 0
|
|
94
|
+
vice.mode = :insert
|
|
95
|
+
when 'i'
|
|
96
|
+
vice.mode = :insert
|
|
97
|
+
when 'A'
|
|
98
|
+
buffer.cursor.col = buffer.cols
|
|
99
|
+
vice.mode = :insert
|
|
100
|
+
when 'a'
|
|
101
|
+
buffer.cursor.col += 1 if buffer.cursor.col < buffer.cols
|
|
102
|
+
vice.mode = :insert
|
|
103
|
+
when 'O'
|
|
104
|
+
buffer.newline buffer.cursor.line
|
|
105
|
+
buffer.cursor.col = 0
|
|
106
|
+
vice.mode = :insert
|
|
107
|
+
when 'o'
|
|
108
|
+
buffer.newline buffer.cursor.line + 1
|
|
109
|
+
buffer.cursor_down
|
|
110
|
+
vice.mode = :insert
|
|
111
|
+
|
|
112
|
+
# etc.
|
|
113
|
+
when 'x'
|
|
114
|
+
buffer.rmchar
|
|
115
|
+
buffer.cursor.col -= 1 if buffer.cursor.col > 0
|
|
116
|
+
when 'c'
|
|
117
|
+
if !@trail.empty? && @trail[0] == 'c'
|
|
118
|
+
buffer.setline buffer.cursor.line, ''
|
|
119
|
+
buffer.cursor.col = 0
|
|
120
|
+
vice.mode = :insert
|
|
121
|
+
@trail = []
|
|
122
|
+
else
|
|
123
|
+
@trail.push 'c'
|
|
124
|
+
end
|
|
125
|
+
when 'd'
|
|
126
|
+
if !@trail.empty? && @trail[0] == 'd'
|
|
127
|
+
if buffer.lines == 1
|
|
128
|
+
buffer.setline 0, ''
|
|
129
|
+
else
|
|
130
|
+
buffer.rmline
|
|
131
|
+
end
|
|
132
|
+
buffer.cursor.line -= 1 if buffer.lines <= buffer.cursor.line
|
|
133
|
+
buffer.cursor.col = 0
|
|
134
|
+
@trail = []
|
|
135
|
+
else
|
|
136
|
+
@trail.push 'd'
|
|
137
|
+
end
|
|
138
|
+
when 'g'
|
|
139
|
+
if !@trail.empty? && @trail[0] == 'g'
|
|
140
|
+
buffer.cursor.line = 0
|
|
141
|
+
buffer.cursor.col = 0
|
|
142
|
+
else
|
|
143
|
+
@trail.push 'g'
|
|
144
|
+
end
|
|
145
|
+
when 'G'
|
|
146
|
+
buffer.cursor.line = buffer.lines - 1
|
|
147
|
+
buffer.cursor.col = 0
|
|
148
|
+
when 'm'
|
|
149
|
+
@trail.push 'm' if @trail.empty?
|
|
150
|
+
when 't'
|
|
151
|
+
vice.next_buffer if !@trail.empty? && @trail[0] == 'g'
|
|
152
|
+
@trail = []
|
|
153
|
+
when 'T'
|
|
154
|
+
vice.prev_buffer if !@trail.empty? && @trail[0] == 'g'
|
|
155
|
+
@trail = []
|
|
156
|
+
when ';', ':'
|
|
157
|
+
vice.mode = :prompt
|
|
158
|
+
when "'"
|
|
159
|
+
@trail.push "'" if @trail.empty?
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def parsechar_insert(vice, current_buffer, char)
|
|
164
|
+
buffer = vice.buffers[current_buffer]
|
|
165
|
+
raise 'insertchar called from insert mode' unless vice.mode == :insert
|
|
166
|
+
case char
|
|
167
|
+
when 9
|
|
168
|
+
buffer.insert "\t"
|
|
169
|
+
buffer.cursor.col += 1
|
|
170
|
+
when 10 # return
|
|
171
|
+
buffer.newline buffer.cursor.line + 1
|
|
172
|
+
buffer.cursor_down
|
|
173
|
+
when 27 # escape
|
|
174
|
+
vice.mode = :command
|
|
175
|
+
buffer.cursor_end_of_line
|
|
176
|
+
when 127 # backspace
|
|
177
|
+
if buffer.cursor.col > 0
|
|
178
|
+
buffer.cursor.col -= 1
|
|
179
|
+
buffer.rmchar
|
|
180
|
+
end
|
|
181
|
+
when Integer
|
|
182
|
+
vice.prompt += char if char >= 0 && char <= 10
|
|
183
|
+
else
|
|
184
|
+
buffer.insert char
|
|
185
|
+
buffer.cursor.col += 1
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
data/lib/vice/prompt.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
class Vice::Prompt
|
|
2
|
+
def self.parse(vice, line, buffer)
|
|
3
|
+
words = line.split ' '
|
|
4
|
+
return if words.empty?
|
|
5
|
+
|
|
6
|
+
case words[0]
|
|
7
|
+
when 'e', 't'
|
|
8
|
+
if words.length > 1
|
|
9
|
+
files = words.dup
|
|
10
|
+
files.shift
|
|
11
|
+
vice.buffers.delete buffer unless buffer.modified || words[0] == 't'
|
|
12
|
+
files.each do |f|
|
|
13
|
+
vice.buffers.push Vice::Buffer.new(f)
|
|
14
|
+
end
|
|
15
|
+
else
|
|
16
|
+
vice.error 'no such file'
|
|
17
|
+
end
|
|
18
|
+
when 'w'
|
|
19
|
+
if words.length > 1
|
|
20
|
+
buffer.writef words[1]
|
|
21
|
+
elsif !buffer.filename.nil?
|
|
22
|
+
buffer.write
|
|
23
|
+
else
|
|
24
|
+
vice.error 'buffer has no filename'
|
|
25
|
+
end
|
|
26
|
+
when 'q'
|
|
27
|
+
vice.buffers.delete buffer
|
|
28
|
+
vice.prev_buffer
|
|
29
|
+
exit if vice.buffers.empty?
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/lib/vice/version.rb
ADDED
data/test/vice.rb
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require 'minitest/autorun'
|
|
2
|
+
|
|
3
|
+
require_relative '../lib/vice'
|
|
4
|
+
|
|
5
|
+
class TestVice < MiniTest::Test
|
|
6
|
+
def setup
|
|
7
|
+
@vice = Vice::Vice.new nil
|
|
8
|
+
@vice.buffers.push Vice::Buffer.new nil
|
|
9
|
+
@vice.buffers.push Vice::Buffer.new nil
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_switch_tab_forward
|
|
13
|
+
assert_equal 0, @vice.current_buffer
|
|
14
|
+
|
|
15
|
+
@vice.next_buffer
|
|
16
|
+
assert_equal 1, @vice.current_buffer
|
|
17
|
+
|
|
18
|
+
@vice.next_buffer
|
|
19
|
+
assert_equal 2, @vice.current_buffer
|
|
20
|
+
|
|
21
|
+
@vice.next_buffer
|
|
22
|
+
assert_equal 0, @vice.current_buffer
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def test_switch_tab_backward
|
|
26
|
+
assert_equal 0, @vice.current_buffer
|
|
27
|
+
|
|
28
|
+
@vice.prev_buffer
|
|
29
|
+
assert_equal 2, @vice.current_buffer
|
|
30
|
+
|
|
31
|
+
@vice.prev_buffer
|
|
32
|
+
assert_equal 1, @vice.current_buffer
|
|
33
|
+
|
|
34
|
+
@vice.prev_buffer
|
|
35
|
+
assert_equal 0, @vice.current_buffer
|
|
36
|
+
end
|
|
37
|
+
end
|
data/test/vice/buffer.rb
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'minitest/autorun'
|
|
2
|
+
|
|
3
|
+
require_relative '../../lib/vice'
|
|
4
|
+
|
|
5
|
+
class TestBuffer < MiniTest::Test
|
|
6
|
+
def setup
|
|
7
|
+
@buffer = Vice::Buffer.new nil
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def test_create_buffer
|
|
11
|
+
assert_equal [''], @buffer.buffer
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_newline_valid
|
|
15
|
+
@buffer.newline 0
|
|
16
|
+
assert_equal ['', ''], @buffer.buffer
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_newline_negative_index
|
|
20
|
+
assert_raises RuntimeError do
|
|
21
|
+
@buffer.newline -1
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def test_insert_and_insertf_valid
|
|
26
|
+
@buffer.insert 'chunky bacon'
|
|
27
|
+
assert_equal 'chunky bacon', @buffer.buffer[0]
|
|
28
|
+
|
|
29
|
+
@buffer.insertf 0, 6, ' crispy'
|
|
30
|
+
assert_equal 'chunky crispy bacon', @buffer.buffer[0]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_insertf_out_of_bounds
|
|
34
|
+
# negative line index
|
|
35
|
+
assert_raises RuntimeError do
|
|
36
|
+
@buffer.insertf -1, 0, ''
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# out of bounds line index
|
|
40
|
+
assert_raises RuntimeError do
|
|
41
|
+
@buffer.insertf 2, 0, ''
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
@buffer.newline 0
|
|
45
|
+
|
|
46
|
+
# negative column index
|
|
47
|
+
assert_raises RuntimeError do
|
|
48
|
+
@buffer.insertf 0, -1, ''
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# out of bounds column index
|
|
52
|
+
assert_raises RuntimeError do
|
|
53
|
+
@buffer.insertf 0, 2, ''
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_setline_valid
|
|
58
|
+
assert_equal [''], @buffer.buffer
|
|
59
|
+
|
|
60
|
+
@buffer.setline 0, 'chunky bacon'
|
|
61
|
+
assert_equal 'chunky bacon', @buffer.buffer[0]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def test_rmlinef_valid
|
|
65
|
+
assert_equal [''], @buffer.buffer
|
|
66
|
+
|
|
67
|
+
@buffer.rmlinef 0
|
|
68
|
+
assert_equal [], @buffer.buffer
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def test_getline_valid
|
|
72
|
+
@buffer.setline 0, 'chunky bacon'
|
|
73
|
+
assert_equal 'chunky bacon', @buffer.getline(0)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def test_modified
|
|
77
|
+
assert_equal false, @buffer.modified
|
|
78
|
+
|
|
79
|
+
@buffer.newline 0
|
|
80
|
+
assert_equal true, @buffer.modified
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require 'minitest/autorun'
|
|
2
|
+
|
|
3
|
+
require_relative '../../lib/vice'
|
|
4
|
+
|
|
5
|
+
class TestMovement < MiniTest::Test
|
|
6
|
+
def test_w_end_of_string
|
|
7
|
+
assert_equal Vice::Movement.w('abc', 0), 2
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def test_w_some_words
|
|
11
|
+
assert_equal Vice::Movement.w('jantje zag eens', 2), 7
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_w_with_other_whitespace_chars
|
|
15
|
+
assert_equal Vice::Movement.w("jantje\t\nzag eens", 2), 8
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_b_start_of_string
|
|
19
|
+
assert_equal Vice::Movement.b('aaaaa', 5), 0
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_b_some_words
|
|
23
|
+
assert_equal Vice::Movement.b('ab cd', 4), 3
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_b_from_start_of_word
|
|
27
|
+
assert_equal Vice::Movement.b('jantje zag eens', 11), 7
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_w_w_large_difference
|
|
31
|
+
string = 'aaa-bbb ccc'
|
|
32
|
+
assert_equal Vice::Movement.w(string, 1), 4
|
|
33
|
+
assert_equal Vice::Movement.w_large(string, 1), 8
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def test_b_b_large_difference
|
|
37
|
+
string = 'bbb-ccc'
|
|
38
|
+
assert_equal Vice::Movement.b(string, 5), 4
|
|
39
|
+
assert_equal Vice::Movement.b_large(string, 5), 0
|
|
40
|
+
end
|
|
41
|
+
end
|
data/test/vice/parser.rb
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require 'minitest/autorun'
|
|
2
|
+
|
|
3
|
+
require_relative '../../lib/vice'
|
|
4
|
+
|
|
5
|
+
class TestParser < MiniTest::Test
|
|
6
|
+
def setup
|
|
7
|
+
@vice = Vice::Vice.new nil
|
|
8
|
+
@vice.buffers.push Vice::Buffer.new nil
|
|
9
|
+
@parser = Vice::Parser.new
|
|
10
|
+
@buffer = 0
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def test_parsechar_command_movement_up_down
|
|
14
|
+
@vice.buffers[@buffer].newline 0
|
|
15
|
+
assert_equal @vice.buffers[@buffer].cursor.line, 0
|
|
16
|
+
|
|
17
|
+
# go down one line
|
|
18
|
+
@parser.parsechar_command @vice, @buffer, 'j'
|
|
19
|
+
assert_equal @vice.buffers[@buffer].cursor.line, 1
|
|
20
|
+
|
|
21
|
+
# don't go down another line if no more lines exist
|
|
22
|
+
@parser.parsechar_command @vice, @buffer, 'j'
|
|
23
|
+
assert_equal @vice.buffers[@buffer].cursor.line, 1
|
|
24
|
+
|
|
25
|
+
# go up one line
|
|
26
|
+
@parser.parsechar_command @vice, @buffer, 'k'
|
|
27
|
+
assert_equal @vice.buffers[@buffer].cursor.line, 0
|
|
28
|
+
|
|
29
|
+
# don't go up another line if no more lines exist
|
|
30
|
+
@parser.parsechar_command @vice, @buffer, 'k'
|
|
31
|
+
assert_equal @vice.buffers[@buffer].cursor.line, 0
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# test that we enter insert mode after pressing i
|
|
35
|
+
def test_parsechar_command_i
|
|
36
|
+
assert_equal @vice.mode, :command
|
|
37
|
+
|
|
38
|
+
@parser.parsechar_command @vice, @buffer, 'i'
|
|
39
|
+
assert_equal @vice.mode, :insert
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# test the I command
|
|
43
|
+
def test_parsechar_command_i_large
|
|
44
|
+
@vice.buffers[@buffer].setline 0, 'abcdefg'
|
|
45
|
+
@vice.buffers[@buffer].cursor.col = 4
|
|
46
|
+
|
|
47
|
+
@parser.parsechar_command @vice, @buffer, 'I'
|
|
48
|
+
assert_equal @vice.mode, :insert
|
|
49
|
+
assert_equal @vice.buffers[@buffer].cursor.col, 0
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# test inserting characters
|
|
53
|
+
def test_insert_some_text
|
|
54
|
+
@vice.mode = :insert
|
|
55
|
+
@parser.parsechar_insert @vice, @buffer, 'h'
|
|
56
|
+
@parser.parsechar_insert @vice, @buffer, 'e'
|
|
57
|
+
@parser.parsechar_insert @vice, @buffer, 'y'
|
|
58
|
+
assert_equal @vice.buffers[@buffer].getline(0), 'hey'
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# test inserting characters in a more random place
|
|
62
|
+
def test_parsechar_insert_in_the_middle
|
|
63
|
+
@vice.mode = :insert
|
|
64
|
+
@vice.buffers[@buffer].newline 0
|
|
65
|
+
@vice.buffers[@buffer].newline 0
|
|
66
|
+
@vice.buffers[@buffer].setline 1, 'é melhorser alegre'
|
|
67
|
+
assert_equal @vice.buffers[@buffer].buffer, ['', 'é melhorser alegre', '']
|
|
68
|
+
|
|
69
|
+
@vice.buffers[@buffer].cursor.line = 1
|
|
70
|
+
@vice.buffers[@buffer].cursor.col = 8
|
|
71
|
+
@parser.parsechar_insert @vice, @buffer, ' '
|
|
72
|
+
assert_equal @vice.buffers[@buffer].getline(1), 'é melhor ser alegre'
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def test_parsechar_insert_escape
|
|
76
|
+
@vice.mode = :insert
|
|
77
|
+
|
|
78
|
+
@parser.parsechar_insert @vice, @buffer, 27
|
|
79
|
+
assert_equal @vice.mode, :command
|
|
80
|
+
end
|
|
81
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: vice-editor
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- knarka
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2018-06-15 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: curses
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
description:
|
|
42
|
+
email: knarka@users.noreply.github.com
|
|
43
|
+
executables:
|
|
44
|
+
- vice
|
|
45
|
+
extensions: []
|
|
46
|
+
extra_rdoc_files: []
|
|
47
|
+
files:
|
|
48
|
+
- README.md
|
|
49
|
+
- Rakefile
|
|
50
|
+
- bin/vice
|
|
51
|
+
- lib/vice.rb
|
|
52
|
+
- lib/vice/blitter.rb
|
|
53
|
+
- lib/vice/buffer.rb
|
|
54
|
+
- lib/vice/cursor.rb
|
|
55
|
+
- lib/vice/movement.rb
|
|
56
|
+
- lib/vice/parser.rb
|
|
57
|
+
- lib/vice/prompt.rb
|
|
58
|
+
- lib/vice/version.rb
|
|
59
|
+
- test/vice.rb
|
|
60
|
+
- test/vice/buffer.rb
|
|
61
|
+
- test/vice/movement.rb
|
|
62
|
+
- test/vice/parser.rb
|
|
63
|
+
homepage: https://github.com/knarka/vice
|
|
64
|
+
licenses: []
|
|
65
|
+
metadata: {}
|
|
66
|
+
post_install_message:
|
|
67
|
+
rdoc_options: []
|
|
68
|
+
require_paths:
|
|
69
|
+
- lib
|
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: 2.3.3
|
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
|
+
requirements:
|
|
77
|
+
- - ">="
|
|
78
|
+
- !ruby/object:Gem::Version
|
|
79
|
+
version: '0'
|
|
80
|
+
requirements: []
|
|
81
|
+
rubyforge_project:
|
|
82
|
+
rubygems_version: 2.5.2.1
|
|
83
|
+
signing_key:
|
|
84
|
+
specification_version: 4
|
|
85
|
+
summary: vi-like text editor
|
|
86
|
+
test_files: []
|