diakonos 0.8.3
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/CHANGELOG +172 -0
- data/README +75 -0
- data/bin/diakonos +6 -0
- data/diakonos.conf +960 -0
- data/home-on-save.rb +6 -0
- data/lib/diakonos.rb +2397 -0
- data/lib/diakonos/array.rb +10 -0
- data/lib/diakonos/bignum.rb +6 -0
- data/lib/diakonos/bookmark.rb +51 -0
- data/lib/diakonos/buffer-hash.rb +18 -0
- data/lib/diakonos/buffer.rb +1700 -0
- data/lib/diakonos/clipboard.rb +47 -0
- data/lib/diakonos/ctag.rb +28 -0
- data/lib/diakonos/enumerable.rb +15 -0
- data/lib/diakonos/finding.rb +32 -0
- data/lib/diakonos/fixnum.rb +13 -0
- data/lib/diakonos/hash.rb +101 -0
- data/lib/diakonos/keycode.rb +110 -0
- data/lib/diakonos/object.rb +6 -0
- data/lib/diakonos/readline.rb +192 -0
- data/lib/diakonos/regexp.rb +6 -0
- data/lib/diakonos/sized-array.rb +48 -0
- data/lib/diakonos/string.rb +318 -0
- data/lib/diakonos/text-mark.rb +19 -0
- data/lib/diakonos/window.rb +32 -0
- data/test/buffer-test.rb +37 -0
- data/test/clipboard-test.rb +70 -0
- data/test/diakonos-test.rb +14 -0
- data/test/hash-test.rb +404 -0
- data/test/regexp-test.rb +26 -0
- data/test/sizedarray-test.rb +113 -0
- data/test/string-test.rb +160 -0
- metadata +77 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
class SizedArray < Array
|
2
|
+
attr_reader :capacity
|
3
|
+
|
4
|
+
def initialize( capacity = 10, *args )
|
5
|
+
@capacity = capacity
|
6
|
+
super( *args )
|
7
|
+
end
|
8
|
+
|
9
|
+
def resize
|
10
|
+
if size > @capacity
|
11
|
+
slice!( (0...-@capacity) )
|
12
|
+
end
|
13
|
+
end
|
14
|
+
private :resize
|
15
|
+
|
16
|
+
def concat( other_array )
|
17
|
+
super( other_array )
|
18
|
+
resize
|
19
|
+
return self
|
20
|
+
end
|
21
|
+
|
22
|
+
def fill( *args )
|
23
|
+
retval = super( *args )
|
24
|
+
resize
|
25
|
+
return self
|
26
|
+
end
|
27
|
+
|
28
|
+
def <<( item )
|
29
|
+
retval = super( item )
|
30
|
+
if size > @capacity
|
31
|
+
retval = shift
|
32
|
+
end
|
33
|
+
return retval
|
34
|
+
end
|
35
|
+
|
36
|
+
def push( item )
|
37
|
+
self << item
|
38
|
+
end
|
39
|
+
|
40
|
+
def unshift( item )
|
41
|
+
retval = super( item )
|
42
|
+
if size > @capacity
|
43
|
+
retval = pop
|
44
|
+
end
|
45
|
+
return retval
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,318 @@
|
|
1
|
+
class String
|
2
|
+
def subHome
|
3
|
+
return gsub( /~/, ENV[ "HOME" ] )
|
4
|
+
end
|
5
|
+
|
6
|
+
def keyCode
|
7
|
+
retval = nil
|
8
|
+
case downcase
|
9
|
+
when "down"
|
10
|
+
retval = Curses::KEY_DOWN
|
11
|
+
when "up"
|
12
|
+
retval = Curses::KEY_UP
|
13
|
+
when "left"
|
14
|
+
retval = Curses::KEY_LEFT
|
15
|
+
when "right"
|
16
|
+
retval = Curses::KEY_RIGHT
|
17
|
+
when "home"
|
18
|
+
retval = Curses::KEY_HOME
|
19
|
+
when "end"
|
20
|
+
retval = Curses::KEY_END
|
21
|
+
when "insert", "ins"
|
22
|
+
retval = Curses::KEY_IC
|
23
|
+
when "delete", "del"
|
24
|
+
retval = Curses::KEY_DC
|
25
|
+
when "backspace"
|
26
|
+
retval = Diakonos::BACKSPACE
|
27
|
+
when "tab"
|
28
|
+
retval = 9
|
29
|
+
when "pageup", "page-up"
|
30
|
+
retval = Curses::KEY_PPAGE
|
31
|
+
when "pagedown", "page-down"
|
32
|
+
retval = Curses::KEY_NPAGE
|
33
|
+
when "enter", "return"
|
34
|
+
retval = Diakonos::ENTER
|
35
|
+
when "numpad7", "keypad7", "kp-7"
|
36
|
+
retval = Curses::KEY_A1
|
37
|
+
when "numpad9", "keypad9", "kp-9"
|
38
|
+
retval = Curses::KEY_A3
|
39
|
+
when "numpad5", "keypad5", "kp-5"
|
40
|
+
retval = Curses::KEY_B2
|
41
|
+
when "numpad1", "keypad1", "kp-1"
|
42
|
+
retval = Curses::KEY_C1
|
43
|
+
when "numpad3", "keypad3", "kp-3"
|
44
|
+
retval = Curses::KEY_C3
|
45
|
+
when "escape", "esc"
|
46
|
+
retval = Diakonos::ESCAPE
|
47
|
+
when "space"
|
48
|
+
retval = 32
|
49
|
+
when "ctrl+space"
|
50
|
+
retval = 0
|
51
|
+
when "find"
|
52
|
+
retval = Curses::KEY_FIND
|
53
|
+
when "select"
|
54
|
+
retval = Curses::KEY_SELECT
|
55
|
+
when "suspend"
|
56
|
+
retval = Curses::KEY_SUSPEND
|
57
|
+
when /^f(\d\d?)$/
|
58
|
+
retval = Curses::KEY_F0 + $1.to_i
|
59
|
+
when /^ctrl\+[a-gi-z]$/
|
60
|
+
retval = downcase[ -1 ] - 96
|
61
|
+
when /^ctrl\+h$/
|
62
|
+
retval = Diakonos::CTRL_H
|
63
|
+
when /^alt\+(.)$/
|
64
|
+
retval = [ Diakonos::ESCAPE, $1[ 0 ] ]
|
65
|
+
when /^ctrl\+alt\+(.)$/, /^alt\+ctrl\+(.)$/
|
66
|
+
retval = [ Diakonos::ESCAPE, downcase[ -1 ] - 96 ]
|
67
|
+
when /^keycode(\d+)$/
|
68
|
+
retval = $1.to_i
|
69
|
+
when /^.$/
|
70
|
+
retval = self[ 0 ]
|
71
|
+
end
|
72
|
+
if retval.class != Array
|
73
|
+
retval = [ retval ]
|
74
|
+
end
|
75
|
+
return retval
|
76
|
+
end
|
77
|
+
|
78
|
+
def toFormatting
|
79
|
+
formatting = Curses::A_NORMAL
|
80
|
+
split( /\s+/ ).each do |format|
|
81
|
+
case format.downcase
|
82
|
+
when "normal"
|
83
|
+
formatting = Curses::A_NORMAL
|
84
|
+
when "black", "0"
|
85
|
+
formatting = formatting | Curses::color_pair( Curses::COLOR_BLACK )
|
86
|
+
when "red", "1"
|
87
|
+
formatting = formatting | Curses::color_pair( Curses::COLOR_RED )
|
88
|
+
when "green", "2"
|
89
|
+
formatting = formatting | Curses::color_pair( Curses::COLOR_GREEN )
|
90
|
+
when "yellow", "brown", "3"
|
91
|
+
formatting = formatting | Curses::color_pair( Curses::COLOR_YELLOW )
|
92
|
+
when "blue", "4"
|
93
|
+
formatting = formatting | Curses::color_pair( Curses::COLOR_BLUE )
|
94
|
+
when "magenta", "purple", "5"
|
95
|
+
formatting = formatting | Curses::color_pair( Curses::COLOR_MAGENTA )
|
96
|
+
when "cyan", "6"
|
97
|
+
formatting = formatting | Curses::color_pair( Curses::COLOR_CYAN )
|
98
|
+
when "white", "7"
|
99
|
+
formatting = formatting | Curses::color_pair( Curses::COLOR_WHITE )
|
100
|
+
when "standout", "s", "so"
|
101
|
+
formatting = formatting | Curses::A_STANDOUT
|
102
|
+
when "underline", "u", "un", "ul"
|
103
|
+
formatting = formatting | Curses::A_UNDERLINE
|
104
|
+
when "reverse", "r", "rev", "inverse", "i", "inv"
|
105
|
+
formatting = formatting | Curses::A_REVERSE
|
106
|
+
when "blink", "bl", "blinking"
|
107
|
+
formatting = formatting | Curses::A_BLINK
|
108
|
+
when "dim", "d"
|
109
|
+
formatting = formatting | Curses::A_DIM
|
110
|
+
when "bold", "b", "bo"
|
111
|
+
formatting = formatting | Curses::A_BOLD
|
112
|
+
else
|
113
|
+
if ( colour_number = format.to_i ) > Curses::COLOR_WHITE
|
114
|
+
formatting = formatting | Curses::color_pair( colour_number )
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
return formatting
|
119
|
+
end
|
120
|
+
|
121
|
+
def toColourConstant
|
122
|
+
retval = Curses::COLOR_WHITE
|
123
|
+
case downcase
|
124
|
+
when "black", "0"
|
125
|
+
retval = Curses::COLOR_BLACK
|
126
|
+
when "red", "1"
|
127
|
+
retval = Curses::COLOR_RED
|
128
|
+
when "green", "2"
|
129
|
+
retval = Curses::COLOR_GREEN
|
130
|
+
when "yellow", "brown", "3"
|
131
|
+
retval = Curses::COLOR_YELLOW
|
132
|
+
when "blue", "4"
|
133
|
+
retval = Curses::COLOR_BLUE
|
134
|
+
when "magenta", "purple", "5"
|
135
|
+
retval = Curses::COLOR_MAGENTA
|
136
|
+
when "cyan", "6"
|
137
|
+
retval = Curses::COLOR_CYAN
|
138
|
+
when "white", "7"
|
139
|
+
retval = Curses::COLOR_WHITE
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def toDirection( default = :down )
|
144
|
+
direction = nil
|
145
|
+
case self
|
146
|
+
when "up"
|
147
|
+
direction = :up
|
148
|
+
when /other/
|
149
|
+
direction = :opposite
|
150
|
+
when "down"
|
151
|
+
direction = :down
|
152
|
+
when "forward"
|
153
|
+
direction = :forward
|
154
|
+
when "backward"
|
155
|
+
direction = :backward
|
156
|
+
else
|
157
|
+
direction = default
|
158
|
+
end
|
159
|
+
return direction
|
160
|
+
end
|
161
|
+
|
162
|
+
def to_a
|
163
|
+
return [ self ]
|
164
|
+
end
|
165
|
+
|
166
|
+
def to_b
|
167
|
+
retval = false
|
168
|
+
case downcase
|
169
|
+
when "true", "t", "1", "yes", "y", "on", "+"
|
170
|
+
retval = true
|
171
|
+
end
|
172
|
+
return retval
|
173
|
+
end
|
174
|
+
|
175
|
+
def indentation_level( indent_size, indent_roundup, tab_size = Diakonos::DEFAULT_TAB_SIZE, indent_ignore_charset = nil )
|
176
|
+
if indent_ignore_charset == nil
|
177
|
+
level = 0
|
178
|
+
if self =~ /^([\s]+)/
|
179
|
+
#whitespace = $1.gsub( /\t/, ' ' * tab_size )
|
180
|
+
whitespace = $1.expandTabs( tab_size )
|
181
|
+
level = whitespace.length / indent_size
|
182
|
+
if indent_roundup and ( whitespace.length % indent_size > 0 )
|
183
|
+
level += 1
|
184
|
+
end
|
185
|
+
end
|
186
|
+
else
|
187
|
+
if self =~ /^[\s#{indent_ignore_charset}]*$/ or self == ""
|
188
|
+
level = -1
|
189
|
+
elsif self =~ /^([\s#{indent_ignore_charset}]+)/
|
190
|
+
#whitespace = $1.gsub( /\t/, ' ' * tab_size )
|
191
|
+
whitespace = $1.expandTabs( tab_size )
|
192
|
+
level = whitespace.length / indent_size
|
193
|
+
if indent_roundup and ( whitespace.length % indent_size > 0 )
|
194
|
+
level += 1
|
195
|
+
end
|
196
|
+
else
|
197
|
+
level = 0
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
return level
|
202
|
+
end
|
203
|
+
|
204
|
+
def expandTabs( tab_size = Diakonos::DEFAULT_TAB_SIZE )
|
205
|
+
s = dup
|
206
|
+
while s.sub!( /\t/ ) { |match_text|
|
207
|
+
match = Regexp.last_match
|
208
|
+
index = match.begin( 0 )
|
209
|
+
# Return value for block:
|
210
|
+
" " * ( tab_size - ( index % tab_size ) )
|
211
|
+
}
|
212
|
+
end
|
213
|
+
return s
|
214
|
+
end
|
215
|
+
|
216
|
+
def newlineSplit
|
217
|
+
retval = split( /\\n/ )
|
218
|
+
if self =~ /\\n$/
|
219
|
+
retval << ""
|
220
|
+
end
|
221
|
+
if retval.length > 1
|
222
|
+
retval[ 0 ] << "$"
|
223
|
+
retval[ 1..-2 ].collect do |el|
|
224
|
+
"^" << el << "$"
|
225
|
+
end
|
226
|
+
retval[ -1 ] = "^" << retval[ -1 ]
|
227
|
+
end
|
228
|
+
return retval
|
229
|
+
end
|
230
|
+
|
231
|
+
# Works like normal String#index except returns the index
|
232
|
+
# of the first matching regexp group if one or more groups are specified
|
233
|
+
# in the regexp. Both the index and the matched text are returned.
|
234
|
+
def group_index( regexp, offset = 0 )
|
235
|
+
if regexp.class != Regexp
|
236
|
+
return index( regexp, offset )
|
237
|
+
end
|
238
|
+
|
239
|
+
i = nil
|
240
|
+
match_text = nil
|
241
|
+
working_offset = 0
|
242
|
+
loop do
|
243
|
+
index( regexp, working_offset )
|
244
|
+
match = Regexp.last_match
|
245
|
+
if match
|
246
|
+
i = match.begin( 0 )
|
247
|
+
match_text = match[ 0 ]
|
248
|
+
if match.length > 1
|
249
|
+
# Find first matching group
|
250
|
+
1.upto( match.length - 1 ) do |match_item_index|
|
251
|
+
if match[ match_item_index ] != nil
|
252
|
+
i = match.begin( match_item_index )
|
253
|
+
match_text = match[ match_item_index ]
|
254
|
+
break
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
break if i >= offset
|
260
|
+
else
|
261
|
+
i = nil
|
262
|
+
break
|
263
|
+
end
|
264
|
+
working_offset += 1
|
265
|
+
end
|
266
|
+
|
267
|
+
return i, match_text
|
268
|
+
end
|
269
|
+
|
270
|
+
# Works like normal String#rindex except returns the index
|
271
|
+
# of the first matching regexp group if one or more groups are specified
|
272
|
+
# in the regexp. Both the index and the matched text are returned.
|
273
|
+
def group_rindex( regexp, offset = length )
|
274
|
+
if regexp.class != Regexp
|
275
|
+
return rindex( regexp, offset )
|
276
|
+
end
|
277
|
+
|
278
|
+
i = nil
|
279
|
+
match_text = nil
|
280
|
+
working_offset = length
|
281
|
+
loop do
|
282
|
+
rindex( regexp, working_offset )
|
283
|
+
match = Regexp.last_match
|
284
|
+
if match
|
285
|
+
i = match.end( 0 ) - 1
|
286
|
+
match_text = match[ 0 ]
|
287
|
+
if match.length > 1
|
288
|
+
# Find first matching group
|
289
|
+
1.upto( match.length - 1 ) do |match_item_index|
|
290
|
+
if match[ match_item_index ] != nil
|
291
|
+
i = match.end( match_item_index ) - 1
|
292
|
+
match_text = match[ match_item_index ]
|
293
|
+
break
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
if match_text == ""
|
299
|
+
# Assume that an empty string means that it matched $
|
300
|
+
i += 1
|
301
|
+
end
|
302
|
+
|
303
|
+
break if i <= offset
|
304
|
+
else
|
305
|
+
i = nil
|
306
|
+
break
|
307
|
+
end
|
308
|
+
working_offset -= 1
|
309
|
+
end
|
310
|
+
|
311
|
+
return i, match_text
|
312
|
+
end
|
313
|
+
|
314
|
+
def movement?
|
315
|
+
return ( ( self =~ /^((cursor|page|scroll)(Up|Down|Left|Right)|find)/ ) != nil )
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Diakonos
|
2
|
+
|
3
|
+
class TextMark
|
4
|
+
attr_reader :formatting, :start_row, :start_col, :end_row, :end_col
|
5
|
+
|
6
|
+
def initialize( start_row, start_col, end_row, end_col, formatting )
|
7
|
+
@start_row = start_row
|
8
|
+
@start_col = start_col
|
9
|
+
@end_row = end_row
|
10
|
+
@end_col = end_col
|
11
|
+
@formatting = formatting
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
return "(#{start_row},#{start_col})-(#{end_row},#{end_col}) #{formatting}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Curses::Window
|
2
|
+
def puts( string = "" )
|
3
|
+
addstr( string + "\n" )
|
4
|
+
end
|
5
|
+
|
6
|
+
# setpos, but with some boundary checks
|
7
|
+
def setpos_( y, x )
|
8
|
+
$diakonos.debugLog "setpos: y < 0 (#{y})" if y < 0
|
9
|
+
$diakonos.debugLog "setpos: x < 0 (#{x})" if x < 0
|
10
|
+
$diakonos.debugLog "setpos: y > lines (#{y})" if y > Curses::lines
|
11
|
+
$diakonos.debugLog "setpos: x > cols (#{x})" if x > Curses::cols
|
12
|
+
setpos( y, x )
|
13
|
+
end
|
14
|
+
|
15
|
+
def addstr_( string )
|
16
|
+
x = curx
|
17
|
+
y = cury
|
18
|
+
x2 = curx + string.length
|
19
|
+
|
20
|
+
if y < 0 or x < 0 or y > Curses::lines or x > Curses::cols or x2 < 0 or x2 > Curses::cols
|
21
|
+
begin
|
22
|
+
raise Exception
|
23
|
+
rescue Exception => e
|
24
|
+
$diakonos.debugLog e.backtrace[ 1 ]
|
25
|
+
$diakonos.debugLog e.backtrace[ 2 ]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
addstr( string )
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
data/test/buffer-test.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'diakonos'
|
5
|
+
|
6
|
+
class TC_Buffer < Test::Unit::TestCase
|
7
|
+
SAMPLE_FILE = File.dirname( File.expand_path( __FILE__ ) ) + '/sample-file.rb'
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@d = Diakonos::Diakonos.new [ '-e', 'quit' ]
|
11
|
+
@d.start
|
12
|
+
end
|
13
|
+
|
14
|
+
def teardown
|
15
|
+
system "reset"
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_selected_text
|
19
|
+
@d.openFile( SAMPLE_FILE )
|
20
|
+
b = Diakonos::Buffer.new( @d, SAMPLE_FILE )
|
21
|
+
@d.anchorSelection
|
22
|
+
@d.cursorDown
|
23
|
+
@d.cursorDown
|
24
|
+
@d.cursorDown
|
25
|
+
@d.copySelection
|
26
|
+
assert_equal(
|
27
|
+
[
|
28
|
+
"#!/usr/bin/env ruby",
|
29
|
+
"",
|
30
|
+
"# This is only a sample file used in the tests.",
|
31
|
+
""
|
32
|
+
],
|
33
|
+
@d.clipboard.clip
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|